]> granicus.if.org Git - clang/commitdiff
Make Decl::isOutOfLine() virtual, and use that to determine when definitions
authorChandler Carruth <chandlerc@gmail.com>
Sun, 21 Feb 2010 07:08:09 +0000 (07:08 +0000)
committerChandler Carruth <chandlerc@gmail.com>
Sun, 21 Feb 2010 07:08:09 +0000 (07:08 +0000)
are for out of line declarations more easily. This simplifies the logic and
handles the case of out-of-line class definitions correctly. Fixes PR6107.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@96729 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Decl.h
include/clang/AST/DeclBase.h
lib/AST/Decl.cpp
lib/Sema/SemaDecl.cpp
test/CXX/class/class.nest/p3.cpp [new file with mode: 0644]

index 07442896dc4bc466ed7f7dd5dc8a0096553bd707..712e8b0b99cf15b26eae1f925d7f6c93c92df3ad 100644 (file)
@@ -561,7 +561,7 @@ public:
 
   /// \brief Determine whether this is or was instantiated from an out-of-line 
   /// definition of a static data member.
-  bool isOutOfLine() const;
+  virtual bool isOutOfLine() const;
 
   /// \brief If this is a static data member, find its out-of-line definition.
   VarDecl *getOutOfLineDefinition();
@@ -1306,7 +1306,7 @@ public:
                        
   /// \brief Determine whether this is or was instantiated from an out-of-line 
   /// definition of a member function.
-  bool isOutOfLine() const;
+  virtual bool isOutOfLine() const;
                        
   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
index 8195fcb253c07c61760ac6c6f1ed9e737b391128..7fb5f9daae17c93e48829026d043f86fc1ee4bc5 100644 (file)
@@ -331,7 +331,7 @@ public:
     return const_cast<Decl*>(this)->getLexicalDeclContext();
   }
 
-  bool isOutOfLine() const {
+  virtual bool isOutOfLine() const {
     return getLexicalDeclContext() != getDeclContext();
   }
 
index 5acb82f31a29128cb1d3dd27f8ab860dc2e7ea7a..23f5fba437a53f7d80cc5dd0e53cff0cf4b8388b 100644 (file)
@@ -680,12 +680,12 @@ const Expr *VarDecl::getAnyInitializer(const VarDecl *&D) const {
 }
 
 bool VarDecl::isOutOfLine() const {
-  if (!isStaticDataMember())
-    return false;
-  
   if (Decl::isOutOfLine())
     return true;
-  
+
+  if (!isStaticDataMember())
+    return false;
+
   // If this static data member was instantiated from a static data member of
   // a class template, check whether that static data member was defined 
   // out-of-line.
index 78bb2ae9b377c985bad7018a58c68559dbf028fc..3d5f9523d9aa55e45c441a649fca5ff4efb0393a 100644 (file)
@@ -436,14 +436,15 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext) {
   if (AddToContext)
     CurContext->addDecl(D);
 
-  // Out-of-line function and variable definitions should not be pushed into
-  // scope.
-  if ((isa<FunctionTemplateDecl>(D) &&
-       cast<FunctionTemplateDecl>(D)->getTemplatedDecl()->isOutOfLine()) ||
-      (isa<FunctionDecl>(D) &&
-       (cast<FunctionDecl>(D)->isFunctionTemplateSpecialization() ||
-        cast<FunctionDecl>(D)->isOutOfLine())) ||
-      (isa<VarDecl>(D) && cast<VarDecl>(D)->isOutOfLine()))
+  // Out-of-line definitions shouldn't be pushed into scope in C++.
+  // Out-of-line variable and function definitions shouldn't even in C.
+  if ((getLangOptions().CPlusPlus || isa<VarDecl>(D) || isa<FunctionDecl>(D)) &&
+      D->isOutOfLine())
+    return;
+
+  // Template instantiations should also not be pushed into scope.
+  if (isa<FunctionDecl>(D) &&
+      cast<FunctionDecl>(D)->isFunctionTemplateSpecialization())
     return;
 
   // If this replaces anything in the current scope, 
diff --git a/test/CXX/class/class.nest/p3.cpp b/test/CXX/class/class.nest/p3.cpp
new file mode 100644 (file)
index 0000000..c4c4ca7
--- /dev/null
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// C++0x [class.nest] p3:
+//   If class X is defined in a namespace scope, a nested class Y may be
+//   declared in class X and later defined in the definition of class X or be
+//   later defined in a namespace scope enclosing the definition of class X.
+
+namespace example {
+  class E {
+    class I1;
+    class I2;
+    class I1 { };
+  };
+  class E::I2 { };
+}
+
+// Don't insert out-of-line inner class definitions into the namespace scope.
+namespace PR6107 {
+  struct S1 { };
+  struct S2 {
+    struct S1;
+  };
+  struct S2::S1 { };
+  S1 s1;
+}