diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-10-04 01:25:59 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-10-04 01:25:59 +0000 |
commit | 38c1f7c254e6e699d3e45e446fa4515418a00c9a (patch) | |
tree | 6b2f0f3d09ec6870dfb652c484c6df9c4a3fc1aa /include | |
parent | 572ddc2d7c229fd9f44c13466b772e005409730f (diff) | |
download | clang-38c1f7c254e6e699d3e45e446fa4515418a00c9a.tar.gz |
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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@373685 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include')
-rw-r--r-- | include/clang/AST/ASTContext.h | 4 | ||||
-rw-r--r-- | include/clang/AST/RecursiveASTVisitor.h | 7 | ||||
-rw-r--r-- | include/clang/AST/Type.h | 84 |
3 files changed, 50 insertions, 45 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 66bd4aa1e3..5105b9c35c 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -185,7 +185,8 @@ private: mutable llvm::FoldingSet<LValueReferenceType> LValueReferenceTypes; mutable llvm::FoldingSet<RValueReferenceType> RValueReferenceTypes; mutable llvm::FoldingSet<MemberPointerType> MemberPointerTypes; - mutable llvm::FoldingSet<ConstantArrayType> ConstantArrayTypes; + mutable llvm::ContextualFoldingSet<ConstantArrayType, ASTContext &> + ConstantArrayTypes; mutable llvm::FoldingSet<IncompleteArrayType> IncompleteArrayTypes; mutable std::vector<VariableArrayType*> VariableArrayTypes; mutable llvm::FoldingSet<DependentSizedArrayType> DependentSizedArrayTypes; @@ -1330,6 +1331,7 @@ public: /// Return the unique reference to the type for a constant array of /// the specified element type. QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, + const Expr *SizeExpr, ArrayType::ArraySizeModifier ASM, unsigned IndexTypeQuals) const; diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index 7d5faf2b8c..426c256b6a 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -959,8 +959,11 @@ DEF_TRAVERSE_TYPE(AdjustedType, { TRY_TO(TraverseType(T->getOriginalType())); }) DEF_TRAVERSE_TYPE(DecayedType, { TRY_TO(TraverseType(T->getOriginalType())); }) -DEF_TRAVERSE_TYPE(ConstantArrayType, - { TRY_TO(TraverseType(T->getElementType())); }) +DEF_TRAVERSE_TYPE(ConstantArrayType, { + TRY_TO(TraverseType(T->getElementType())); + if (T->getSizeExpr()) + TRY_TO(TraverseStmt(const_cast<Expr*>(T->getSizeExpr()))); +}) DEF_TRAVERSE_TYPE(IncompleteArrayType, { TRY_TO(TraverseType(T->getElementType())); }) diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 2f00034c0e..ecbbd73e19 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -1513,6 +1513,15 @@ protected: unsigned SizeModifier : 3; }; + class ConstantArrayTypeBitfields { + friend class ConstantArrayType; + + unsigned : NumTypeBits + 3 + 3; + + /// Whether we have a stored size expression. + unsigned HasStoredSizeExpr : 1; + }; + class BuiltinTypeBitfields { friend class BuiltinType; @@ -1734,6 +1743,7 @@ protected: union { TypeBitfields TypeBits; ArrayTypeBitfields ArrayTypeBits; + ConstantArrayTypeBitfields ConstantArrayTypeBits; AttributedTypeBitfields AttributedTypeBits; AutoTypeBitfields AutoTypeBits; BuiltinTypeBitfields BuiltinTypeBits; @@ -2864,22 +2874,8 @@ private: protected: friend class ASTContext; // ASTContext creates these. - // C++ [temp.dep.type]p1: - // A type is dependent if it is... - // - an array type constructed from any dependent type or whose - // size is specified by a constant expression that is - // value-dependent, - ArrayType(TypeClass tc, QualType et, QualType can, - ArraySizeModifier sm, unsigned tq, - bool ContainsUnexpandedParameterPack) - : Type(tc, can, et->isDependentType() || tc == DependentSizedArray, - et->isInstantiationDependentType() || tc == DependentSizedArray, - (tc == VariableArray || et->isVariablyModifiedType()), - ContainsUnexpandedParameterPack), - ElementType(et) { - ArrayTypeBits.IndexTypeQuals = tq; - ArrayTypeBits.SizeModifier = sm; - } + ArrayType(TypeClass tc, QualType et, QualType can, ArraySizeModifier sm, + unsigned tq, const Expr *sz = nullptr); public: QualType getElementType() const { return ElementType; } @@ -2907,25 +2903,35 @@ public: /// Represents the canonical version of C arrays with a specified constant size. /// For example, the canonical type for 'int A[4 + 4*100]' is a /// ConstantArrayType where the element type is 'int' and the size is 404. -class ConstantArrayType : public ArrayType { +class ConstantArrayType final + : public ArrayType, + private llvm::TrailingObjects<ConstantArrayType, const Expr *> { + friend class ASTContext; // ASTContext creates these. + friend TrailingObjects; + llvm::APInt Size; // Allows us to unique the type. ConstantArrayType(QualType et, QualType can, const llvm::APInt &size, - ArraySizeModifier sm, unsigned tq) - : ArrayType(ConstantArray, et, can, sm, tq, - et->containsUnexpandedParameterPack()), - Size(size) {} - -protected: - friend class ASTContext; // ASTContext creates these. + const Expr *sz, ArraySizeModifier sm, unsigned tq) + : ArrayType(ConstantArray, et, can, sm, tq, sz), Size(size) { + ConstantArrayTypeBits.HasStoredSizeExpr = sz != nullptr; + if (ConstantArrayTypeBits.HasStoredSizeExpr) { + assert(!can.isNull() && "canonical constant array should not have size"); + *getTrailingObjects<const Expr*>() = sz; + } + } - ConstantArrayType(TypeClass tc, QualType et, QualType can, - const llvm::APInt &size, ArraySizeModifier sm, unsigned tq) - : ArrayType(tc, et, can, sm, tq, et->containsUnexpandedParameterPack()), - Size(size) {} + unsigned numTrailingObjects(OverloadToken<const Expr*>) const { + return ConstantArrayTypeBits.HasStoredSizeExpr; + } public: const llvm::APInt &getSize() const { return Size; } + const Expr *getSizeExpr() const { + return ConstantArrayTypeBits.HasStoredSizeExpr + ? *getTrailingObjects<const Expr *>() + : nullptr; + } bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -2939,19 +2945,15 @@ public: /// can require, which limits the maximum size of the array. static unsigned getMaxSizeBits(const ASTContext &Context); - void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getElementType(), getSize(), + void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx) { + Profile(ID, Ctx, getElementType(), getSize(), getSizeExpr(), getSizeModifier(), getIndexTypeCVRQualifiers()); } - static void Profile(llvm::FoldingSetNodeID &ID, QualType ET, - const llvm::APInt &ArraySize, ArraySizeModifier SizeMod, - unsigned TypeQuals) { - ID.AddPointer(ET.getAsOpaquePtr()); - ID.AddInteger(ArraySize.getZExtValue()); - ID.AddInteger(SizeMod); - ID.AddInteger(TypeQuals); - } + static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx, + QualType ET, const llvm::APInt &ArraySize, + const Expr *SizeExpr, ArraySizeModifier SizeMod, + unsigned TypeQuals); static bool classof(const Type *T) { return T->getTypeClass() == ConstantArray; @@ -2966,8 +2968,7 @@ class IncompleteArrayType : public ArrayType { IncompleteArrayType(QualType et, QualType can, ArraySizeModifier sm, unsigned tq) - : ArrayType(IncompleteArray, et, can, sm, tq, - et->containsUnexpandedParameterPack()) {} + : ArrayType(IncompleteArray, et, can, sm, tq) {} public: friend class StmtIteratorBase; @@ -3019,8 +3020,7 @@ class VariableArrayType : public ArrayType { VariableArrayType(QualType et, QualType can, Expr *e, ArraySizeModifier sm, unsigned tq, SourceRange brackets) - : ArrayType(VariableArray, et, can, sm, tq, - et->containsUnexpandedParameterPack()), + : ArrayType(VariableArray, et, can, sm, tq, e), SizeExpr((Stmt*) e), Brackets(brackets) {} public: |