From f10137399a3c9239a6acd1d3df12a40766b64759 Mon Sep 17 00:00:00 2001 From: Kadir Cetinkaya Date: Thu, 18 Feb 2021 13:48:43 +0100 Subject: [PATCH] [clang][CodeComplete] Ensure there are no crashes when completing with ParenListExprs as LHS Differential Revision: https://reviews.llvm.org/D96950 --- clang/lib/Sema/SemaCodeComplete.cpp | 30 +++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index 1e4d5dd62aa0..2feb02bbe4ed 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -5245,6 +5245,19 @@ QualType getApproximateType(const Expr *E) { return Unresolved; } +// If \p Base is ParenListExpr, assume a chain of comma operators and pick the +// last expr. We expect other ParenListExprs to be resolved to e.g. constructor +// calls before here. (So the ParenListExpr should be nonempty, but check just +// in case) +Expr *unwrapParenList(Expr *Base) { + if (auto *PLE = llvm::dyn_cast_or_null(Base)) { + if (PLE->getNumExprs() == 0) + return nullptr; + Base = PLE->getExpr(PLE->getNumExprs() - 1); + } + return Base; +} + } // namespace void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, @@ -5252,18 +5265,11 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, SourceLocation OpLoc, bool IsArrow, bool IsBaseExprStatement, QualType PreferredType) { + Base = unwrapParenList(Base); + OtherOpBase = unwrapParenList(OtherOpBase); if (!Base || !CodeCompleter) return; - // Peel off the ParenListExpr by chosing the last one, as they don't have a - // predefined type. - if (auto *PLE = llvm::dyn_cast(Base)) - Base = PLE->getExpr(PLE->getNumExprs() - 1); - if (OtherOpBase) { - if (auto *PLE = llvm::dyn_cast(OtherOpBase)) - OtherOpBase = PLE->getExpr(PLE->getNumExprs() - 1); - } - ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow); if (ConvertedBase.isInvalid()) return; @@ -5693,14 +5699,10 @@ ProduceSignatureHelp(Sema &SemaRef, Scope *S, QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn, ArrayRef Args, SourceLocation OpenParLoc) { + Fn = unwrapParenList(Fn); if (!CodeCompleter || !Fn) return QualType(); - // If we have a ParenListExpr for LHS, peel it off by chosing the last expr. - // As ParenListExprs don't have a predefined type. - if (auto *PLE = llvm::dyn_cast(Fn)) - Fn = PLE->getExpr(PLE->getNumExprs() - 1); - // FIXME: Provide support for variadic template functions. // Ignore type-dependent call expressions entirely. if (Fn->isTypeDependent() || anyNullArguments(Args))