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

Reply via email to