diff options
author | Kadir Cetinkaya <kadircet@google.com> | 2021-02-03 12:45:46 +0100 |
---|---|---|
committer | Kadir Cetinkaya <kadircet@google.com> | 2021-02-23 11:12:08 +0100 |
commit | 99df95fd910becbcf89dd6f17f1e259353a72d27 (patch) | |
tree | 469dcaac9b8a8b29c350880d486b34cf6e644051 | |
parent | a92ceea91116e7b95d23eff634507fa2cff86ef2 (diff) | |
download | llvm-99df95fd910becbcf89dd6f17f1e259353a72d27.zip llvm-99df95fd910becbcf89dd6f17f1e259353a72d27.tar.gz llvm-99df95fd910becbcf89dd6f17f1e259353a72d27.tar.bz2 |
[clang][CodeComplete] Fix crash on ParenListExprs
Fixes https://github.com/clangd/clangd/issues/676.
Differential Revision: https://reviews.llvm.org/D95935
-rw-r--r-- | clang/lib/Sema/SemaCodeComplete.cpp | 18 | ||||
-rw-r--r-- | clang/test/CodeCompletion/function-overloads.cpp | 6 | ||||
-rw-r--r-- | clang/test/CodeCompletion/member-access.c | 7 | ||||
-rw-r--r-- | clang/unittests/Sema/CodeCompleteTest.cpp | 1 |
4 files changed, 30 insertions, 2 deletions
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index c2785fd..40ea0f5 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -5168,6 +5168,15 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, 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; @@ -5597,12 +5606,17 @@ ProduceSignatureHelp(Sema &SemaRef, Scope *S, QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn, ArrayRef<Expr *> Args, SourceLocation OpenParLoc) { - if (!CodeCompleter) + 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 || Fn->isTypeDependent() || anyNullArguments(Args)) + if (Fn->isTypeDependent() || anyNullArguments(Args)) return QualType(); // 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 diff --git a/clang/test/CodeCompletion/function-overloads.cpp b/clang/test/CodeCompletion/function-overloads.cpp index 11c864c..7b8ccef 100644 --- a/clang/test/CodeCompletion/function-overloads.cpp +++ b/clang/test/CodeCompletion/function-overloads.cpp @@ -21,6 +21,8 @@ namespace NS { void test_adl() { NS::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 @@ -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:23:7 %s -o - | \ // 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(<#int i#>) // CHECK-CC1-NOT, CHECK-CC2-NOT: OVERLOAD: A( diff --git a/clang/test/CodeCompletion/member-access.c b/clang/test/CodeCompletion/member-access.c index 72afbf2..545349f 100644 --- a/clang/test/CodeCompletion/member-access.c +++ b/clang/test/CodeCompletion/member-access.c @@ -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 // 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 diff --git a/clang/unittests/Sema/CodeCompleteTest.cpp b/clang/unittests/Sema/CodeCompleteTest.cpp index d8b303d..dae0793 100644 --- a/clang/unittests/Sema/CodeCompleteTest.cpp +++ b/clang/unittests/Sema/CodeCompleteTest.cpp @@ -488,6 +488,7 @@ TEST(PreferredTypeTest, NoCrashOnInvalidTypes) { auto y = new decltype(&1)(^); // GNU decimal type extension is not supported in clang. auto z = new _Decimal128(^); + void foo() { (void)(foo)(^); } )cpp"; EXPECT_THAT(collectPreferredTypes(Code), Each("NULL TYPE")); } |