diff options
author | Krystian Stasiowski <sdkrystian@gmail.com> | 2024-07-09 16:40:53 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-07-09 16:40:53 -0400 |
commit | 9e1f1cfa59c4513798de5c326d77e1e5912b1634 (patch) | |
tree | 2318eeaf194145f0e2127b816a653db58d0fe8c8 /clang/lib/Sema/SemaExprMember.cpp | |
parent | 10f3f06d865fe5ec434fbaf78009301e95b59ea5 (diff) | |
download | llvm-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.cpp | 17 |
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) |