From: Chandler Carruth Date: Sun, 21 Feb 2010 07:08:09 +0000 (+0000) Subject: Make Decl::isOutOfLine() virtual, and use that to determine when definitions X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8761d680eaa7386e03f51286f4b84a1ffe575e2e;p=clang Make Decl::isOutOfLine() virtual, and use that to determine when definitions 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 --- diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 07442896dc..712e8b0b99 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -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()); } diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index 8195fcb253..7fb5f9daae 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -331,7 +331,7 @@ public: return const_cast(this)->getLexicalDeclContext(); } - bool isOutOfLine() const { + virtual bool isOutOfLine() const { return getLexicalDeclContext() != getDeclContext(); } diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 5acb82f31a..23f5fba437 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -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. diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 78bb2ae9b3..3d5f9523d9 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -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(D) && - cast(D)->getTemplatedDecl()->isOutOfLine()) || - (isa(D) && - (cast(D)->isFunctionTemplateSpecialization() || - cast(D)->isOutOfLine())) || - (isa(D) && cast(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(D) || isa(D)) && + D->isOutOfLine()) + return; + + // Template instantiations should also not be pushed into scope. + if (isa(D) && + cast(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 index 0000000000..c4c4ca7e09 --- /dev/null +++ b/test/CXX/class/class.nest/p3.cpp @@ -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; +}