summaryrefslogtreecommitdiff
path: root/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mangle.C
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mangle.C')
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mangle.C103
1 files changed, 103 insertions, 0 deletions
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mangle.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mangle.C
new file mode 100644
index 000000000..5c9b483d3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mangle.C
@@ -0,0 +1,103 @@
+// Test lambda mangling
+// { dg-require-weak "" }
+// { dg-options "-std=c++0x -fno-inline" }
+
+template<typename F> int algo(F fn) { return fn(); }
+inline void g(int n) {
+ int bef(int i = []{ return 1; }());
+ // Default arguments of block-extern function declarations
+ // remain in the context of the encloding function body.
+ // The closure type is encoded as Z1giEUlvE_.
+ // The call operator of that type is _ZZ1giENKUlvE_clEv.
+
+// { dg-final { scan-assembler "_ZZ1giENKUlvE_clEv" } }
+// { dg-final { scan-assembler "weak\[^\n\r\]*_?_ZZ1giENKUlvE_clEv" { target { ! { *-*-darwin* *-*-mingw* *-*-cygwin } } } } }
+
+ algo([=]{return n+bef();});
+ // The captured entities do not participate in <lambda-sig>
+ // and so this closure type has the same <lambda-sig> as
+ // the previous one. It encoding is therefore Z1giEUlvE0_
+ // and the call operator is _ZZ1giENKUlvE0_clEv. The
+ // instance of "algo" being called is then
+ // _Z4algoIZ1giEUlvE0_EiT_.
+
+// { dg-final { scan-assembler "_Z4algoIZ1giEUlvE0_EiT_" } }
+// { dg-final { scan-assembler "_ZZ1giENKUlvE0_clEv" } }
+
+ int i = []{return 1;}();
+
+}
+
+struct S {
+ void f(int =
+ // Type: ZN1S1fEiiEd0_UlvE_
+ // Operator: _ZZN1S1fEiiEd0_NKUlvE_clEv
+// { dg-final { scan-assembler "_ZZN1S1fEiiEd0_NKUlvE_clEv" } }
+// { dg-final { scan-assembler "weak\[^\n\r\]*_?_ZZN1S1fEiiEd0_NKUlvE_clEv" { target { ! { *-*-darwin* *-*-mingw* *-*-cygwin } } } } }
+ []{return 1;}()
+ // Type: ZN1S1fEiiEd0_UlvE0_
+ // Operator: _ZZN1S1fEiiEd0_NKUlvE0_clEv
+// { dg-final { scan-assembler "_ZZN1S1fEiiEd0_NKUlvE0_clEv" } }
+ + []{return 2;}(),
+ int =
+ // Type: ZN1S1fEiiEd_UlvE_
+ // Operator: _ZZN1S1fEiiEd_NKUlvE_clEv
+// { dg-final { scan-assembler "_ZZN1S1fEiiEd_NKUlvE_clEv" } }
+ []{return 3;}());
+};
+
+template<typename T> struct R {
+ static int x;
+};
+template<typename T> int R<T>::x = []{return 1;}();
+template int R<int>::x;
+// Type of lambda in intializer of R<int>::x: N1RIiE1xMUlvE_E
+// Corresponding operator(): _ZNK1RIiE1xMUlvE_clEv
+// { dg-final { scan-assembler "_ZNK1RIiE1xMUlvE_clEv" } }
+// { dg-final { scan-assembler "weak\[^\n\r\]*_?_ZNK1RIiE1xMUlvE_clEv" { target { ! { *-*-mingw* *-*-cygwin } } } } }
+
+void bar()
+{
+ // lambdas in non-vague linkage functions have internal linkage.
+ // { dg-final { scan-assembler-not "weak\[^\n\r\]*bar\[^\n\r\]*Ul" } }
+ []{}();
+}
+
+// lambdas used in non-template, non-class body initializers are internal.
+// { dg-final { scan-assembler-not "weak\[^\n\r\]*_ZNKUlv" } }
+// { dg-final { scan-assembler-not "weak\[^\n\r\]*variable" } }
+int variable = []{return 1;}();
+
+// And a template instantiated with such a lambda is also internal.
+// { dg-final { scan-assembler-not "weak\[^\n\r\]*algoIUl" } }
+int var2 = algo([]{return 1;});
+
+// As are lambdas used in non-class-body default arguments.
+// { dg-final { scan-assembler-not "weak\[^\n\r\]*function" } }
+void function (int i = []{return 1;}()+[]{return 1;}());
+
+struct Foo
+{
+ static int Int;
+ void Bar(int);
+};
+
+int Foo::Int = []{return 1;}();
+// Even default arguments for member functions that appear outside the
+// class body are internal.
+// { dg-final { scan-assembler-not "weak\[^\n\r\]*Foo" } }
+void Foo::Bar(int i = []{return 1;}()) {}
+
+// Even default arguments for function templates.
+// { dg-final { scan-assembler-not "weak\[^\n\r\]*fn2\[^\n\r\]*Ulv" } }
+template <class T>
+void fn2 (T t = []{return 1;}()) {}
+
+int main()
+{
+ g(42);
+ S().f();
+ function();
+ Foo().Bar();
+ fn2<int>();
+}