[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:05:25 PDT 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: arrowten

<details>
<summary>Changes</summary>

Clang incorrectly accepts unqualified use of a nested class declared inside a local class, even when it is not visible in the current scope.

---
Full diff: https://github.com/llvm/llvm-project/pull/192678.diff


2 Files Affected:

- (modified) clang/lib/Sema/SemaLookup.cpp (+12) 
- (added) clang/test/Sema/unqualified-lookup-local-class.cpp (+51) 


``````````diff
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'}}
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/192678


More information about the cfe-commits mailing list