[clang] 9e1f1cf - [Clang][Sema] Handle class member access expressions with valid nested-name-specifiers that become invalid after lookup (#98167)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Jul 9 13:40:56 PDT 2024
Author: Krystian Stasiowski
Date: 2024-07-09T16:40:53-04:00
New Revision: 9e1f1cfa59c4513798de5c326d77e1e5912b1634
URL: https://github.com/llvm/llvm-project/commit/9e1f1cfa59c4513798de5c326d77e1e5912b1634
DIFF: https://github.com/llvm/llvm-project/commit/9e1f1cfa59c4513798de5c326d77e1e5912b1634.diff
LOG: [Clang][Sema] Handle class member access expressions with valid nested-name-specifiers that become invalid after lookup (#98167)
The following code causes an assert in `SemaExprMember.cpp` on line 981
to fail:
```
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 being
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.
I also removed the `if (SS.isSet() && SS.isInvalid())` check in
`ActOnMemberAccessExpr` because the condition can never be true (`isSet`
returns `getScopeRep() != nullptr` and `isInvalid` returns
`Range.isValid() && getScopeRep() == nullptr`).
Added:
clang/test/CXX/basic/basic.lookup/basic.lookup.qual/basic.lookup.qual.general/p2.cpp
Modified:
clang/lib/Sema/SemaExprMember.cpp
Removed:
################################################################################
diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp
index b7ea24790d361..2070f3b7bb3a2 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,11 @@ ExprResult Sema::BuildMemberReferenceExpr(
BaseType = Base->getType();
}
+ // BuildMemberReferenceExpr expects the nested-name-specifier, if any, to be
+ // valid.
+ if (SS.isInvalid())
+ return ExprError();
+
return BuildMemberReferenceExpr(Base, BaseType,
OpLoc, IsArrow, SS, TemplateKWLoc,
FirstQualifierInScope, R, TemplateArgs, S,
@@ -1745,14 +1747,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'}}
+}
More information about the cfe-commits
mailing list