https://github.com/ojhunt created 
https://github.com/llvm/llvm-project/pull/211745

I was looking at https://github.com/llvm/llvm-project/issues/210512 and found 
that the underlying cause seemed to be a failure to ignore expansion contexts 
when traversing contexts, and found the same issue hit extern var decls as well.

Alas these go through different paths.

So caveats: not an area I'm familiar with, so is it right? no idea! it _seems_ 
reasonable, but this is the result of debugging to find where things went weird 
in the test case, and then looking at other code added as part of the statement 
expansion changes. But "looking reasonable" doesn't mean correct. It's 
generally a correctness progression from the point of code being compiled, but 
is it the right way?

>From 92aeb06977b61c87c9f6f6ddae3030053b47ee70 Mon Sep 17 00:00:00 2001
From: Oliver Hunt <[email protected]>
Date: Fri, 24 Jul 2026 01:04:02 -0700
Subject: [PATCH] [clang][sema][wat] peek through expansion statements to try
 and fix weird decl problems

---
 clang/lib/AST/Decl.cpp                        |  5 ++-
 clang/lib/Sema/SemaDecl.cpp                   |  3 +-
 ...xpansion-statements-local-extern-decls.cpp | 45 +++++++++++++++++++
 3 files changed, 51 insertions(+), 2 deletions(-)
 create mode 100644 
clang/test/SemaCXX/expansion-statements-local-extern-decls.cpp

diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 4eaef0d87f3e5..49852c1afa795 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -1566,7 +1566,10 @@ LinkageInfo LinkageComputer::computeLVForDecl(const 
NamedDecl *D,
   //   one such matching entity, the program is ill-formed. Otherwise,
   //   if no matching entity is found, the block scope entity receives
   //   external linkage.
-  if (D->getDeclContext()->isFunctionOrMethod())
+  // **REVIEWER***: peeking through expansion statements lalalala
+  if (D->getDeclContext()
+          ->getEnclosingNonExpansionStatementContext()
+          ->isFunctionOrMethod())
     return getLVForLocalDecl(D, computation);
 
   // C++ [basic.link]p6:
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 7de5542e72559..93bc2a51ebfaf 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -7510,7 +7510,8 @@ static bool hasParsedAttr(Scope *S, const Declarator &PD,
 }
 
 bool Sema::adjustContextForLocalExternDecl(DeclContext *&DC) {
-  if (!DC->isFunctionOrMethod())
+  // **REVIEWER***: Peeking through expansion statements lalalala
+  if (!DC->getEnclosingNonExpansionStatementContext()->isFunctionOrMethod())
     return false;
 
   // If this is a local extern function or variable declared within a function
diff --git a/clang/test/SemaCXX/expansion-statements-local-extern-decls.cpp 
b/clang/test/SemaCXX/expansion-statements-local-extern-decls.cpp
new file mode 100644
index 0000000000000..8dd703a298bed
--- /dev/null
+++ b/clang/test/SemaCXX/expansion-statements-local-extern-decls.cpp
@@ -0,0 +1,45 @@
+// RUN: %clang_cc1 %s -std=c++2c -fsyntax-only -verify
+
+int wibble(); // #wibble_decl
+
+void foo1() {
+  template for (auto x : {1}) { // #foo1_instantiation
+    void wibble();
+    // expected-error@-1 {{functions that differ only in their return type 
cannot be overloaded}}
+    // expected-note@#wibble_decl {{previous declaration is here}}
+    // expected-note@#foo1_instantiation {{in instantiation of expansion 
statement requested here}}
+  }
+}
+
+void foo2() {
+  template for (auto x : {1}) { // #foo2_instantiation
+    template for (auto x : {1}) {
+      void wibble();
+      // expected-error@-1 {{functions that differ only in their return type 
cannot be overloaded}}
+      // expected-note@#wibble_decl {{previous declaration is here}}
+      // expected-note@#foo2_instantiation {{in instantiation of expansion 
statement requested here}}
+    }
+  }
+}
+
+int woffle; // #woffle_decl
+
+void foo3() {
+  template for (auto x : {1}) { // #foo3_instantiation
+    extern double woffle;
+    // expected-error@-1 {{redeclaration of 'woffle' with a different type: 
'double' vs 'int'}}
+    // expected-note@#woffle_decl {{previous definition is here}}
+    // expected-note@#foo3_instantiation {{in instantiation of expansion 
statement requested here}}
+  }
+}
+
+void foo4() {
+  template for (auto x : {1}) { // #foo4_instantiation
+    template for (auto x : {1}) {
+      extern double woffle;
+      // expected-error@-1 {{redeclaration of 'woffle' with a different type: 
'double' vs 'int'}}
+      // expected-note@#woffle_decl {{previous definition is here}}
+      // expected-note@#foo4_instantiation {{in instantiation of expansion 
statement requested here}}
+    }
+  }
+}

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to