From: Chandler Carruth Date: Sun, 1 May 2011 00:51:33 +0000 (+0000) Subject: Re-applies the patch first applied way back in r106099, with X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4fb86f8c4585e53c21c847ad3de9e3b2de123cd9;p=clang Re-applies the patch first applied way back in r106099, with accompanying fixes to make it work today. The core of this patch is to provide a link from a TemplateTypeParmType back to the TemplateTypeParmDecl node which declared it. This in turn provides much more precise information about the type, where it came from, and how it functions for AST consumers. To make the patch work almost a year after its first attempt, it needed serialization support, and it now retains the old getName() interface. Finally, it requires us to not attempt to instantiate the type in an unsupported friend decl -- specifically those coming from template friend decls but which refer to a specific type through a dependent name. A cleaner representation of the last item would be to build FriendTemplateDecl nodes for these, storing their template parameters etc, and to perform proper instantation of them like any other template declaration. They can still be flagged as unsupported for the purpose of access checking, etc. This passed an asserts-enabled bootstrap for me, and the reduced test case mentioned in the original review thread no longer causes issues, likely fixed at somewhere amidst the 24k revisions that have elapsed. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@130628 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index ad02aac360..3ca3c3b8a2 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -699,7 +699,7 @@ public: QualType getTemplateTypeParmType(unsigned Depth, unsigned Index, bool ParameterPack, - IdentifierInfo *Name = 0) const; + TemplateTypeParmDecl *ParmDecl = 0) const; QualType getTemplateSpecializationType(TemplateName T, const TemplateArgument *Args, diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h index 4d7fcfd1d1..ce2b3cdea4 100644 --- a/include/clang/AST/CanonicalType.h +++ b/include/clang/AST/CanonicalType.h @@ -655,6 +655,7 @@ struct CanProxyAdaptor LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getDepth) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getIndex) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isParameterPack) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(TemplateTypeParmDecl *, getDecl) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(IdentifierInfo *, getName) }; diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index 823bd84b38..ddbe344cdf 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -945,19 +945,14 @@ class TemplateTypeParmDecl : public TypeDecl { /// default argument. bool InheritedDefault : 1; - /// \brief Whether this is a parameter pack. - bool ParameterPack : 1; - /// \brief The default template argument, if any. TypeSourceInfo *DefaultArgument; TemplateTypeParmDecl(DeclContext *DC, SourceLocation KeyLoc, SourceLocation IdLoc, IdentifierInfo *Id, - bool Typename, QualType Type, bool ParameterPack) + bool Typename) : TypeDecl(TemplateTypeParm, DC, IdLoc, Id, KeyLoc), Typename(Typename), - InheritedDefault(false), ParameterPack(ParameterPack), DefaultArgument() { - TypeForDecl = Type.getTypePtrOrNull(); - } + InheritedDefault(false), DefaultArgument() { } /// Sema creates these on the stack during auto type deduction. friend class Sema; @@ -1011,9 +1006,6 @@ public: /// the 'typename' or 'class' keyword. void setDeclaredWithTypename(bool withTypename) { Typename = withTypename; } - /// \brief Set whether this is a parameter pack. - void setParameterPack(bool isParamPack) { ParameterPack = isParamPack; } - /// \brief Retrieve the depth of the template parameter. unsigned getDepth() const; @@ -1021,7 +1013,7 @@ public: unsigned getIndex() const; /// \brief Returns whether this is a parameter pack. - bool isParameterPack() const { return ParameterPack; } + bool isParameterPack() const; SourceRange getSourceRange() const; diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index f01e2351ab..cd7138de69 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -2969,44 +2969,68 @@ public: }; class TemplateTypeParmType : public Type, public llvm::FoldingSetNode { - unsigned Depth : 15; - unsigned ParameterPack : 1; - unsigned Index : 16; - IdentifierInfo *Name; + // Helper data collector for canonical types. + struct CanonicalTTPTInfo { + unsigned Depth : 15; + unsigned ParameterPack : 1; + unsigned Index : 16; + }; + + union { + // Info for the canonical type. + CanonicalTTPTInfo CanTTPTInfo; + // Info for the non-canonical type. + TemplateTypeParmDecl *TTPDecl; + }; - TemplateTypeParmType(unsigned D, unsigned I, bool PP, IdentifierInfo *N, - QualType Canon) + /// Build a non-canonical type. + TemplateTypeParmType(TemplateTypeParmDecl *TTPDecl, QualType Canon) : Type(TemplateTypeParm, Canon, /*Dependent=*/true, - /*VariablyModified=*/false, PP), - Depth(D), ParameterPack(PP), Index(I), Name(N) { } + /*VariablyModified=*/false, + Canon->getAs()->CanTTPTInfo.ParameterPack), + TTPDecl(TTPDecl) { } + /// Build the canonical type. TemplateTypeParmType(unsigned D, unsigned I, bool PP) : Type(TemplateTypeParm, QualType(this, 0), /*Dependent=*/true, - /*VariablyModified=*/false, PP), - Depth(D), ParameterPack(PP), Index(I), Name(0) { } + /*VariablyModified=*/false, PP) { + CanTTPTInfo.Depth = D; + CanTTPTInfo.Index = I; + CanTTPTInfo.ParameterPack = PP; + } friend class ASTContext; // ASTContext creates these + const CanonicalTTPTInfo& getCanTTPTInfo() const { + QualType Can = getCanonicalTypeInternal(); + return Can->getAs()->CanTTPTInfo; + } + public: - unsigned getDepth() const { return Depth; } - unsigned getIndex() const { return Index; } - bool isParameterPack() const { return ParameterPack; } - IdentifierInfo *getName() const { return Name; } + unsigned getDepth() const { return getCanTTPTInfo().Depth; } + unsigned getIndex() const { return getCanTTPTInfo().Index; } + bool isParameterPack() const { return getCanTTPTInfo().ParameterPack; } + + TemplateTypeParmDecl *getDecl() const { + return isCanonicalUnqualified() ? 0 : TTPDecl; + } + + IdentifierInfo *getName() const; bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, Depth, Index, ParameterPack, Name); + Profile(ID, getDepth(), getIndex(), isParameterPack(), getDecl()); } static void Profile(llvm::FoldingSetNodeID &ID, unsigned Depth, unsigned Index, bool ParameterPack, - IdentifierInfo *Name) { + TemplateTypeParmDecl *TTPDecl) { ID.AddInteger(Depth); ID.AddInteger(Index); ID.AddBoolean(ParameterPack); - ID.AddPointer(Name); + ID.AddPointer(TTPDecl); } static bool classof(const Type *T) { @@ -3035,8 +3059,6 @@ class SubstTemplateTypeParmType : public Type, public llvm::FoldingSetNode { friend class ASTContext; public: - IdentifierInfo *getName() const { return Replaced->getName(); } - /// Gets the template parameter that was substituted for. const TemplateTypeParmType *getReplacedParameter() const { return Replaced; diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index de8c26bd70..1f4d9a3718 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -2196,9 +2196,9 @@ QualType ASTContext::getSubstTemplateTypeParmPackType( /// name. QualType ASTContext::getTemplateTypeParmType(unsigned Depth, unsigned Index, bool ParameterPack, - IdentifierInfo *Name) const { + TemplateTypeParmDecl *TTPDecl) const { llvm::FoldingSetNodeID ID; - TemplateTypeParmType::Profile(ID, Depth, Index, ParameterPack, Name); + TemplateTypeParmType::Profile(ID, Depth, Index, ParameterPack, TTPDecl); void *InsertPos = 0; TemplateTypeParmType *TypeParm = TemplateTypeParmTypes.FindNodeOrInsertPos(ID, InsertPos); @@ -2206,10 +2206,9 @@ QualType ASTContext::getTemplateTypeParmType(unsigned Depth, unsigned Index, if (TypeParm) return QualType(TypeParm, 0); - if (Name) { + if (TTPDecl) { QualType Canon = getTemplateTypeParmType(Depth, Index, ParameterPack); - TypeParm = new (*this, TypeAlignment) - TemplateTypeParmType(Depth, Index, ParameterPack, Name, Canon); + TypeParm = new (*this, TypeAlignment) TemplateTypeParmType(TTPDecl, Canon); TemplateTypeParmType *TypeCheck = TemplateTypeParmTypes.FindNodeOrInsertPos(ID, InsertPos); diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp index 556fc72cec..bc1e899a61 100644 --- a/lib/AST/DeclPrinter.cpp +++ b/lib/AST/DeclPrinter.cpp @@ -706,7 +706,7 @@ void DeclPrinter::VisitTemplateDecl(const TemplateDecl *D) { if (TTP->isParameterPack()) Out << "... "; - Out << ParamType.getAsString(Policy); + Out << TTP->getNameAsString(); if (TTP->hasDefaultArgument()) { Out << " = "; diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp index 73c91dbd72..6272340691 100644 --- a/lib/AST/DeclTemplate.cpp +++ b/lib/AST/DeclTemplate.cpp @@ -425,15 +425,17 @@ TemplateTypeParmDecl::Create(const ASTContext &C, DeclContext *DC, SourceLocation KeyLoc, SourceLocation NameLoc, unsigned D, unsigned P, IdentifierInfo *Id, bool Typename, bool ParameterPack) { - QualType Type = C.getTemplateTypeParmType(D, P, ParameterPack, Id); - return new (C) TemplateTypeParmDecl(DC, KeyLoc, NameLoc, Id, Typename, - Type, ParameterPack); + TemplateTypeParmDecl *TTPDecl = + new (C) TemplateTypeParmDecl(DC, KeyLoc, NameLoc, Id, Typename); + QualType TTPType = C.getTemplateTypeParmType(D, P, ParameterPack, TTPDecl); + TTPDecl->TypeForDecl = TTPType.getTypePtr(); + return TTPDecl; } TemplateTypeParmDecl * TemplateTypeParmDecl::Create(const ASTContext &C, EmptyShell Empty) { return new (C) TemplateTypeParmDecl(0, SourceLocation(), SourceLocation(), - 0, false, QualType(), false); + 0, false); } SourceLocation TemplateTypeParmDecl::getDefaultArgumentLoc() const { @@ -458,6 +460,10 @@ unsigned TemplateTypeParmDecl::getIndex() const { return TypeForDecl->getAs()->getIndex(); } +bool TemplateTypeParmDecl::isParameterPack() const { + return TypeForDecl->getAs()->isParameterPack(); +} + //===----------------------------------------------------------------------===// // NonTypeTemplateParmDecl Method Implementations //===----------------------------------------------------------------------===// diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index f0737400fc..1ed1770426 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -1504,6 +1504,10 @@ bool EnumType::classof(const TagType *TT) { return isa(TT->getDecl()); } +IdentifierInfo *TemplateTypeParmType::getName() const { + return isCanonicalUnqualified() ? 0 : getDecl()->getIdentifier(); +} + SubstTemplateTypeParmPackType:: SubstTemplateTypeParmPackType(const TemplateTypeParmType *Param, QualType Canon, diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp index a8f9559b29..a0d40e14d7 100644 --- a/lib/AST/TypePrinter.cpp +++ b/lib/AST/TypePrinter.cpp @@ -652,12 +652,12 @@ void TypePrinter::printTemplateTypeParm(const TemplateTypeParmType *T, std::string &S) { if (!S.empty()) // Prefix the basic type, e.g. 'parmname X'. S = ' ' + S; - - if (!T->getName()) + + if (IdentifierInfo *Id = T->getDecl() ? T->getDecl()->getIdentifier() : 0) + S = Id->getName().str() + S; + else S = "type-parameter-" + llvm::utostr_32(T->getDepth()) + '-' + llvm::utostr_32(T->getIndex()) + S; - else - S = T->getName()->getName().str() + S; } void TypePrinter::printSubstTemplateTypeParm(const SubstTemplateTypeParmType *T, diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 677b6f3560..ef0912485b 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -503,7 +503,7 @@ void Sema::translateTemplateArguments(const ASTTemplateArgsPtr &TemplateArgsIn, /// (otherwise, "class" was used), and KeyLoc is the location of the /// "class" or "typename" keyword. ParamName is the name of the /// parameter (NULL indicates an unnamed template parameter) and -/// ParamName is the location of the parameter name (if any). +/// ParamNameLoc is the location of the parameter name (if any). /// If the type parameter has a default argument, it will be added /// later via ActOnTypeParameterDefault. Decl *Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis, diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index 7df6de4a30..235af049cf 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -3059,10 +3059,11 @@ Sema::DeduceAutoType(TypeSourceInfo *Type, Expr *Init, LocalInstantiationScope InstScope(*this); // Build template void Func(FuncParam); - QualType TemplArg = Context.getTemplateTypeParmType(0, 0, false); - TemplateTypeParmDecl TemplParam(0, SourceLocation(), Loc, 0, false, - TemplArg, false); - NamedDecl *TemplParamPtr = &TemplParam; + TemplateTypeParmDecl *TemplParam = + TemplateTypeParmDecl::Create(Context, 0, SourceLocation(), Loc, 0, 0, 0, + false, false); + QualType TemplArg = QualType(TemplParam->getTypeForDecl(), 0); + NamedDecl *TemplParamPtr = TemplParam; FixedSizeTemplateParameterList<1> TemplateParams(Loc, Loc, &TemplParamPtr, Loc); diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 749c4a18a4..dbe51a8252 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -1238,12 +1238,17 @@ TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB, // the template parameter list of a member template inside the // template we are instantiating). Create a new template type // parameter with the template "level" reduced by one. + TemplateTypeParmDecl *NewTTPDecl = 0; + if (TemplateTypeParmDecl *OldTTPDecl = T->getDecl()) + NewTTPDecl = cast_or_null( + TransformDecl(TL.getNameLoc(), OldTTPDecl)); + QualType Result = getSema().Context.getTemplateTypeParmType(T->getDepth() - TemplateArgs.getNumLevels(), T->getIndex(), T->isParameterPack(), - T->getName()); + NewTTPDecl); TemplateTypeParmTypeLoc NewTL = TLB.push(Result); NewTL.setNameLoc(TL.getNameLoc()); return Result; diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index c4e171e637..e38ecd43b1 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -495,10 +495,18 @@ Decl *TemplateDeclInstantiator::VisitFriendDecl(FriendDecl *D) { // Handle friend type expressions by simply substituting template // parameters into the pattern type and checking the result. if (TypeSourceInfo *Ty = D->getFriendType()) { - TypeSourceInfo *InstTy = - SemaRef.SubstType(Ty, TemplateArgs, - D->getLocation(), DeclarationName()); - if (!InstTy) + TypeSourceInfo *InstTy; + // If this is an unsupported friend, don't bother substituting template + // arguments into it. The actual type referred to won't be used by any + // parts of Clang, and may not be valid for instantiating. Just use the + // same info for the instantiated friend. + if (D->isUnsupportedFriend()) { + InstTy = Ty; + } else { + InstTy = SemaRef.SubstType(Ty, TemplateArgs, + D->getLocation(), DeclarationName()); + } + if (!InstTy) return 0; FriendDecl *FD = SemaRef.CheckFriendTypeDecl(D->getFriendLoc(), InstTy); @@ -1466,15 +1474,13 @@ ParmVarDecl *TemplateDeclInstantiator::VisitParmVarDecl(ParmVarDecl *D) { Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl( TemplateTypeParmDecl *D) { // TODO: don't always clone when decls are refcounted. - const Type* T = D->getTypeForDecl(); - assert(T->isTemplateTypeParmType()); - const TemplateTypeParmType *TTPT = T->getAs(); + assert(D->getTypeForDecl()->isTemplateTypeParmType()); TemplateTypeParmDecl *Inst = TemplateTypeParmDecl::Create(SemaRef.Context, Owner, D->getLocStart(), D->getLocation(), - TTPT->getDepth() - TemplateArgs.getNumLevels(), - TTPT->getIndex(), D->getIdentifier(), + D->getDepth() - TemplateArgs.getNumLevels(), + D->getIndex(), D->getIdentifier(), D->wasDeclaredWithTypename(), D->isParameterPack()); Inst->setAccess(AS_public); diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index b362aa43be..d2e41a96c9 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -3303,8 +3303,9 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) { unsigned Depth = Record[Idx++]; unsigned Index = Record[Idx++]; bool Pack = Record[Idx++]; - IdentifierInfo *Name = GetIdentifierInfo(Record, Idx); - return Context->getTemplateTypeParmType(Depth, Index, Pack, Name); + TemplateTypeParmDecl *D = + cast_or_null(GetDecl(Record[Idx++])); + return Context->getTemplateTypeParmType(Depth, Index, Pack, D); } case TYPE_DEPENDENT_NAME: { diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index 481763e91a..b79d07631f 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -1216,7 +1216,6 @@ void ASTDeclReader::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { VisitTypeDecl(D); D->setDeclaredWithTypename(Record[Idx++]); - D->setParameterPack(Record[Idx++]); bool Inherited = Record[Idx++]; TypeSourceInfo *DefArg = GetTypeSourceInfo(Record, Idx); diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index 52c28ff6e8..6d44fb63e5 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -303,7 +303,7 @@ ASTTypeWriter::VisitTemplateTypeParmType(const TemplateTypeParmType *T) { Record.push_back(T->getDepth()); Record.push_back(T->getIndex()); Record.push_back(T->isParameterPack()); - Writer.AddIdentifierRef(T->getName(), Record); + Writer.AddDeclRef(T->getDecl(), Record); Code = TYPE_TEMPLATE_TYPE_PARM; } diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index df83f2f694..31eb003d00 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -1029,7 +1029,6 @@ void ASTDeclWriter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { VisitTypeDecl(D); Record.push_back(D->wasDeclaredWithTypename()); - Record.push_back(D->isParameterPack()); Record.push_back(D->defaultArgumentWasInherited()); Writer.AddTypeSourceInfo(D->getDefaultArgumentInfo(), Record);