diff options
author | Abramo Bagnara <abramo.bagnara@gmail.com> | 2011-03-18 15:16:37 +0000 |
---|---|---|
committer | Abramo Bagnara <abramo.bagnara@gmail.com> | 2011-03-18 15:16:37 +0000 |
commit | 7f0a915eb546d353071be08c8adec155e5d9a0dc (patch) | |
tree | 695a7a87d2f72f72da5891709654603b71802f58 | |
parent | a9d129329b36660417af8f43fd5dfc75d9a5f0a1 (diff) |
Fixed inconsistency when adding TemplateParameterListsInfo.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@127876 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/AST/Decl.h | 24 | ||||
-rw-r--r-- | lib/AST/Decl.cpp | 56 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 138 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 7 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 35 |
5 files changed, 151 insertions, 109 deletions
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 4fc9bf55a3..08e4525f55 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -507,16 +507,24 @@ public: /// name qualifier, to be used for the case of out-of-line declarations. struct QualifierInfo { NestedNameSpecifierLoc QualifierLoc; - /// NumTemplParamLists - The number of template parameter lists - /// that were matched against the template-ids occurring into the NNS. + + /// NumTemplParamLists - The number of "outer" template parameter lists. + /// The count includes all of the template parameter lists that were matched + /// against the template-ids occurring into the NNS and possibly (in the + /// case of an explicit specialization) a final "template <>". unsigned NumTemplParamLists; + /// TemplParamLists - A new-allocated array of size NumTemplParamLists, - /// containing pointers to the matched template parameter lists. + /// containing pointers to the "outer" template parameter lists. + /// It includes all of the template parameter lists that were matched + /// against the template-ids occurring into the NNS and possibly (in the + /// case of an explicit specialization) a final "template <>". TemplateParameterList** TemplParamLists; /// Default constructor. QualifierInfo() : QualifierLoc(), NumTemplParamLists(0), TemplParamLists(0) {} - /// setTemplateParameterListsInfo - Sets info about matched template + + /// setTemplateParameterListsInfo - Sets info about "outer" template /// parameter lists. void setTemplateParameterListsInfo(ASTContext &Context, unsigned NumTPLists, @@ -603,9 +611,7 @@ public: return getExtInfo()->TemplParamLists[index]; } void setTemplateParameterListsInfo(ASTContext &Context, unsigned NumTPLists, - TemplateParameterList **TPLists) { - getExtInfo()->setTemplateParameterListsInfo(Context, NumTPLists, TPLists); - } + TemplateParameterList **TPLists); SourceLocation getTypeSpecStartLoc() const; @@ -2238,9 +2244,7 @@ public: return getExtInfo()->TemplParamLists[i]; } void setTemplateParameterListsInfo(ASTContext &Context, unsigned NumTPLists, - TemplateParameterList **TPLists) { - getExtInfo()->setTemplateParameterListsInfo(Context, NumTPLists, TPLists); - } + TemplateParameterList **TPLists); // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index b2d9af2361..0dce211c13 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -961,16 +961,38 @@ void DeclaratorDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) { else { // Here Qualifier == 0, i.e., we are removing the qualifier (if any). if (hasExtInfo()) { - // Save type source info pointer. - TypeSourceInfo *savedTInfo = getExtInfo()->TInfo; - // Deallocate the extended decl info. - getASTContext().Deallocate(getExtInfo()); - // Restore savedTInfo into (non-extended) decl info. - DeclInfo = savedTInfo; + if (getExtInfo()->NumTemplParamLists == 0) { + // Save type source info pointer. + TypeSourceInfo *savedTInfo = getExtInfo()->TInfo; + // Deallocate the extended decl info. + getASTContext().Deallocate(getExtInfo()); + // Restore savedTInfo into (non-extended) decl info. + DeclInfo = savedTInfo; + } + else + getExtInfo()->QualifierLoc = QualifierLoc; } } } +void +DeclaratorDecl::setTemplateParameterListsInfo(ASTContext &Context, + unsigned NumTPLists, + TemplateParameterList **TPLists) { + assert(NumTPLists > 0); + // Make sure the extended decl info is allocated. + if (!hasExtInfo()) { + // Save (non-extended) type source info pointer. + TypeSourceInfo *savedTInfo = DeclInfo.get<TypeSourceInfo*>(); + // Allocate external info struct. + DeclInfo = new (getASTContext()) ExtInfo; + // Restore savedTInfo into (extended) decl info. + getExtInfo()->TInfo = savedTInfo; + } + // Set the template parameter lists info. + getExtInfo()->setTemplateParameterListsInfo(Context, NumTPLists, TPLists); +} + SourceLocation DeclaratorDecl::getOuterLocStart() const { return getTemplateOrInnerLocStart(this); } @@ -1030,8 +1052,6 @@ QualifierInfo::setTemplateParameterListsInfo(ASTContext &Context, TemplateParameterList **TPLists) { assert((NumTPLists == 0 || TPLists != 0) && "Empty array of template parameters with positive size!"); - assert((NumTPLists == 0 || QualifierLoc) && - "Nonempty array of template parameters with no qualifier!"); // Free previous template parameters (if any). if (NumTemplParamLists > 0) { @@ -2100,12 +2120,28 @@ void TagDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) { else { // Here Qualifier == 0, i.e., we are removing the qualifier (if any). if (hasExtInfo()) { - getASTContext().Deallocate(getExtInfo()); - TypedefDeclOrQualifier = (TypedefDecl*) 0; + if (getExtInfo()->NumTemplParamLists == 0) { + getASTContext().Deallocate(getExtInfo()); + TypedefDeclOrQualifier = (TypedefDecl*) 0; + } + else + getExtInfo()->QualifierLoc = QualifierLoc; } } } +void TagDecl::setTemplateParameterListsInfo(ASTContext &Context, + unsigned NumTPLists, + TemplateParameterList **TPLists) { + assert(NumTPLists > 0); + // Make sure the extended decl info is allocated. + if (!hasExtInfo()) + // Allocate external info struct. + TypedefDeclOrQualifier = new (getASTContext()) ExtInfo; + // Set the template parameter lists info. + getExtInfo()->setTemplateParameterListsInfo(Context, NumTPLists, TPLists); +} + //===----------------------------------------------------------------------===// // EnumDecl Implementation //===----------------------------------------------------------------------===// diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 540c4e0bf0..832864014a 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -3094,7 +3094,6 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, // Match up the template parameter lists with the scope specifier, then // determine whether we have a template or a template specialization. isExplicitSpecialization = false; - unsigned NumMatchedTemplateParamLists = TemplateParamLists.size(); bool Invalid = false; if (TemplateParameterList *TemplateParams = MatchTemplateParametersToScopeSpecifier( @@ -3105,9 +3104,6 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, /*never a friend*/ false, isExplicitSpecialization, Invalid)) { - // All but one template parameter lists have been matching. - --NumMatchedTemplateParamLists; - if (TemplateParams->size() > 0) { // There is no such thing as a variable template. Diag(D.getIdentifierLoc(), diag::err_template_variable) @@ -3123,7 +3119,6 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, << II << SourceRange(TemplateParams->getTemplateLoc(), TemplateParams->getRAngleLoc()); - isExplicitSpecialization = true; } } @@ -3143,9 +3138,9 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, SetNestedNameSpecifier(NewVD, D); - if (NumMatchedTemplateParamLists > 0 && D.getCXXScopeSpec().isSet()) { + if (TemplateParamLists.size() > 0 && D.getCXXScopeSpec().isSet()) { NewVD->setTemplateParameterListsInfo(Context, - NumMatchedTemplateParamLists, + TemplateParamLists.size(), TemplateParamLists.release()); } } @@ -3636,8 +3631,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, FunctionTemplateDecl *FunctionTemplate = 0; bool isExplicitSpecialization = false; bool isFunctionTemplateSpecialization = false; - unsigned NumMatchedTemplateParamLists = 0; - + if (!getLangOptions().CPlusPlus) { // Determine whether the function was written with a // prototype. This true when: @@ -3783,7 +3777,6 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, SetNestedNameSpecifier(NewFD, D); isExplicitSpecialization = false; isFunctionTemplateSpecialization = false; - NumMatchedTemplateParamLists = TemplateParamLists.size(); if (D.isInvalidType()) NewFD->setInvalidDecl(); @@ -3804,61 +3797,71 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, isFriend, isExplicitSpecialization, Invalid)) { - // All but one template parameter lists have been matching. - --NumMatchedTemplateParamLists; + if (TemplateParams->size() > 0) { + // This is a function template - if (TemplateParams->size() > 0) { - // This is a function template + // Check that we can declare a template here. + if (CheckTemplateDeclScope(S, TemplateParams)) + return 0; - // Check that we can declare a template here. - if (CheckTemplateDeclScope(S, TemplateParams)) - return 0; + // A destructor cannot be a template. + if (Name.getNameKind() == DeclarationName::CXXDestructorName) { + Diag(NewFD->getLocation(), diag::err_destructor_template); + return 0; + } - // A destructor cannot be a template. - if (Name.getNameKind() == DeclarationName::CXXDestructorName) { - Diag(NewFD->getLocation(), diag::err_destructor_template); - return 0; - } - - - FunctionTemplate = FunctionTemplateDecl::Create(Context, DC, - NewFD->getLocation(), - Name, TemplateParams, - NewFD); - FunctionTemplate->setLexicalDeclContext(CurContext); - NewFD->setDescribedFunctionTemplate(FunctionTemplate); - } else { - // This is a function template specialization. - isFunctionTemplateSpecialization = true; - - // C++0x [temp.expl.spec]p20 forbids "template<> friend void foo(int);". - if (isFriend && isFunctionTemplateSpecialization) { - // We want to remove the "template<>", found here. - SourceRange RemoveRange = TemplateParams->getSourceRange(); - - // If we remove the template<> and the name is not a - // template-id, we're actually silently creating a problem: - // the friend declaration will refer to an untemplated decl, - // and clearly the user wants a template specialization. So - // we need to insert '<>' after the name. - SourceLocation InsertLoc; - if (D.getName().getKind() != UnqualifiedId::IK_TemplateId) { - InsertLoc = D.getName().getSourceRange().getEnd(); - InsertLoc = PP.getLocForEndOfToken(InsertLoc); - } + FunctionTemplate = FunctionTemplateDecl::Create(Context, DC, + NewFD->getLocation(), + Name, TemplateParams, + NewFD); + FunctionTemplate->setLexicalDeclContext(CurContext); + NewFD->setDescribedFunctionTemplate(FunctionTemplate); + + // For source fidelity, store the other template param lists. + if (TemplateParamLists.size() > 1) { + NewFD->setTemplateParameterListsInfo(Context, + TemplateParamLists.size() - 1, + TemplateParamLists.release()); + } + } else { + // This is a function template specialization. + isFunctionTemplateSpecialization = true; + // For source fidelity, store all the template param lists. + NewFD->setTemplateParameterListsInfo(Context, + TemplateParamLists.size(), + TemplateParamLists.release()); - Diag(D.getIdentifierLoc(), diag::err_template_spec_decl_friend) - << Name << RemoveRange - << FixItHint::CreateRemoval(RemoveRange) - << FixItHint::CreateInsertion(InsertLoc, "<>"); - } + // C++0x [temp.expl.spec]p20 forbids "template<> friend void foo(int);". + if (isFriend) { + // We want to remove the "template<>", found here. + SourceRange RemoveRange = TemplateParams->getSourceRange(); + + // If we remove the template<> and the name is not a + // template-id, we're actually silently creating a problem: + // the friend declaration will refer to an untemplated decl, + // and clearly the user wants a template specialization. So + // we need to insert '<>' after the name. + SourceLocation InsertLoc; + if (D.getName().getKind() != UnqualifiedId::IK_TemplateId) { + InsertLoc = D.getName().getSourceRange().getEnd(); + InsertLoc = PP.getLocForEndOfToken(InsertLoc); } - } - if (NumMatchedTemplateParamLists > 0 && D.getCXXScopeSpec().isSet()) { - NewFD->setTemplateParameterListsInfo(Context, - NumMatchedTemplateParamLists, - TemplateParamLists.release()); + Diag(D.getIdentifierLoc(), diag::err_template_spec_decl_friend) + << Name << RemoveRange + << FixItHint::CreateRemoval(RemoveRange) + << FixItHint::CreateInsertion(InsertLoc, "<>"); + } + } + } + else { + // All template param lists were matched against the scope specifier: + // this is NOT (an explicit specialization of) a template. + if (TemplateParamLists.size() > 0) + // For source fidelity, store all the template param lists. + NewFD->setTemplateParameterListsInfo(Context, + TemplateParamLists.size(), + TemplateParamLists.release()); } if (Invalid) { @@ -4180,7 +4183,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // are situations where these conditions don't apply and we // can actually do this check immediately. if (isFriend && - (NumMatchedTemplateParamLists || + (TemplateParamLists.size() || D.getCXXScopeSpec().getScopeRep()->isDependent() || CurContext->isDependentContext())) { // ignore these @@ -6035,27 +6038,24 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // FIXME: Check explicit specializations more carefully. bool isExplicitSpecialization = false; - unsigned NumMatchedTemplateParamLists = TemplateParameterLists.size(); bool Invalid = false; // We only need to do this matching if we have template parameters // or a scope specifier, which also conveniently avoids this work // for non-C++ cases. - if (NumMatchedTemplateParamLists || + if (TemplateParameterLists.size() > 0 || (SS.isNotEmpty() && TUK != TUK_Reference)) { if (TemplateParameterList *TemplateParams = MatchTemplateParametersToScopeSpecifier(KWLoc, SS, TemplateParameterLists.get(), - TemplateParameterLists.size(), + TemplateParameterLists.size(), TUK == TUK_Friend, isExplicitSpecialization, Invalid)) { - // All but one template parameter lists have been matching. - --NumMatchedTemplateParamLists; - if (TemplateParams->size() > 0) { // This is a declaration or definition of a class template (which may // be a member of another template). + if (Invalid) return 0; @@ -6063,7 +6063,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, DeclResult Result = CheckClassTemplate(S, TagSpec, TUK, KWLoc, SS, Name, NameLoc, Attr, TemplateParams, AS, - NumMatchedTemplateParamLists, + TemplateParameterLists.size() - 1, (TemplateParameterList**) TemplateParameterLists.release()); return Result.get(); } else { @@ -6584,9 +6584,9 @@ CreateNewDecl: if (SS.isNotEmpty()) { if (SS.isSet()) { New->setQualifierInfo(SS.getWithLocInContext(Context)); - if (NumMatchedTemplateParamLists > 0) { + if (TemplateParameterLists.size() > 0) { New->setTemplateParameterListsInfo(Context, - NumMatchedTemplateParamLists, + TemplateParameterLists.size(), (TemplateParameterList**) TemplateParameterLists.release()); } } diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 430f9c8052..858a5f9251 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -6977,7 +6977,6 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec); bool isExplicitSpecialization = false; - unsigned NumMatchedTemplateParamLists = TempParamLists.size(); bool Invalid = false; if (TemplateParameterList *TemplateParams @@ -6987,8 +6986,6 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, /*friend*/ true, isExplicitSpecialization, Invalid)) { - --NumMatchedTemplateParamLists; - if (TemplateParams->size() > 0) { // This is a declaration of a class template. if (Invalid) @@ -6997,7 +6994,7 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, return CheckClassTemplate(S, TagSpec, TUK_Friend, TagLoc, SS, Name, NameLoc, Attr, TemplateParams, AS_public, - NumMatchedTemplateParamLists, + TempParamLists.size() - 1, (TemplateParameterList**) TempParamLists.release()).take(); } else { // The "template<>" header is extraneous. @@ -7012,7 +7009,7 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, assert(SS.isNotEmpty() && "valid templated tag with no SS and no direct?"); bool isAllExplicitSpecializations = true; - for (unsigned I = 0; I != NumMatchedTemplateParamLists; ++I) { + for (unsigned I = TempParamLists.size(); I-- > 0; ) { if (TempParamLists.get()[I]->size()) { isAllExplicitSpecializations = false; break; diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index ec1cf6c556..ad3ad0c54c 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -1456,9 +1456,9 @@ DependsOnTemplateParameters(const TemplateSpecializationType *TemplateId, /// /// \returns the template parameter list, if any, that corresponds to the /// name that is preceded by the scope specifier @p SS. This template -/// parameter list may be have template parameters (if we're declaring a +/// parameter list may have template parameters (if we're declaring a /// template) or may have no template parameters (if we're declaring a -/// template specialization), or may be NULL (if we were's declaring isn't +/// template specialization), or may be NULL (if what we're declaring isn't /// itself a template). TemplateParameterList * Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, @@ -4390,6 +4390,11 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, MultiTemplateParamsArg TemplateParameterLists) { assert(TUK != TUK_Reference && "References are not specializations"); + // NOTE: KWLoc is the location of the tag keyword. This will instead + // store the location of the outermost template keyword in the declaration. + SourceLocation TemplateKWLoc = TemplateParameterLists.size() > 0 + ? TemplateParameterLists.get()[0]->getTemplateLoc() : SourceLocation(); + // Find the class template we're specializing TemplateName Name = TemplateD.getAsVal<TemplateName>(); ClassTemplateDecl *ClassTemplate @@ -4420,10 +4425,6 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, if (Invalid) return true; - unsigned NumMatchedTemplateParamLists = TemplateParameterLists.size(); - if (TemplateParams) - --NumMatchedTemplateParamLists; - if (TemplateParams && TemplateParams->size() > 0) { isPartialSpecialization = true; @@ -4565,10 +4566,15 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, // Since the only prior class template specialization with these // arguments was referenced but not declared, or we're only // referencing this specialization as a friend, reuse that - // declaration node as our own, updating its source location to - // reflect our new declaration. + // declaration node as our own, updating its source location and + // the list of outer template parameters to reflect our new declaration. Specialization = PrevDecl; Specialization->setLocation(TemplateNameLoc); + if (TemplateParameterLists.size() > 0) { + Specialization->setTemplateParameterListsInfo(Context, + TemplateParameterLists.size(), + (TemplateParameterList**) TemplateParameterLists.release()); + } PrevDecl = 0; CanonType = Context.getTypeDeclType(Specialization); } else if (isPartialSpecialization) { @@ -4594,7 +4600,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, Attr, TemplateParams, AS_none, - NumMatchedTemplateParamLists, + TemplateParameterLists.size() - 1, (TemplateParameterList**) TemplateParameterLists.release()); } @@ -4616,9 +4622,9 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, PrevPartial, SequenceNumber); SetNestedNameSpecifier(Partial, SS); - if (NumMatchedTemplateParamLists > 0 && SS.isSet()) { + if (TemplateParameterLists.size() > 1 && SS.isSet()) { Partial->setTemplateParameterListsInfo(Context, - NumMatchedTemplateParamLists, + TemplateParameterLists.size() - 1, (TemplateParameterList**) TemplateParameterLists.release()); } @@ -4675,9 +4681,9 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, Converted.size(), PrevDecl); SetNestedNameSpecifier(Specialization, SS); - if (NumMatchedTemplateParamLists > 0 && SS.isSet()) { + if (TemplateParameterLists.size() > 0) { Specialization->setTemplateParameterListsInfo(Context, - NumMatchedTemplateParamLists, + TemplateParameterLists.size(), (TemplateParameterList**) TemplateParameterLists.release()); } @@ -4747,8 +4753,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TemplateArgs, CanonType); if (TUK != TUK_Friend) { Specialization->setTypeAsWritten(WrittenTy); - if (TemplateParams) - Specialization->setTemplateKeywordLoc(TemplateParams->getTemplateLoc()); + Specialization->setTemplateKeywordLoc(TemplateKWLoc); } TemplateArgsIn.release(); |