[clang] [Sema] Reject unqualified lookup of local nested class name (PR #192678)
via cfe-commits
cfe-commits at lists.llvm.org
Fri May 8 04:51:59 PDT 2026
https://github.com/arrowten updated https://github.com/llvm/llvm-project/pull/192678
>From d82fa62db7f39cfcf459ce8aa9cbaccb4b2e39f8 Mon Sep 17 00:00:00 2001
From: Ajay Wakodikar <ajaywakodikarsocial at gmail.com>
Date: Fri, 8 May 2026 07:49:43 -0400
Subject: [PATCH] [Sema] Reject unqualified lookup of local nested class
---
clang/lib/Sema/SemaDecl.cpp | 9 ++++-
.../Sema/unqualified-lookup-local-class.cpp | 39 +++++++++++++++++++
2 files changed, 46 insertions(+), 2 deletions(-)
create mode 100644 clang/test/Sema/unqualified-lookup-local-class.cpp
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index be9654078940f..654682d61ca87 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -1585,8 +1585,13 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext) {
// Out-of-line definitions shouldn't be pushed into scope in C++, unless they
// are function-local declarations.
- if (getLangOpts().CPlusPlus && D->isOutOfLine() && !S->getFnParent())
- return;
+ if (getLangOpts().CPlusPlus && D->isOutOfLine()) {
+ if (!S->getFnParent())
+ return;
+
+ if (isa<TagDecl>(D) && isa<CXXRecordDecl>(D->getDeclContext()))
+ return;
+ }
// Template instantiations should also not be pushed into scope.
if (isa<FunctionDecl>(D) &&
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..c87025afe6af8
--- /dev/null
+++ b/clang/test/Sema/unqualified-lookup-local-class.cpp
@@ -0,0 +1,39 @@
+// 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
+
+ class C { public: class B; };
+ class C::B {};
+ C::B b2; // OK
+}
+
+template<class T>
+struct Wrapper { Wrapper(T) {} };
+
+void fail() {
+ class A { public: class B; };
+ class A::B {};
+ B b; // expected-error {{'B'}}
+ Wrapper w = Wrapper{B{}}; // expected-error {{'B'}}
+}
More information about the cfe-commits
mailing list