Author: fogsong233
Date: 2026-02-12T11:23:49+02:00
New Revision: f6f0503673b746a2e43a995006ced39c5c7e412e

URL: 
https://github.com/llvm/llvm-project/commit/f6f0503673b746a2e43a995006ced39c5c7e412e
DIFF: 
https://github.com/llvm/llvm-project/commit/f6f0503673b746a2e43a995006ced39c5c7e412e.diff

LOG: [clang-repl] Fix disambiguation of out-of-line member with private types 
(#178842)

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.

Fixes llvm#164885.
See also jank-lang/jank#609.

Added: 
    clang/test/Interpreter/access.cpp

Modified: 
    clang/lib/Parse/ParseTentative.cpp
    clang/test/Interpreter/disambiguate-decl-stmt.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Parse/ParseTentative.cpp 
b/clang/lib/Parse/ParseTentative.cpp
index 34b86db793890..0047e3ea3749b 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

Reply via email to