llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Krystian Stasiowski (sdkrystian) <details> <summary>Changes</summary> 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. --- Full diff: https://github.com/llvm/llvm-project/pull/98167.diff 2 Files Affected: - (modified) clang/lib/Sema/SemaExprMember.cpp (+6-10) - (added) clang/test/CXX/basic/basic.lookup/basic.lookup.qual/basic.lookup.qual.general/p2.cpp (+16) ``````````diff 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'}} +} `````````` </details> https://github.com/llvm/llvm-project/pull/98167 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits