https://github.com/sdkrystian created 
https://github.com/llvm/llvm-project/pull/98167

The following code causes [this 
assert](https://github.com/llvm/llvm-project/blob/main/clang/lib/Sema/SemaExprMember.cpp#L981)
 to fail:
```cpp
struct A { };
struct B;

void f(A *x) {
  x->B::y; // crash here
}
```
This happens because we only return early from `BuildMemberReferenceExpr` when 
the `CXXScopeSpecifier` is invalid _before_ the lookup is performed. Since the 
lookup may invalidate the `CXXScopeSpecifier` (e.g. if the 
_nested-name-specifier_ is incomplete), this results in the second 
`BuildMemberReferenceExpr` overload to be called with an invalid 
`CXXScopeSpecifier`, which causes the assert to fail. This patch moves the 
early return for invalid `CXXScopeSpecifiers` to occur _after_ lookup is 
performed. This fixes #92972.

>From 85efbad994685903e01726b97ba0ab82172bae63 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkryst...@gmail.com>
Date: Tue, 9 Jul 2024 11:03:14 -0400
Subject: [PATCH] [Clang][Sema] Handle class member access expressions with
 valid nested-name-specifiers that become invalid after lookup

---
 clang/lib/Sema/SemaExprMember.cpp                | 16 ++++++----------
 .../basic.lookup.qual.general/p2.cpp             | 16 ++++++++++++++++
 2 files changed, 22 insertions(+), 10 deletions(-)
 create mode 100644 
clang/test/CXX/basic/basic.lookup/basic.lookup.qual/basic.lookup.qual.general/p2.cpp

diff --git a/clang/lib/Sema/SemaExprMember.cpp 
b/clang/lib/Sema/SemaExprMember.cpp
index b7ea24790d361..daa9a4948f66c 100644
--- a/clang/lib/Sema/SemaExprMember.cpp
+++ b/clang/lib/Sema/SemaExprMember.cpp
@@ -789,9 +789,6 @@ ExprResult Sema::BuildMemberReferenceExpr(
     ActOnMemberAccessExtraArgs *ExtraArgs) {
   LookupResult R(*this, NameInfo, LookupMemberName);
 
-  if (SS.isInvalid())
-    return ExprError();
-
   // Implicit member accesses.
   if (!Base) {
     TypoExpr *TE = nullptr;
@@ -826,6 +823,10 @@ ExprResult Sema::BuildMemberReferenceExpr(
     BaseType = Base->getType();
   }
 
+  // BuildMemberReferenceExpr expects a valid nested-name-specifier, if any.
+  if (SS.isInvalid())
+    return ExprError();
+
   return BuildMemberReferenceExpr(Base, BaseType,
                                   OpLoc, IsArrow, SS, TemplateKWLoc,
                                   FirstQualifierInScope, R, TemplateArgs, S,
@@ -1745,14 +1746,9 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult 
&R,
 
 ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base,
                                        SourceLocation OpLoc,
-                                       tok::TokenKind OpKind,
-                                       CXXScopeSpec &SS,
+                                       tok::TokenKind OpKind, CXXScopeSpec &SS,
                                        SourceLocation TemplateKWLoc,
-                                       UnqualifiedId &Id,
-                                       Decl *ObjCImpDecl) {
-  if (SS.isSet() && SS.isInvalid())
-    return ExprError();
-
+                                       UnqualifiedId &Id, Decl *ObjCImpDecl) {
   // Warn about the explicit constructor calls Microsoft extension.
   if (getLangOpts().MicrosoftExt &&
       Id.getKind() == UnqualifiedIdKind::IK_ConstructorName)
diff --git 
a/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/basic.lookup.qual.general/p2.cpp
 
b/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/basic.lookup.qual.general/p2.cpp
new file mode 100644
index 0000000000000..ebdae971a929e
--- /dev/null
+++ 
b/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/basic.lookup.qual.general/p2.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -verify -Wno-unused %s
+
+struct A {
+  int y;
+};
+
+struct B; // expected-note 4{{forward declaration of 'B'}}
+
+void f(A *a, B *b) {
+  a->B::x; // expected-error {{incomplete type 'B' named in nested name 
specifier}}
+  a->A::x; // expected-error {{no member named 'x' in 'A'}}
+  a->A::y;
+  b->B::x; // expected-error {{member access into incomplete type 'B'}}
+  b->A::x; // expected-error {{member access into incomplete type 'B'}}
+  b->A::y; // expected-error {{member access into incomplete type 'B'}}
+}

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to