[cfe-commits] r61735 - in /cfe/trunk: Driver/ASTConsumers.cpp docs/InternalsManual.html include/clang/AST/DeclBase.h include/clang/AST/DeclCXX.h include/clang/Parse/Action.h lib/AST/DeclBase.cpp lib/AST/DeclCXX.cpp lib/AST/DeclSerialization.cpp lib/Parse/ParseDecl.cpp lib/Parse/ParseDeclCXX.cpp lib/Sema/IdentifierResolver.cpp lib/Sema/IdentifierResolver.h lib/Sema/Sema.h lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp test/SemaCXX/qualified-id-lookup.cpp

Douglas Gregor dgregor at apple.com
Mon Jan 5 11:45:36 PST 2009


Author: dgregor
Date: Mon Jan  5 13:45:36 2009
New Revision: 61735

URL: http://llvm.org/viewvc/llvm-project?rev=61735&view=rev
Log:
Introduce support for "transparent" DeclContexts, which are
DeclContexts whose members are visible from enclosing DeclContexts up
to (and including) the innermost enclosing non-transparent
DeclContexts. Transparent DeclContexts unify the mechanism to be used
for various language features, including C enumerations, anonymous
unions, C++0x inline namespaces, and C++ linkage
specifications. Please refer to the documentation in the Clang
internals manual for more information.

Only enumerations and linkage specifications currently use transparent
DeclContexts.

Still to do: use transparent DeclContexts to implement anonymous
unions and GCC's anonymous structs extension, and, later, the C++0x
features. We also need to tighten up the DeclContext/ScopedDecl link
to ensure that every ScopedDecl is in a single DeclContext, which
will ensure that we can then enforce ownership and reduce the memory
footprint of DeclContext.


Modified:
    cfe/trunk/Driver/ASTConsumers.cpp
    cfe/trunk/docs/InternalsManual.html
    cfe/trunk/include/clang/AST/DeclBase.h
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/include/clang/Parse/Action.h
    cfe/trunk/lib/AST/DeclBase.cpp
    cfe/trunk/lib/AST/DeclCXX.cpp
    cfe/trunk/lib/AST/DeclSerialization.cpp
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Parse/ParseDeclCXX.cpp
    cfe/trunk/lib/Sema/IdentifierResolver.cpp
    cfe/trunk/lib/Sema/IdentifierResolver.h
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/test/SemaCXX/qualified-id-lookup.cpp

Modified: cfe/trunk/Driver/ASTConsumers.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/ASTConsumers.cpp?rev=61735&r1=61734&r2=61735&view=diff

==============================================================================
--- cfe/trunk/Driver/ASTConsumers.cpp (original)
+++ cfe/trunk/Driver/ASTConsumers.cpp Mon Jan  5 13:45:36 2009
@@ -116,14 +116,14 @@
     Out << "};\n";
   } else if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
     Out << "Read top-level tag decl: '" << TD->getNameAsString() << "'\n";
-  } else if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D)) {
-    Out << "Read top-level variable decl: '" << SD->getNameAsString() << "'\n";
   } else if (LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(D)) {
     PrintLinkageSpec(LSD);
   } else if (FileScopeAsmDecl *AD = dyn_cast<FileScopeAsmDecl>(D)) {
     Out << "asm(";
     AD->getAsmString()->printPretty(Out);
     Out << ")\n";
+  } else if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D)) {
+    Out << "Read top-level variable decl: '" << SD->getNameAsString() << "'\n";
   } else {
     assert(0 && "Unknown decl type!");
   }
@@ -197,8 +197,8 @@
   if (LS->hasBraces()) 
     Out << "{\n";
 
-  for (LinkageSpecDecl::decl_const_iterator D = LS->decls_begin(), 
-                                         DEnd = LS->decls_end();
+  for (LinkageSpecDecl::decl_iterator D = LS->decls_begin(), 
+                                   DEnd = LS->decls_end();
        D != DEnd; ++D)
     PrintDecl(*D);
 

Modified: cfe/trunk/docs/InternalsManual.html
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/InternalsManual.html?rev=61735&r1=61734&r2=61735&view=diff

==============================================================================
--- cfe/trunk/docs/InternalsManual.html (original)
+++ cfe/trunk/docs/InternalsManual.html Mon Jan  5 13:45:36 2009
@@ -44,6 +44,15 @@
   <li><a href="#Type">The Type class and its subclasses</a></li>
   <li><a href="#QualType">The QualType class</a></li>
   <li><a href="#DeclarationName">Declaration names</a></li>
+  <li><a href="#DeclContext">Declaration contexts</a>
+    <ul>
+      <li><a href="#Redeclarations">Redeclarations and Overloads</a></li>
+      <li><a href="#LexicalAndSemanticContexts">Lexical and Semantic
+      Contexts</a></li>
+      <li><a href="#TransparentContexts">Transparent Declaration Contexts</a></li>
+      <li><a href="#MultiDeclContext">Multiply-Defined Declaration Contexts</a></li>
+    </ul>
+  </li>
   <li><a href="#CFG">The CFG class</a></li>
   <li><a href="#Constants">Constant Folding in the Clang AST</a></li>
   </ul>
@@ -871,6 +880,298 @@
   C++ special function names.</p>
 
 <!-- ======================================================================= -->
+<h3 id="DeclContext">Declaration contexts</h3>
+<!-- ======================================================================= -->
+<p>Every declaration in a program exists within some <i>declaration
+    context</i>, such as a translation unit, namespace, class, or
+    function. Declaration contexts in Clang are represented by
+    the <code>DeclContext</code> class, from which the various
+  declaration-context AST nodes
+  (<code>TranslationUnitDecl</code>, <code>NamespaceDecl</code>, <code>RecordDecl</code>, <code>FunctionDecl</code>,
+  etc.) will derive. The <code>DeclContext</code> class provides
+  several facilities common to each declaration context:</p>
+<dl>
+  <dt>Source-centric vs. Semantics-centric View of Declarations</dt>
+  <dd><code>DeclContext</code> provides two views of the declarations
+  stored within a declaration context. The source-centric view
+  accurately represents the program source code as written, including
+  multiple declarations of entities where present (see the
+    section <a href="#Redeclarations">Redeclarations and
+  Overloads</a>), while the semantics-centric view represents the
+  program semantics. The two views are kept synchronized by semantic
+  analysis while the ASTs are being constructed.</dd>
+
+  <dt>Storage of declarations within that context</dt>
+  <dd>Every declaration context can contain some number of
+    declarations. For example, a C++ class (represented
+    by <code>RecordDecl</code>) contains various member functions,
+    fields, nested types, and so on. All of these declarations will be
+    stored within the <code>DeclContext</code>, and one can iterate
+    over the declarations via
+    [<code>DeclContext::decls_begin()</code>, 
+    <code>DeclContext::decls_end()</code>). This mechanism provides
+    the source-centric view of declarations in the context.</dd>
+
+  <dt>Lookup of declarations within that context</dt>
+  <dd>The <code>DeclContext</code> structure provides efficient name
+    lookup for names within that declaration context. For example,
+    if <code>N</code> is a namespace we can look for the
+    name <code>N::f</code>
+    using <code>DeclContext::lookup</code>. The lookup itself is
+    based on a lazily-constructed array (for declaration contexts
+    with a small number of declarations) or hash table (for
+    declaration contexts with more declarations). The lookup
+    operation provides the semantics-centric view of the declarations
+    in the context.</dd>
+
+  <dt>Ownership of declarations</dt>
+  <dd>The <code>DeclContext</code> owns all of the declarations that
+  were declared within its declaration context, and is responsible
+  for the management of their memory as well as their
+  (de-)serialization.</dd>
+</dl>
+
+<p>The declarations stored within each declaration context are
+  called <i>scoped declarations</i> and the AST nodes for each of
+  these declarations are 
+  derived from the <code>ScopedDecl</code> class, which provides
+  information about the context in which that declaration lives. One
+  can retrieve the <code>DeclContext</code> that contains a
+  particular <code>ScopedDecl</code>
+  using <code>ScopedDecl::getDeclContext</code>. However, see the
+  section <a href="#LexicalAndSemanticContexts">Lexical and Semantic
+  Contexts</a> for more information about how to interpret this
+  context information.</p>
+
+<h4 id="Redeclarations">Redeclarations and Overloads</h4>
+<p>Within a translation unit, it is common for an entity to be
+declared several times. For example, we might declare a function "f"
+  and then later re-declare it as part of an inlined definition:</p>
+
+<pre>
+void f(int x, int y, int z = 1);
+
+inline void f(int x, int y, int z) { /* ... */ }
+</pre>
+
+<p>The representation of "f" differs in the source-centric and
+  semantics-centric views of a declaration context. In the
+  source-centric view, all redeclarations will be present, in the
+  order they occurred in the source code, making 
+    this view suitable for clients that wish to see the structure of
+    the source code. In the semantics-centric view, only the most recent "f"
+  will be found by the lookup, since it effectively replaces the first
+  declaration of "f".</p>
+
+<p>In the semantics-centric view, overloading of functions is
+  represented explicitly. For example, given two declarations of a
+  function "g" that are overloaded, e.g.,</p>
+<pre>
+void g();
+void g(int);
+</pre>
+<p>the <code>DeclContext::lookup</code> operation will return
+  an <code>OverloadedFunctionDecl</code> that contains both
+  declarations of "g". Clients that perform semantic analysis on a
+  program that is not concerned with the actual source code will
+  primarily use this semantics-centric view.</p>
+
+<h4 id="LexicalAndSemanticContexts">Lexical and Semantic Contexts</h4>
+<p>Each scoped declaration (whose AST node derived
+  from <code>ScopedDecl</code>) has two potentially different
+  declaration contexts: a <i>lexical</i> context, which corresponds to
+  the source-centric view of the declaration context, and
+  a <i>semantic</i> context, which corresponds to the
+  semantics-centric view. The lexical context is accessible
+  via <code>ScopedDecl::getLexicalDeclContext</code> while the
+  semantic context is accessible
+  via <code>ScopedDecl::getDeclContext</code>, both of which return
+  <code>DeclContext</code> pointers. For most declarations, the two
+  contexts are identical. For example:</p>
+
+<pre>
+class X {
+public:
+  void f(int x);
+};
+</pre>
+
+<p>Here, the semantic and lexical contexts of <code>X::f</code> are
+  the <code>DeclContext</code> associated with the
+  class <code>X</code> (itself stored as a <code>RecordDecl</code> AST
+  node). However, we can now define <code>X::f</code> out-of-line:</p>
+
+<pre>
+void X::f(int x = 17) { /* ... */ }
+</pre>
+
+<p>This definition of has different lexical and semantic
+  contexts. The lexical context corresponds to the declaration
+  context in which the actual declaration occurred in the source
+  code, e.g., the translation unit containing <code>X</code>. Thus,
+  this declaration of <code>X::f</code> can be found by traversing
+  the declarations provided by
+  [<code>decls_begin()</code>, <code>decls_end()</code>) in the
+  translation unit.</p>
+
+<p>The semantic context of <code>X::f</code> corresponds to the
+  class <code>X</code>, since this member function is (semantically) a
+  member of <code>X</code>. Lookup of the name <code>f</code> into
+  the <code>DeclContext</code> associated with <code>X</code> will
+  then return the definition of <code>X::f</code> (including
+  information about the default argument).</p>
+
+<h4 id="TransparentContexts">Transparent Declaration Contexts</h4>
+<p>In C and C++, there are several contexts in which names that are
+  logically declared inside another declaration will actually "leak"
+  out into the enclosing scope from the perspective of name
+  lookup. The most obvious instance of this behavior is in
+  enumeration types, e.g.,</p>
+<pre>
+enum Color {
+  Red, 
+  Green,
+  Blue
+};
+</pre>
+
+<p>Here, <code>Color</code> is an enumeration, which is a declaration
+  context that contains the
+  enumerators <code>Red</code>, <code>Green</code>,
+  and <code>Blue</code>. Thus, traversing the list of declarations
+  contained in the enumeration <code>Color</code> will
+  yield <code>Red</code>, <code>Green</code>,
+  and <code>Blue</code>. However, outside of the scope
+  of <code>Color</code> one can name the enumerator <code>Red</code>
+  without qualifying the name, e.g.,</p>
+
+<pre>
+Color c = Red;
+</pre>
+
+<p>There are other entities in C++ that provide similar behavior. For
+  example, linkage specifications that use curly braces:</p>
+
+<pre>
+extern "C" {
+  void f(int);
+  void g(int);
+}
+// f and g are visible here
+</pre>
+
+<p>For source-level accuracy, we treat the linkage specification and
+  enumeration type as a
+  declaration context in which its enclosed declarations ("Red",
+  "Green", and "Blue"; "f" and "g")
+  are declared. However, these declarations are visible outside of the
+  scope of the declaration context.</p>
+
+<p>These language features (and several others, described below) have
+  roughly the same set of 
+  requirements: declarations are declared within a particular lexical
+  context, but the declarations are also found via name lookup in
+  scopes enclosing the declaration itself. This feature is implemented
+  via <i>transparent</i> declaration contexts
+  (see <code>DeclContext::isTransparentContext()</code>), whose
+  declarations are visible in the nearest enclosing non-transparent
+  declaration context. This means that the lexical context of the
+  declaration (e.g., an enumerator) will be the
+  transparent <code>DeclContext</code> itself, as will the semantic
+  context, but the declaration will be visible in every outer context
+  up to and including the first non-transparent declaration context (since
+  transparent declaration contexts can be nested).</p>
+
+<p>The transparent <code>DeclContexts</code> are:</p>
+<ul>
+  <li>Enumerations (but not C++0x "scoped enumerations"):
+    <pre>
+enum Color { 
+  Red, 
+  Green, 
+  Blue 
+};
+// Red, Green, and Blue are in scope
+  </pre></li>
+  <li>C++ linkage specifications:
+  <pre>
+extern "C" {
+  void f(int);
+  void g(int);
+}
+// f and g are in scope
+  </pre></li>
+  <li>Anonymous unions and structs:
+    <pre>
+struct LookupTable {
+  bool IsVector;
+  union {
+    std::vector<Item> *Vector;
+    std::set<Item> *Set;
+  };
+};
+
+LookupTable LT;
+LT.Vector = 0; // Okay: finds Vector inside the unnamed union
+    </pre>
+  </li>
+  <li>C++0x inline namespaces:
+<pre>
+namespace mylib {
+  inline namespace debug {
+    class X;
+  }
+}
+mylib::X *xp; // okay: mylib::X refers to mylib::debug::X
+</pre>
+</li>
+</ul>
+
+
+<h4 id="MultiDeclContext">Multiply-Defined Declaration Contexts</h4>
+<p>C++ namespaces have the interesting--and, so far, unique--property that 
+the namespace can be defined multiple times, and the declarations
+provided by each namespace definition are effectively merged (from
+the semantic point of view). For example, the following two code
+snippets are semantically indistinguishable:</p>
+<pre>
+// Snippet #1:
+namespace N {
+  void f();
+}
+namespace N {
+  void f(int);
+}
+
+// Snippet #2:
+namespace N {
+  void f();
+  void f(int);
+}
+</pre>
+
+<p>In Clang's representation, the source-centric view of declaration
+  contexts will actually have two separate <code>NamespaceDecl</code>
+  nodes in Snippet #1, each of which is a declaration context that
+  contains a single declaration of "f". However, the semantics-centric
+  view provided by name lookup into the namespace <code>N</code> for
+  "f" will return an <code>OverloadedFunctionDecl</code> that contains
+  both declarations of "f".</p>
+
+<p><code>DeclContext</code> manages multiply-defined declaration
+  contexts internally. The
+  function <code>DeclContext::getPrimaryContext</code> retrieves the
+  "primary" context for a given <code>DeclContext</code> instance,
+  which is the <code>DeclContext</code> responsible for maintaining
+  the lookup table used for the semantics-centric view. Given the
+  primary context, one can follow the chain
+  of <code>DeclContext</code> nodes that define additional
+  declarations via <code>DeclContext::getNextContext</code>. Note that
+  these functions are used internally within the lookup and insertion
+  methods of the <code>DeclContext</code>, so the vast majority of
+  clients can ignore them.</p>
+
+<!-- ======================================================================= -->
 <h3 id="CFG">The <tt>CFG</tt> class</h3>
 <!-- ======================================================================= -->
 

Modified: cfe/trunk/include/clang/AST/DeclBase.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclBase.h?rev=61735&r1=61734&r2=61735&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/DeclBase.h (original)
+++ cfe/trunk/include/clang/AST/DeclBase.h Mon Jan  5 13:45:36 2009
@@ -31,6 +31,7 @@
 class EnumDecl;
 class ObjCMethodDecl;
 class ObjCInterfaceDecl;
+class LinkageSpecDecl;
 class BlockDecl;
 class DeclarationName;
 
@@ -80,12 +81,12 @@
                  ParmVar,
                    OriginalParmVar,
   	         NonTypeTemplateParm,
+             LinkageSpec, // [DeclContext]
            ObjCInterface,  // [DeclContext]
            ObjCCompatibleAlias,
            ObjCClass,
            ObjCForwardProtocol,
            ObjCPropertyImpl,
-         LinkageSpec,
          FileScopeAsm,
 	     Block, // [DeclContext]
   
@@ -93,7 +94,7 @@
     // of the class, to allow efficient classof.
     NamedFirst     = OverloadedFunction , NamedLast     = NonTypeTemplateParm,
     FieldFirst     = Field        , FieldLast     = ObjCAtDefsField,
-    ScopedFirst    = Field        , ScopedLast    = NonTypeTemplateParm,
+    ScopedFirst    = Field        , ScopedLast    = LinkageSpec,
     TypeFirst      = Typedef      , TypeLast      = TemplateTypeParm,
     TagFirst       = Enum         , TagLast       = CXXRecord,
     RecordFirst    = Record       , RecordLast    = CXXRecord,
@@ -260,8 +261,8 @@
 ///   EnumDecl
 ///   ObjCMethodDecl
 ///   ObjCInterfaceDecl
+///   LinkageSpecDecl
 ///   BlockDecl
-///
 class DeclContext {
   /// DeclKind - This indicates which class this is.
   Decl::Kind DeclKind   :  8;
@@ -299,8 +300,6 @@
   static To *CastTo(const From *D) {
     Decl::Kind DK = KindTrait<From>::getKind(D);
     switch(DK) {
-      case Decl::Block:
-        return static_cast<BlockDecl*>(const_cast<From*>(D));
       case Decl::TranslationUnit:
         return static_cast<TranslationUnitDecl*>(const_cast<From*>(D));
       case Decl::Namespace:
@@ -315,6 +314,10 @@
         return static_cast<ObjCMethodDecl*>(const_cast<From*>(D));
       case Decl::ObjCInterface:
         return static_cast<ObjCInterfaceDecl*>(const_cast<From*>(D));
+      case Decl::LinkageSpec:
+        return static_cast<LinkageSpecDecl*>(const_cast<From*>(D));
+      case Decl::Block:
+        return static_cast<BlockDecl*>(const_cast<From*>(D));
       default:
         if (DK >= Decl::FunctionFirst && DK <= Decl::FunctionLast)
           return static_cast<FunctionDecl*>(const_cast<From*>(D));
@@ -385,6 +388,24 @@
     return DeclKind == Decl::Namespace;
   }
 
+  /// isTransparentContext - Determines whether this context is a
+  /// "transparent" context, meaning that the members declared in this
+  /// context are semantically declared in the nearest enclosing
+  /// non-transparent (opaque) context but are lexically declared in
+  /// this context. For example, consider the enumerators of an
+  /// enumeration type: 
+  /// @code
+  /// enum E {
+  ///   Val1 
+  /// };
+  /// @endcode
+  /// Here, E is a transparent context, so its enumerator (Val1) will
+  /// appear (semantically) that it is in the same context of E.
+  /// Examples of transparent contexts include: enumerations (except for
+  /// C++0x scoped enums), C++ linkage specifications, and C++0x
+  /// inline namespaces.
+  bool isTransparentContext() const;
+
   bool Encloses(DeclContext *DC) const {
     for (; DC; DC = DC->getParent())
       if (DC == this)
@@ -435,10 +456,7 @@
   /// declaration into data structure for name lookup.
   void addDecl(ASTContext &Context, ScopedDecl *D, bool AllowLookup = true);
 
-  /// reverseDeclChain - Reverse the chain of declarations stored in
-  /// this scope. Typically called once after all declarations have
-  /// been added and the scope is closed.
-  void reverseDeclChain();
+  void buildLookup(ASTContext &Context, DeclContext *DCtx);
 
   /// lookup_iterator - An iterator that provides access to the results
   /// of looking up a name within this context.
@@ -484,6 +502,7 @@
       case Decl::CXXRecord:
       case Decl::ObjCMethod:
       case Decl::ObjCInterface:
+      case Decl::LinkageSpec:
       case Decl::Block:
         return true;
       default:
@@ -502,6 +521,7 @@
   static bool classof(const EnumDecl *D) { return true; }
   static bool classof(const ObjCMethodDecl *D) { return true; }
   static bool classof(const ObjCInterfaceDecl *D) { return true; }
+  static bool classof(const LinkageSpecDecl *D) { return true; }
   static bool classof(const BlockDecl *D) { return true; }
 
 private:

Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=61735&r1=61734&r2=61735&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Mon Jan  5 13:45:36 2009
@@ -882,7 +882,7 @@
 /// LinkageSpecDecl - This represents a linkage specification.  For example:
 ///   extern "C" void foo();
 ///
-class LinkageSpecDecl : public Decl {
+class LinkageSpecDecl : public ScopedDecl, public DeclContext {
 public:
   /// LanguageIDs - Used to represent the language in a linkage
   /// specification.  The values are part of the serialization abi for
@@ -898,43 +898,22 @@
   /// HadBraces - Whether this linkage specification had curly braces or not.
   bool HadBraces : 1;
 
-  /// Decls - The declarations that were parsed as part of this
-  /// linkage specification. If HadBraces is false, this is a
-  /// Decl*. Otherwise, it's a Decl**.
-  void *Decls;
-
-  /// NumDecls - The number of declarations stored in this linkage
-  /// specification. 
-  unsigned NumDecls : 31;
-
-  LinkageSpecDecl(SourceLocation L, LanguageIDs lang, Decl *d)
-    : Decl(LinkageSpec, L), Language(lang), HadBraces(false), 
-      Decls(d), NumDecls(1) {}
-
-  LinkageSpecDecl(SourceLocation L, LanguageIDs lang, 
-                  Decl **InDecls, unsigned InNumDecls);
+  LinkageSpecDecl(DeclContext *DC, SourceLocation L, LanguageIDs lang, 
+                  bool Braces)
+    : ScopedDecl(LinkageSpec, DC, L, DeclarationName(), 0), 
+      DeclContext(LinkageSpec), Language(lang), HadBraces(Braces) { }
 
 public:
-  ~LinkageSpecDecl();
-
-  static LinkageSpecDecl *Create(ASTContext &C, SourceLocation L,
-                                 LanguageIDs Lang, Decl *D);
+  static LinkageSpecDecl *Create(ASTContext &C, DeclContext *DC, 
+                                 SourceLocation L, LanguageIDs Lang, 
+                                 bool Braces);
 
-  static LinkageSpecDecl *Create(ASTContext &C, SourceLocation L,
-                                 LanguageIDs Lang, 
-                                 Decl **Decls, unsigned NumDecls);
-  
   LanguageIDs getLanguage() const { return Language; }
 
   /// hasBraces - Determines whether this linkage specification had
   /// braces in its syntactic form.
   bool hasBraces() const { return HadBraces; }
 
-  typedef Decl** decl_iterator;
-  typedef Decl** decl_const_iterator;
-  decl_const_iterator decls_begin() const;
-  decl_const_iterator decls_end() const;
-  
   static bool classof(const Decl *D) {
     return D->getKind() == LinkageSpec;
   }

Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=61735&r1=61734&r2=61735&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Mon Jan  5 13:45:36 2009
@@ -264,25 +264,32 @@
     return 0;
   }
 
-  /// ActOnLinkageSpec - Parsed a C++ linkage-specification that
-  /// contained braces. Lang/StrSize contains the language string that
-  /// was parsed at location Loc. Decls/NumDecls provides the
-  /// declarations parsed inside the linkage specification.
-  virtual DeclTy *ActOnLinkageSpec(SourceLocation Loc, SourceLocation LBrace,
-                                   SourceLocation RBrace, const char *Lang,
-                                   unsigned StrSize, 
-                                   DeclTy **Decls, unsigned NumDecls) {
+  /// ActOnStartLinkageSpecification - Parsed the beginning of a C++
+  /// linkage specification, including the language and (if present)
+  /// the '{'. ExternLoc is the location of the 'extern', LangLoc is
+  /// the location of the language string literal, which is provided
+  /// by Lang/StrSize. LBraceLoc, if valid, provides the location of
+  /// the '{' brace. Otherwise, this linkage specification does not
+  /// have any braces.
+  virtual DeclTy *ActOnStartLinkageSpecification(Scope *S,
+                                                 SourceLocation ExternLoc,
+                                                 SourceLocation LangLoc,
+                                                 const char *Lang,
+                                                 unsigned StrSize,
+                                                 SourceLocation LBraceLoc) {
     return 0;
   }
 
-  /// ActOnLinkageSpec - Parsed a C++ linkage-specification without
-  /// braces. Lang/StrSize contains the language string that was
-  /// parsed at location Loc. D is the declaration parsed.
-  virtual DeclTy *ActOnLinkageSpec(SourceLocation Loc, const char *Lang,
-                                   unsigned StrSize, DeclTy *D) {
-    return 0;
+  /// ActOnFinishLinkageSpecification - Completely the definition of
+  /// the C++ linkage specification LinkageSpec. If RBraceLoc is
+  /// valid, it's the position of the closing '}' brace in a linkage
+  /// specification that uses braces.
+  virtual DeclTy *ActOnFinishLinkageSpecification(Scope *S,
+                                                  DeclTy *LinkageSpec,
+                                                  SourceLocation RBraceLoc) {
+    return LinkageSpec;
   }
-  
+
   /// ActOnEndOfTranslationUnit - This is called at the very end of the
   /// translation unit when EOF is reached and all but the top-level scope is
   /// popped.
@@ -333,6 +340,11 @@
                            SourceLocation LBrac, SourceLocation RBrac,
                            AttributeList *AttrList) {}
   
+  /// ActOnEnumStartDefinition - Invoked when we have entered the
+  /// scope of the enumeration body and will be parsing its
+  /// enumerators.  
+  virtual void ActOnEnumStartDefinition(Scope *S, DeclTy *EnumDecl) { }
+
   virtual DeclTy *ActOnEnumConstant(Scope *S, DeclTy *EnumDecl,
                                     DeclTy *LastEnumConstant,
                                     SourceLocation IdLoc, IdentifierInfo *Id,

Modified: cfe/trunk/lib/AST/DeclBase.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=61735&r1=61734&r2=61735&view=diff

==============================================================================
--- cfe/trunk/lib/AST/DeclBase.cpp (original)
+++ cfe/trunk/lib/AST/DeclBase.cpp Mon Jan  5 13:45:36 2009
@@ -406,10 +406,24 @@
   }
 }
 
+bool DeclContext::isTransparentContext() const {
+  if (DeclKind == Decl::Enum)
+    return true; // FIXME: Check for C++0x scoped enums
+  else if (DeclKind == Decl::LinkageSpec)
+    return true;
+  else if (DeclKind == Decl::Record || DeclKind == Decl::CXXRecord)
+    return false; // FIXME: need to know about anonymous unions/structs
+  else if (DeclKind == Decl::Namespace)
+    return false; // FIXME: Check for C++0x inline namespaces
+
+  return false;
+}
+
 DeclContext *DeclContext::getPrimaryContext(ASTContext &Context) {
   switch (DeclKind) {
-  case Decl::Block:
   case Decl::TranslationUnit:
+  case Decl::LinkageSpec:
+  case Decl::Block:    
     // There is only one DeclContext for these entities.
     return this;
 
@@ -418,10 +432,15 @@
     return static_cast<NamespaceDecl*>(this)->getOriginalNamespace();
 
   case Decl::Enum:
+#if 0
+    // FIXME: See the comment for CXXRecord, below.
     // The declaration associated with the enumeration type is our
     // primary context.
     return Context.getTypeDeclType(static_cast<EnumDecl*>(this))
              ->getAsEnumType()->getDecl();
+#else
+    return this;
+#endif
 
   case Decl::Record:
   case Decl::CXXRecord: {
@@ -461,13 +480,14 @@
 
 DeclContext *DeclContext::getNextContext() {
   switch (DeclKind) {
-  case Decl::Block:
   case Decl::TranslationUnit:
   case Decl::Enum:
   case Decl::Record:
   case Decl::CXXRecord:
   case Decl::ObjCMethod:
   case Decl::ObjCInterface:
+  case Decl::LinkageSpec:
+  case Decl::Block:
     // There is only one DeclContext for these entities.
     return 0;
 
@@ -488,6 +508,24 @@
     D->getDeclContext()->insert(Context, D);
 }
 
+/// buildLookup - Build the lookup data structure with all of the
+/// declarations in DCtx (and any other contexts linked to it or
+/// transparent contexts nested within it).
+void DeclContext::buildLookup(ASTContext &Context, DeclContext *DCtx) {
+  for (; DCtx; DCtx = DCtx->getNextContext()) {
+    for (decl_iterator D = DCtx->decls_begin(); D != DCtx->decls_end(); ++D) {
+      // Insert this declaration into the lookup structure
+      insertImpl(*D);
+
+      // If this declaration is itself a transparent declaration context,
+      // add its members (recursively).
+      if (DeclContext *InnerCtx = dyn_cast<DeclContext>(*D))
+        if (InnerCtx->isTransparentContext())
+          buildLookup(Context, InnerCtx->getPrimaryContext(Context));
+    }
+  }
+}
+
 DeclContext::lookup_result 
 DeclContext::lookup(ASTContext &Context, DeclarationName Name) {
   DeclContext *PrimaryContext = getPrimaryContext(Context);
@@ -497,11 +535,8 @@
   /// If there is no lookup data structure, build one now by walking
   /// all of the linked DeclContexts (in declaration order!) and
   /// inserting their values.
-  if (LookupPtr.getPointer() == 0) {
-    for (DeclContext *DCtx = this; DCtx; DCtx = DCtx->getNextContext())
-      for (decl_iterator D = DCtx->decls_begin(); D != DCtx->decls_end(); ++D)
-        insertImpl(*D);
-  }
+  if (LookupPtr.getPointer() == 0)
+    buildLookup(Context, this);
 
   if (isLookupMap()) {
     StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(LookupPtr.getPointer());
@@ -543,9 +578,19 @@
   // someone asks for it.
   if (LookupPtr.getPointer())
     insertImpl(D);
+
+
+  // If we are a transparent context, insert into our parent context,
+  // too. This operation is recursive.
+  if (isTransparentContext())
+    getParent()->insert(Context, D);
 }
 
 void DeclContext::insertImpl(ScopedDecl *D) {
+  // Skip unnamed declarations.
+  if (!D->getDeclName())
+    return;
+
   bool MayBeRedeclaration = true;
 
   if (!isLookupMap()) {

Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=61735&r1=61734&r2=61735&view=diff

==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Mon Jan  5 13:45:36 2009
@@ -291,42 +291,10 @@
   return new (Mem) OverloadedFunctionDecl(DC, N);
 }
 
-LinkageSpecDecl::LinkageSpecDecl(SourceLocation L, LanguageIDs lang, 
-                                 Decl **InDecls, unsigned InNumDecls)
-  : Decl(LinkageSpec, L), Language(lang), HadBraces(true),
-    Decls(0), NumDecls(InNumDecls) {
-  Decl **NewDecls = new Decl*[NumDecls];
-  for (unsigned I = 0; I < NumDecls; ++I)
-    NewDecls[I] = InDecls[I];
-  Decls = NewDecls;
-}
-
-LinkageSpecDecl::~LinkageSpecDecl() {
-  if (HadBraces)
-    delete [] (Decl**)Decls;
-}
-
 LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C,
+                                         DeclContext *DC, 
                                          SourceLocation L,
-                                         LanguageIDs Lang, Decl *D) {
+                                         LanguageIDs Lang, bool Braces) {
   void *Mem = C.getAllocator().Allocate<LinkageSpecDecl>();
-  return new (Mem) LinkageSpecDecl(L, Lang, D);
-}
-
-LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C,
-                                         SourceLocation L,
-                                         LanguageIDs Lang, 
-                                         Decl **Decls, unsigned NumDecls) {
-  void *Mem = C.getAllocator().Allocate<LinkageSpecDecl>();
-  return new (Mem) LinkageSpecDecl(L, Lang, Decls, NumDecls);
-}
-
-LinkageSpecDecl::decl_const_iterator LinkageSpecDecl::decls_begin() const {
-  if (hasBraces()) return (Decl**)Decls;
-  else return (Decl**)&Decls;
-}
-
-LinkageSpecDecl::decl_iterator LinkageSpecDecl::decls_end() const {
-  if (hasBraces()) return (Decl**)Decls + NumDecls;
-  else return (Decl**)&Decls + 1;
+  return new (Mem) LinkageSpecDecl(DC, L, Lang, Braces);
 }

Modified: cfe/trunk/lib/AST/DeclSerialization.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclSerialization.cpp?rev=61735&r1=61734&r2=61735&view=diff

==============================================================================
--- cfe/trunk/lib/AST/DeclSerialization.cpp (original)
+++ cfe/trunk/lib/AST/DeclSerialization.cpp Mon Jan  5 13:45:36 2009
@@ -686,29 +686,12 @@
   Decl::EmitInRec(S);
   S.EmitInt(getLanguage());
   S.EmitBool(HadBraces);
-  if (HadBraces) {
-    S.EmitInt(NumDecls);
-    for (decl_const_iterator D = decls_begin(), DEnd = decls_end(); 
-         D != DEnd; ++D)
-      S.EmitPtr(*D);
-  } else {
-    S.EmitPtr((Decl*)Decls);
-  }
 }
 
 void LinkageSpecDecl::ReadInRec(Deserializer& D, ASTContext& C) {
   Decl::ReadInRec(D, C);
   Language = static_cast<LanguageIDs>(D.ReadInt());
   HadBraces = D.ReadBool();
-  if (HadBraces) {
-    NumDecls = D.ReadInt();
-    Decl **NewDecls = new Decl*[NumDecls];
-    Decls = NewDecls;
-    for (unsigned I = 0; I < NumDecls; ++I)
-      D.ReadPtr(NewDecls[I]);
-  } else {
-    D.ReadPtr(this->Decls);
-  }
 }
 
 //===----------------------------------------------------------------------===//

Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=61735&r1=61734&r2=61735&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Mon Jan  5 13:45:36 2009
@@ -1123,6 +1123,10 @@
 ///         identifier
 ///
 void Parser::ParseEnumBody(SourceLocation StartLoc, DeclTy *EnumDecl) {
+  // Enter the scope of the enum body and start the definition.
+  ParseScope EnumScope(this, Scope::DeclScope);
+  Actions.ActOnEnumStartDefinition(CurScope, EnumDecl);
+
   SourceLocation LBraceLoc = ConsumeBrace();
   
   // C does not allow an empty enumerator-list, C++ does [dcl.enum].

Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=61735&r1=61734&r2=61735&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Mon Jan  5 13:45:36 2009
@@ -108,27 +108,28 @@
   unsigned StrSize = PP.getSpelling(Tok, LangBufPtr);
 
   SourceLocation Loc = ConsumeStringToken();
-  DeclTy *D = 0;
-  
-  if (Tok.isNot(tok::l_brace)) {
-    D = ParseDeclarationOrFunctionDefinition();
-    if (D)
-      return Actions.ActOnLinkageSpec(Loc, LangBufPtr, StrSize, D);
 
-    return 0;
+  ParseScope LinkageScope(this, Scope::DeclScope);
+  DeclTy *LinkageSpec 
+    = Actions.ActOnStartLinkageSpecification(CurScope, 
+                                             /*FIXME: */SourceLocation(),
+                                             Loc, LangBufPtr, StrSize,
+                                       Tok.is(tok::l_brace)? Tok.getLocation() 
+                                                           : SourceLocation());
+
+  if (Tok.isNot(tok::l_brace)) {
+    ParseDeclarationOrFunctionDefinition();
+    return Actions.ActOnFinishLinkageSpecification(CurScope, LinkageSpec, 
+                                                   SourceLocation());
   } 
 
   SourceLocation LBrace = ConsumeBrace();
-  llvm::SmallVector<DeclTy *, 8> InnerDecls;
   while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
-    D = ParseExternalDeclaration();
-    if (D)
-      InnerDecls.push_back(D);
+    ParseExternalDeclaration();
   }
 
   SourceLocation RBrace = MatchRHSPunctuation(tok::r_brace, LBrace);
-  return Actions.ActOnLinkageSpec(Loc, LBrace, RBrace, LangBufPtr, StrSize,
-                                  &InnerDecls.front(), InnerDecls.size());
+  return Actions.ActOnFinishLinkageSpecification(CurScope, LinkageSpec, RBrace);
 }
 
 /// ParseUsingDirectiveOrDeclaration - Parse C++ using using-declaration or

Modified: cfe/trunk/lib/Sema/IdentifierResolver.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/IdentifierResolver.cpp?rev=61735&r1=61734&r2=61735&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/IdentifierResolver.cpp (original)
+++ cfe/trunk/lib/Sema/IdentifierResolver.cpp Mon Jan  5 13:45:36 2009
@@ -60,6 +60,9 @@
   else
     return TUCtx();
 
+  while (Ctx->isTransparentContext())
+    Ctx = Ctx->getParent();
+
   if (isa<TranslationUnitDecl>(Ctx))
     return TUCtx();
 
@@ -83,30 +86,12 @@
 // IdDeclInfo Implementation
 //===----------------------------------------------------------------------===//
 
-/// FindContext - Returns an iterator pointing just after the decl that is
-/// in the given context or in a parent of it. The search is in reverse
-/// order, from end to begin.
-IdentifierResolver::IdDeclInfo::DeclsTy::iterator
-IdentifierResolver::IdDeclInfo::FindDeclVisibleInContext(
-                                            const LookupContext &Ctx,
-                                            const DeclsTy::iterator &Start) {
-  for (DeclsTy::iterator I = Start; I != Decls.begin(); --I) {
-    if (Ctx.isEqOrContainedBy(LookupContext(*(I-1))))
-      return I;
-  }
-
-  return Decls.begin();
-}
-
 /// AddShadowed - Add a decl by putting it directly above the 'Shadow' decl.
 /// Later lookups will find the 'Shadow' decl first. The 'Shadow' decl must
 /// be already added to the scope chain and must be in the same context as
 /// the decl that we want to add.
 void IdentifierResolver::IdDeclInfo::AddShadowed(NamedDecl *D,
                                                  NamedDecl *Shadow) {
-  assert(LookupContext(D) == LookupContext(Shadow) &&
-    "Decl and Shadow not in same context!");
-
   for (DeclsTy::iterator I = Decls.end(); I != Decls.begin(); --I) {
     if (Shadow == *(I-1)) {
       Decls.insert(I-1, D);
@@ -147,7 +132,15 @@
 /// true if 'D' belongs to the given declaration context.
 bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx,
                                        ASTContext &Context, Scope *S) const {
+  while (Ctx->isTransparentContext())
+    Ctx = Ctx->getParent();
+
   if (Ctx->isFunctionOrMethod()) {
+    // Ignore the scopes associated within transparent declaration contexts.
+    while (S->getEntity() && 
+           ((DeclContext *)S->getEntity())->isTransparentContext())
+      S = S->getParent();
+
     if (S->isDeclScope(D))
       return true;
     if (LangOpt.CPlusPlus) {
@@ -201,7 +194,6 @@
 /// encountered before the 'D' decl.
 void IdentifierResolver::AddShadowedDecl(NamedDecl *D, NamedDecl *Shadow) {
   assert(D->getDeclName() == Shadow->getDeclName() && "Different ids!");
-  assert(LookupContext(D) == LookupContext(Shadow) && "Different context!");
 
   DeclarationName Name = D->getDeclName();
   void *Ptr = Name.getFETokenInfo<void>();
@@ -252,30 +244,14 @@
   void *Ptr = Name.getFETokenInfo<void>();
   if (!Ptr) return end();
 
-  LookupContext LC(Ctx);
-
   if (isDeclPtr(Ptr)) {
     NamedDecl *D = static_cast<NamedDecl*>(Ptr);
-    LookupContext DC(D);
-
-    if (( LookInParentCtx && LC.isEqOrContainedBy(DC)) ||
-        (!LookInParentCtx && LC == DC))
-      return iterator(D);
-    else
-      return end();
+    return iterator(D);
   }
 
   IdDeclInfo *IDI = toIdDeclInfo(Ptr);
 
-  IdDeclInfo::DeclsTy::iterator I;
-  if (LookInParentCtx)
-    I = IDI->FindDeclVisibleInContext(LC);
-  else {
-    for (I = IDI->decls_end(); I != IDI->decls_begin(); --I)
-      if (LookupContext(*(I-1)) == LC)
-        break;
-  }
-
+  IdDeclInfo::DeclsTy::iterator I = IDI->decls_end();
   if (I != IDI->decls_begin())
     return iterator(I-1, LookInParentCtx);
   else // No decls found.
@@ -285,22 +261,11 @@
 /// PreIncIter - Do a preincrement when 'Ptr' is a BaseIter.
 void IdentifierResolver::iterator::PreIncIter() {
   NamedDecl *D = **this;
-  LookupContext Ctx(D);
   void *InfoPtr = D->getDeclName().getFETokenInfo<void>();
   assert(!isDeclPtr(InfoPtr) && "Decl with wrong id ?");
   IdDeclInfo *Info = toIdDeclInfo(InfoPtr);
 
   BaseIter I = getIterator();
-  if (LookInParentCtx())
-    I = Info->FindDeclVisibleInContext(Ctx, I);
-  else {
-    if (I != Info->decls_begin() && LookupContext(*(I-1)) != Ctx) {
-      // The next decl is in different declaration context.
-      // Skip remaining decls and set the iterator to the end.
-      I = Info->decls_begin();
-    }
-  }
-
   if (I != Info->decls_begin())
     *this = iterator(I-1, LookInParentCtx());
   else // No more decls.

Modified: cfe/trunk/lib/Sema/IdentifierResolver.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/IdentifierResolver.h?rev=61735&r1=61734&r2=61735&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/IdentifierResolver.h (original)
+++ cfe/trunk/lib/Sema/IdentifierResolver.h Mon Jan  5 13:45:36 2009
@@ -91,22 +91,7 @@
     inline DeclsTy::iterator decls_begin() { return Decls.begin(); }
     inline DeclsTy::iterator decls_end() { return Decls.end(); }
 
-    /// FindContext - Returns an iterator pointing just after the decl that is
-    /// in the given context or in a parent of it. The search is in reverse
-    /// order, from end to begin.
-    DeclsTy::iterator FindDeclVisibleInContext(const LookupContext &Ctx) {
-      return FindDeclVisibleInContext(Ctx, Decls.end());
-    }
-
-    /// FindContext - Returns an iterator pointing just after the decl that is
-    /// in the given context or in a parent of it. The search is in reverse
-    /// order, from end to begin.
-    DeclsTy::iterator FindDeclVisibleInContext(const LookupContext &Ctx,
-                                  const DeclsTy::iterator &Start);
-
-    void AddDecl(NamedDecl *D) {
-      Decls.insert(FindDeclVisibleInContext(LookupContext(D)), D);
-    }
+    void AddDecl(NamedDecl *D) { Decls.push_back(D); }
 
     /// AddShadowed - Add a decl by putting it directly above the 'Shadow' decl.
     /// Later lookups will find the 'Shadow' decl first. The 'Shadow' decl must

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=61735&r1=61734&r2=61735&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Mon Jan  5 13:45:36 2009
@@ -288,12 +288,6 @@
   virtual void ObjCActOnStartOfMethodDef(Scope *S, DeclTy *D);
   
   virtual DeclTy *ActOnFinishFunctionBody(DeclTy *Decl, StmtArg Body);
-  virtual DeclTy *ActOnLinkageSpec(SourceLocation Loc, SourceLocation LBrace,
-                                   SourceLocation RBrace, const char *Lang,
-                                   unsigned StrSize, 
-                                   DeclTy **Decls, unsigned NumDecls);
-  virtual DeclTy *ActOnLinkageSpec(SourceLocation Loc, const char *Lang,
-                                   unsigned StrSize, DeclTy *D);
   virtual DeclTy *ActOnFileScopeAsmDecl(SourceLocation Loc, ExprArg expr);
 
   /// Scope actions.
@@ -326,6 +320,7 @@
                            DeclTy **Fields, unsigned NumFields,
                            SourceLocation LBrac, SourceLocation RBrac,
                            AttributeList *AttrList);
+  virtual void ActOnEnumStartDefinition(Scope *S, DeclTy *EnumDecl);
   virtual DeclTy *ActOnEnumConstant(Scope *S, DeclTy *EnumDecl,
                                     DeclTy *LastEnumConstant,
                                     SourceLocation IdLoc, IdentifierInfo *Id,
@@ -980,6 +975,20 @@
                                                  SourceLocation RParenLoc);
 
   //===--------------------------------------------------------------------===//
+  // C++ Declarations
+  //
+  virtual DeclTy *ActOnStartLinkageSpecification(Scope *S,
+                                                 SourceLocation ExternLoc,
+                                                 SourceLocation LangLoc,
+                                                 const char *Lang,
+                                                 unsigned StrSize,
+                                                 SourceLocation LBraceLoc);
+  virtual DeclTy *ActOnFinishLinkageSpecification(Scope *S,
+                                                  DeclTy *LinkageSpec,
+                                                  SourceLocation RBraceLoc);
+
+
+  //===--------------------------------------------------------------------===//
   // C++ Classes
   //
   virtual bool isCurrentClassName(const IdentifierInfo &II, Scope *S,

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=61735&r1=61734&r2=61735&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Jan  5 13:45:36 2009
@@ -93,6 +93,13 @@
 
 /// Add this decl to the scope shadowed decl chains.
 void Sema::PushOnScopeChains(NamedDecl *D, Scope *S) {
+  // Move up the scope chain until we find the nearest enclosing
+  // non-transparent context. The declaration will be introduced into this
+  // scope.
+  while (S->getEntity() && 
+         ((DeclContext *)S->getEntity())->isTransparentContext())
+    S = S->getParent();
+
   S->AddDecl(D);
 
   // Add scoped declarations into their context, so that they can be
@@ -149,8 +156,11 @@
     // We are pushing the name of a function, which might be an
     // overloaded name.
     FunctionDecl *FD = cast<FunctionDecl>(D);
+    DeclContext *DC = FD->getDeclContext();                                     
+    while (DC->isTransparentContext())
+      DC = DC->getParent(); 
     IdentifierResolver::iterator Redecl
-      = std::find_if(IdResolver.begin(FD->getDeclName(), CurContext, 
+      = std::find_if(IdResolver.begin(FD->getDeclName(), DC, 
                                       false/*LookInParentCtx*/),
                      IdResolver.end(),
                      std::bind1st(std::mem_fun(&ScopedDecl::declarationReplaces),
@@ -337,7 +347,7 @@
         Ctx = Ctx->getParent();
       }
       
-      if (!LookInParent)
+      if (!LookInParent && !Ctx->isTransparentContext())
         return 0;
     }
   }
@@ -3117,6 +3127,15 @@
     ProcessDeclAttributeList(Record, Attr);
 }
 
+void Sema::ActOnEnumStartDefinition(Scope *S, DeclTy *EnumD) {
+  EnumDecl *Enum = cast_or_null<EnumDecl>((Decl *)EnumD);
+
+  if (Enum) {
+    // Enter the enumeration context.
+    PushDeclContext(S, Enum);
+  }
+}
+
 Sema::DeclTy *Sema::ActOnEnumConstant(Scope *S, DeclTy *theEnumDecl,
                                       DeclTy *lastEnumConst,
                                       SourceLocation IdLoc, IdentifierInfo *Id,
@@ -3212,20 +3231,22 @@
 void Sema::ActOnEnumBody(SourceLocation EnumLoc, DeclTy *EnumDeclX,
                          DeclTy **Elements, unsigned NumElements) {
   EnumDecl *Enum = cast<EnumDecl>(static_cast<Decl*>(EnumDeclX));
+  QualType EnumType = Context.getTypeDeclType(Enum);
   
-  if (Enum) {
-    if (EnumDecl *Def = cast_or_null<EnumDecl>(Enum->getDefinition(Context))) {
-      // Diagnose code like:
-      //   enum e0 {
-      //     E0 = sizeof(enum e0 { E1 })
-      //   };
-      Diag(Def->getLocation(), diag::err_nested_redefinition)
-        << Enum->getDeclName();
-      Diag(Enum->getLocation(), diag::note_previous_definition);
-      Enum->setInvalidDecl();
-      return;
-    }
+  if (EnumType->getAsEnumType()->getDecl()->isDefinition()) {
+    EnumDecl *Def = EnumType->getAsEnumType()->getDecl();
+    // Diagnose code like:
+    //   enum e0 {
+    //     E0 = sizeof(enum e0 { E1 })
+    //   };
+    Diag(Def->getLocation(), diag::err_nested_redefinition)
+      << Enum->getDeclName();
+    Diag(Enum->getLocation(), diag::note_previous_definition);
+    Enum->setInvalidDecl();
+    PopDeclContext();
+    return;
   }
+
   // TODO: If the result value doesn't fit in an int, it must be a long or long
   // long value.  ISO C does not support this, but GCC does as an extension,
   // emit a warning.
@@ -3239,7 +3260,6 @@
   // Keep track of whether all elements have type int.
   bool AllElementsInt = true;
   
-  QualType EnumType = Context.getTypeDeclType(Enum);
   EnumConstantDecl *EltList = 0;
   for (unsigned i = 0; i != NumElements; ++i) {
     EnumConstantDecl *ECD =
@@ -3392,6 +3412,9 @@
   
   Enum->completeDefinition(Context, BestType);
   Consumer.HandleTagDeclDefinition(Enum);
+
+  // Leave the context of the enumeration.
+  PopDeclContext();
 }
 
 Sema::DeclTy *Sema::ActOnFileScopeAsmDecl(SourceLocation Loc,

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=61735&r1=61734&r2=61735&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon Jan  5 13:45:36 2009
@@ -2003,48 +2003,49 @@
   return false;
 }
 
-/// ActOnLinkageSpec - Parsed a C++ linkage-specification that
-/// contained braces. Lang/StrSize contains the language string that
-/// was parsed at location Loc. Decls/NumDecls provides the
-/// declarations parsed inside the linkage specification.
-Sema::DeclTy *Sema::ActOnLinkageSpec(SourceLocation Loc,
-                                     SourceLocation LBrace,
-                                     SourceLocation RBrace,
-                                     const char *Lang,
-                                     unsigned StrSize,
-                                     DeclTy **Decls, unsigned NumDecls) {
+/// ActOnStartLinkageSpecification - Parsed the beginning of a C++
+/// linkage specification, including the language and (if present)
+/// the '{'. ExternLoc is the location of the 'extern', LangLoc is
+/// the location of the language string literal, which is provided
+/// by Lang/StrSize. LBraceLoc, if valid, provides the location of
+/// the '{' brace. Otherwise, this linkage specification does not
+/// have any braces.
+Sema::DeclTy *Sema::ActOnStartLinkageSpecification(Scope *S,
+                                                   SourceLocation ExternLoc,
+                                                   SourceLocation LangLoc,
+                                                   const char *Lang,
+                                                   unsigned StrSize,
+                                                   SourceLocation LBraceLoc) {
   LinkageSpecDecl::LanguageIDs Language;
   if (strncmp(Lang, "\"C\"", StrSize) == 0)
     Language = LinkageSpecDecl::lang_c;
   else if (strncmp(Lang, "\"C++\"", StrSize) == 0)
     Language = LinkageSpecDecl::lang_cxx;
   else {
-    Diag(Loc, diag::err_bad_language);
+    Diag(LangLoc, diag::err_bad_language);
     return 0;
   }
   
   // FIXME: Add all the various semantics of linkage specifications
   
-  return LinkageSpecDecl::Create(Context, Loc, Language, 
-                                 (Decl **)Decls, NumDecls);
+  LinkageSpecDecl *D = LinkageSpecDecl::Create(Context, CurContext,
+                                               LangLoc, Language, 
+                                               LBraceLoc.isValid());
+  CurContext->addDecl(Context, D);
+  PushDeclContext(S, D);
+  return D;
 }
 
-Sema::DeclTy *Sema::ActOnLinkageSpec(SourceLocation Loc,
-                                     const char *Lang, unsigned StrSize,
-                                     DeclTy *D) {
-  LinkageSpecDecl::LanguageIDs Language;
-  Decl *dcl = static_cast<Decl *>(D);
-  if (strncmp(Lang, "\"C\"", StrSize) == 0)
-    Language = LinkageSpecDecl::lang_c;
-  else if (strncmp(Lang, "\"C++\"", StrSize) == 0)
-    Language = LinkageSpecDecl::lang_cxx;
-  else {
-    Diag(Loc, diag::err_bad_language);
-    return 0;
-  }
-  
-  // FIXME: Add all the various semantics of linkage specifications
-  return LinkageSpecDecl::Create(Context, Loc, Language, dcl);
+/// ActOnFinishLinkageSpecification - Completely the definition of
+/// the C++ linkage specification LinkageSpec. If RBraceLoc is
+/// valid, it's the position of the closing '}' brace in a linkage
+/// specification that uses braces.
+Sema::DeclTy *Sema::ActOnFinishLinkageSpecification(Scope *S,
+                                                    DeclTy *LinkageSpec,
+                                                    SourceLocation RBraceLoc) {
+  if (LinkageSpec)
+    PopDeclContext();
+  return LinkageSpec;
 }
 
 /// ActOnExceptionDeclarator - Parsed the exception-declarator in a C++ catch

Modified: cfe/trunk/test/SemaCXX/qualified-id-lookup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/qualified-id-lookup.cpp?rev=61735&r1=61734&r2=61735&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/qualified-id-lookup.cpp (original)
+++ cfe/trunk/test/SemaCXX/qualified-id-lookup.cpp Mon Jan  5 13:45:36 2009
@@ -2,15 +2,23 @@
 
 namespace Ns {
   int f(); // expected-note{{previous declaration is here}}
+
+  enum E {
+    Enumerator
+  };
 }
 namespace Ns {
   double f(); // expected-error{{functions that differ only in their return type cannot be overloaded}}
+
+  int x = Enumerator;
 }
 
 namespace Ns2 {
   float f();
 }
 
+int y = Ns::Enumerator;
+
 namespace Ns2 {
   float f(int); // expected-note{{previous declaration is here}}
 }





More information about the cfe-commits mailing list