aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
authorKrystian Stasiowski <sdkrystian@gmail.com>2024-02-02 12:53:34 -0500
committerGitHub <noreply@github.com>2024-02-02 12:53:34 -0500
commit7ecfb66c77ad77dabbb705cbb1f3b17a3d1391a4 (patch)
treedc981fe439e5daf313e0923dab957a8b064985be /clang/lib/Sema/SemaDecl.cpp
parent7b08b4360b488b35428c97132b3f9d2a777bd770 (diff)
downloadllvm-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.cpp11
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