From d9c0bcfd2844035a20806fc3959ef51dc018b879 Mon Sep 17 00:00:00 2001 From: Serge Pavlov Date: Tue, 14 Jul 2015 10:02:10 +0000 Subject: [PATCH] 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 --- clang/lib/Parse/ParseDeclCXX.cpp | 14 +++------- clang/test/SemaCXX/cxx1y-generic-lambdas.cpp | 38 ++++++++++++++++++++++++++++ clang/test/SemaCXX/lambda-expressions.cpp | 30 ++++++++++++++++++++++ 3 files changed, 72 insertions(+), 10 deletions(-) diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 1d5443d..e347d4e 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 b49a641..c937c67 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 7911c1b..72adcdb 100644 --- a/clang/test/SemaCXX/lambda-expressions.cpp +++ b/clang/test/SemaCXX/lambda-expressions.cpp @@ -446,3 +446,33 @@ namespace PR21857 { template fun 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 struct A { + void f(int x = []() { + struct B { + void g() {} + }; + return 0; + }()); +}; + +int main() { +} + +A a; +} -- 2.7.4