diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-07-01 01:22:09 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-07-01 01:22:09 +0000 |
commit | 561f81243f665cf2001caadc45df505f826b72d6 (patch) | |
tree | b294898bc5e1eb5b81b1699d4d4f00ba764a9ac8 /lib/AST/Type.cpp | |
parent | 68a51a7f9c01ccbe7232d41beeb4deb26f40b013 (diff) |
Introduce the notion of instantiation dependence into Clang's AST. A
type/expression/template argument/etc. is instantiation-dependent if
it somehow involves a template parameter, even if it doesn't meet the
requirements for the more common kinds of dependence (dependent type,
type-dependent expression, value-dependent expression).
When we see an instantiation-dependent type, we know we always need to
perform substitution into that instantiation-dependent type. This
keeps us from short-circuiting evaluation in places where we
shouldn't, and lets us properly implement C++0x [temp.type]p2.
In theory, this would also allow us to properly mangle
instantiation-dependent-but-not-dependent decltype types per the
Itanium C++ ABI, but we aren't quite there because we still mangle
based on the canonical type in cases like, e.g.,
template<unsigned> struct A { };
template<typename T>
void f(A<sizeof(sizeof(decltype(T() + T())))>) { }
template void f<int>(A<sizeof(sizeof(int))>);
and therefore get the wrong answer.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@134225 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST/Type.cpp')
-rw-r--r-- | lib/AST/Type.cpp | 77 |
1 files changed, 62 insertions, 15 deletions
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 1569173df7..ca63ec87b1 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -110,6 +110,7 @@ DependentSizedExtVectorType::DependentSizedExtVectorType(const Expr *SizeExpr, SourceLocation loc) : Type(DependentSizedExtVector, can, /*Dependent=*/true, + /*InstantiationDependent=*/true, ElementType->isVariablyModifiedType(), (ElementType->containsUnexpandedParameterPack() || (SizeExpr && SizeExpr->containsUnexpandedParameterPack()))), @@ -129,6 +130,7 @@ DependentSizedExtVectorType::Profile(llvm::FoldingSetNodeID &ID, VectorType::VectorType(QualType vecType, unsigned nElements, QualType canonType, VectorKind vecKind) : Type(Vector, canonType, vecType->isDependentType(), + vecType->isInstantiationDependentType(), vecType->isVariablyModifiedType(), vecType->containsUnexpandedParameterPack()), ElementType(vecType) @@ -140,6 +142,7 @@ VectorType::VectorType(QualType vecType, unsigned nElements, QualType canonType, VectorType::VectorType(TypeClass tc, QualType vecType, unsigned nElements, QualType canonType, VectorKind vecKind) : Type(tc, canonType, vecType->isDependentType(), + vecType->isInstantiationDependentType(), vecType->isVariablyModifiedType(), vecType->containsUnexpandedParameterPack()), ElementType(vecType) @@ -387,7 +390,7 @@ const RecordType *Type::getAsUnionType() const { ObjCObjectType::ObjCObjectType(QualType Canonical, QualType Base, ObjCProtocolDecl * const *Protocols, unsigned NumProtocols) - : Type(ObjCObject, Canonical, false, false, false), + : Type(ObjCObject, Canonical, false, false, false, false), BaseType(Base) { ObjCObjectTypeBits.NumProtocols = NumProtocols; @@ -1350,7 +1353,7 @@ DependentTemplateSpecializationType::DependentTemplateSpecializationType( NestedNameSpecifier *NNS, const IdentifierInfo *Name, unsigned NumArgs, const TemplateArgument *Args, QualType Canon) - : TypeWithKeyword(Keyword, DependentTemplateSpecialization, Canon, true, + : TypeWithKeyword(Keyword, DependentTemplateSpecialization, Canon, true, true, /*VariablyModified=*/false, NNS && NNS->containsUnexpandedParameterPack()), NNS(NNS), Name(Name), NumArgs(NumArgs) { @@ -1485,6 +1488,7 @@ FunctionProtoType::FunctionProtoType(QualType result, const QualType *args, : FunctionType(FunctionProto, result, epi.Variadic, epi.TypeQuals, epi.RefQualifier, canonical, result->isDependentType(), + result->isInstantiationDependentType(), result->isVariablyModifiedType(), result->containsUnexpandedParameterPack(), epi.ExtInfo), @@ -1497,7 +1501,9 @@ FunctionProtoType::FunctionProtoType(QualType result, const QualType *args, for (unsigned i = 0; i != numArgs; ++i) { if (args[i]->isDependentType()) setDependent(); - + else if (args[i]->isInstantiationDependentType()) + setInstantiationDependent(); + if (args[i]->containsUnexpandedParameterPack()) setContainsUnexpandedParameterPack(); @@ -1510,7 +1516,9 @@ FunctionProtoType::FunctionProtoType(QualType result, const QualType *args, for (unsigned i = 0, e = epi.NumExceptions; i != e; ++i) { if (epi.Exceptions[i]->isDependentType()) setDependent(); - + else if (epi.Exceptions[i]->isInstantiationDependentType()) + setInstantiationDependent(); + if (epi.Exceptions[i]->containsUnexpandedParameterPack()) setContainsUnexpandedParameterPack(); @@ -1520,6 +1528,14 @@ FunctionProtoType::FunctionProtoType(QualType result, const QualType *args, // Store the noexcept expression and context. Expr **noexSlot = reinterpret_cast<Expr**>(argSlot + numArgs); *noexSlot = epi.NoexceptExpr; + + if (epi.NoexceptExpr) { + if (epi.NoexceptExpr->isValueDependent() + || epi.NoexceptExpr->isTypeDependent()) + setDependent(); + else if (epi.NoexceptExpr->isInstantiationDependent()) + setInstantiationDependent(); + } } if (epi.ConsumedArguments) { @@ -1623,6 +1639,7 @@ QualType TypedefType::desugar() const { TypeOfExprType::TypeOfExprType(Expr *E, QualType can) : Type(TypeOfExpr, can, E->isTypeDependent(), + E->isInstantiationDependent(), E->getType()->isVariablyModifiedType(), E->containsUnexpandedParameterPack()), TOExpr(E) { @@ -1639,6 +1656,7 @@ void DependentTypeOfExprType::Profile(llvm::FoldingSetNodeID &ID, DecltypeType::DecltypeType(Expr *E, QualType underlyingType, QualType can) : Type(Decltype, can, E->isTypeDependent(), + E->isInstantiationDependent(), E->getType()->isVariablyModifiedType(), E->containsUnexpandedParameterPack()), E(E), @@ -1654,7 +1672,9 @@ void DependentDecltypeType::Profile(llvm::FoldingSetNodeID &ID, } TagType::TagType(TypeClass TC, const TagDecl *D, QualType can) - : Type(TC, can, D->isDependentType(), /*VariablyModified=*/false, + : Type(TC, can, D->isDependentType(), + /*InstantiationDependent=*/D->isDependentType(), + /*VariablyModified=*/false, /*ContainsUnexpandedParameterPack=*/false), decl(const_cast<TagDecl*>(D)) {} @@ -1674,6 +1694,7 @@ UnaryTransformType::UnaryTransformType(QualType BaseType, UTTKind UKind, QualType CanonicalType) : Type(UnaryTransform, CanonicalType, UnderlyingType->isDependentType(), + UnderlyingType->isInstantiationDependentType(), UnderlyingType->isVariablyModifiedType(), BaseType->containsUnexpandedParameterPack()) , BaseType(BaseType), UnderlyingType(UnderlyingType), UKind(UKind) @@ -1707,7 +1728,8 @@ SubstTemplateTypeParmPackType:: SubstTemplateTypeParmPackType(const TemplateTypeParmType *Param, QualType Canon, const TemplateArgument &ArgPack) - : Type(SubstTemplateTypeParmPack, Canon, true, false, true), Replaced(Param), + : Type(SubstTemplateTypeParmPack, Canon, true, true, false, true), + Replaced(Param), Arguments(ArgPack.pack_begin()), NumArguments(ArgPack.pack_size()) { } @@ -1732,23 +1754,39 @@ void SubstTemplateTypeParmPackType::Profile(llvm::FoldingSetNodeID &ID, } bool TemplateSpecializationType:: -anyDependentTemplateArguments(const TemplateArgumentListInfo &Args) { - return anyDependentTemplateArguments(Args.getArgumentArray(), Args.size()); +anyDependentTemplateArguments(const TemplateArgumentListInfo &Args, + bool &InstantiationDependent) { + return anyDependentTemplateArguments(Args.getArgumentArray(), Args.size(), + InstantiationDependent); } bool TemplateSpecializationType:: -anyDependentTemplateArguments(const TemplateArgumentLoc *Args, unsigned N) { - for (unsigned i = 0; i != N; ++i) - if (Args[i].getArgument().isDependent()) +anyDependentTemplateArguments(const TemplateArgumentLoc *Args, unsigned N, + bool &InstantiationDependent) { + for (unsigned i = 0; i != N; ++i) { + if (Args[i].getArgument().isDependent()) { + InstantiationDependent = true; return true; + } + + if (Args[i].getArgument().isInstantiationDependent()) + InstantiationDependent = true; + } return false; } bool TemplateSpecializationType:: -anyDependentTemplateArguments(const TemplateArgument *Args, unsigned N) { - for (unsigned i = 0; i != N; ++i) - if (Args[i].isDependent()) +anyDependentTemplateArguments(const TemplateArgument *Args, unsigned N, + bool &InstantiationDependent) { + for (unsigned i = 0; i != N; ++i) { + if (Args[i].isDependent()) { + InstantiationDependent = true; return true; + } + + if (Args[i].isInstantiationDependent()) + InstantiationDependent = true; + } return false; } @@ -1759,6 +1797,8 @@ TemplateSpecializationType(TemplateName T, : Type(TemplateSpecialization, Canon.isNull()? QualType(this, 0) : Canon, Canon.isNull()? T.isDependent() : Canon->isDependentType(), + Canon.isNull()? T.isDependent() + : Canon->isInstantiationDependentType(), false, T.containsUnexpandedParameterPack()), Template(T), NumArgs(NumArgs) { assert(!T.getAsDependentTemplateName() && @@ -1767,8 +1807,12 @@ TemplateSpecializationType(TemplateName T, T.getKind() == TemplateName::SubstTemplateTemplateParm || T.getKind() == TemplateName::SubstTemplateTemplateParmPack) && "Unexpected template name for TemplateSpecializationType"); + bool InstantiationDependent; + (void)InstantiationDependent; assert((!Canon.isNull() || - T.isDependent() || anyDependentTemplateArguments(Args, NumArgs)) && + T.isDependent() || + anyDependentTemplateArguments(Args, NumArgs, + InstantiationDependent)) && "No canonical type for non-dependent class template specialization"); TemplateArgument *TemplateArgs @@ -1782,6 +1826,9 @@ TemplateSpecializationType(TemplateName T, // U<T> is always non-dependent, irrespective of the type T. if (Canon.isNull() && Args[Arg].isDependent()) setDependent(); + else if (Args[Arg].isInstantiationDependent()) + setInstantiationDependent(); + if (Args[Arg].getKind() == TemplateArgument::Type && Args[Arg].getAsType()->isVariablyModifiedType()) setVariablyModified(); |