summaryrefslogtreecommitdiff
path: root/lib/AST/Type.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2019-10-04 01:25:59 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2019-10-04 01:25:59 +0000
commit38c1f7c254e6e699d3e45e446fa4515418a00c9a (patch)
tree6b2f0f3d09ec6870dfb652c484c6df9c4a3fc1aa /lib/AST/Type.cpp
parent572ddc2d7c229fd9f44c13466b772e005409730f (diff)
downloadclang-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 'lib/AST/Type.cpp')
-rw-r--r--lib/AST/Type.cpp48
1 files changed, 44 insertions, 4 deletions
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 8ab2f1e271..4fed5b410b 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -109,6 +109,33 @@ bool QualType::isConstant(QualType T, const ASTContext &Ctx) {
return T.getAddressSpace() == LangAS::opencl_constant;
}
+// 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::ArrayType(TypeClass tc, QualType et, QualType can,
+ ArraySizeModifier sm, unsigned tq, const Expr *sz)
+ // Note, we need to check for DependentSizedArrayType explicitly here
+ // because we use a DependentSizedArrayType with no size expression as the
+ // type of a dependent array of unknown bound with a dependent braced
+ // initializer:
+ //
+ // template<int ...N> int arr[] = {N...};
+ : Type(tc, can,
+ et->isDependentType() || (sz && sz->isValueDependent()) ||
+ tc == DependentSizedArray,
+ et->isInstantiationDependentType() ||
+ (sz && sz->isInstantiationDependent()) ||
+ tc == DependentSizedArray,
+ (tc == VariableArray || et->isVariablyModifiedType()),
+ et->containsUnexpandedParameterPack() ||
+ (sz && sz->containsUnexpandedParameterPack())),
+ ElementType(et) {
+ ArrayTypeBits.IndexTypeQuals = tq;
+ ArrayTypeBits.SizeModifier = sm;
+}
+
unsigned ConstantArrayType::getNumAddressingBits(const ASTContext &Context,
QualType ElementType,
const llvm::APInt &NumElements) {
@@ -156,14 +183,26 @@ unsigned ConstantArrayType::getMaxSizeBits(const ASTContext &Context) {
return Bits;
}
+void ConstantArrayType::Profile(llvm::FoldingSetNodeID &ID,
+ const ASTContext &Context, QualType ET,
+ const llvm::APInt &ArraySize,
+ const Expr *SizeExpr, ArraySizeModifier SizeMod,
+ unsigned TypeQuals) {
+ ID.AddPointer(ET.getAsOpaquePtr());
+ ID.AddInteger(ArraySize.getZExtValue());
+ ID.AddInteger(SizeMod);
+ ID.AddInteger(TypeQuals);
+ ID.AddBoolean(SizeExpr != 0);
+ if (SizeExpr)
+ SizeExpr->Profile(ID, Context, true);
+}
+
DependentSizedArrayType::DependentSizedArrayType(const ASTContext &Context,
QualType et, QualType can,
Expr *e, ArraySizeModifier sm,
unsigned tq,
SourceRange brackets)
- : ArrayType(DependentSizedArray, et, can, sm, tq,
- (et->containsUnexpandedParameterPack() ||
- (e && e->containsUnexpandedParameterPack()))),
+ : ArrayType(DependentSizedArray, et, can, sm, tq, e),
Context(Context), SizeExpr((Stmt*) e), Brackets(brackets) {}
void DependentSizedArrayType::Profile(llvm::FoldingSetNodeID &ID,
@@ -860,7 +899,7 @@ public:
if (elementType.getAsOpaquePtr() == T->getElementType().getAsOpaquePtr())
return QualType(T, 0);
- return Ctx.getConstantArrayType(elementType, T->getSize(),
+ return Ctx.getConstantArrayType(elementType, T->getSize(), T->getSizeExpr(),
T->getSizeModifier(),
T->getIndexTypeCVRQualifiers());
}
@@ -3590,6 +3629,7 @@ static CachedProperties computeCachedProperties(const Type *T) {
#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class,Base) case Type::Class:
#include "clang/AST/TypeNodes.inc"
// Treat instantiation-dependent types as external.
+ if (!T->isInstantiationDependentType()) T->dump();
assert(T->isInstantiationDependentType());
return CachedProperties(ExternalLinkage, false);