2013-10-24 09:11:55 +08:00
|
|
|
// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -emit-llvm-only %s
|
2013-11-01 10:01:01 +08:00
|
|
|
// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -fdelayed-template-parsing %s -DDELAYED_TEMPLATE_PARSING
|
|
|
|
// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -fms-extensions %s -DMS_EXTENSIONS
|
|
|
|
// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -fdelayed-template-parsing -fms-extensions %s -DMS_EXTENSIONS -DDELAYED_TEMPLATE_PARSING
|
2020-11-17 07:26:22 +08:00
|
|
|
// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -triple i386-windows-pc -emit-llvm-only %s
|
|
|
|
// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -triple i386-windows-pc -fdelayed-template-parsing %s -DDELAYED_TEMPLATE_PARSING
|
|
|
|
// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -triple i386-windows-pc -fms-extensions %s -DMS_EXTENSIONS
|
|
|
|
// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -triple i386-windows-pc -fdelayed-template-parsing -fms-extensions %s -DMS_EXTENSIONS -DDELAYED_TEMPLATE_PARSING
|
2013-09-29 16:45:24 +08:00
|
|
|
|
2014-01-09 10:22:22 +08:00
|
|
|
template<class F, class ...Rest> struct first_impl { typedef F type; };
|
|
|
|
template<class ...Args> using first = typename first_impl<Args...>::type;
|
|
|
|
|
2013-12-08 23:11:48 +08:00
|
|
|
namespace simple_explicit_capture {
|
|
|
|
void test() {
|
|
|
|
int i;
|
|
|
|
auto L = [i](auto a) { return i + a; };
|
|
|
|
L(3.14);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-29 16:45:24 +08:00
|
|
|
namespace explicit_call {
|
|
|
|
int test() {
|
|
|
|
auto L = [](auto a) { return a; };
|
|
|
|
L.operator()(3);
|
|
|
|
L.operator()<char>(3.14); //expected-warning{{implicit conversion}}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
} //end ns
|
|
|
|
|
This patch implements capturing of variables within generic lambdas.
Both Richard and I felt that the current wording in the working paper needed some tweaking - Please see http://llvm-reviews.chandlerc.com/D2035 for additional context and references to core-reflector messages that discuss wording tweaks.
What is implemented is what we had intended to specify in Bristol; but, recently felt that the specification might benefit from some tweaking and fleshing.
As a rough attempt to explain the semantics: If a nested lambda with a default-capture names a variable within its body, and if the enclosing full expression that contains the name of that variable is instantiation-dependent - then an enclosing lambda that is capture-ready (i.e. within a non-dependent context) must capture that variable, if all intervening nested lambdas can potentially capture that variable if they need to, and all intervening parent lambdas of the capture-ready lambda can and do capture the variable.
Of note, 'this' capturing is also currently underspecified in the working paper for generic lambdas. What is implemented here is if the set of candidate functions in a nested generic lambda includes both static and non-static member functions (regardless of viability checking - i.e. num and type of parameters/arguments) - and if all intervening nested-inner lambdas between the capture-ready lambda and the function-call containing nested lambda can capture 'this' and if all enclosing lambdas of the capture-ready lambda can capture 'this', then 'this' is speculatively captured by that capture-ready lambda.
Hopefully a paper for the C++ committee (that Richard and I had started some preliminary work on) is forthcoming.
This essentially makes generic lambdas feature complete, except for known bugs. The more prominent ones (and the ones I am currently aware of) being:
- generic lambdas and init-captures are broken - but a patch that fixes this is already in the works ...
- nested variadic expansions such as:
auto K = [](auto ... OuterArgs) {
vp([=](auto ... Is) {
decltype(OuterArgs) OA = OuterArgs;
return 0;
}(5)...);
return 0;
};
auto M = K('a', ' ', 1, " -- ", 3.14);
currently cause crashes. I think I know how to fix this (since I had done so in my initial implementation) - but it will probably take some work and back & forth with Doug and Richard.
A warm thanks to all who provided feedback - and especially to Doug Gregor and Richard Smith for their pivotal guidance: their insight and prestidigitation in such matters is boundless!
Now let's hope this commit doesn't upset the buildbot gods ;)
Thanks!
llvm-svn: 194188
2013-11-07 13:17:06 +08:00
|
|
|
namespace test_conversion_to_fptr_2 {
|
|
|
|
|
|
|
|
template<class T> struct X {
|
|
|
|
|
|
|
|
T (*fp)(T) = [](auto a) { return a; };
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
X<int> xi;
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
void fooT(T t, T (*fp)(T) = [](auto a) { return a; }) {
|
|
|
|
fp(t);
|
|
|
|
}
|
|
|
|
|
|
|
|
int test() {
|
|
|
|
{
|
|
|
|
auto L = [](auto a) { return a; };
|
|
|
|
int (*fp)(int) = L;
|
|
|
|
fp(5);
|
|
|
|
L(3);
|
|
|
|
char (*fc)(char) = L;
|
|
|
|
fc('b');
|
|
|
|
L('c');
|
|
|
|
double (*fd)(double) = L;
|
|
|
|
fd(3.14);
|
|
|
|
fd(6.26);
|
|
|
|
L(4.25);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
auto L = [](auto a) ->int { return a; }; //expected-note 2{{candidate template ignored}}
|
|
|
|
int (*fp)(int) = L;
|
|
|
|
char (*fc)(char) = L; //expected-error{{no viable conversion}}
|
|
|
|
double (*fd)(double) = L; //expected-error{{no viable conversion}}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
int x = 5;
|
|
|
|
auto L = [=](auto b, char c = 'x') {
|
|
|
|
int i = x;
|
|
|
|
return [](auto a) ->decltype(a) { return a; };
|
|
|
|
};
|
|
|
|
int (*fp)(int) = L(8);
|
|
|
|
fp(5);
|
|
|
|
L(3);
|
|
|
|
char (*fc)(char) = L('a');
|
|
|
|
fc('b');
|
|
|
|
L('c');
|
|
|
|
double (*fd)(double) = L(3.14);
|
|
|
|
fd(3.14);
|
|
|
|
fd(6.26);
|
|
|
|
|
|
|
|
}
|
|
|
|
{
|
|
|
|
auto L = [=](auto b) {
|
|
|
|
return [](auto a) ->decltype(b)* { return (decltype(b)*)0; };
|
|
|
|
};
|
|
|
|
int* (*fp)(int) = L(8);
|
|
|
|
fp(5);
|
|
|
|
L(3);
|
|
|
|
char* (*fc)(char) = L('a');
|
|
|
|
fc('b');
|
|
|
|
L('c');
|
|
|
|
double* (*fd)(double) = L(3.14);
|
|
|
|
fd(3.14);
|
|
|
|
fd(6.26);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
auto L = [=](auto b) {
|
|
|
|
return [](auto a) ->decltype(b)* { return (decltype(b)*)0; }; //expected-note{{candidate template ignored}}
|
|
|
|
};
|
|
|
|
char* (*fp)(int) = L('8');
|
|
|
|
fp(5);
|
|
|
|
char* (*fc)(char) = L('a');
|
|
|
|
fc('b');
|
|
|
|
double* (*fi)(int) = L(3.14);
|
|
|
|
fi(5);
|
|
|
|
int* (*fi2)(int) = L(3.14); //expected-error{{no viable conversion}}
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
auto L = [=](auto b) {
|
|
|
|
return [](auto a) {
|
|
|
|
return [=](auto c) {
|
|
|
|
return [](auto d) ->decltype(a + b + c + d) { return d; };
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
int (*fp)(int) = L('8')(3)(short{});
|
|
|
|
double (*fs)(char) = L(3.14)(short{})('4');
|
|
|
|
}
|
|
|
|
|
|
|
|
fooT(3);
|
|
|
|
fooT('a');
|
|
|
|
fooT(3.14);
|
|
|
|
fooT("abcdefg");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
int run2 = test();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-09-29 16:45:24 +08:00
|
|
|
namespace test_conversion_to_fptr {
|
|
|
|
|
|
|
|
void f1(int (*)(int)) { }
|
|
|
|
void f2(char (*)(int)) { } // expected-note{{candidate}}
|
|
|
|
void g(int (*)(int)) { } // #1 expected-note{{candidate}}
|
|
|
|
void g(char (*)(char)) { } // #2 expected-note{{candidate}}
|
|
|
|
void h(int (*)(int)) { } // #3
|
|
|
|
void h(char (*)(int)) { } // #4
|
|
|
|
|
|
|
|
int test() {
|
|
|
|
{
|
|
|
|
auto glambda = [](auto a) { return a; };
|
|
|
|
glambda(1);
|
|
|
|
f1(glambda); // OK
|
|
|
|
f2(glambda); // expected-error{{no matching function}}
|
|
|
|
g(glambda); // expected-error{{call to 'g' is ambiguous}}
|
|
|
|
h(glambda); // OK: calls #3 since it is convertible from ID
|
|
|
|
|
|
|
|
int& (*fpi)(int*) = [](auto* a) -> auto& { return *a; }; // OK
|
|
|
|
|
|
|
|
}
|
|
|
|
{
|
|
|
|
|
|
|
|
auto L = [](auto a) { return a; };
|
|
|
|
int (*fp)(int) = L;
|
|
|
|
fp(5);
|
|
|
|
L(3);
|
|
|
|
char (*fc)(char) = L;
|
|
|
|
fc('b');
|
|
|
|
L('c');
|
|
|
|
double (*fd)(double) = L;
|
|
|
|
fd(3.14);
|
|
|
|
fd(6.26);
|
|
|
|
L(4.25);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
auto L = [](auto a) ->int { return a; }; //expected-note 2{{candidate template ignored}}
|
|
|
|
int (*fp)(int) = L;
|
|
|
|
char (*fc)(char) = L; //expected-error{{no viable conversion}}
|
|
|
|
double (*fd)(double) = L; //expected-error{{no viable conversion}}
|
|
|
|
}
|
2013-10-25 07:40:02 +08:00
|
|
|
{
|
|
|
|
int* (*fp)(int*) = [](auto *a) -> auto* { return a; };
|
|
|
|
fp(0);
|
|
|
|
}
|
2013-09-29 16:45:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
namespace more_converion_to_ptr_to_function_tests {
|
|
|
|
|
|
|
|
|
|
|
|
int test() {
|
|
|
|
{
|
|
|
|
int& (*fpi)(int*) = [](auto* a) -> auto& { return *a; }; // OK
|
|
|
|
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}}\
|
2020-01-22 08:03:05 +08:00
|
|
|
//expected-note{{candidate function [with d:auto = int]}}
|
2013-09-29 16:45:24 +08:00
|
|
|
char (*fp5)(char) = [](auto e) -> int { return e; }; //expected-error{{no viable conversion}}\
|
|
|
|
//expected-note{{candidate template ignored}}
|
|
|
|
|
|
|
|
fp2(3);
|
|
|
|
fp3('\n');
|
|
|
|
fp3('a');
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
} // end test()
|
|
|
|
|
|
|
|
template<class ... Ts> void vfun(Ts ... ) { }
|
|
|
|
|
|
|
|
int variadic_test() {
|
|
|
|
|
|
|
|
int (*fp)(int, char, double) = [](auto ... a) -> int { vfun(a...); return 4; };
|
|
|
|
fp(3, '4', 3.14);
|
|
|
|
|
|
|
|
int (*fp2)(int, char, double) = [](auto ... a) { vfun(a...); return 4; };
|
|
|
|
fp(3, '4', 3.14);
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // end ns
|
|
|
|
|
|
|
|
namespace conversion_operator {
|
2018-01-03 07:52:42 +08:00
|
|
|
void test() {
|
|
|
|
auto L = [](auto a) -> int { return a; }; // expected-error {{cannot initialize}}
|
2013-09-29 16:45:24 +08:00
|
|
|
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}}
|
2018-01-03 07:52:42 +08:00
|
|
|
|
|
|
|
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)'}}
|
2013-09-29 16:45:24 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace return_type_deduction_ok {
|
|
|
|
auto l = [](auto a) ->auto { return a; }(2);
|
|
|
|
auto l2 = [](auto a) ->decltype(auto) { return a; }(2);
|
|
|
|
auto l3 = [](auto a) { return a; }(2);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace generic_lambda_as_default_argument_ok {
|
|
|
|
void test(int i = [](auto a)->int { return a; }(3)) {
|
|
|
|
}
|
|
|
|
}
|
2013-10-23 14:44:28 +08:00
|
|
|
|
|
|
|
namespace nested_non_capturing_lambda_tests {
|
|
|
|
template<class ... Ts> void print(Ts ...) { }
|
|
|
|
int test() {
|
|
|
|
{
|
|
|
|
auto L = [](auto a) {
|
|
|
|
return [](auto b) {
|
|
|
|
return b;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
auto M = L(3);
|
|
|
|
M(4.15);
|
|
|
|
}
|
|
|
|
{
|
This patch implements capturing of variables within generic lambdas.
Both Richard and I felt that the current wording in the working paper needed some tweaking - Please see http://llvm-reviews.chandlerc.com/D2035 for additional context and references to core-reflector messages that discuss wording tweaks.
What is implemented is what we had intended to specify in Bristol; but, recently felt that the specification might benefit from some tweaking and fleshing.
As a rough attempt to explain the semantics: If a nested lambda with a default-capture names a variable within its body, and if the enclosing full expression that contains the name of that variable is instantiation-dependent - then an enclosing lambda that is capture-ready (i.e. within a non-dependent context) must capture that variable, if all intervening nested lambdas can potentially capture that variable if they need to, and all intervening parent lambdas of the capture-ready lambda can and do capture the variable.
Of note, 'this' capturing is also currently underspecified in the working paper for generic lambdas. What is implemented here is if the set of candidate functions in a nested generic lambda includes both static and non-static member functions (regardless of viability checking - i.e. num and type of parameters/arguments) - and if all intervening nested-inner lambdas between the capture-ready lambda and the function-call containing nested lambda can capture 'this' and if all enclosing lambdas of the capture-ready lambda can capture 'this', then 'this' is speculatively captured by that capture-ready lambda.
Hopefully a paper for the C++ committee (that Richard and I had started some preliminary work on) is forthcoming.
This essentially makes generic lambdas feature complete, except for known bugs. The more prominent ones (and the ones I am currently aware of) being:
- generic lambdas and init-captures are broken - but a patch that fixes this is already in the works ...
- nested variadic expansions such as:
auto K = [](auto ... OuterArgs) {
vp([=](auto ... Is) {
decltype(OuterArgs) OA = OuterArgs;
return 0;
}(5)...);
return 0;
};
auto M = K('a', ' ', 1, " -- ", 3.14);
currently cause crashes. I think I know how to fix this (since I had done so in my initial implementation) - but it will probably take some work and back & forth with Doug and Richard.
A warm thanks to all who provided feedback - and especially to Doug Gregor and Richard Smith for their pivotal guidance: their insight and prestidigitation in such matters is boundless!
Now let's hope this commit doesn't upset the buildbot gods ;)
Thanks!
llvm-svn: 194188
2013-11-07 13:17:06 +08:00
|
|
|
int i = 10; //expected-note 3{{declared here}}
|
2013-10-23 14:44:28 +08:00
|
|
|
auto L = [](auto a) {
|
2021-03-11 21:46:24 +08:00
|
|
|
return [](auto b) { //expected-note 3{{begins here}} expected-note 6 {{capture 'i' by}} expected-note 6 {{default capture by}}
|
This patch implements capturing of variables within generic lambdas.
Both Richard and I felt that the current wording in the working paper needed some tweaking - Please see http://llvm-reviews.chandlerc.com/D2035 for additional context and references to core-reflector messages that discuss wording tweaks.
What is implemented is what we had intended to specify in Bristol; but, recently felt that the specification might benefit from some tweaking and fleshing.
As a rough attempt to explain the semantics: If a nested lambda with a default-capture names a variable within its body, and if the enclosing full expression that contains the name of that variable is instantiation-dependent - then an enclosing lambda that is capture-ready (i.e. within a non-dependent context) must capture that variable, if all intervening nested lambdas can potentially capture that variable if they need to, and all intervening parent lambdas of the capture-ready lambda can and do capture the variable.
Of note, 'this' capturing is also currently underspecified in the working paper for generic lambdas. What is implemented here is if the set of candidate functions in a nested generic lambda includes both static and non-static member functions (regardless of viability checking - i.e. num and type of parameters/arguments) - and if all intervening nested-inner lambdas between the capture-ready lambda and the function-call containing nested lambda can capture 'this' and if all enclosing lambdas of the capture-ready lambda can capture 'this', then 'this' is speculatively captured by that capture-ready lambda.
Hopefully a paper for the C++ committee (that Richard and I had started some preliminary work on) is forthcoming.
This essentially makes generic lambdas feature complete, except for known bugs. The more prominent ones (and the ones I am currently aware of) being:
- generic lambdas and init-captures are broken - but a patch that fixes this is already in the works ...
- nested variadic expansions such as:
auto K = [](auto ... OuterArgs) {
vp([=](auto ... Is) {
decltype(OuterArgs) OA = OuterArgs;
return 0;
}(5)...);
return 0;
};
auto M = K('a', ' ', 1, " -- ", 3.14);
currently cause crashes. I think I know how to fix this (since I had done so in my initial implementation) - but it will probably take some work and back & forth with Doug and Richard.
A warm thanks to all who provided feedback - and especially to Doug Gregor and Richard Smith for their pivotal guidance: their insight and prestidigitation in such matters is boundless!
Now let's hope this commit doesn't upset the buildbot gods ;)
Thanks!
llvm-svn: 194188
2013-11-07 13:17:06 +08:00
|
|
|
i = b; //expected-error 3{{cannot be implicitly captured}}
|
2013-10-23 14:44:28 +08:00
|
|
|
return b;
|
|
|
|
};
|
|
|
|
};
|
This patch implements capturing of variables within generic lambdas.
Both Richard and I felt that the current wording in the working paper needed some tweaking - Please see http://llvm-reviews.chandlerc.com/D2035 for additional context and references to core-reflector messages that discuss wording tweaks.
What is implemented is what we had intended to specify in Bristol; but, recently felt that the specification might benefit from some tweaking and fleshing.
As a rough attempt to explain the semantics: If a nested lambda with a default-capture names a variable within its body, and if the enclosing full expression that contains the name of that variable is instantiation-dependent - then an enclosing lambda that is capture-ready (i.e. within a non-dependent context) must capture that variable, if all intervening nested lambdas can potentially capture that variable if they need to, and all intervening parent lambdas of the capture-ready lambda can and do capture the variable.
Of note, 'this' capturing is also currently underspecified in the working paper for generic lambdas. What is implemented here is if the set of candidate functions in a nested generic lambda includes both static and non-static member functions (regardless of viability checking - i.e. num and type of parameters/arguments) - and if all intervening nested-inner lambdas between the capture-ready lambda and the function-call containing nested lambda can capture 'this' and if all enclosing lambdas of the capture-ready lambda can capture 'this', then 'this' is speculatively captured by that capture-ready lambda.
Hopefully a paper for the C++ committee (that Richard and I had started some preliminary work on) is forthcoming.
This essentially makes generic lambdas feature complete, except for known bugs. The more prominent ones (and the ones I am currently aware of) being:
- generic lambdas and init-captures are broken - but a patch that fixes this is already in the works ...
- nested variadic expansions such as:
auto K = [](auto ... OuterArgs) {
vp([=](auto ... Is) {
decltype(OuterArgs) OA = OuterArgs;
return 0;
}(5)...);
return 0;
};
auto M = K('a', ' ', 1, " -- ", 3.14);
currently cause crashes. I think I know how to fix this (since I had done so in my initial implementation) - but it will probably take some work and back & forth with Doug and Richard.
A warm thanks to all who provided feedback - and especially to Doug Gregor and Richard Smith for their pivotal guidance: their insight and prestidigitation in such matters is boundless!
Now let's hope this commit doesn't upset the buildbot gods ;)
Thanks!
llvm-svn: 194188
2013-11-07 13:17:06 +08:00
|
|
|
auto M = L(3); //expected-note{{instantiation}}
|
2013-10-23 14:44:28 +08:00
|
|
|
M(4.15); //expected-note{{instantiation}}
|
|
|
|
}
|
This patch implements capturing of variables within generic lambdas.
Both Richard and I felt that the current wording in the working paper needed some tweaking - Please see http://llvm-reviews.chandlerc.com/D2035 for additional context and references to core-reflector messages that discuss wording tweaks.
What is implemented is what we had intended to specify in Bristol; but, recently felt that the specification might benefit from some tweaking and fleshing.
As a rough attempt to explain the semantics: If a nested lambda with a default-capture names a variable within its body, and if the enclosing full expression that contains the name of that variable is instantiation-dependent - then an enclosing lambda that is capture-ready (i.e. within a non-dependent context) must capture that variable, if all intervening nested lambdas can potentially capture that variable if they need to, and all intervening parent lambdas of the capture-ready lambda can and do capture the variable.
Of note, 'this' capturing is also currently underspecified in the working paper for generic lambdas. What is implemented here is if the set of candidate functions in a nested generic lambda includes both static and non-static member functions (regardless of viability checking - i.e. num and type of parameters/arguments) - and if all intervening nested-inner lambdas between the capture-ready lambda and the function-call containing nested lambda can capture 'this' and if all enclosing lambdas of the capture-ready lambda can capture 'this', then 'this' is speculatively captured by that capture-ready lambda.
Hopefully a paper for the C++ committee (that Richard and I had started some preliminary work on) is forthcoming.
This essentially makes generic lambdas feature complete, except for known bugs. The more prominent ones (and the ones I am currently aware of) being:
- generic lambdas and init-captures are broken - but a patch that fixes this is already in the works ...
- nested variadic expansions such as:
auto K = [](auto ... OuterArgs) {
vp([=](auto ... Is) {
decltype(OuterArgs) OA = OuterArgs;
return 0;
}(5)...);
return 0;
};
auto M = K('a', ' ', 1, " -- ", 3.14);
currently cause crashes. I think I know how to fix this (since I had done so in my initial implementation) - but it will probably take some work and back & forth with Doug and Richard.
A warm thanks to all who provided feedback - and especially to Doug Gregor and Richard Smith for their pivotal guidance: their insight and prestidigitation in such matters is boundless!
Now let's hope this commit doesn't upset the buildbot gods ;)
Thanks!
llvm-svn: 194188
2013-11-07 13:17:06 +08:00
|
|
|
{
|
|
|
|
int i = 10;
|
|
|
|
auto L = [](auto a) {
|
|
|
|
return [](auto b) {
|
|
|
|
b = sizeof(i); //ok
|
|
|
|
return b;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
}
|
2013-10-23 14:44:28 +08:00
|
|
|
{
|
|
|
|
auto L = [](auto a) {
|
|
|
|
print("a = ", a, "\n");
|
|
|
|
return [](auto b) ->decltype(a) {
|
|
|
|
print("b = ", b, "\n");
|
|
|
|
return b;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
auto M = L(3);
|
|
|
|
M(4.15);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
auto L = [](auto a) ->decltype(a) {
|
|
|
|
print("a = ", a, "\n");
|
|
|
|
return [](auto b) ->decltype(a) { //expected-error{{no viable conversion}}\
|
|
|
|
//expected-note{{candidate template ignored}}
|
|
|
|
print("b = ", b, "\n");
|
|
|
|
return b;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
auto M = L(3); //expected-note{{in instantiation of}}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
auto L = [](auto a) {
|
|
|
|
print("a = ", a, "\n");
|
|
|
|
return [](auto ... b) ->decltype(a) {
|
|
|
|
print("b = ", b ..., "\n");
|
|
|
|
return 4;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
auto M = L(3);
|
|
|
|
M(4.15, 3, "fv");
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
auto L = [](auto a) {
|
|
|
|
print("a = ", a, "\n");
|
|
|
|
return [](auto ... b) ->decltype(a) {
|
|
|
|
print("b = ", b ..., "\n");
|
|
|
|
return 4;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
auto M = L(3);
|
|
|
|
int (*fp)(double, int, const char*) = M;
|
|
|
|
fp(4.15, 3, "fv");
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
auto L = [](auto a) {
|
|
|
|
print("a = ", a, "\n");
|
|
|
|
return [](char b) {
|
|
|
|
return [](auto ... c) ->decltype(b) {
|
|
|
|
print("c = ", c ..., "\n");
|
|
|
|
return 42;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
L(4);
|
|
|
|
auto M = L(3);
|
|
|
|
M('a');
|
|
|
|
auto N = M('x');
|
|
|
|
N("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456);
|
|
|
|
char (*np)(const char*, int, const char*, double, const char*, int) = N;
|
|
|
|
np("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
auto L = [](auto a) {
|
|
|
|
print("a = ", a, "\n");
|
|
|
|
return [](decltype(a) b) {
|
|
|
|
return [](auto ... c) ->decltype(b) {
|
|
|
|
print("c = ", c ..., "\n");
|
|
|
|
return 42;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
L('4');
|
|
|
|
auto M = L('3');
|
|
|
|
M('a');
|
|
|
|
auto N = M('x');
|
|
|
|
N("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456);
|
|
|
|
char (*np)(const char*, int, const char*, double, const char*, int) = N;
|
|
|
|
np("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
struct X {
|
|
|
|
static void foo(double d) { }
|
|
|
|
void test() {
|
|
|
|
auto L = [](auto a) {
|
|
|
|
print("a = ", a, "\n");
|
|
|
|
foo(a);
|
|
|
|
return [](decltype(a) b) {
|
|
|
|
foo(b);
|
|
|
|
foo(sizeof(a) + sizeof(b));
|
|
|
|
return [](auto ... c) ->decltype(b) {
|
|
|
|
print("c = ", c ..., "\n");
|
|
|
|
foo(decltype(b){});
|
|
|
|
foo(sizeof(decltype(a)*) + sizeof(decltype(b)*));
|
|
|
|
return 42;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
L('4');
|
|
|
|
auto M = L('3');
|
|
|
|
M('a');
|
|
|
|
auto N = M('x');
|
|
|
|
N("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456);
|
|
|
|
char (*np)(const char*, int, const char*, double, const char*, int) = N;
|
|
|
|
np("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
X x;
|
|
|
|
x.test();
|
|
|
|
}
|
|
|
|
// Make sure we can escape the function
|
|
|
|
{
|
|
|
|
struct X {
|
|
|
|
static void foo(double d) { }
|
|
|
|
auto test() {
|
|
|
|
auto L = [](auto a) {
|
|
|
|
print("a = ", a, "\n");
|
|
|
|
foo(a);
|
|
|
|
return [](decltype(a) b) {
|
|
|
|
foo(b);
|
|
|
|
foo(sizeof(a) + sizeof(b));
|
|
|
|
return [](auto ... c) ->decltype(b) {
|
|
|
|
print("c = ", c ..., "\n");
|
|
|
|
foo(decltype(b){});
|
|
|
|
foo(sizeof(decltype(a)*) + sizeof(decltype(b)*));
|
|
|
|
return 42;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
return L;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
X x;
|
|
|
|
auto L = x.test();
|
|
|
|
L('4');
|
|
|
|
auto M = L('3');
|
|
|
|
M('a');
|
|
|
|
auto N = M('x');
|
|
|
|
N("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456);
|
|
|
|
char (*np)(const char*, int, const char*, double, const char*, int) = N;
|
|
|
|
np("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
struct X {
|
|
|
|
static void foo(double d) { }
|
|
|
|
auto test() {
|
|
|
|
auto L = [](auto a) {
|
|
|
|
print("a = ", a, "\n");
|
|
|
|
foo(a);
|
|
|
|
return [](decltype(a) b) {
|
|
|
|
foo(b);
|
|
|
|
foo(sizeof(a) + sizeof(b));
|
|
|
|
return [](auto ... c) {
|
|
|
|
print("c = ", c ..., "\n");
|
|
|
|
foo(decltype(b){});
|
|
|
|
foo(sizeof(decltype(a)*) + sizeof(decltype(b)*));
|
|
|
|
return [](decltype(c) ... d) ->decltype(a) { //expected-note{{candidate}}
|
|
|
|
print("d = ", d ..., "\n");
|
|
|
|
foo(decltype(b){});
|
|
|
|
foo(sizeof(decltype(a)*) + sizeof(decltype(b)*));
|
|
|
|
return decltype(a){};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
return L;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
X x;
|
|
|
|
auto L = x.test();
|
|
|
|
L('4');
|
|
|
|
auto M = L('3');
|
|
|
|
M('a');
|
|
|
|
auto N = M('x');
|
|
|
|
auto O = N("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456);
|
|
|
|
char (*np)(const char*, int, const char*, double, const char*, int) = O;
|
|
|
|
np("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456);
|
|
|
|
int (*np2)(const char*, int, const char*, double, const char*, int) = O; // expected-error{{no viable conversion}}
|
|
|
|
|
|
|
|
}
|
|
|
|
} // end test()
|
|
|
|
|
|
|
|
namespace wrapped_within_templates {
|
|
|
|
|
|
|
|
namespace explicit_return {
|
|
|
|
template<class T> int fooT(T t) {
|
|
|
|
auto L = [](auto a) -> void {
|
|
|
|
auto M = [](char b) -> void {
|
|
|
|
auto N = [](auto c) -> void {
|
|
|
|
int x = 0;
|
|
|
|
x = sizeof(a);
|
|
|
|
x = sizeof(b);
|
|
|
|
x = sizeof(c);
|
|
|
|
};
|
|
|
|
N('a');
|
|
|
|
N(decltype(a){});
|
|
|
|
};
|
|
|
|
};
|
|
|
|
L(t);
|
|
|
|
L(3.14);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int run = fooT('a') + fooT(3.14);
|
|
|
|
|
|
|
|
} // end explicit_return
|
|
|
|
|
|
|
|
namespace implicit_return_deduction {
|
|
|
|
template<class T> auto fooT(T t) {
|
|
|
|
auto L = [](auto a) {
|
|
|
|
auto M = [](char b) {
|
|
|
|
auto N = [](auto c) {
|
|
|
|
int x = 0;
|
|
|
|
x = sizeof(a);
|
|
|
|
x = sizeof(b);
|
|
|
|
x = sizeof(c);
|
|
|
|
};
|
|
|
|
N('a');
|
|
|
|
N(decltype(a){});
|
|
|
|
};
|
|
|
|
};
|
|
|
|
L(t);
|
|
|
|
L(3.14);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int run = fooT('a') + fooT(3.14);
|
|
|
|
|
|
|
|
template<class ... Ts> void print(Ts ... ts) { }
|
|
|
|
|
|
|
|
template<class ... Ts> auto fooV(Ts ... ts) {
|
|
|
|
auto L = [](auto ... a) {
|
|
|
|
auto M = [](decltype(a) ... b) {
|
|
|
|
auto N = [](auto c) {
|
|
|
|
int x = 0;
|
|
|
|
x = sizeof...(a);
|
|
|
|
x = sizeof...(b);
|
|
|
|
x = sizeof(c);
|
|
|
|
};
|
|
|
|
N('a');
|
|
|
|
N(N);
|
|
|
|
N(first<Ts...>{});
|
|
|
|
};
|
|
|
|
M(a...);
|
|
|
|
print("a = ", a..., "\n");
|
|
|
|
};
|
|
|
|
L(L, ts...);
|
|
|
|
print("ts = ", ts..., "\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int run2 = fooV(3.14, " ", '4', 5) + fooV("BC", 3, 2.77, 'A', float{}, short{}, unsigned{});
|
|
|
|
|
|
|
|
} //implicit_return_deduction
|
|
|
|
|
|
|
|
|
|
|
|
} //wrapped_within_templates
|
|
|
|
|
|
|
|
namespace at_ns_scope {
|
|
|
|
void foo(double d) { }
|
|
|
|
auto test() {
|
|
|
|
auto L = [](auto a) {
|
|
|
|
print("a = ", a, "\n");
|
|
|
|
foo(a);
|
|
|
|
return [](decltype(a) b) {
|
|
|
|
foo(b);
|
|
|
|
foo(sizeof(a) + sizeof(b));
|
|
|
|
return [](auto ... c) {
|
|
|
|
print("c = ", c ..., "\n");
|
|
|
|
foo(decltype(b){});
|
|
|
|
foo(sizeof(decltype(a)*) + sizeof(decltype(b)*));
|
|
|
|
return [](decltype(c) ... d) ->decltype(a) { //expected-note{{candidate}}
|
|
|
|
print("d = ", d ..., "\n");
|
|
|
|
foo(decltype(b){});
|
|
|
|
foo(sizeof(decltype(a)*) + sizeof(decltype(b)*));
|
|
|
|
return decltype(a){};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
return L;
|
|
|
|
}
|
|
|
|
auto L = test();
|
|
|
|
auto L_test = L('4');
|
|
|
|
auto M = L('3');
|
|
|
|
auto M_test = M('a');
|
|
|
|
auto N = M('x');
|
|
|
|
auto O = N("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456);
|
|
|
|
char (*np)(const char*, int, const char*, double, const char*, int) = O;
|
|
|
|
auto NP_result = np("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456);
|
|
|
|
int (*np2)(const char*, int, const char*, double, const char*, int) = O; // expected-error{{no viable conversion}}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace variadic_tests_1 {
|
|
|
|
template<class ... Ts> void print(Ts ... ts) { }
|
|
|
|
|
|
|
|
template<class F, class ... Rest> F& FirstArg(F& f, Rest...) { return f; }
|
|
|
|
|
|
|
|
template<class ... Ts> int fooV(Ts ... ts) {
|
|
|
|
auto L = [](auto ... a) -> void {
|
|
|
|
auto M = [](decltype(a) ... b) -> void {
|
|
|
|
auto N = [](auto c) -> void {
|
|
|
|
int x = 0;
|
|
|
|
x = sizeof...(a);
|
|
|
|
x = sizeof...(b);
|
|
|
|
x = sizeof(c);
|
|
|
|
};
|
|
|
|
N('a');
|
|
|
|
N(N);
|
2014-01-09 10:22:22 +08:00
|
|
|
N(first<Ts...>{});
|
2013-10-23 14:44:28 +08:00
|
|
|
};
|
|
|
|
M(a...);
|
|
|
|
print("a = ", a..., "\n");
|
|
|
|
};
|
|
|
|
L(L, ts...);
|
|
|
|
print("ts = ", ts..., "\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int run2 = fooV(3.14, " ", '4', 5) + fooV("BC", 3, 2.77, 'A', float{}, short{}, unsigned{});
|
|
|
|
|
|
|
|
namespace more_variadic_1 {
|
|
|
|
|
|
|
|
template<class ... Ts> int fooV(Ts ... ts) {
|
|
|
|
auto L = [](auto ... a) {
|
|
|
|
auto M = [](decltype(a) ... b) -> void {
|
|
|
|
auto N = [](auto c) -> void {
|
|
|
|
int x = 0;
|
|
|
|
x = sizeof...(a);
|
|
|
|
x = sizeof...(b);
|
|
|
|
x = sizeof(c);
|
|
|
|
};
|
|
|
|
N('a');
|
|
|
|
N(N);
|
2014-01-09 10:22:22 +08:00
|
|
|
N(first<Ts...>{});
|
2013-10-23 14:44:28 +08:00
|
|
|
};
|
|
|
|
M(a...);
|
|
|
|
return M;
|
|
|
|
};
|
|
|
|
auto M = L(L, ts...);
|
|
|
|
decltype(L(L, ts...)) (*fp)(decltype(L), decltype(ts) ...) = L;
|
|
|
|
void (*fp2)(decltype(L), decltype(ts) ...) = L(L, ts...);
|
|
|
|
|
|
|
|
{
|
|
|
|
auto L = [](auto ... a) {
|
|
|
|
auto M = [](decltype(a) ... b) {
|
|
|
|
auto N = [](auto c) -> void {
|
|
|
|
int x = 0;
|
|
|
|
x = sizeof...(a);
|
|
|
|
x = sizeof...(b);
|
|
|
|
x = sizeof(c);
|
|
|
|
};
|
|
|
|
N('a');
|
|
|
|
N(N);
|
2014-01-09 10:22:22 +08:00
|
|
|
N(first<Ts...>{});
|
2013-10-23 14:44:28 +08:00
|
|
|
return N;
|
|
|
|
};
|
|
|
|
M(a...);
|
|
|
|
return M;
|
|
|
|
};
|
|
|
|
auto M = L(L, ts...);
|
|
|
|
decltype(L(L, ts...)) (*fp)(decltype(L), decltype(ts) ...) = L;
|
|
|
|
fp(L, ts...);
|
|
|
|
decltype(L(L, ts...)(L, ts...)) (*fp2)(decltype(L), decltype(ts) ...) = L(L, ts...);
|
|
|
|
fp2 = fp(L, ts...);
|
|
|
|
void (*fp3)(char) = fp2(L, ts...);
|
|
|
|
fp3('a');
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int run2 = fooV(3.14, " ", '4', 5) + fooV("BC", 3, 2.77, 'A', float{}, short{}, unsigned{});
|
|
|
|
|
|
|
|
|
|
|
|
} //end ns more_variadic_1
|
|
|
|
|
|
|
|
} // end ns variadic_tests_1
|
|
|
|
|
|
|
|
namespace at_ns_scope_within_class_member {
|
|
|
|
struct X {
|
|
|
|
static void foo(double d) { }
|
|
|
|
auto test() {
|
|
|
|
auto L = [](auto a) {
|
|
|
|
print("a = ", a, "\n");
|
|
|
|
foo(a);
|
|
|
|
return [](decltype(a) b) {
|
|
|
|
foo(b);
|
|
|
|
foo(sizeof(a) + sizeof(b));
|
|
|
|
return [](auto ... c) {
|
|
|
|
print("c = ", c ..., "\n");
|
|
|
|
foo(decltype(b){});
|
|
|
|
foo(sizeof(decltype(a)*) + sizeof(decltype(b)*));
|
|
|
|
return [](decltype(c) ... d) ->decltype(a) { //expected-note{{candidate}}
|
|
|
|
print("d = ", d ..., "\n");
|
|
|
|
foo(decltype(b){});
|
|
|
|
foo(sizeof(decltype(a)*) + sizeof(decltype(b)*));
|
|
|
|
return decltype(a){};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
return L;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
X x;
|
|
|
|
auto L = x.test();
|
|
|
|
auto L_test = L('4');
|
|
|
|
auto M = L('3');
|
|
|
|
auto M_test = M('a');
|
|
|
|
auto N = M('x');
|
|
|
|
auto O = N("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456);
|
|
|
|
char (*np)(const char*, int, const char*, double, const char*, int) = O;
|
|
|
|
auto NP_result = np("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456);
|
|
|
|
int (*np2)(const char*, int, const char*, double, const char*, int) = O; // expected-error{{no viable conversion}}
|
2013-11-01 10:01:01 +08:00
|
|
|
|
|
|
|
} //end at_ns_scope_within_class_member
|
|
|
|
|
|
|
|
|
|
|
|
namespace at_ns_scope_within_class_template_member {
|
|
|
|
struct X {
|
|
|
|
static void foo(double d) { }
|
|
|
|
template<class T = int>
|
|
|
|
auto test(T = T{}) {
|
|
|
|
auto L = [](auto a) {
|
|
|
|
print("a = ", a, "\n");
|
|
|
|
foo(a);
|
|
|
|
return [](decltype(a) b) {
|
|
|
|
foo(b);
|
|
|
|
foo(sizeof(a) + sizeof(b));
|
|
|
|
return [](auto ... c) {
|
|
|
|
print("c = ", c ..., "\n");
|
|
|
|
foo(decltype(b){});
|
|
|
|
foo(sizeof(decltype(a)*) + sizeof(decltype(b)*));
|
|
|
|
return [](decltype(c) ... d) ->decltype(a) { //expected-note{{candidate}}
|
|
|
|
print("d = ", d ..., "\n");
|
|
|
|
foo(decltype(b){});
|
|
|
|
foo(sizeof(decltype(a)*) + sizeof(decltype(b)*));
|
|
|
|
return decltype(a){};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
return L;
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
X x;
|
|
|
|
auto L = x.test();
|
|
|
|
auto L_test = L('4');
|
|
|
|
auto M = L('3');
|
|
|
|
auto M_test = M('a');
|
|
|
|
auto N = M('x');
|
|
|
|
auto O = N("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456);
|
|
|
|
char (*np)(const char*, int, const char*, double, const char*, int) = O;
|
|
|
|
auto NP_result = np("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456);
|
|
|
|
int (*np2)(const char*, int, const char*, double, const char*, int) = O; // expected-error{{no viable conversion}}
|
2013-10-23 14:44:28 +08:00
|
|
|
|
|
|
|
} //end at_ns_scope_within_class_member
|
|
|
|
|
|
|
|
|
|
|
|
namespace nested_generic_lambdas_123 {
|
|
|
|
void test() {
|
|
|
|
auto L = [](auto a) -> int {
|
|
|
|
auto M = [](auto b, decltype(a) b2) -> int {
|
|
|
|
return 1;
|
|
|
|
};
|
|
|
|
M(a, a);
|
|
|
|
};
|
|
|
|
L(3);
|
|
|
|
}
|
|
|
|
template<class T> void foo(T) {
|
|
|
|
auto L = [](auto a) { return a; };
|
|
|
|
}
|
|
|
|
template void foo(int);
|
|
|
|
} // end ns nested_generic_lambdas_123
|
|
|
|
|
2013-10-24 09:05:22 +08:00
|
|
|
namespace nested_fptr_235 {
|
|
|
|
int test()
|
|
|
|
{
|
|
|
|
auto L = [](auto b) {
|
|
|
|
return [](auto a) ->decltype(a) { return a; };
|
|
|
|
};
|
|
|
|
int (*fp)(int) = L(8);
|
|
|
|
fp(5);
|
|
|
|
L(3);
|
|
|
|
char (*fc)(char) = L('a');
|
|
|
|
fc('b');
|
|
|
|
L('c');
|
|
|
|
double (*fd)(double) = L(3.14);
|
|
|
|
fd(3.14);
|
|
|
|
fd(6.26);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
int run = test();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
namespace fptr_with_decltype_return_type {
|
|
|
|
template<class F, class ... Rest> F& FirstArg(F& f, Rest& ... r) { return f; };
|
|
|
|
template<class ... Ts> auto vfun(Ts&& ... ts) {
|
|
|
|
print(ts...);
|
|
|
|
return FirstArg(ts...);
|
|
|
|
}
|
|
|
|
int test()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
auto L = [](auto ... As) {
|
|
|
|
return [](auto b) ->decltype(b) {
|
2014-01-09 10:22:22 +08:00
|
|
|
vfun([](decltype(As) a) -> decltype(a) { return a; } ...)(first<decltype(As)...>{});
|
2013-10-24 09:05:22 +08:00
|
|
|
return decltype(b){};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
auto LL = L(1, 'a', 3.14, "abc");
|
|
|
|
LL("dim");
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
int run = test();
|
|
|
|
}
|
2013-10-23 14:44:28 +08:00
|
|
|
|
|
|
|
} // end ns nested_non_capturing_lambda_tests
|
|
|
|
|
|
|
|
namespace PR17476 {
|
|
|
|
struct string {
|
|
|
|
string(const char *__s) { }
|
|
|
|
string &operator+=(const string &__str) { return *this; }
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
void finalizeDefaultAtomValues() {
|
|
|
|
auto startEnd = [](const char * sym) -> void {
|
|
|
|
string start("__");
|
|
|
|
start += sym;
|
|
|
|
};
|
|
|
|
startEnd("preinit_array");
|
|
|
|
}
|
|
|
|
|
|
|
|
void f() { finalizeDefaultAtomValues<char>(); }
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace PR17476_variant {
|
|
|
|
struct string {
|
|
|
|
string(const char *__s) { }
|
|
|
|
string &operator+=(const string &__str) { return *this; }
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
void finalizeDefaultAtomValues() {
|
|
|
|
auto startEnd = [](const T *sym) -> void {
|
|
|
|
string start("__");
|
|
|
|
start += sym;
|
|
|
|
};
|
|
|
|
startEnd("preinit_array");
|
|
|
|
}
|
|
|
|
|
|
|
|
void f() { finalizeDefaultAtomValues<char>(); }
|
|
|
|
|
2013-11-12 11:48:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
namespace PR17877_lambda_declcontext_and_get_cur_lambda_disconnect {
|
|
|
|
|
|
|
|
|
|
|
|
template<class T> struct U {
|
|
|
|
int t = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
struct V {
|
|
|
|
U<T> size() const { return U<T>{}; }
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
void Do() {
|
|
|
|
V<int> v{};
|
|
|
|
[=] { v.size(); };
|
|
|
|
}
|
|
|
|
|
2013-12-05 06:43:08 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
namespace inclass_lambdas_within_nested_classes {
|
|
|
|
namespace ns1 {
|
|
|
|
|
|
|
|
struct X1 {
|
|
|
|
struct X2 {
|
|
|
|
enum { E = [](auto i) { return i; }(3) }; //expected-error{{inside of a constant expression}}\
|
2015-10-08 16:28:09 +08:00
|
|
|
//expected-error{{constant}}\
|
2014-10-08 02:01:33 +08:00
|
|
|
//expected-note{{non-literal type}}
|
2013-12-05 06:43:08 +08:00
|
|
|
int L = ([] (int i) { return i; })(2);
|
|
|
|
void foo(int i = ([] (int i) { return i; })(2)) { }
|
|
|
|
int B : ([](int i) { return i; })(3); //expected-error{{inside of a constant expression}}\
|
2014-10-08 02:01:33 +08:00
|
|
|
//expected-error{{not an integral constant}}\
|
|
|
|
//expected-note{{non-literal type}}
|
2013-12-05 06:43:08 +08:00
|
|
|
int arr[([](int i) { return i; })(3)]; //expected-error{{inside of a constant expression}}\
|
|
|
|
//expected-error{{must have a constant size}}
|
|
|
|
int (*fp)(int) = [](int i) { return i; };
|
|
|
|
void fooptr(int (*fp)(char) = [](char c) { return 0; }) { }
|
|
|
|
int L2 = ([](auto i) { return i; })(2);
|
|
|
|
void fooG(int i = ([] (auto i) { return i; })(2)) { }
|
|
|
|
int BG : ([](auto i) { return i; })(3); //expected-error{{inside of a constant expression}} \
|
2014-10-08 02:01:33 +08:00
|
|
|
//expected-error{{not an integral constant}}\
|
|
|
|
//expected-note{{non-literal type}}
|
2013-12-05 06:43:08 +08:00
|
|
|
int arrG[([](auto i) { return i; })(3)]; //expected-error{{inside of a constant expression}}\
|
2014-10-08 02:01:33 +08:00
|
|
|
//expected-error{{must have a constant size}}
|
2013-12-05 06:43:08 +08:00
|
|
|
int (*fpG)(int) = [](auto i) { return i; };
|
|
|
|
void fooptrG(int (*fp)(char) = [](auto c) { return 0; }) { }
|
|
|
|
};
|
|
|
|
};
|
|
|
|
} //end ns
|
|
|
|
|
|
|
|
namespace ns2 {
|
|
|
|
struct X1 {
|
|
|
|
template<class T>
|
|
|
|
struct X2 {
|
|
|
|
int L = ([] (T i) { return i; })(2);
|
|
|
|
void foo(int i = ([] (int i) { return i; })(2)) { }
|
|
|
|
int B : ([](T i) { return i; })(3); //expected-error{{inside of a constant expression}}\
|
2014-10-08 02:01:33 +08:00
|
|
|
//expected-error{{not an integral constant}}\
|
|
|
|
//expected-note{{non-literal type}}
|
2013-12-05 06:43:08 +08:00
|
|
|
int arr[([](T i) { return i; })(3)]; //expected-error{{inside of a constant expression}}\
|
2014-10-08 02:01:33 +08:00
|
|
|
//expected-error{{must have a constant size}}
|
2013-12-05 06:43:08 +08:00
|
|
|
int (*fp)(T) = [](T i) { return i; };
|
|
|
|
void fooptr(T (*fp)(char) = [](char c) { return 0; }) { }
|
|
|
|
int L2 = ([](auto i) { return i; })(2);
|
|
|
|
void fooG(T i = ([] (auto i) { return i; })(2)) { }
|
2014-10-08 02:01:33 +08:00
|
|
|
int BG : ([](auto i) { return i; })(3); //expected-error{{not an integral constant}}\
|
2015-04-28 05:27:54 +08:00
|
|
|
//expected-note{{non-literal type}}\
|
|
|
|
//expected-error{{inside of a constant expression}}
|
|
|
|
int arrG[([](auto i) { return i; })(3)]; //expected-error{{must have a constant size}} \
|
|
|
|
//expected-error{{inside of a constant expression}}
|
2013-12-05 06:43:08 +08:00
|
|
|
int (*fpG)(T) = [](auto i) { return i; };
|
|
|
|
void fooptrG(T (*fp)(char) = [](auto c) { return 0; }) { }
|
|
|
|
template<class U = char> int fooG2(T (*fp)(U) = [](auto a) { return 0; }) { return 0; }
|
|
|
|
template<class U = char> int fooG3(T (*fp)(U) = [](auto a) { return 0; });
|
|
|
|
};
|
|
|
|
};
|
|
|
|
template<class T>
|
|
|
|
template<class U>
|
|
|
|
int X1::X2<T>::fooG3(T (*fp)(U)) { return 0; }
|
2017-02-23 10:09:03 +08:00
|
|
|
X1::X2<int> x2; //expected-note {{in instantiation of}}
|
2013-12-05 06:43:08 +08:00
|
|
|
int run1 = x2.fooG2();
|
|
|
|
int run2 = x2.fooG3();
|
|
|
|
} // end ns
|
|
|
|
|
|
|
|
|
2013-11-12 11:48:27 +08:00
|
|
|
|
2014-01-09 10:22:22 +08:00
|
|
|
} //end ns inclass_lambdas_within_nested_classes
|
2014-12-04 20:40:21 +08:00
|
|
|
|
|
|
|
namespace pr21684_disambiguate_auto_followed_by_ellipsis_no_id {
|
|
|
|
int a = [](auto ...) { return 0; }();
|
2015-01-09 09:19:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
namespace PR22117 {
|
|
|
|
int x = [](auto) {
|
|
|
|
return [](auto... run_args) {
|
|
|
|
using T = int(decltype(run_args)...);
|
|
|
|
return 0;
|
2019-04-11 04:25:07 +08:00
|
|
|
};
|
|
|
|
}(0)(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace PR41139 {
|
|
|
|
int y = [](auto outer) {
|
|
|
|
return [](auto inner) {
|
|
|
|
using T = int(decltype(outer), decltype(inner));
|
|
|
|
return 0;
|
2015-01-09 09:19:56 +08:00
|
|
|
};
|
|
|
|
}(0)(0);
|
|
|
|
}
|
2015-06-26 08:09:55 +08:00
|
|
|
|
|
|
|
namespace PR23716 {
|
|
|
|
template<typename T>
|
|
|
|
auto f(T x) {
|
|
|
|
auto g = [](auto&&... args) {
|
|
|
|
auto h = [args...]() -> int {
|
|
|
|
return 0;
|
|
|
|
};
|
|
|
|
return h;
|
|
|
|
};
|
|
|
|
return g;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto x = f(0)();
|
|
|
|
}
|
2015-07-14 18:02:10 +08:00
|
|
|
|
|
|
|
namespace PR13987 {
|
|
|
|
class Enclosing {
|
|
|
|
void Method(char c = []()->char {
|
|
|
|
int d = [](auto x)->int {
|
|
|
|
struct LocalClass {
|
|
|
|
int Method() { return 0; }
|
|
|
|
};
|
|
|
|
return 0;
|
|
|
|
}(0);
|
|
|
|
return d; }()
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
class Enclosing2 {
|
|
|
|
void Method(char c = [](auto x)->char {
|
|
|
|
int d = []()->int {
|
|
|
|
struct LocalClass {
|
|
|
|
int Method() { return 0; }
|
|
|
|
};
|
|
|
|
return 0;
|
|
|
|
}();
|
|
|
|
return d; }(0)
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
class Enclosing3 {
|
|
|
|
void Method(char c = [](auto x)->char {
|
|
|
|
int d = [](auto y)->int {
|
|
|
|
struct LocalClass {
|
|
|
|
int Method() { return 0; }
|
|
|
|
};
|
|
|
|
return 0;
|
|
|
|
}(0);
|
|
|
|
return d; }(0)
|
|
|
|
);
|
|
|
|
};
|
|
|
|
}
|
2017-05-09 12:17:15 +08:00
|
|
|
|
|
|
|
namespace PR32638 {
|
|
|
|
//https://bugs.llvm.org/show_bug.cgi?id=32638
|
|
|
|
void test() {
|
|
|
|
[](auto x) noexcept(noexcept(x)) { } (0);
|
|
|
|
}
|
2018-01-03 07:52:42 +08:00
|
|
|
}
|
2020-07-29 06:51:13 +08:00
|
|
|
|
|
|
|
namespace PR46637 {
|
|
|
|
auto x = [](auto (*p)()) { return p(); };
|
|
|
|
auto y = [](auto (*p)() -> auto) { return p(); };
|
|
|
|
int f();
|
|
|
|
void *v = x(f); // expected-error {{cannot initialize a variable of type 'void *' with an rvalue of type 'int'}}
|
|
|
|
void *w = y(f); // expected-error {{cannot initialize a variable of type 'void *' with an rvalue of type 'int'}}
|
|
|
|
}
|