[cfe-commits] r93653 - in /cfe/trunk: lib/Parse/ParseDeclCXX.cpp test/SemaTemplate/instantiate-local-class.cpp
Douglas Gregor
dgregor at apple.com
Sat Jan 16 12:53:00 PST 2010
Author: dgregor
Date: Sat Jan 16 14:52:59 2010
New Revision: 93653
URL: http://llvm.org/viewvc/llvm-project?rev=93653&view=rev
Log:
While determining when to parse inline member functions of a class,
distinguish between nested classes (whose member functions cannot be
parsed until the innermost non-nested class is complete) and local
classes (that are defined within a function but are not necessarily
nested). The upshot of this change, which fixes PR5764, is that the
bodies of member functions of local (non-nested) classes need to be
parsed when the local class is complete (and no later), since they may
refer to function-local static variables, typedefs, enums, etc.
Modified:
cfe/trunk/lib/Parse/ParseDeclCXX.cpp
cfe/trunk/test/SemaTemplate/instantiate-local-class.cpp
Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=93653&r1=93652&r2=93653&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Sat Jan 16 14:52:59 2010
@@ -1398,15 +1398,35 @@
PP.getSourceManager(),
"parsing struct/union/class body");
- // Determine whether this is a top-level (non-nested) class.
- bool TopLevelClass = ClassStack.empty() ||
- CurScope->isInCXXInlineMethodScope();
+ // Determine whether this is a non-nested class. Note that local
+ // classes are *not* considered to be nested classes.
+ bool NonNestedClass = true;
+ if (!ClassStack.empty()) {
+ for (const Scope *S = CurScope; S; S = S->getParent()) {
+ if (S->isClassScope()) {
+ // We're inside a class scope, so this is a nested class.
+ NonNestedClass = false;
+ 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;
+ }
+ }
+ }
// Enter a scope for the class.
ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope);
// Note that we are parsing a new (potentially-nested) class definition.
- ParsingClassDefinition ParsingDef(*this, TagDecl, TopLevelClass);
+ ParsingClassDefinition ParsingDef(*this, TagDecl, NonNestedClass);
if (TagDecl)
Actions.ActOnTagStartDefinition(CurScope, TagDecl);
@@ -1484,7 +1504,7 @@
//
// FIXME: Only function bodies and constructor ctor-initializers are
// parsed correctly, fix the rest.
- if (TopLevelClass) {
+ if (NonNestedClass) {
// We are not inside a nested class. This class and its nested classes
// are complete and we can parse the delayed portions of method
// declarations and the lexed inline method definitions.
@@ -1666,10 +1686,10 @@
/// \brief We have just started parsing the definition of a new class,
/// so push that class onto our stack of classes that is currently
/// being parsed.
-void Parser::PushParsingClass(DeclPtrTy ClassDecl, bool TopLevelClass) {
- assert((TopLevelClass || !ClassStack.empty()) &&
+void Parser::PushParsingClass(DeclPtrTy ClassDecl, bool NonNestedClass) {
+ assert((NonNestedClass || !ClassStack.empty()) &&
"Nested class without outer class");
- ClassStack.push(new ParsingClass(ClassDecl, TopLevelClass));
+ ClassStack.push(new ParsingClass(ClassDecl, NonNestedClass));
}
/// \brief Deallocate the given parsed class and all of its nested
Modified: cfe/trunk/test/SemaTemplate/instantiate-local-class.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-local-class.cpp?rev=93653&r1=93652&r2=93653&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-local-class.cpp (original)
+++ cfe/trunk/test/SemaTemplate/instantiate-local-class.cpp Sat Jan 16 14:52:59 2010
@@ -10,3 +10,22 @@
}
template void f0<int>();
+
+// PR5764
+namespace PR5764 {
+ class X {
+ template <typename T>
+ void Bar() {
+ class Y {
+ Y() {}
+ };
+
+ Y y;
+ }
+ };
+
+ void test(X x) {
+ x.Bar<int>();
+ }
+}
+
More information about the cfe-commits
mailing list