https://github.com/vgvassilev updated https://github.com/llvm/llvm-project/pull/178842
>From 591f69d6c3b918f0544d9c32f6e8b2fb53117730 Mon Sep 17 00:00:00 2001 From: fogsong233 <[email protected]> Date: Tue, 10 Feb 2026 23:15:08 +0800 Subject: [PATCH] [clang-repl] Fix disambiguation of out-of-line member with private types This patch fixes a bug in clang-repl where out-of-line member function definitions were incorrectly identified as statements when they involved private type aliases. The issue occurred because `isCXXDeclarationStatement` would trigger immediate access checks during tentative parsing. Since the context of an out-of-line definition isn't fully established during this phase, Sema would incorrectly flag private members as inaccessible, causing the parser to fail the declaration check and fall back to statement parsing. Changes: - In `isCXXDeclarationStatement`, use `TentativeParsingAction` to ensure the token stream is fully restored. - Use `SuppressAccessChecks` during the tentative disambiguation phase to prevent premature access errors. - Ensure that formal access verification still occurs during the actual parsing phase in `ParseDeclarationOrFunctionDefinition`. - Add tests and resolve a FIXME in clang/test/Interpreter/disambiguate-decl-stmt.cpp. See also jank-lang/jank#609. Fixes llvm#169272. Fixes llvm#164885. --- clang/lib/Parse/ParseTentative.cpp | 16 ++++++++++++++++ clang/test/Interpreter/access.cpp | 15 +++++++++++++++ .../test/Interpreter/disambiguate-decl-stmt.cpp | 5 ++--- 3 files changed, 33 insertions(+), 3 deletions(-) create mode 100644 clang/test/Interpreter/access.cpp diff --git a/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp index 9622a00687ca5..c8ddc120aa87e 100644 --- a/clang/lib/Parse/ParseTentative.cpp +++ b/clang/lib/Parse/ParseTentative.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "clang/Parse/Parser.h" +#include "clang/Parse/RAIIObjectsForParser.h" #include "clang/Sema/ParsedTemplate.h" using namespace clang; @@ -78,6 +79,21 @@ bool Parser::isCXXDeclarationStatement( [[fallthrough]]; // simple-declaration default: + + if (DisambiguatingWithExpression) { + TentativeParsingAction TPA(*this, /*Unannotated=*/true); + // Skip early access checks to support edge cases like extern declarations + // involving private types. Tokens are unannotated by reverting so that + // access integrity is verified during the subsequent type-lookup phase. + SuppressAccessChecks AccessExporter(*this, /*activate=*/true); + if (isCXXSimpleDeclaration(/*AllowForRangeDecl=*/false)) { + // Do not annotate the tokens, otherwise access will be neglected later. + TPA.Revert(); + return true; + } + TPA.Commit(); + return false; + } return isCXXSimpleDeclaration(/*AllowForRangeDecl=*/false); } } diff --git a/clang/test/Interpreter/access.cpp b/clang/test/Interpreter/access.cpp new file mode 100644 index 0000000000000..c6b535bc1db92 --- /dev/null +++ b/clang/test/Interpreter/access.cpp @@ -0,0 +1,15 @@ +// REQUIRES: host-supports-jit +// RUN: cat %s | clang-repl 2>&1 | FileCheck %s + +struct A { }; + +class B { using u = A; const static int p = 1; public: u *foo(); }; + +B::u* foo() { return nullptr; } +// CHECK: error: 'u' is a private member of 'B' + +B::u * B::foo() { return nullptr; } +// CHECK-NOT: error: 'u' is a private member of 'B' + +int p = B::p; +// CHECK: error: 'p' is a private member of 'B' diff --git a/clang/test/Interpreter/disambiguate-decl-stmt.cpp b/clang/test/Interpreter/disambiguate-decl-stmt.cpp index 1f4d5e267288b..24902cee8ed1f 100644 --- a/clang/test/Interpreter/disambiguate-decl-stmt.cpp +++ b/clang/test/Interpreter/disambiguate-decl-stmt.cpp @@ -70,11 +70,10 @@ class PrivateUsingFriendVar { static PrivateUsingFriend::T i; }; PrivateUsingFriend::T PrivateUsingFriendVar::i = 42; // The following should still diagnose (inspired by PR13642) -// FIXME: Should not be diagnosed twice! class PR13642 { class Inner { public: static int i; }; }; -// expected-note@-1 2 {{implicitly declared private here}} +// expected-note@-1 {{implicitly declared private here}} PR13642::Inner::i = 5; -// expected-error@-1 2 {{'Inner' is a private member of 'PR13642'}} +// expected-error@-1 {{'Inner' is a private member of 'PR13642'}} // Deduction guide template<typename T> struct A { A(); A(T); }; _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
