[clang] [Clang] Fixed a crash when instantiating an invalid out-of-line static data member definition in a local class (PR #196772)

via cfe-commits cfe-commits at lists.llvm.org
Sun May 10 19:51:10 PDT 2026


https://github.com/TPPPP72 updated https://github.com/llvm/llvm-project/pull/196772

>From c03519a4223c2a46dd6e68cbf061205fa832b499 Mon Sep 17 00:00:00 2001
From: TPPPP <TPPPP72 at outlook.com>
Date: Sun, 10 May 2026 09:53:16 +0800
Subject: [PATCH 1/8] temp

---
 clang/lib/Sema/SemaDecl.cpp                    | 1 +
 clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 8 ++++++++
 2 files changed, 9 insertions(+)

diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index a9a4cb89d115f..d9ba3b30dcca9 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -7948,6 +7948,7 @@ NamedDecl *Sema::ActOnVariableDeclarator(
             Diag(D.getIdentifierLoc(),
                  diag::err_static_data_member_not_allowed_in_local_class)
                 << Name << RD->getDeclName() << RD->getTagKind();
+            Invalid = true;
           } else if (AnonStruct) {
             // C++ [class.static.data]p4: Unnamed classes and classes contained
             // directly or indirectly within unnamed classes shall not contain
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index c9bc613a7c4ea..2a4f459dbe40f 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1799,6 +1799,14 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D,
   if (SemaRef.getLangOpts().OpenCL)
     SemaRef.deduceOpenCLAddressSpace(Var);
 
+  if (D->getQualifierLoc()) {
+    if (D->getLexicalDeclContext()->isDependentContext() &&
+        DC->isFunctionOrMethod()) {
+      Var->setInvalidDecl();
+      return nullptr;
+    }
+  }
+
   // Substitute the nested name specifier, if any.
   if (SubstQualifier(D, Var))
     return nullptr;

>From b8803bc218f49f06ac7bc1b8dfb6bdc78a857169 Mon Sep 17 00:00:00 2001
From: TPPPP <TPPPP72 at outlook.com>
Date: Sun, 10 May 2026 10:44:28 +0800
Subject: [PATCH 2/8] [Clang] Fixed a crash when instantiating an invalid
 out-of-line static data member definition in a local class

---
 clang/docs/ReleaseNotes.rst          |  2 +-
 clang/test/SemaTemplate/gh176152.cpp | 13 +++++++++++++
 2 files changed, 14 insertions(+), 1 deletion(-)
 create mode 100644 clang/test/SemaTemplate/gh176152.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index c17143e3c0398..06adba419b192 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -581,7 +581,7 @@ Bug Fixes to C++ Support
 - Fixed a crash on ``typeid`` of incomplete local types during template instantiation. (#GH63242), (#GH176397)
 - Fixed a crash when an immediate-invoked ``consteval`` lambda is used as an invalid initializer. (#GH185270)
 - Fixed an assertion failure when using a global destructor with a target with a non-default program address space. (#GH186484)
-
+- Fixed a crash when instantiating an invalid out-of-line static data member definition in a local class. (#GH176152)
 - Inherited constructors in ``dllexport`` classes are now exported for ABI-compatible cases, matching
   MSVC behavior. Constructors with variadic arguments or callee-cleanup parameters are not yet supported
   and produce a warning. (#GH162640)
diff --git a/clang/test/SemaTemplate/gh176152.cpp b/clang/test/SemaTemplate/gh176152.cpp
new file mode 100644
index 0000000000000..feae5d0f0a825
--- /dev/null
+++ b/clang/test/SemaTemplate/gh176152.cpp
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+template <class T> int f(T) {
+  struct A {
+    static int B;
+    // expected-error at -1 {{static data member 'staticField' not allowed in local struct 'MyClass'}}
+  };
+  int A::B;
+  int A::B = 1;
+  return 0;
+}
+
+int x = f(0);
\ No newline at end of file

>From 6f394a5df991acb2f62d653201af09f93f790a80 Mon Sep 17 00:00:00 2001
From: TPPPP <TPPPP72 at outlook.com>
Date: Sun, 10 May 2026 11:06:03 +0800
Subject: [PATCH 3/8] Add a blank line

---
 clang/test/SemaTemplate/gh176152.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/test/SemaTemplate/gh176152.cpp b/clang/test/SemaTemplate/gh176152.cpp
index feae5d0f0a825..27cb1c53dcf16 100644
--- a/clang/test/SemaTemplate/gh176152.cpp
+++ b/clang/test/SemaTemplate/gh176152.cpp
@@ -10,4 +10,4 @@ template <class T> int f(T) {
   return 0;
 }
 
-int x = f(0);
\ No newline at end of file
+int x = f(0);

>From 2eae3d9f5f7bbdad964b76a24e462695d269121a Mon Sep 17 00:00:00 2001
From: TPPPP <TPPPP72 at outlook.com>
Date: Sun, 10 May 2026 12:03:20 +0800
Subject: [PATCH 4/8] fix test

---
 clang/test/SemaTemplate/gh176152.cpp | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/clang/test/SemaTemplate/gh176152.cpp b/clang/test/SemaTemplate/gh176152.cpp
index 27cb1c53dcf16..288b9d645faec 100644
--- a/clang/test/SemaTemplate/gh176152.cpp
+++ b/clang/test/SemaTemplate/gh176152.cpp
@@ -2,11 +2,10 @@
 
 template <class T> int f(T) {
   struct A {
-    static int B;
-    // expected-error at -1 {{static data member 'staticField' not allowed in local struct 'MyClass'}}
+    static int B; // expected-error {{static data member 'B' not allowed in local struct 'A'}}
   };
-  int A::B;
-  int A::B = 1;
+  int A::B; // expected-note {{previous definition is here}}
+  int A::B = 1; // expected-error {{redefinition of 'B'}}
   return 0;
 }
 

>From 55bf2b1d47c7f73a3725350c26b2a84cda31dc21 Mon Sep 17 00:00:00 2001
From: TPPPP <TPPPP72 at outlook.com>
Date: Sun, 10 May 2026 23:45:54 +0800
Subject: [PATCH 5/8] remove check in VisitVarDecl

---
 clang/lib/Sema/SemaDecl.cpp                    | 2 ++
 clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 8 --------
 2 files changed, 2 insertions(+), 8 deletions(-)

diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index d9ba3b30dcca9..eedbaf425666b 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -4898,6 +4898,8 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
       VarDecl *Def = Old->getDefinition();
       if (Def && checkVarDeclRedefinition(Def, New))
         return;
+      if(Old->isInvalidDecl())
+        New->setInvalidDecl();
     }
   } else {
     // C++ may not have a tentative definition rule, but it has a different
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 2a4f459dbe40f..c9bc613a7c4ea 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1799,14 +1799,6 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D,
   if (SemaRef.getLangOpts().OpenCL)
     SemaRef.deduceOpenCLAddressSpace(Var);
 
-  if (D->getQualifierLoc()) {
-    if (D->getLexicalDeclContext()->isDependentContext() &&
-        DC->isFunctionOrMethod()) {
-      Var->setInvalidDecl();
-      return nullptr;
-    }
-  }
-
   // Substitute the nested name specifier, if any.
   if (SubstQualifier(D, Var))
     return nullptr;

>From b5a6045096b40044c0bf62013f7d2c4a217ac7ad Mon Sep 17 00:00:00 2001
From: TPPPP <TPPPP72 at outlook.com>
Date: Sun, 10 May 2026 23:48:31 +0800
Subject: [PATCH 6/8] format

---
 clang/lib/Sema/SemaDecl.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index eedbaf425666b..3c5f2fa4a7389 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -4898,7 +4898,7 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
       VarDecl *Def = Old->getDefinition();
       if (Def && checkVarDeclRedefinition(Def, New))
         return;
-      if(Old->isInvalidDecl())
+      if (Old->isInvalidDecl())
         New->setInvalidDecl();
     }
   } else {

>From 3c98b9c8711a3982f574674ee93c7f7e2c867a5a Mon Sep 17 00:00:00 2001
From: TPPPP <TPPPP72 at outlook.com>
Date: Mon, 11 May 2026 10:48:52 +0800
Subject: [PATCH 7/8] update test

---
 clang/test/SemaTemplate/gh176152.cpp | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/clang/test/SemaTemplate/gh176152.cpp b/clang/test/SemaTemplate/gh176152.cpp
index 288b9d645faec..a0cbdf0850ce4 100644
--- a/clang/test/SemaTemplate/gh176152.cpp
+++ b/clang/test/SemaTemplate/gh176152.cpp
@@ -1,6 +1,6 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
 
-template <class T> int f(T) {
+template <class T> int test1(T) {
   struct A {
     static int B; // expected-error {{static data member 'B' not allowed in local struct 'A'}}
   };
@@ -9,4 +9,13 @@ template <class T> int f(T) {
   return 0;
 }
 
-int x = f(0);
+int x = test1(1);
+
+template <class T> int f2(T) {
+  struct A {
+    static int B; // expected-error {{static data member 'B' not allowed in local struct 'A'}}
+  };
+  int A::B; // expected-note {{previous definition is here}}
+  int A::B = 1; // expected-error {{redefinition of 'B'}}
+  return 0;
+}

>From d2190c3c7f7c72177ff62e53af6dc0ed4cc3e9ee Mon Sep 17 00:00:00 2001
From: TPPPP <TPPPP72 at outlook.com>
Date: Mon, 11 May 2026 10:50:36 +0800
Subject: [PATCH 8/8] update test

---
 clang/test/SemaTemplate/gh176152.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/test/SemaTemplate/gh176152.cpp b/clang/test/SemaTemplate/gh176152.cpp
index a0cbdf0850ce4..567fb66167830 100644
--- a/clang/test/SemaTemplate/gh176152.cpp
+++ b/clang/test/SemaTemplate/gh176152.cpp
@@ -11,7 +11,7 @@ template <class T> int test1(T) {
 
 int x = test1(1);
 
-template <class T> int f2(T) {
+template <class T> int test2(T) {
   struct A {
     static int B; // expected-error {{static data member 'B' not allowed in local struct 'A'}}
   };



More information about the cfe-commits mailing list