diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2014-01-16 23:39:20 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2014-01-16 23:39:20 +0000 |
commit | beef3453cd12923bd8100a40d6a2e6281dd250ab (patch) | |
tree | 48047feba2f0821f10968c4c3d75a436bde0ca2e /clang/lib/Sema/SemaDecl.cpp | |
parent | 98d3c101ddf7e657e2dc6171860fe41f03cb0dfc (diff) | |
download | bcm5719-llvm-beef3453cd12923bd8100a40d6a2e6281dd250ab.tar.gz bcm5719-llvm-beef3453cd12923bd8100a40d6a2e6281dd250ab.zip |
Clean up variable template handling a bit, and correct the behavior of name
lookup when declaring a variable template specialization.
llvm-svn: 199438
Diffstat (limited to 'clang/lib/Sema/SemaDecl.cpp')
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 201 |
1 files changed, 84 insertions, 117 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 76472651e1e..e14fc53750c 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -3000,14 +3000,17 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { if (New->isInvalidDecl()) return; + VarTemplateDecl *NewTemplate = New->getDescribedVarTemplate(); + // Verify the old decl was also a variable or variable template. VarDecl *Old = 0; - if (Previous.isSingleResult() && - (Old = dyn_cast<VarDecl>(Previous.getFoundDecl()))) { - if (New->getDescribedVarTemplate()) - Old = Old->getDescribedVarTemplate() ? Old : 0; - else - Old = Old->getDescribedVarTemplate() ? 0 : Old; + VarTemplateDecl *OldTemplate = 0; + if (Previous.isSingleResult()) { + if (NewTemplate) { + OldTemplate = dyn_cast<VarTemplateDecl>(Previous.getFoundDecl()); + Old = OldTemplate ? OldTemplate->getTemplatedDecl() : 0; + } else + Old = dyn_cast<VarDecl>(Previous.getFoundDecl()); } if (!Old) { Diag(New->getLocation(), diag::err_redefinition_different_kind) @@ -3020,6 +3023,13 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { if (!shouldLinkPossiblyHiddenDecl(Old, New)) return; + // Ensure the template parameters are compatible. + if (NewTemplate && + !TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(), + OldTemplate->getTemplateParameters(), + /*Complain=*/true, TPL_TemplateMatch)) + return; + // C++ [class.mem]p1: // A member shall not be declared twice in the member-specification [...] // @@ -3145,14 +3155,13 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { // Keep a chain of previous declarations. New->setPreviousDecl(Old); + if (NewTemplate) + NewTemplate->setPreviousDecl(OldTemplate); // Inherit access appropriately. New->setAccess(Old->getAccess()); - - if (VarTemplateDecl *VTD = New->getDescribedVarTemplate()) { - if (New->isStaticDataMember() && New->isOutOfLine()) - VTD->setAccess(New->getAccess()); - } + if (NewTemplate) + NewTemplate->setAccess(New->getAccess()); } /// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with @@ -5065,9 +5074,9 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, bool IsVariableTemplateSpecialization = false; bool IsPartialSpecialization = false; bool IsVariableTemplate = false; - VarTemplateDecl *PrevVarTemplate = 0; VarDecl *NewVD = 0; VarTemplateDecl *NewTemplate = 0; + TemplateParameterList *TemplateParams = 0; if (!getLangOpts().CPlusPlus) { NewVD = VarDecl::Create(Context, DC, D.getLocStart(), D.getIdentifierLoc(), II, @@ -5129,18 +5138,33 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, } } - NamedDecl *PrevDecl = 0; - if (Previous.begin() != Previous.end()) - PrevDecl = (*Previous.begin())->getUnderlyingDecl(); - PrevVarTemplate = dyn_cast_or_null<VarTemplateDecl>(PrevDecl); - // Match up the template parameter lists with the scope specifier, then // determine whether we have a template or a template specialization. - TemplateParameterList *TemplateParams = - MatchTemplateParametersToScopeSpecifier( - D.getDeclSpec().getLocStart(), D.getIdentifierLoc(), - D.getCXXScopeSpec(), TemplateParamLists, - /*never a friend*/ false, IsExplicitSpecialization, Invalid); + TemplateParams = MatchTemplateParametersToScopeSpecifier( + D.getDeclSpec().getLocStart(), D.getIdentifierLoc(), + D.getCXXScopeSpec(), TemplateParamLists, + /*never a friend*/ false, IsExplicitSpecialization, Invalid); + + if (D.getName().getKind() == UnqualifiedId::IK_TemplateId && + !TemplateParams) { + TemplateIdAnnotation *TemplateId = D.getName().TemplateId; + + // We have encountered something that the user meant to be a + // specialization (because it has explicitly-specified template + // arguments) but that was not introduced with a "template<>" (or had + // too few of them). + // FIXME: Differentiate between attempts for explicit instantiations + // (starting with "template") and the rest. + Diag(D.getIdentifierLoc(), diag::err_template_spec_needs_header) + << SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc) + << FixItHint::CreateInsertion(D.getDeclSpec().getLocStart(), + "template<> "); + IsVariableTemplateSpecialization = true; + TemplateParams = TemplateParameterList::Create(Context, SourceLocation(), + SourceLocation(), 0, 0, + SourceLocation()); + } + if (TemplateParams) { if (!TemplateParams->size() && D.getName().getKind() != UnqualifiedId::IK_TemplateId) { @@ -5151,6 +5175,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, << II << SourceRange(TemplateParams->getTemplateLoc(), TemplateParams->getRAngleLoc()); + TemplateParams = 0; } else { // Only C++1y supports variable templates (N3651). Diag(D.getIdentifierLoc(), @@ -5160,11 +5185,9 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) { // This is an explicit specialization or a partial specialization. - // Check that we can declare a specialization here - + // FIXME: Check that we can declare a specialization here. IsVariableTemplateSpecialization = true; IsPartialSpecialization = TemplateParams->size() > 0; - } else { // if (TemplateParams->size() > 0) // This is a template declaration. IsVariableTemplate = true; @@ -5172,89 +5195,17 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, // Check that we can declare a template here. if (CheckTemplateDeclScope(S, TemplateParams)) return 0; - - // If there is a previous declaration with the same name, check - // whether this is a valid redeclaration. - if (PrevDecl && !isDeclInScope(PrevDecl, DC, S)) - PrevDecl = PrevVarTemplate = 0; - - if (PrevVarTemplate) { - // Ensure that the template parameter lists are compatible. - if (!TemplateParameterListsAreEqual( - TemplateParams, PrevVarTemplate->getTemplateParameters(), - /*Complain=*/true, TPL_TemplateMatch)) - return 0; - } else if (PrevDecl && PrevDecl->isTemplateParameter()) { - // Maybe we will complain about the shadowed template parameter. - DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl); - - // Just pretend that we didn't see the previous declaration. - PrevDecl = 0; - } else if (PrevDecl) { - // C++ [temp]p5: - // ... a template name declared in namespace scope or in class - // scope shall be unique in that scope. - Diag(D.getIdentifierLoc(), diag::err_redefinition_different_kind) - << Name; - Diag(PrevDecl->getLocation(), diag::note_previous_definition); - return 0; - } - - // Check the template parameter list of this declaration, possibly - // merging in the template parameter list from the previous variable - // template declaration. - if (CheckTemplateParameterList( - TemplateParams, - PrevVarTemplate ? PrevVarTemplate->getTemplateParameters() - : 0, - (D.getCXXScopeSpec().isSet() && DC && DC->isRecord() && - DC->isDependentContext()) - ? TPC_ClassTemplateMember - : TPC_VarTemplate)) - Invalid = true; - - if (D.getCXXScopeSpec().isSet()) { - // If the name of the template was qualified, we must be defining - // the template out-of-line. - if (!D.getCXXScopeSpec().isInvalid() && !Invalid && - !PrevVarTemplate) { - Diag(D.getIdentifierLoc(), diag::err_member_decl_does_not_match) - << Name << DC << /*IsDefinition*/true - << D.getCXXScopeSpec().getRange(); - Invalid = true; - } - } } } - } else if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) { - TemplateIdAnnotation *TemplateId = D.getName().TemplateId; - - // We have encountered something that the user meant to be a - // specialization (because it has explicitly-specified template - // arguments) but that was not introduced with a "template<>" (or had - // too few of them). - // FIXME: Differentiate between attempts for explicit instantiations - // (starting with "template") and the rest. - Diag(D.getIdentifierLoc(), diag::err_template_spec_needs_header) - << SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc) - << FixItHint::CreateInsertion(D.getDeclSpec().getLocStart(), - "template<> "); - IsVariableTemplateSpecialization = true; } if (IsVariableTemplateSpecialization) { - if (!PrevVarTemplate) { - Diag(D.getIdentifierLoc(), diag::err_var_spec_no_template) - << IsPartialSpecialization; - return 0; - } - SourceLocation TemplateKWLoc = TemplateParamLists.size() > 0 ? TemplateParamLists[0]->getTemplateLoc() : SourceLocation(); DeclResult Res = ActOnVarTemplateSpecialization( - S, PrevVarTemplate, D, TInfo, TemplateKWLoc, TemplateParams, SC, + S, D, TInfo, TemplateKWLoc, TemplateParams, SC, IsPartialSpecialization); if (Res.isInvalid()) return 0; @@ -5268,7 +5219,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, if (IsVariableTemplate) { NewTemplate = VarTemplateDecl::Create(Context, DC, D.getIdentifierLoc(), Name, - TemplateParams, NewVD, PrevVarTemplate); + TemplateParams, NewVD); NewVD->setDescribedVarTemplate(NewTemplate); } @@ -5453,6 +5404,11 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, if (!getLangOpts().CPlusPlus) { D.setRedeclaration(CheckVariableDeclaration(NewVD, Previous)); } else { + // If this is an explicit specialization of a static data member, check it. + if (IsExplicitSpecialization && !NewVD->isInvalidDecl() && + CheckMemberSpecialization(NewVD, Previous)) + NewVD->setInvalidDecl(); + // Merge the decl with the existing one if appropriate. if (!Previous.empty()) { if (Previous.isSingleResult() && @@ -5473,20 +5429,34 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, NewVD->setInvalidDecl(); } - if (!IsVariableTemplateSpecialization) { - if (PrevVarTemplate) { - LookupResult PrevDecl(*this, GetNameForDeclarator(D), - LookupOrdinaryName, ForRedeclaration); - PrevDecl.addDecl(PrevVarTemplate->getTemplatedDecl()); - D.setRedeclaration(CheckVariableDeclaration(NewVD, PrevDecl)); - } else - D.setRedeclaration(CheckVariableDeclaration(NewVD, Previous)); - } + if (!IsVariableTemplateSpecialization) + D.setRedeclaration(CheckVariableDeclaration(NewVD, Previous)); + + if (NewTemplate) { + VarTemplateDecl *PrevVarTemplate = + NewVD->getPreviousDecl() + ? NewVD->getPreviousDecl()->getDescribedVarTemplate() + : 0; + + // Check the template parameter list of this declaration, possibly + // merging in the template parameter list from the previous variable + // template declaration. + if (CheckTemplateParameterList( + TemplateParams, + PrevVarTemplate ? PrevVarTemplate->getTemplateParameters() + : 0, + (D.getCXXScopeSpec().isSet() && DC && DC->isRecord() && + DC->isDependentContext()) + ? TPC_ClassTemplateMember + : TPC_VarTemplate)) + NewVD->setInvalidDecl(); - // This is an explicit specialization of a static data member. Check it. - if (IsExplicitSpecialization && !NewVD->isInvalidDecl() && - CheckMemberSpecialization(NewVD, Previous)) - NewVD->setInvalidDecl(); + // If we are providing an explicit specialization of a static variable + // template, make a note of that. + if (PrevVarTemplate && + PrevVarTemplate->getInstantiatedFromMemberTemplate()) + PrevVarTemplate->setMemberSpecialization(); + } } ProcessPragmaWeak(S, NewVD); @@ -5507,12 +5477,9 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, } } - // If we are providing an explicit specialization of a static variable - // template, make a note of that. - if (PrevVarTemplate && PrevVarTemplate->getInstantiatedFromMemberTemplate()) - PrevVarTemplate->setMemberSpecialization(); - if (NewTemplate) { + if (NewVD->isInvalidDecl()) + NewTemplate->setInvalidDecl(); ActOnDocumentableDecl(NewTemplate); return NewTemplate; } |