Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/llvm/llvm-project.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSerge Pavlov <sepavloff@gmail.com>2015-07-14 13:02:10 +0300
committerSerge Pavlov <sepavloff@gmail.com>2015-07-14 13:02:10 +0300
commitd9c0bcfd2844035a20806fc3959ef51dc018b879 (patch)
tree9d940fd0453c11e2b3db123a837be928e59e7fbd
parentb2c7c9fce4d576ac6df8a87728597df93901fd25 (diff)
Classes inside lambdas are local not nested.
If a lambda used as default argument in a method declaration contained a local class, that class was incorrectly recognized as nested class. In this case compiler tried to postpone parsing of this class until the enclosing class is finished, which caused crashes in some cases. This change fixes PR13987. Differential Revision: http://reviews.llvm.org/D11006 llvm-svn: 242132
-rw-r--r--clang/lib/Parse/ParseDeclCXX.cpp14
-rw-r--r--clang/test/SemaCXX/cxx1y-generic-lambdas.cpp38
-rw-r--r--clang/test/SemaCXX/lambda-expressions.cpp30
3 files changed, 72 insertions, 10 deletions
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 1d5443d6c96f..e347d4e27e26 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -2815,16 +2815,10 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
break;
}
- if ((S->getFlags() & Scope::FnScope)) {
- // If we're in a function or function template declared in the
- // body of a class, then this is a local class rather than a
- // nested class.
- const Scope *Parent = S->getParent();
- if (Parent->isTemplateParamScope())
- Parent = Parent->getParent();
- if (Parent->isClassScope())
- break;
- }
+ if ((S->getFlags() & Scope::FnScope))
+ // If we're in a function or function template then this is a local
+ // class rather than a nested class.
+ break;
}
}
diff --git a/clang/test/SemaCXX/cxx1y-generic-lambdas.cpp b/clang/test/SemaCXX/cxx1y-generic-lambdas.cpp
index b49a6418ea85..c937c6728c2b 100644
--- a/clang/test/SemaCXX/cxx1y-generic-lambdas.cpp
+++ b/clang/test/SemaCXX/cxx1y-generic-lambdas.cpp
@@ -948,3 +948,41 @@ auto f(T x) {
auto x = f(0)();
}
+
+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)
+ );
+};
+}
diff --git a/clang/test/SemaCXX/lambda-expressions.cpp b/clang/test/SemaCXX/lambda-expressions.cpp
index 7911c1b7cc53..72adcdbce2fe 100644
--- a/clang/test/SemaCXX/lambda-expressions.cpp
+++ b/clang/test/SemaCXX/lambda-expressions.cpp
@@ -446,3 +446,33 @@ namespace PR21857 {
template<typename Fn> fun<Fn> wrap(Fn fn);
auto x = wrap([](){});
}
+
+namespace PR13987 {
+class Enclosing {
+ void Method(char c = []()->char {
+ int d = []()->int {
+ struct LocalClass {
+ int Method() { return 0; }
+ };
+ return 0;
+ }();
+ return d; }()
+ );
+};
+}
+
+namespace PR23860 {
+template <class> struct A {
+ void f(int x = []() {
+ struct B {
+ void g() {}
+ };
+ return 0;
+ }());
+};
+
+int main() {
+}
+
+A<int> a;
+}