forked from OSchip/llvm-project
[clang][CodeComplete] Fix crash on ParenListExprs
Fixes https://github.com/clangd/clangd/issues/676. Differential Revision: https://reviews.llvm.org/D95935
This commit is contained in:
parent
e22677bbdb
commit
f743184911
|
@ -5186,6 +5186,15 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
|
||||||
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;
|
||||||
|
@ -5615,12 +5624,17 @@ 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) {
|
||||||
if (!CodeCompleter)
|
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 || Fn->isTypeDependent() || anyNullArguments(Args))
|
if (Fn->isTypeDependent() || anyNullArguments(Args))
|
||||||
return QualType();
|
return QualType();
|
||||||
// In presence of dependent args we surface all possible signatures using the
|
// In presence of dependent args we surface all possible signatures using the
|
||||||
// non-dependent args in the prefix. Afterwards we do a post filtering to make
|
// non-dependent args in the prefix. Afterwards we do a post filtering to make
|
||||||
|
|
|
@ -21,6 +21,8 @@ namespace NS {
|
||||||
void test_adl() {
|
void test_adl() {
|
||||||
NS::X x;
|
NS::X x;
|
||||||
g(x, x);
|
g(x, x);
|
||||||
|
(void)(f)(1, 2, 3);
|
||||||
|
(void)(test, test, test, f)(1, 2, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:9 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
|
// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:9 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
|
||||||
|
@ -31,6 +33,10 @@ void test_adl() {
|
||||||
// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:21 %s -o - | FileCheck -check-prefix=CHECK-CC4 %s
|
// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:21 %s -o - | FileCheck -check-prefix=CHECK-CC4 %s
|
||||||
// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:23:7 %s -o - | \
|
// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:23:7 %s -o - | \
|
||||||
// RUN: FileCheck -check-prefix=CHECK-CC5 %s
|
// RUN: FileCheck -check-prefix=CHECK-CC5 %s
|
||||||
|
// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:24:13 %s -o - | \
|
||||||
|
// RUN: FileCheck -check-prefix=CHECK-CC1 %s
|
||||||
|
// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:25:31 %s -o - | \
|
||||||
|
// RUN: FileCheck -check-prefix=CHECK-CC1 %s
|
||||||
// CHECK-CC1: OVERLOAD: [#int#]f(<#float x#>, float y)
|
// CHECK-CC1: OVERLOAD: [#int#]f(<#float x#>, float y)
|
||||||
// CHECK-CC1: OVERLOAD: [#int#]f(<#int i#>)
|
// CHECK-CC1: OVERLOAD: [#int#]f(<#int i#>)
|
||||||
// CHECK-CC1-NOT, CHECK-CC2-NOT: OVERLOAD: A(
|
// CHECK-CC1-NOT, CHECK-CC2-NOT: OVERLOAD: A(
|
||||||
|
|
|
@ -29,3 +29,10 @@ void test3(struct Point2 *p) {
|
||||||
|
|
||||||
// RUN: %clang_cc1 -fsyntax-only -code-completion-with-fixits -code-completion-at=%s:24:5 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s
|
// RUN: %clang_cc1 -fsyntax-only -code-completion-with-fixits -code-completion-at=%s:24:5 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s
|
||||||
// CHECK-CC3: x (requires fix-it: {24:4-24:5} to "->")
|
// CHECK-CC3: x (requires fix-it: {24:4-24:5} to "->")
|
||||||
|
|
||||||
|
void test4(struct Point *p) {
|
||||||
|
(int)(p)->x;
|
||||||
|
(int)(0,1,2,3,4,p)->x;
|
||||||
|
}
|
||||||
|
// RUN: %clang_cc1 -fsyntax-only -code-completion-with-fixits -code-completion-at=%s:34:13 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
|
||||||
|
// RUN: %clang_cc1 -fsyntax-only -code-completion-with-fixits -code-completion-at=%s:35:23 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
|
||||||
|
|
|
@ -488,6 +488,7 @@ TEST(PreferredTypeTest, NoCrashOnInvalidTypes) {
|
||||||
auto y = new decltype(&1)(^);
|
auto y = new decltype(&1)(^);
|
||||||
// GNU decimal type extension is not supported in clang.
|
// GNU decimal type extension is not supported in clang.
|
||||||
auto z = new _Decimal128(^);
|
auto z = new _Decimal128(^);
|
||||||
|
void foo() { (void)(foo)(^); }
|
||||||
)cpp";
|
)cpp";
|
||||||
EXPECT_THAT(collectPreferredTypes(Code), Each("NULL TYPE"));
|
EXPECT_THAT(collectPreferredTypes(Code), Each("NULL TYPE"));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue