https://github.com/pfeodrippe updated 
https://github.com/llvm/llvm-project/pull/169272

>From 58432c222b651a9b7f309790eb7f50ea771138b7 Mon Sep 17 00:00:00 2001
From: Paulo Feodrippe <[email protected]>
Date: Sun, 23 Nov 2025 22:34:43 -0500
Subject: [PATCH] [clang][Parser] Allow private type aliases in out-of-line
 member function return types

When parsing qualified type names (e.g., `io_context::impl_type`) at file scope 
in
clang-repl, suppress access checks during type annotation. This allows private 
member
type aliases to be used in return types of out-of-line member function 
definitions,
matching the C++ standard's scoping rules for such declarations.

Fixes: Parsing errors in clang-repl when including headers with out-of-line 
member
functions that return private nested types (e.g., ASIO's io_context::impl_type).
---
 clang/lib/Parse/Parser.cpp                    | 21 +++++++++++++
 .../Interpreter/private-member-access.cpp     | 31 +++++++++++++++++++
 2 files changed, 52 insertions(+)
 create mode 100644 clang/test/Interpreter/private-member-access.cpp

diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp
index a6fc676f23a51..ac5c90bf7c7ac 100644
--- a/clang/lib/Parse/Parser.cpp
+++ b/clang/lib/Parse/Parser.cpp
@@ -2020,6 +2020,27 @@ bool Parser::TryAnnotateTypeOrScopeTokenAfterScopeSpec(
     CXXScopeSpec &SS, bool IsNewScope,
     ImplicitTypenameContext AllowImplicitTypename) {
   if (Tok.is(tok::identifier)) {
+    // In incremental/clang-repl mode, suppress access checks for qualified
+    // type lookups when no delayed diagnostic pool is active. This handles
+    // the case where we're parsing input like "A::B *A::foo()" where the type
+    // "A::B" might be a private member type, but if this turns out to be an
+    // out-of-line member function definition, access should be allowed.
+    //
+    // When the declaration is actually parsed (via 
ParseDeclarationOrFunctionDefinition),
+    // the ParsingDeclSpec will set up proper delayed diagnostics to handle
+    // access checking in the correct context.
+    //
+    // We only do this in incremental mode because this is where the issue
+    // manifests - disambiguation happens before ParsingDeclSpec is created.
+    // In normal compilation, these access checks would be re-triggered during
+    // actual parsing with delayed diagnostics active.
+    bool SuppressAccess = getLangOpts().IncrementalExtensions &&
+                          SS.isNotEmpty() &&
+                          !Actions.DelayedDiagnostics.shouldDelayDiagnostics();
+    std::optional<SuppressAccessChecks> SAC;
+    if (SuppressAccess)
+      SAC.emplace(*this, true);
+
     // Determine whether the identifier is a type name.
     if (ParsedType Ty = Actions.getTypeName(
             *Tok.getIdentifierInfo(), Tok.getLocation(), getCurScope(), &SS,
diff --git a/clang/test/Interpreter/private-member-access.cpp 
b/clang/test/Interpreter/private-member-access.cpp
new file mode 100644
index 0000000000000..0d02f09332612
--- /dev/null
+++ b/clang/test/Interpreter/private-member-access.cpp
@@ -0,0 +1,31 @@
+// RUN: cat %s | clang-repl | FileCheck %s
+
+extern "C" int printf(const char*, ...);
+
+struct scheduler { };
+class io_context { using impl_type = scheduler; public: impl_type *get_impl(); 
};
+io_context::impl_type *io_context::get_impl() { return nullptr; }
+printf("Private type alias: passed\n");
+// CHECK: Private type alias: passed
+
+class Container { struct Node { int data; }; public: Node* create(); };
+Container::Node* Container::create() { return new Node{456}; }
+printf("Private nested struct: %d\n", Container().create()->data);
+// CHECK: Private nested struct: 456
+
+class Status { enum Code { OK = 0 }; public: Code get(); };
+Status::Code Status::get() { return OK; }
+printf("Private enum: %d\n", Status().get());
+// CHECK: Private enum: 0
+
+template<typename T> class Handler { using ptr = T*; public: ptr get(); };
+template<typename T> typename Handler<T>::ptr Handler<T>::get() { return 
nullptr; }
+printf("Template with private type: passed\n");
+// CHECK: Template with private type: passed
+
+namespace ns { class C { using val_t = double; public: val_t compute(); }; }
+ns::C::val_t ns::C::compute() { return 3.14; }
+printf("Namespace qualified: %.2f\n", ns::C().compute());
+// CHECK: Namespace qualified: 3.14
+
+%quit

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

Reply via email to