aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema/SemaExprMember.cpp
diff options
context:
space:
mode:
authorKrystian Stasiowski <sdkrystian@gmail.com>2024-07-09 16:40:53 -0400
committerGitHub <noreply@github.com>2024-07-09 16:40:53 -0400
commit9e1f1cfa59c4513798de5c326d77e1e5912b1634 (patch)
tree2318eeaf194145f0e2127b816a653db58d0fe8c8 /clang/lib/Sema/SemaExprMember.cpp
parent10f3f06d865fe5ec434fbaf78009301e95b59ea5 (diff)
downloadllvm-9e1f1cfa59c4513798de5c326d77e1e5912b1634.zip
llvm-9e1f1cfa59c4513798de5c326d77e1e5912b1634.tar.gz
llvm-9e1f1cfa59c4513798de5c326d77e1e5912b1634.tar.bz2
[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`).
Diffstat (limited to 'clang/lib/Sema/SemaExprMember.cpp')
-rw-r--r--clang/lib/Sema/SemaExprMember.cpp17
1 files changed, 7 insertions, 10 deletions
diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp
index b7ea247..2070f3b 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)