[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