summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/lib/Sema/SemaDecl.cpp11
-rw-r--r--clang/test/SemaCXX/cxx1y-generic-lambdas.cpp62
2 files changed, 71 insertions, 2 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index dc8e66dae4c..07d7ceebdb8 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -870,7 +870,16 @@ DeclContext *Sema::getContainingDC(DeclContext *DC) {
// Functions defined inline within classes aren't parsed until we've
// finished parsing the top-level class, so the top-level class is
// the context we'll need to return to.
- if (isa<FunctionDecl>(DC)) {
+ // A Lambda call operator whose parent is a class must not be treated
+ // as an inline member function. A Lambda can be used legally
+ // either as an in-class member initializer or a default argument. These
+ // are parsed once the class has been marked complete and so the containing
+ // context would be the nested class (when the lambda is defined in one);
+ // If the class is not complete, then the lambda is being used in an
+ // ill-formed fashion (such as to specify the width of a bit-field, or
+ // in an array-bound) - in which case we still want to return the
+ // lexically containing DC (which could be a nested class).
+ if (isa<FunctionDecl>(DC) && !isLambdaCallOperator(DC)) {
DC = DC->getLexicalParent();
// A function not defined within a class will always return to its
diff --git a/clang/test/SemaCXX/cxx1y-generic-lambdas.cpp b/clang/test/SemaCXX/cxx1y-generic-lambdas.cpp
index a8518a3a40b..20e06f48a1c 100644
--- a/clang/test/SemaCXX/cxx1y-generic-lambdas.cpp
+++ b/clang/test/SemaCXX/cxx1y-generic-lambdas.cpp
@@ -844,5 +844,65 @@ void Do() {
[=] { v.size(); };
}
+}
+
+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}}\
+ //expected-error{{not an integral constant}}
+ 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}}\
+ //expected-error{{not an integral constant}}
+ 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}} \
+ //expected-error{{not an integral constant}}
+ int arrG[([](auto i) { return i; })(3)]; //expected-error{{inside of a constant expression}}\
+ //expected-error{{must have a constant size}}
+ 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}}\
+ //expected-error{{not an integral constant}}
+ int arr[([](T i) { return i; })(3)]; //expected-error{{inside of a constant expression}}\
+ //expected-error{{must have a constant size}}
+ 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)) { }
+ int BG : ([](auto i) { return i; })(3); //expected-error{{not an integral constant}}
+ int arrG[([](auto i) { return i; })(3)]; //expected-error{{must have a constant size}}
+ 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; }
+X1::X2<int> x2; //expected-note 3{{in instantiation of}}
+int run1 = x2.fooG2();
+int run2 = x2.fooG3();
+} // end ns
+
+
-} \ No newline at end of file
+} //end ns inclass_lambdas_within_nested_classes \ No newline at end of file
OpenPOWER on IntegriCloud