[clang] [clang][sema][wat] peek through expansion statements to try and fix weird decl problems (PR #211745)
Oliver Hunt via cfe-commits
cfe-commits at lists.llvm.org
Fri Jul 24 01:13:05 PDT 2026
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 <oliver at apple.com>
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 at -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 at -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 at -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 at -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}}
+ }
+ }
+}
More information about the cfe-commits
mailing list