Author: faisalv
Date: Wed Dec  4 16:43:08 2013
New Revision: 196423

URL: http://llvm.org/viewvc/llvm-project?rev=196423&view=rev
Log:
Fix for PR18052 - Lambdas within NSDMI's and default arguments in Nested 
classes.

Clang currently croaks on the following:
  struct X1 {
    struct X2 {
      int L = ([] (int i) { return i; })(2);
    };
  };

asserting that the containing lexical context of the lambda is not Sema's cur 
context, when pushing the lambda's decl context on.

This occurs because (prior to this patch) getContainingDC always returns the 
non-nested class for functions at class scope (even for inline member functions 
of nested classes (to account for delayed parsing of their bodies)).  The patch 
addresses this by having getContainingDC always return the lexical DC for a 
lambda's call operator.

Link to the bug: http://llvm.org/bugs/show_bug.cgi?id=18052
Link to Richard Smith's feedback on phabricator: 
http://llvm-reviews.chandlerc.com/D2331

Thanks!

Modified:
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/test/SemaCXX/cxx1y-generic-lambdas.cpp

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=196423&r1=196422&r2=196423&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Dec  4 16:43:08 2013
@@ -870,7 +870,16 @@ DeclContext *Sema::getContainingDC(DeclC
   // 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

Modified: cfe/trunk/test/SemaCXX/cxx1y-generic-lambdas.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx1y-generic-lambdas.cpp?rev=196423&r1=196422&r2=196423&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx1y-generic-lambdas.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx1y-generic-lambdas.cpp Wed Dec  4 16:43:08 2013
@@ -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


_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to