llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: llvmbot <details> <summary>Changes</summary> Backport 2c2e43675910603bab1b163655786e4850569d74 Requested by: @<!-- -->erichkeane --- Full diff: https://github.com/llvm/llvm-project/pull/209823.diff 2 Files Affected: - (modified) clang/lib/Sema/SemaDecl.cpp (+15) - (modified) clang/test/SemaTemplate/class-template-spec.cpp (+21) ``````````diff diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 7e1b23c971a9c..c5920f03ed6e1 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -8374,6 +8374,21 @@ NamedDecl *Sema::ActOnVariableDeclarator( << Name << computeDeclContext(D.getCXXScopeSpec(), true) << D.getCXXScopeSpec().getRange(); NewVD->setInvalidDecl(); + + // if this is a member specialization, we don't have any primary template + // to be instantiated from. We set ourselves to a 'fake' clone of this so + // that anything that attempts to refer to this invalid declaration can + // act as if there IS a primary instantiation. + if (NewTemplate && IsMemberSpecialization) { + VarDecl *FakeVD = + VarDecl::Create(Context, DC, D.getBeginLoc(), D.getIdentifierLoc(), + II, R, TInfo, SC); + FakeVD->setInvalidDecl(); + VarTemplateDecl *FakeInstantiatedFrom = VarTemplateDecl::Create( + Context, DC, D.getIdentifierLoc(), Name, TemplateParams, FakeVD); + FakeInstantiatedFrom->setInvalidDecl(); + NewTemplate->setInstantiatedFromMemberTemplate(FakeInstantiatedFrom); + } } if (!IsPlaceholderVariable) diff --git a/clang/test/SemaTemplate/class-template-spec.cpp b/clang/test/SemaTemplate/class-template-spec.cpp index e2486f912e2c4..e60763feb2e1f 100644 --- a/clang/test/SemaTemplate/class-template-spec.cpp +++ b/clang/test/SemaTemplate/class-template-spec.cpp @@ -1,6 +1,7 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s // RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s +// RUN: %clang_cc1 -fsyntax-only -triple x86_64-linux-gnu -verify=expected,cxx14 -std=c++14 %s // RUN: %clang_cc1 -fsyntax-only -verify -std=c++26 %s template<typename T, typename U = int> struct A; // expected-note {{template is declared here}} \ @@ -251,4 +252,24 @@ namespace VarTemplateMismatch { template<> template<int> const int A<short>::x = 0; // expected-error@-1 {{template non-type parameter has a different type 'int' in template redeclaration}} } // namespace VarTemplateMismatch + +namespace VarTemplateNoMember { + template<typename T> struct S {}; + // expected-error@+1{{no member named 'foo' in 'VarTemplateNoMember::S<long>'}} + template<> template<typename U> constexpr int S<long>::foo; + // In C++14, these are definitions, not declarations, so they get a + // redefinition error. + // cxx14-error@+2{{redefinition of 'foo'}} + // cxx14-note@-4{{previous definition is here}} + template<> template<typename U> constexpr int S<long>::foo; + // cxx14-error@+2{{redefinition of 'foo'}} + // cxx14-note@-2{{previous definition is here}} + template<> template<typename U> constexpr int S<long>::foo; + // cxx14-error@+2{{redefinition of 'foo'}} + // cxx14-note@-2{{previous definition is here}} + template<> template<typename U> constexpr int S<long>::foo; + // cxx14-error@+2{{redefinition of 'foo'}} + // cxx14-note@-2{{previous definition is here}} + template<> template<typename U> constexpr int S<long>::foo; +} // namespace VarTemplateNoMember #endif `````````` </details> https://github.com/llvm/llvm-project/pull/209823 _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
