Files
clang-p2996/clang/test/CodeCompletion/desig-init.cpp
Sam McCall 128ce70eef [CodeCompletion] Avoid spurious signature help for init-list args
Somewhat surprisingly, signature help is emitted as a side-effect of
computing the expected type of a function argument.
The reason is that both actions require enumerating the possible
function signatures and running partial overload resolution, and doing
this twice would be wasteful and complicated.

Change #1: document this, it's subtle :-)

However, sometimes we need to compute the expected type without having
reached the code completion cursor yet - in particular to allow
completion of designators.
eb4ab3358c did this but introduced a
regression - it emits signature help in the wrong location as a side-effect.

Change #2: only emit signature help if the code completion cursor was reached.

Currently there is PP.isCodeCompletionReached(), but we can't use it
because it's set *after* running code completion.
It'd be nice to set this implicitly when the completion token is lexed,
but ConsumeCodeCompletionToken() makes this complicated.

Change #3: call cutOffParsing() *first* when seeing a completion token.

After this, the fact that the Sema::Produce*SignatureHelp() functions
are even more confusing, as they only sometimes do that.
I don't want to rename them in this patch as it's another large
mechanical change, but we should soon.

Change #4: prepare to rename ProduceSignatureHelp() to GuessArgumentType() etc.

Differential Revision: https://reviews.llvm.org/D98488
2021-03-16 12:46:40 +01:00

80 lines
3.4 KiB
C++

struct Base {
int t;
};
struct Foo : public Base {
int x;
Base b;
void foo();
};
void foo() {
Foo F{.x = 2, .b.t = 0};
// RUN: %clang_cc1 -fsyntax-only -code-completion-patterns -code-completion-at=%s:11:10 %s -o - -std=c++2a | FileCheck -check-prefix=CHECK-CC1 %s
// RUN: %clang_cc1 -fsyntax-only -code-completion-patterns -code-completion-at=%s:11:18 %s -o - -std=c++2a | FileCheck -check-prefix=CHECK-CC1 %s
// CHECK-CC1: COMPLETION: b : [#Base#]b
// CHECK-CC1-NEXT: COMPLETION: x : [#int#]x
// CHECK-CC1-NOT: foo
// CHECK-CC1-NOT: t
// RUN: %clang_cc1 -fsyntax-only -code-completion-patterns -code-completion-at=%s:11:20 %s -o - | FileCheck -check-prefix=CHECK-NESTED %s
// CHECK-NESTED: COMPLETION: t : [#int#]t
Base B = {.t = 2};
auto z = [](Base B) {};
z({.t = 1});
z(Base{.t = 2});
z((Base){.t = 2});
// RUN: %clang_cc1 -fsyntax-only -code-completion-patterns -code-completion-at=%s:22:14 %s -o - -std=c++2a | FileCheck -check-prefix=CHECK-CC2 %s
// RUN: %clang_cc1 -fsyntax-only -code-completion-patterns -code-completion-at=%s:24:7 %s -o - -std=c++2a | FileCheck -check-prefix=CHECK-CC2 %s
// RUN: %clang_cc1 -fsyntax-only -code-completion-patterns -code-completion-at=%s:25:11 %s -o - -std=c++2a | FileCheck -check-prefix=CHECK-CC2 %s
// RUN: %clang_cc1 -fsyntax-only -code-completion-patterns -code-completion-at=%s:26:13 %s -o - -std=c++2a | FileCheck -check-prefix=CHECK-CC2 %s
// CHECK-CC2: COMPLETION: t : [#int#]t
Foo G1{.b = {.t = 0}};
Foo G2{.b{.t = 0}};
Foo G3{b: {.t = 0}};
// RUN: %clang_cc1 -code-completion-at=%s:33:17 -fsyntax-only -code-completion-patterns %s -o - -std=c++2a | FileCheck -check-prefix=CHECK-NESTED-2 %s
// RUN: %clang_cc1 -code-completion-at=%s:34:14 -fsyntax-only -code-completion-patterns %s -o - -std=c++2a | FileCheck -check-prefix=CHECK-NESTED-2 %s
// RUN: %clang_cc1 -code-completion-at=%s:35:15 -fsyntax-only -code-completion-patterns %s -o - -std=c++2a | FileCheck -check-prefix=CHECK-NESTED-2 %s
// CHECK-NESTED-2: COMPLETION: t : [#int#]t
}
// Handle templates
template <typename T>
struct Test { T x; };
template <>
struct Test<int> {
int x;
char y;
};
void bar() {
Test<char> T{.x = 2};
// RUN: %clang_cc1 -fsyntax-only -code-completion-patterns -code-completion-at=%s:51:17 %s -o - -std=c++2a | FileCheck -check-prefix=CHECK-CC3 %s
// CHECK-CC3: COMPLETION: x : [#T#]x
Test<int> X{.x = 2};
// RUN: %clang_cc1 -fsyntax-only -code-completion-patterns -code-completion-at=%s:54:16 %s -o - -std=c++2a | FileCheck -check-prefix=CHECK-CC4 %s
// CHECK-CC4: COMPLETION: x : [#int#]x
// CHECK-CC4-NEXT: COMPLETION: y : [#char#]y
}
template <typename T>
void aux() {
Test<T> X{.x = T(2)};
// RUN: %clang_cc1 -fsyntax-only -code-completion-patterns -code-completion-at=%s:62:14 %s -o - -std=c++2a | FileCheck -check-prefix=CHECK-CC3 %s
}
namespace signature_regression {
// Verify that an old bug is gone: passing an init-list as a constructor arg
// would emit overloads as a side-effect.
struct S{int x;};
int wrongFunction(S);
int rightFunction();
int dummy = wrongFunction({1});
int x = rightFunction();
// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:73:25 %s -o - -std=c++2a | FileCheck -check-prefix=CHECK-SIGNATURE-REGRESSION %s
// CHECK-SIGNATURE-REGRESSION-NOT: OVERLOAD: [#int#]wrongFunction
// CHECK-SIGNATURE-REGRESSION: OVERLOAD: [#int#]rightFunction
// CHECK-SIGNATURE-REGRESSION-NOT: OVERLOAD: [#int#]wrongFunction
}