diff options
author | 2021-02-18 13:48:43 +0100 | |
---|---|---|
committer | 2021-02-23 11:13:07 +0100 | |
commit | 7fc6c60608e416e7f8f5c194768c6dd511449c1b (patch) | |
tree | 3e12d3351a8b8a59fd7b111aaa19b26198efc328 | |
parent | [clang][CodeComplete] Fix crash on ParenListExprs (diff) | |
download | llvm-project-7fc6c60608e416e7f8f5c194768c6dd511449c1b.tar.gz llvm-project-7fc6c60608e416e7f8f5c194768c6dd511449c1b.tar.bz2 llvm-project-7fc6c60608e416e7f8f5c194768c6dd511449c1b.zip |
[clang][CodeComplete] Ensure there are no crashes when completing with ParenListExprs as LHS
Differential Revision: https://reviews.llvm.org/D96950
-rw-r--r-- | clang/lib/Sema/SemaCodeComplete.cpp | 31 |
1 files changed, 17 insertions, 14 deletions
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index 40ea0f5d24b3..be04970979b3 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -5158,6 +5158,20 @@ private: llvm::DenseMap<const IdentifierInfo *, Member> Results; }; + +// 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<ParenListExpr>(Base)) { + if (PLE->getNumExprs() == 0) + return nullptr; + Base = PLE->getExpr(PLE->getNumExprs() - 1); + } + return Base; +} + } // namespace void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, @@ -5165,18 +5179,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<ParenListExpr>(Base)) - Base = PLE->getExpr(PLE->getNumExprs() - 1); - if (OtherOpBase) { - if (auto *PLE = llvm::dyn_cast<ParenListExpr>(OtherOpBase)) - OtherOpBase = PLE->getExpr(PLE->getNumExprs() - 1); - } - ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow); if (ConvertedBase.isInvalid()) return; @@ -5606,14 +5613,10 @@ ProduceSignatureHelp(Sema &SemaRef, Scope *S, QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn, ArrayRef<Expr *> 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<ParenListExpr>(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)) |