[clang][CodeComplete] Ensure there are no crashes when completing with ParenListExprs as LHS

Differential Revision: https://reviews.llvm.org/D96950
This commit is contained in:
Kadir Cetinkaya 2021-02-18 13:48:43 +01:00
parent 820e0c49fc
commit f10137399a
No known key found for this signature in database
GPG Key ID: E39E36B8D2057ED6
1 changed files with 16 additions and 14 deletions

View File

@ -5245,6 +5245,19 @@ QualType getApproximateType(const Expr *E) {
return Unresolved; 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<ParenListExpr>(Base)) {
if (PLE->getNumExprs() == 0)
return nullptr;
Base = PLE->getExpr(PLE->getNumExprs() - 1);
}
return Base;
}
} // namespace } // namespace
void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
@ -5252,18 +5265,11 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
SourceLocation OpLoc, bool IsArrow, SourceLocation OpLoc, bool IsArrow,
bool IsBaseExprStatement, bool IsBaseExprStatement,
QualType PreferredType) { QualType PreferredType) {
Base = unwrapParenList(Base);
OtherOpBase = unwrapParenList(OtherOpBase);
if (!Base || !CodeCompleter) if (!Base || !CodeCompleter)
return; 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); ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
if (ConvertedBase.isInvalid()) if (ConvertedBase.isInvalid())
return; return;
@ -5693,14 +5699,10 @@ ProduceSignatureHelp(Sema &SemaRef, Scope *S,
QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn, QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn,
ArrayRef<Expr *> Args, ArrayRef<Expr *> Args,
SourceLocation OpenParLoc) { SourceLocation OpenParLoc) {
Fn = unwrapParenList(Fn);
if (!CodeCompleter || !Fn) if (!CodeCompleter || !Fn)
return QualType(); 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. // FIXME: Provide support for variadic template functions.
// Ignore type-dependent call expressions entirely. // Ignore type-dependent call expressions entirely.
if (Fn->isTypeDependent() || anyNullArguments(Args)) if (Fn->isTypeDependent() || anyNullArguments(Args))