diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2018-01-02 23:52:42 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2018-01-02 23:52:42 +0000 |
commit | 78f3c1f12f22bb890addc680a9955297d5155aff (patch) | |
tree | 6da14fb19511730a6c130e2ea4c71b279baf3e60 /test/SemaCXX/cxx1y-generic-lambdas.cpp | |
parent | 606fddaecab7587d3470a6f118c852cfbc0d7912 (diff) | |
download | clang-78f3c1f12f22bb890addc680a9955297d5155aff.tar.gz |
Fix and simplify handling of return type for (generic) lambda conversion function to function pointer.
Previously, we would:
* compute the type of the conversion function and static invoker as a
side-effect of template argument deduction for a conversion
* re-compute the type as part of deduced return type deduction when building
the conversion function itself
Neither of these turns out to be quite correct. There are other ways to reach a
declaration of the conversion function than in a conversion (such as an
explicit call or friend declaration), and performing auto deduction causes the
function type to be rebuilt in the context of the lambda closure type (which is
different from the context in which it originally appeared, resulting in
spurious substitution failures for constructs that are valid in one context but
not the other, such as the use of an enclosing class's "this" pointer).
This patch switches us to use a different strategy: as before, we use the
declared type of the operator() to form the type of the conversion function and
invoker, but we now populate that type as part of return type deduction for the
conversion function. And the invoker is now treated as simply being an
implementation detail of building the conversion function, and isn't given
special treatment by template argument deduction for the conversion function
any more.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@321683 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/SemaCXX/cxx1y-generic-lambdas.cpp')
-rw-r--r-- | test/SemaCXX/cxx1y-generic-lambdas.cpp | 18 |
1 files changed, 14 insertions, 4 deletions
diff --git a/test/SemaCXX/cxx1y-generic-lambdas.cpp b/test/SemaCXX/cxx1y-generic-lambdas.cpp index 9f3c77591a..49386e7f43 100644 --- a/test/SemaCXX/cxx1y-generic-lambdas.cpp +++ b/test/SemaCXX/cxx1y-generic-lambdas.cpp @@ -181,7 +181,7 @@ int test() { int (*fp2)(int) = [](auto b) -> int { return b; }; int (*fp3)(char) = [](auto c) -> int { return c; }; char (*fp4)(int) = [](auto d) { return d; }; //expected-error{{no viable conversion}}\ - //expected-note{{candidate template ignored}} + //expected-note{{candidate function[with $0 = int]}} char (*fp5)(char) = [](auto e) -> int { return e; }; //expected-error{{no viable conversion}}\ //expected-note{{candidate template ignored}} @@ -207,12 +207,22 @@ int variadic_test() { } // end ns namespace conversion_operator { -void test() { - auto L = [](auto a) -> int { return a; }; + void test() { + auto L = [](auto a) -> int { return a; }; // expected-error {{cannot initialize}} int (*fp)(int) = L; int (&fp2)(int) = [](auto a) { return a; }; // expected-error{{non-const lvalue}} int (&&fp3)(int) = [](auto a) { return a; }; // expected-error{{no viable conversion}}\ //expected-note{{candidate}} + + using F = int(int); + using G = int(void*); + L.operator F*(); + L.operator G*(); // expected-note-re {{instantiation of function template specialization '{{.*}}::operator()<void *>'}} + + // Here, the conversion function is named 'operator auto (*)(int)', and + // there is no way to write that name in valid C++. + auto M = [](auto a) -> auto { return a; }; + M.operator F*(); // expected-error {{no member named 'operator int (*)(int)'}} } } } @@ -992,4 +1002,4 @@ namespace PR32638 { void test() { [](auto x) noexcept(noexcept(x)) { } (0); } -}
\ No newline at end of file +} |