Skip to content

Commit 772e266

Browse files
committed
Properly handle instantiation-dependent array bounds.
We previously failed to treat an array with an instantiation-dependent but not value-dependent bound as being an instantiation-dependent type. We now track the array bound expression as part of a constant array type if it's an instantiation-dependent expression. llvm-svn: 373685
1 parent 053391f commit 772e266

31 files changed

+237
-156
lines changed

clang/include/clang/AST/ASTContext.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
185185
mutable llvm::FoldingSet<LValueReferenceType> LValueReferenceTypes;
186186
mutable llvm::FoldingSet<RValueReferenceType> RValueReferenceTypes;
187187
mutable llvm::FoldingSet<MemberPointerType> MemberPointerTypes;
188-
mutable llvm::FoldingSet<ConstantArrayType> ConstantArrayTypes;
188+
mutable llvm::ContextualFoldingSet<ConstantArrayType, ASTContext &>
189+
ConstantArrayTypes;
189190
mutable llvm::FoldingSet<IncompleteArrayType> IncompleteArrayTypes;
190191
mutable std::vector<VariableArrayType*> VariableArrayTypes;
191192
mutable llvm::FoldingSet<DependentSizedArrayType> DependentSizedArrayTypes;
@@ -1330,6 +1331,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
13301331
/// Return the unique reference to the type for a constant array of
13311332
/// the specified element type.
13321333
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize,
1334+
const Expr *SizeExpr,
13331335
ArrayType::ArraySizeModifier ASM,
13341336
unsigned IndexTypeQuals) const;
13351337

clang/include/clang/AST/RecursiveASTVisitor.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -959,8 +959,11 @@ DEF_TRAVERSE_TYPE(AdjustedType, { TRY_TO(TraverseType(T->getOriginalType())); })
959959

960960
DEF_TRAVERSE_TYPE(DecayedType, { TRY_TO(TraverseType(T->getOriginalType())); })
961961

962-
DEF_TRAVERSE_TYPE(ConstantArrayType,
963-
{ TRY_TO(TraverseType(T->getElementType())); })
962+
DEF_TRAVERSE_TYPE(ConstantArrayType, {
963+
TRY_TO(TraverseType(T->getElementType()));
964+
if (T->getSizeExpr())
965+
TRY_TO(TraverseStmt(const_cast<Expr*>(T->getSizeExpr())));
966+
})
964967

965968
DEF_TRAVERSE_TYPE(IncompleteArrayType,
966969
{ TRY_TO(TraverseType(T->getElementType())); })

clang/include/clang/AST/Type.h

Lines changed: 42 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1513,6 +1513,15 @@ class alignas(8) Type : public ExtQualsTypeCommonBase {
15131513
unsigned SizeModifier : 3;
15141514
};
15151515

1516+
class ConstantArrayTypeBitfields {
1517+
friend class ConstantArrayType;
1518+
1519+
unsigned : NumTypeBits + 3 + 3;
1520+
1521+
/// Whether we have a stored size expression.
1522+
unsigned HasStoredSizeExpr : 1;
1523+
};
1524+
15161525
class BuiltinTypeBitfields {
15171526
friend class BuiltinType;
15181527

@@ -1734,6 +1743,7 @@ class alignas(8) Type : public ExtQualsTypeCommonBase {
17341743
union {
17351744
TypeBitfields TypeBits;
17361745
ArrayTypeBitfields ArrayTypeBits;
1746+
ConstantArrayTypeBitfields ConstantArrayTypeBits;
17371747
AttributedTypeBitfields AttributedTypeBits;
17381748
AutoTypeBitfields AutoTypeBits;
17391749
BuiltinTypeBitfields BuiltinTypeBits;
@@ -2864,22 +2874,8 @@ class ArrayType : public Type, public llvm::FoldingSetNode {
28642874
protected:
28652875
friend class ASTContext; // ASTContext creates these.
28662876

2867-
// C++ [temp.dep.type]p1:
2868-
// A type is dependent if it is...
2869-
// - an array type constructed from any dependent type or whose
2870-
// size is specified by a constant expression that is
2871-
// value-dependent,
2872-
ArrayType(TypeClass tc, QualType et, QualType can,
2873-
ArraySizeModifier sm, unsigned tq,
2874-
bool ContainsUnexpandedParameterPack)
2875-
: Type(tc, can, et->isDependentType() || tc == DependentSizedArray,
2876-
et->isInstantiationDependentType() || tc == DependentSizedArray,
2877-
(tc == VariableArray || et->isVariablyModifiedType()),
2878-
ContainsUnexpandedParameterPack),
2879-
ElementType(et) {
2880-
ArrayTypeBits.IndexTypeQuals = tq;
2881-
ArrayTypeBits.SizeModifier = sm;
2882-
}
2877+
ArrayType(TypeClass tc, QualType et, QualType can, ArraySizeModifier sm,
2878+
unsigned tq, const Expr *sz = nullptr);
28832879

28842880
public:
28852881
QualType getElementType() const { return ElementType; }
@@ -2907,25 +2903,35 @@ class ArrayType : public Type, public llvm::FoldingSetNode {
29072903
/// Represents the canonical version of C arrays with a specified constant size.
29082904
/// For example, the canonical type for 'int A[4 + 4*100]' is a
29092905
/// ConstantArrayType where the element type is 'int' and the size is 404.
2910-
class ConstantArrayType : public ArrayType {
2906+
class ConstantArrayType final
2907+
: public ArrayType,
2908+
private llvm::TrailingObjects<ConstantArrayType, const Expr *> {
2909+
friend class ASTContext; // ASTContext creates these.
2910+
friend TrailingObjects;
2911+
29112912
llvm::APInt Size; // Allows us to unique the type.
29122913

29132914
ConstantArrayType(QualType et, QualType can, const llvm::APInt &size,
2914-
ArraySizeModifier sm, unsigned tq)
2915-
: ArrayType(ConstantArray, et, can, sm, tq,
2916-
et->containsUnexpandedParameterPack()),
2917-
Size(size) {}
2918-
2919-
protected:
2920-
friend class ASTContext; // ASTContext creates these.
2915+
const Expr *sz, ArraySizeModifier sm, unsigned tq)
2916+
: ArrayType(ConstantArray, et, can, sm, tq, sz), Size(size) {
2917+
ConstantArrayTypeBits.HasStoredSizeExpr = sz != nullptr;
2918+
if (ConstantArrayTypeBits.HasStoredSizeExpr) {
2919+
assert(!can.isNull() && "canonical constant array should not have size");
2920+
*getTrailingObjects<const Expr*>() = sz;
2921+
}
2922+
}
29212923

2922-
ConstantArrayType(TypeClass tc, QualType et, QualType can,
2923-
const llvm::APInt &size, ArraySizeModifier sm, unsigned tq)
2924-
: ArrayType(tc, et, can, sm, tq, et->containsUnexpandedParameterPack()),
2925-
Size(size) {}
2924+
unsigned numTrailingObjects(OverloadToken<const Expr*>) const {
2925+
return ConstantArrayTypeBits.HasStoredSizeExpr;
2926+
}
29262927

29272928
public:
29282929
const llvm::APInt &getSize() const { return Size; }
2930+
const Expr *getSizeExpr() const {
2931+
return ConstantArrayTypeBits.HasStoredSizeExpr
2932+
? *getTrailingObjects<const Expr *>()
2933+
: nullptr;
2934+
}
29292935
bool isSugared() const { return false; }
29302936
QualType desugar() const { return QualType(this, 0); }
29312937

@@ -2939,19 +2945,15 @@ class ConstantArrayType : public ArrayType {
29392945
/// can require, which limits the maximum size of the array.
29402946
static unsigned getMaxSizeBits(const ASTContext &Context);
29412947

2942-
void Profile(llvm::FoldingSetNodeID &ID) {
2943-
Profile(ID, getElementType(), getSize(),
2948+
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx) {
2949+
Profile(ID, Ctx, getElementType(), getSize(), getSizeExpr(),
29442950
getSizeModifier(), getIndexTypeCVRQualifiers());
29452951
}
29462952

2947-
static void Profile(llvm::FoldingSetNodeID &ID, QualType ET,
2948-
const llvm::APInt &ArraySize, ArraySizeModifier SizeMod,
2949-
unsigned TypeQuals) {
2950-
ID.AddPointer(ET.getAsOpaquePtr());
2951-
ID.AddInteger(ArraySize.getZExtValue());
2952-
ID.AddInteger(SizeMod);
2953-
ID.AddInteger(TypeQuals);
2954-
}
2953+
static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx,
2954+
QualType ET, const llvm::APInt &ArraySize,
2955+
const Expr *SizeExpr, ArraySizeModifier SizeMod,
2956+
unsigned TypeQuals);
29552957

29562958
static bool classof(const Type *T) {
29572959
return T->getTypeClass() == ConstantArray;
@@ -2966,8 +2968,7 @@ class IncompleteArrayType : public ArrayType {
29662968

29672969
IncompleteArrayType(QualType et, QualType can,
29682970
ArraySizeModifier sm, unsigned tq)
2969-
: ArrayType(IncompleteArray, et, can, sm, tq,
2970-
et->containsUnexpandedParameterPack()) {}
2971+
: ArrayType(IncompleteArray, et, can, sm, tq) {}
29712972

29722973
public:
29732974
friend class StmtIteratorBase;
@@ -3019,8 +3020,7 @@ class VariableArrayType : public ArrayType {
30193020
VariableArrayType(QualType et, QualType can, Expr *e,
30203021
ArraySizeModifier sm, unsigned tq,
30213022
SourceRange brackets)
3022-
: ArrayType(VariableArray, et, can, sm, tq,
3023-
et->containsUnexpandedParameterPack()),
3023+
: ArrayType(VariableArray, et, can, sm, tq, e),
30243024
SizeExpr((Stmt*) e), Brackets(brackets) {}
30253025

30263026
public:

clang/lib/AST/ASTContext.cpp

Lines changed: 38 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -829,7 +829,8 @@ static bool isAddrSpaceMapManglingEnabled(const TargetInfo &TI,
829829
ASTContext::ASTContext(LangOptions &LOpts, SourceManager &SM,
830830
IdentifierTable &idents, SelectorTable &sels,
831831
Builtin::Context &builtins)
832-
: FunctionProtoTypes(this_()), TemplateSpecializationTypes(this_()),
832+
: ConstantArrayTypes(this_()), FunctionProtoTypes(this_()),
833+
TemplateSpecializationTypes(this_()),
833834
DependentTemplateSpecializationTypes(this_()),
834835
SubstTemplateTemplateParmPacks(this_()), SourceMgr(SM), LangOpts(LOpts),
835836
SanitizerBL(new SanitizerBlacklist(LangOpts.SanitizerBlacklistFiles, SM)),
@@ -3165,31 +3166,38 @@ QualType ASTContext::getMemberPointerType(QualType T, const Type *Cls) const {
31653166
/// array of the specified element type.
31663167
QualType ASTContext::getConstantArrayType(QualType EltTy,
31673168
const llvm::APInt &ArySizeIn,
3169+
const Expr *SizeExpr,
31683170
ArrayType::ArraySizeModifier ASM,
31693171
unsigned IndexTypeQuals) const {
31703172
assert((EltTy->isDependentType() ||
31713173
EltTy->isIncompleteType() || EltTy->isConstantSizeType()) &&
31723174
"Constant array of VLAs is illegal!");
31733175

3176+
// We only need the size as part of the type if it's instantiation-dependent.
3177+
if (SizeExpr && !SizeExpr->isInstantiationDependent())
3178+
SizeExpr = nullptr;
3179+
31743180
// Convert the array size into a canonical width matching the pointer size for
31753181
// the target.
31763182
llvm::APInt ArySize(ArySizeIn);
31773183
ArySize = ArySize.zextOrTrunc(Target->getMaxPointerWidth());
31783184

31793185
llvm::FoldingSetNodeID ID;
3180-
ConstantArrayType::Profile(ID, EltTy, ArySize, ASM, IndexTypeQuals);
3186+
ConstantArrayType::Profile(ID, *this, EltTy, ArySize, SizeExpr, ASM,
3187+
IndexTypeQuals);
31813188

31823189
void *InsertPos = nullptr;
31833190
if (ConstantArrayType *ATP =
31843191
ConstantArrayTypes.FindNodeOrInsertPos(ID, InsertPos))
31853192
return QualType(ATP, 0);
31863193

3187-
// If the element type isn't canonical or has qualifiers, this won't
3188-
// be a canonical type either, so fill in the canonical type field.
3194+
// If the element type isn't canonical or has qualifiers, or the array bound
3195+
// is instantiation-dependent, this won't be a canonical type either, so fill
3196+
// in the canonical type field.
31893197
QualType Canon;
3190-
if (!EltTy.isCanonical() || EltTy.hasLocalQualifiers()) {
3198+
if (!EltTy.isCanonical() || EltTy.hasLocalQualifiers() || SizeExpr) {
31913199
SplitQualType canonSplit = getCanonicalType(EltTy).split();
3192-
Canon = getConstantArrayType(QualType(canonSplit.Ty, 0), ArySize,
3200+
Canon = getConstantArrayType(QualType(canonSplit.Ty, 0), ArySize, nullptr,
31933201
ASM, IndexTypeQuals);
31943202
Canon = getQualifiedType(Canon, canonSplit.Quals);
31953203

@@ -3199,8 +3207,11 @@ QualType ASTContext::getConstantArrayType(QualType EltTy,
31993207
assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP;
32003208
}
32013209

3202-
auto *New = new (*this,TypeAlignment)
3203-
ConstantArrayType(EltTy, Canon, ArySize, ASM, IndexTypeQuals);
3210+
void *Mem = Allocate(
3211+
ConstantArrayType::totalSizeToAlloc<const Expr *>(SizeExpr ? 1 : 0),
3212+
TypeAlignment);
3213+
auto *New = new (Mem)
3214+
ConstantArrayType(EltTy, Canon, ArySize, SizeExpr, ASM, IndexTypeQuals);
32043215
ConstantArrayTypes.InsertNode(New, InsertPos);
32053216
Types.push_back(New);
32063217
return QualType(New, 0);
@@ -3297,6 +3308,7 @@ QualType ASTContext::getVariableArrayDecayedType(QualType type) const {
32973308
result = getConstantArrayType(
32983309
getVariableArrayDecayedType(cat->getElementType()),
32993310
cat->getSize(),
3311+
cat->getSizeExpr(),
33003312
cat->getSizeModifier(),
33013313
cat->getIndexTypeCVRQualifiers());
33023314
break;
@@ -5192,7 +5204,7 @@ QualType ASTContext::getUnqualifiedArrayType(QualType type,
51925204

51935205
if (const auto *CAT = dyn_cast<ConstantArrayType>(AT)) {
51945206
return getConstantArrayType(unqualElementType, CAT->getSize(),
5195-
CAT->getSizeModifier(), 0);
5207+
CAT->getSizeExpr(), CAT->getSizeModifier(), 0);
51965208
}
51975209

51985210
if (const auto *IAT = dyn_cast<IncompleteArrayType>(AT)) {
@@ -5565,6 +5577,7 @@ const ArrayType *ASTContext::getAsArrayType(QualType T) const {
55655577

55665578
if (const auto *CAT = dyn_cast<ConstantArrayType>(ATy))
55675579
return cast<ArrayType>(getConstantArrayType(NewEltTy, CAT->getSize(),
5580+
CAT->getSizeExpr(),
55685581
CAT->getSizeModifier(),
55695582
CAT->getIndexTypeCVRQualifiers()));
55705583
if (const auto *IAT = dyn_cast<IncompleteArrayType>(ATy))
@@ -7471,7 +7484,7 @@ static TypedefDecl *CreatePowerABIBuiltinVaListDecl(const ASTContext *Context) {
74717484
llvm::APInt Size(Context->getTypeSize(Context->getSizeType()), 1);
74727485
QualType VaListTagArrayType
74737486
= Context->getConstantArrayType(VaListTagTypedefType,
7474-
Size, ArrayType::Normal, 0);
7487+
Size, nullptr, ArrayType::Normal, 0);
74757488
return Context->buildImplicitTypedef(VaListTagArrayType, "__builtin_va_list");
74767489
}
74777490

@@ -7524,16 +7537,16 @@ CreateX86_64ABIBuiltinVaListDecl(const ASTContext *Context) {
75247537

75257538
// typedef struct __va_list_tag __builtin_va_list[1];
75267539
llvm::APInt Size(Context->getTypeSize(Context->getSizeType()), 1);
7527-
QualType VaListTagArrayType =
7528-
Context->getConstantArrayType(VaListTagType, Size, ArrayType::Normal, 0);
7540+
QualType VaListTagArrayType = Context->getConstantArrayType(
7541+
VaListTagType, Size, nullptr, ArrayType::Normal, 0);
75297542
return Context->buildImplicitTypedef(VaListTagArrayType, "__builtin_va_list");
75307543
}
75317544

75327545
static TypedefDecl *CreatePNaClABIBuiltinVaListDecl(const ASTContext *Context) {
75337546
// typedef int __builtin_va_list[4];
75347547
llvm::APInt Size(Context->getTypeSize(Context->getSizeType()), 4);
7535-
QualType IntArrayType =
7536-
Context->getConstantArrayType(Context->IntTy, Size, ArrayType::Normal, 0);
7548+
QualType IntArrayType = Context->getConstantArrayType(
7549+
Context->IntTy, Size, nullptr, ArrayType::Normal, 0);
75377550
return Context->buildImplicitTypedef(IntArrayType, "__builtin_va_list");
75387551
}
75397552

@@ -7627,8 +7640,8 @@ CreateSystemZBuiltinVaListDecl(const ASTContext *Context) {
76277640

76287641
// typedef __va_list_tag __builtin_va_list[1];
76297642
llvm::APInt Size(Context->getTypeSize(Context->getSizeType()), 1);
7630-
QualType VaListTagArrayType =
7631-
Context->getConstantArrayType(VaListTagType, Size, ArrayType::Normal, 0);
7643+
QualType VaListTagArrayType = Context->getConstantArrayType(
7644+
VaListTagType, Size, nullptr, ArrayType::Normal, 0);
76327645

76337646
return Context->buildImplicitTypedef(VaListTagArrayType, "__builtin_va_list");
76347647
}
@@ -9072,10 +9085,14 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
90729085
return LHS;
90739086
if (RCAT && getCanonicalType(RHSElem) == getCanonicalType(ResultType))
90749087
return RHS;
9075-
if (LCAT) return getConstantArrayType(ResultType, LCAT->getSize(),
9076-
ArrayType::ArraySizeModifier(), 0);
9077-
if (RCAT) return getConstantArrayType(ResultType, RCAT->getSize(),
9078-
ArrayType::ArraySizeModifier(), 0);
9088+
if (LCAT)
9089+
return getConstantArrayType(ResultType, LCAT->getSize(),
9090+
LCAT->getSizeExpr(),
9091+
ArrayType::ArraySizeModifier(), 0);
9092+
if (RCAT)
9093+
return getConstantArrayType(ResultType, RCAT->getSize(),
9094+
RCAT->getSizeExpr(),
9095+
ArrayType::ArraySizeModifier(), 0);
90799096
if (LVAT && getCanonicalType(LHSElem) == getCanonicalType(ResultType))
90809097
return LHS;
90819098
if (RVAT && getCanonicalType(RHSElem) == getCanonicalType(ResultType))
@@ -10317,7 +10334,7 @@ QualType ASTContext::getStringLiteralArrayType(QualType EltTy,
1031710334

1031810335
// Get an array type for the string, according to C99 6.4.5. This includes
1031910336
// the null terminator character.
10320-
return getConstantArrayType(EltTy, llvm::APInt(32, Length + 1),
10337+
return getConstantArrayType(EltTy, llvm::APInt(32, Length + 1), nullptr,
1032110338
ArrayType::Normal, /*IndexTypeQuals*/ 0);
1032210339
}
1032310340

clang/lib/AST/ASTImporter.cpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1098,14 +1098,16 @@ ASTNodeImporter::VisitMemberPointerType(const MemberPointerType *T) {
10981098

10991099
ExpectedType
11001100
ASTNodeImporter::VisitConstantArrayType(const ConstantArrayType *T) {
1101-
ExpectedType ToElementTypeOrErr = import(T->getElementType());
1102-
if (!ToElementTypeOrErr)
1103-
return ToElementTypeOrErr.takeError();
1101+
QualType ToElementType;
1102+
const Expr *ToSizeExpr;
1103+
if (auto Imp = importSeq(T->getElementType(), T->getSizeExpr()))
1104+
std::tie(ToElementType, ToSizeExpr) = *Imp;
1105+
else
1106+
return Imp.takeError();
11041107

1105-
return Importer.getToContext().getConstantArrayType(*ToElementTypeOrErr,
1106-
T->getSize(),
1107-
T->getSizeModifier(),
1108-
T->getIndexTypeCVRQualifiers());
1108+
return Importer.getToContext().getConstantArrayType(
1109+
ToElementType, T->getSize(), ToSizeExpr, T->getSizeModifier(),
1110+
T->getIndexTypeCVRQualifiers());
11091111
}
11101112

11111113
ExpectedType

clang/lib/AST/ExprConstant.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6004,8 +6004,8 @@ static bool HandleOperatorNewCall(EvalInfo &Info, const CallExpr *E,
60046004
return false;
60056005
}
60066006

6007-
QualType AllocType =
6008-
Info.Ctx.getConstantArrayType(ElemType, Size, ArrayType::Normal, 0);
6007+
QualType AllocType = Info.Ctx.getConstantArrayType(ElemType, Size, nullptr,
6008+
ArrayType::Normal, 0);
60096009
APValue *Val = Info.createHeapAlloc(E, AllocType, Result);
60106010
*Val = APValue(APValue::UninitArray(), 0, Size.getZExtValue());
60116011
Result.addArray(Info, E, cast<ConstantArrayType>(AllocType));
@@ -8561,7 +8561,7 @@ bool PointerExprEvaluator::VisitCXXNewExpr(const CXXNewExpr *E) {
85618561
ResizedArrayILE = cast<InitListExpr>(Init);
85628562
}
85638563

8564-
AllocType = Info.Ctx.getConstantArrayType(AllocType, ArrayBound,
8564+
AllocType = Info.Ctx.getConstantArrayType(AllocType, ArrayBound, nullptr,
85658565
ArrayType::Normal, 0);
85668566
} else {
85678567
assert(!AllocType->isArrayType() &&

0 commit comments

Comments
 (0)