Skip to content

Commit d9c0bcf

Browse files
committed
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
1 parent b2c7c9f commit d9c0bcf

File tree

3 files changed

+72
-10
lines changed

3 files changed

+72
-10
lines changed

clang/lib/Parse/ParseDeclCXX.cpp

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2815,16 +2815,10 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
28152815
break;
28162816
}
28172817

2818-
if ((S->getFlags() & Scope::FnScope)) {
2819-
// If we're in a function or function template declared in the
2820-
// body of a class, then this is a local class rather than a
2821-
// nested class.
2822-
const Scope *Parent = S->getParent();
2823-
if (Parent->isTemplateParamScope())
2824-
Parent = Parent->getParent();
2825-
if (Parent->isClassScope())
2826-
break;
2827-
}
2818+
if ((S->getFlags() & Scope::FnScope))
2819+
// If we're in a function or function template then this is a local
2820+
// class rather than a nested class.
2821+
break;
28282822
}
28292823
}
28302824

clang/test/SemaCXX/cxx1y-generic-lambdas.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -948,3 +948,41 @@ auto f(T x) {
948948

949949
auto x = f(0)();
950950
}
951+
952+
namespace PR13987 {
953+
class Enclosing {
954+
void Method(char c = []()->char {
955+
int d = [](auto x)->int {
956+
struct LocalClass {
957+
int Method() { return 0; }
958+
};
959+
return 0;
960+
}(0);
961+
return d; }()
962+
);
963+
};
964+
965+
class Enclosing2 {
966+
void Method(char c = [](auto x)->char {
967+
int d = []()->int {
968+
struct LocalClass {
969+
int Method() { return 0; }
970+
};
971+
return 0;
972+
}();
973+
return d; }(0)
974+
);
975+
};
976+
977+
class Enclosing3 {
978+
void Method(char c = [](auto x)->char {
979+
int d = [](auto y)->int {
980+
struct LocalClass {
981+
int Method() { return 0; }
982+
};
983+
return 0;
984+
}(0);
985+
return d; }(0)
986+
);
987+
};
988+
}

clang/test/SemaCXX/lambda-expressions.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,3 +446,33 @@ namespace PR21857 {
446446
template<typename Fn> fun<Fn> wrap(Fn fn);
447447
auto x = wrap([](){});
448448
}
449+
450+
namespace PR13987 {
451+
class Enclosing {
452+
void Method(char c = []()->char {
453+
int d = []()->int {
454+
struct LocalClass {
455+
int Method() { return 0; }
456+
};
457+
return 0;
458+
}();
459+
return d; }()
460+
);
461+
};
462+
}
463+
464+
namespace PR23860 {
465+
template <class> struct A {
466+
void f(int x = []() {
467+
struct B {
468+
void g() {}
469+
};
470+
return 0;
471+
}());
472+
};
473+
474+
int main() {
475+
}
476+
477+
A<int> a;
478+
}

0 commit comments

Comments
 (0)