[clang] [Sema] Reject unqualified lookup of local nested class name (PR #192678)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Apr 17 08:04:30 PDT 2026
https://github.com/arrowten created https://github.com/llvm/llvm-project/pull/192678
Clang incorrectly accepts unqualified use of a nested class declared inside a local class, even when it is not visible in the current scope.
>From dafafa6e4109648dfec40e691be3ab315101b30b Mon Sep 17 00:00:00 2001
From: Ajay Wakodikar <ajaywakodikarsocial at gmail.com>
Date: Fri, 17 Apr 2026 10:48:20 -0400
Subject: [PATCH] [Sema] Reject unqualified lookup of local nested class name
---
clang/lib/Sema/SemaLookup.cpp | 12 +++++
.../Sema/unqualified-lookup-local-class.cpp | 51 +++++++++++++++++++
2 files changed, 63 insertions(+)
create mode 100644 clang/test/Sema/unqualified-lookup-local-class.cpp
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index b96065f8619d2..21c3e479e2738 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -1369,6 +1369,18 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
// namespace scope
SearchNamespaceScope = false;
}
+
+ if (R.getLookupKind() == LookupOrdinaryName) {
+ DeclContext *DC = ND->getDeclContext();
+
+ if (DC->isRecord()) {
+ // Only restrict when we're in function or block scope
+ if (S->getFnParent() && !S->isClassScope()) {
+ continue;
+ }
+ }
+ }
+
R.addDecl(ND);
}
}
diff --git a/clang/test/Sema/unqualified-lookup-local-class.cpp b/clang/test/Sema/unqualified-lookup-local-class.cpp
new file mode 100644
index 0000000000000..6893425d4fb50
--- /dev/null
+++ b/clang/test/Sema/unqualified-lookup-local-class.cpp
@@ -0,0 +1,51 @@
+// RUN: %clang_cc1 -std=c++20 -verify %s
+
+struct A1 {
+ int x;
+ void f() { x = 1; } // OK
+};
+
+struct Base {
+ int y;
+};
+struct Derived : Base {
+ void f() { y = 2; } // OK
+};
+
+struct A2 { int z; };
+struct B2 : A2 {
+ using A2::z;
+ void f() { z = 3; } // OK
+};
+
+void pass1() {
+ struct A { struct B {}; };
+ A::B b; // OK
+}
+
+void pass2() {
+ class A { public: class B; };
+ class A::B {};
+ A::B b; // OK
+}
+
+void fail1() {
+ class A { public: class B; };
+ class A::B {};
+ B b; // expected-error {{'B'}}
+}
+
+template<class T>
+struct Wrapper { Wrapper(T) {} };
+
+void fail2() {
+ class A { public: class B; };
+ class A::B {};
+ Wrapper w = Wrapper{B{}}; // expected-error {{'B'}}
+}
+
+void fail3() {
+ struct A { public: struct B; };
+ struct A::B {};
+ B b; // expected-error {{'B'}}
+}
More information about the cfe-commits
mailing list