diff options
author | Krystian Stasiowski <sdkrystian@gmail.com> | 2024-02-02 12:53:34 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-02-02 12:53:34 -0500 |
commit | 7ecfb66c77ad77dabbb705cbb1f3b17a3d1391a4 (patch) | |
tree | dc981fe439e5daf313e0923dab957a8b064985be /clang/lib/Sema/SemaDecl.cpp | |
parent | 7b08b4360b488b35428c97132b3f9d2a777bd770 (diff) | |
download | llvm-7ecfb66c77ad77dabbb705cbb1f3b17a3d1391a4.zip llvm-7ecfb66c77ad77dabbb705cbb1f3b17a3d1391a4.tar.gz llvm-7ecfb66c77ad77dabbb705cbb1f3b17a3d1391a4.tar.bz2 |
[Clang][Sema] Correctly look up primary template for variable template specializations (#80359)
Consider the following:
```
namespace N0 {
namespace N1 {
template<typename T>
int x1 = 0;
}
using namespace N1;
}
template<>
int N0::x1<int>;
```
According to [dcl.meaning.general] p3.3:
> - If the _declarator_ declares an explicit instantiation or a partial
or explicit specialization, the _declarator_ does not bind a name. If it
declares a class member, the terminal name of the _declarator-id_ is not
looked up; otherwise, **only those lookup results that are nominable in
`S` are considered when identifying any function template specialization
being declared**.
In particular, the requirement for lookup results to be nominal in the
lookup context of the terminal name of the _declarator-id_ only applies
to function template specializations -- not variable template
specializations. We currently reject the above declaration, but we do
(correctly) accept it if the using-directive is replaced with a `using`
declaration naming `N0::N1::x1`. This patch makes it so the above
specialization is (correctly) accepted.
Diffstat (limited to 'clang/lib/Sema/SemaDecl.cpp')
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 11 |
1 files changed, 6 insertions, 5 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index fd1c470..de6067b 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -7727,7 +7727,7 @@ NamedDecl *Sema::ActOnVariableDeclarator( ? TemplateParamLists[0]->getTemplateLoc() : SourceLocation(); DeclResult Res = ActOnVarTemplateSpecialization( - S, D, TInfo, TemplateKWLoc, TemplateParams, SC, + S, D, TInfo, Previous, TemplateKWLoc, TemplateParams, SC, IsPartialSpecialization); if (Res.isInvalid()) return nullptr; @@ -8070,8 +8070,8 @@ NamedDecl *Sema::ActOnVariableDeclarator( D.setRedeclaration(CheckVariableDeclaration(NewVD, Previous)); } else { // If this is an explicit specialization of a static data member, check it. - if (IsMemberSpecialization && !NewVD->isInvalidDecl() && - CheckMemberSpecialization(NewVD, Previous)) + if (IsMemberSpecialization && !IsVariableTemplateSpecialization && + !NewVD->isInvalidDecl() && CheckMemberSpecialization(NewVD, Previous)) NewVD->setInvalidDecl(); // Merge the decl with the existing one if appropriate. @@ -8086,7 +8086,8 @@ NamedDecl *Sema::ActOnVariableDeclarator( Previous.clear(); NewVD->setInvalidDecl(); } - } else if (D.getCXXScopeSpec().isSet()) { + } else if (D.getCXXScopeSpec().isSet() && + !IsVariableTemplateSpecialization) { // No previous declaration in the qualifying scope. Diag(D.getIdentifierLoc(), diag::err_no_member) << Name << computeDeclContext(D.getCXXScopeSpec(), true) @@ -8094,7 +8095,7 @@ NamedDecl *Sema::ActOnVariableDeclarator( NewVD->setInvalidDecl(); } - if (!IsVariableTemplateSpecialization && !IsPlaceholderVariable) + if (!IsPlaceholderVariable) D.setRedeclaration(CheckVariableDeclaration(NewVD, Previous)); // CheckVariableDeclaration will set NewVD as invalid if something is in |