[cfe-commits] r50321 - in /cfe/trunk: include/clang/AST/Decl.h include/clang/AST/DeclBase.h include/clang/Basic/DiagnosticKinds.def include/clang/Parse/Action.h lib/AST/Decl.cpp lib/AST/DeclSerialization.cpp lib/Parse/ParseDeclCXX.cpp lib/Sema/Sema.h lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaExpr.cpp test/Sema/cxx-namespace.cpp

Argiris Kirtzidis akyrtzi at gmail.com
Sun Apr 27 06:50:30 PDT 2008


Author: akirtzidis
Date: Sun Apr 27 08:50:30 2008
New Revision: 50321

URL: http://llvm.org/viewvc/llvm-project?rev=50321&view=rev
Log:
Parsing of namespaces:

-NamespaceDecl for the AST
-Checks for name clashes between namespaces and tag/normal declarations.

This commit doesn't implement proper name lookup for namespaces.

Added:
    cfe/trunk/test/Sema/cxx-namespace.cpp
Modified:
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/include/clang/AST/DeclBase.h
    cfe/trunk/include/clang/Basic/DiagnosticKinds.def
    cfe/trunk/include/clang/Parse/Action.h
    cfe/trunk/lib/AST/Decl.cpp
    cfe/trunk/lib/AST/DeclSerialization.cpp
    cfe/trunk/lib/Parse/ParseDeclCXX.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp

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

==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Sun Apr 27 08:50:30 2008
@@ -127,6 +127,66 @@
   void ReadOutRec(llvm::Deserializer& D, ASTContext& C);
 };
 
+/// NamespaceDecl - Represent a C++ namespace.
+class NamespaceDecl : public ScopedDecl, public DeclContext {
+  SourceLocation LBracLoc, RBracLoc;
+  
+  // For extended namespace definitions:
+  //
+  // namespace A { int x; }
+  // namespace A { int y; }
+  //
+  // there will be one NamespaceDecl for each declaration.
+  // NextDeclarator points to the next extended declaration.
+  // OrigNamespace points to the original namespace declaration.
+  // OrigNamespace of the first namespace decl points to itself.
+
+  NamespaceDecl *OrigNamespace;
+
+  NamespaceDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id)
+    : ScopedDecl(Namespace, DC, L, Id, 0), DeclContext(Namespace) {
+      OrigNamespace = this;
+  }
+public:
+  static NamespaceDecl *Create(ASTContext &C, DeclContext *DC,
+                               SourceLocation L, IdentifierInfo *Id);
+
+  NamespaceDecl *getNextNamespace() {
+    return cast_or_null<NamespaceDecl>(getNextDeclarator());
+  }
+  const NamespaceDecl *getNextNamespace() const {
+    return cast_or_null<NamespaceDecl>(getNextDeclarator());
+  }
+  void setNextNamespace(NamespaceDecl *ND) { setNextDeclarator(ND); }
+
+  NamespaceDecl *getOriginalNamespace() const {
+    return OrigNamespace;
+  }
+  void setOriginalNamespace(NamespaceDecl *ND) { OrigNamespace = ND; }
+  
+  SourceRange getSourceRange() const { 
+    return SourceRange(LBracLoc, RBracLoc); 
+  }
+
+  SourceLocation getLBracLoc() const { return LBracLoc; }
+  SourceLocation getRBracLoc() const { return RBracLoc; }
+  void setLBracLoc(SourceLocation LBrace) { LBracLoc = LBrace; }
+  void setRBracLoc(SourceLocation RBrace) { RBracLoc = RBrace; }
+  
+  // Implement isa/cast/dyncast/etc.
+  static bool classof(const Decl *D) { return D->getKind() == Namespace; }
+  static bool classof(const NamespaceDecl *D) { return true; }
+  
+protected:
+  /// EmitImpl - Serialize this NamespaceDecl. Called by Decl::Emit.
+  virtual void EmitImpl(llvm::Serializer& S) const;
+
+  /// CreateImpl - Deserialize a NamespaceDecl.  Called by Decl::Create.
+  static NamespaceDecl* CreateImpl(llvm::Deserializer& D, ASTContext& C);
+
+  friend Decl* Decl::Create(llvm::Deserializer& D, ASTContext& C);
+};
+
 /// ValueDecl - Represent the declaration of a variable (in which case it is 
 /// an lvalue) a function (in which case it is a function designator) or
 /// an enum constant. 

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

==============================================================================
--- cfe/trunk/include/clang/AST/DeclBase.h (original)
+++ cfe/trunk/include/clang/AST/DeclBase.h Sun Apr 27 08:50:30 2008
@@ -20,6 +20,7 @@
 
 namespace clang {
 class TranslationUnitDecl;
+class NamespaceDecl;
 class FunctionDecl;
 class ObjCMethodDecl;
 class EnumDecl;
@@ -46,6 +47,7 @@
            ObjCProtocol,
            ObjCProperty,
     //     ScopedDecl
+             Namespace,
     //       TypeDecl
                Typedef,
     //         TagDecl
@@ -72,7 +74,7 @@
     // of the class, to allow efficient classof.
     NamedFirst  = Field,         NamedLast  = ParmVar,
     FieldFirst  = Field,         FieldLast  = ObjCIvar,
-    ScopedFirst = Typedef,       ScopedLast = ParmVar,
+    ScopedFirst = Namespace,     ScopedLast = ParmVar,
     TypeFirst   = Typedef,       TypeLast   = Class,
     TagFirst    = Enum         , TagLast    = Class,
     RecordFirst = Struct       , RecordLast = Class,
@@ -163,6 +165,8 @@
     case Class:
     case Enum:
       return IDNS_Tag;
+    case Namespace:
+      return IdentifierNamespace(IDNS_Tag | IDNS_Ordinary);
     }
   }
   // global temp stats (until we have a per-module visitor)
@@ -198,6 +202,7 @@
 /// can act as declaration contexts. These decls are:
 ///
 ///   TranslationUnitDecl
+///   NamespaceDecl
 ///   FunctionDecl
 ///   ObjCMethodDecl
 ///   EnumDecl
@@ -221,6 +226,8 @@
     switch(DK) {
       case Decl::TranslationUnit:
         return static_cast<TranslationUnitDecl*>(const_cast<From*>(D));
+      case Decl::Namespace:
+        return static_cast<NamespaceDecl*>(const_cast<From*>(D));
       case Decl::Function:
         return static_cast<FunctionDecl*>(const_cast<From*>(D));
       case Decl::ObjCMethod:
@@ -262,6 +269,7 @@
   static bool classof(const Decl *D) {
     switch (D->getKind()) {
       case Decl::TranslationUnit:
+      case Decl::Namespace:
       case Decl::Function:
       case Decl::ObjCMethod:
       case Decl::ObjCInterface:
@@ -273,6 +281,7 @@
   }
   static bool classof(const DeclContext *D) { return true; }
   static bool classof(const TranslationUnitDecl *D) { return true; }
+  static bool classof(const NamespaceDecl *D) { return true; }
   static bool classof(const FunctionDecl *D) { return true; }
   static bool classof(const ObjCMethodDecl *D) { return true; }
   static bool classof(const EnumDecl *D) { return true; }

Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=50321&r1=50320&r2=50321&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Sun Apr 27 08:50:30 2008
@@ -666,6 +666,8 @@
 
 DIAG(err_unexpected_typedef, ERROR,
      "unexpected type name '%0': expected expression")
+DIAG(err_unexpected_namespace, ERROR,
+     "unexpected namespace name '%0': expected expression")
 DIAG(err_unexpected_typedef_ident, ERROR,
      "unexpected type name '%0': expected identifier")
 DIAG(err_undeclared_var_use, ERROR,

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

==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Sun Apr 27 08:50:30 2008
@@ -133,6 +133,20 @@
     return Group;
   }
 
+  /// ActOnStartNamespaceDef - This is called at the start of a namespace
+  /// definition.
+  virtual DeclTy *ActOnStartNamespaceDef(Scope *S, SourceLocation IdentLoc,
+                                        IdentifierInfo *Ident,
+                                        SourceLocation LBrace) {
+    return 0;
+  }
+
+  /// ActOnFinishNamespaceDef - This callback is called after a namespace is
+  /// exited. Decl is the DeclTy returned by ActOnStartNamespaceDef.
+  virtual void ActOnFinishNamespaceDef(DeclTy *Dcl,SourceLocation RBrace) {
+    return;
+  }
+
   /// ActOnStartOfFunctionDef - This is called at the start of a function
   /// definition, instead of calling ActOnDeclarator.  The Declarator includes
   /// information about formal arguments that are part of this function.

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

==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Sun Apr 27 08:50:30 2008
@@ -29,6 +29,7 @@
 static unsigned nSUC = 0;
 static unsigned nEnumConst = 0;
 static unsigned nEnumDecls = 0;
+static unsigned nNamespaces = 0;
 static unsigned nTypedef = 0;
 static unsigned nFieldDecls = 0;
 static unsigned nInterfaceDecls = 0;
@@ -57,6 +58,7 @@
 const char *Decl::getDeclKindName() const {
   switch (DeclKind) {
   default: assert(0 && "Unknown decl kind!");
+  case Namespace:           return "Namespace";
   case Typedef:             return "Typedef";
   case Function:            return "Function";
   case Var:                 return "Var";
@@ -85,7 +87,11 @@
   fprintf(stderr, "  %d decls total.\n", 
           int(nFuncs+nVars+nParmVars+nFieldDecls+nSUC+
               nEnumDecls+nEnumConst+nTypedef+nInterfaceDecls+nClassDecls+
-              nMethodDecls+nProtocolDecls+nCategoryDecls+nIvarDecls));
+              nMethodDecls+nProtocolDecls+nCategoryDecls+nIvarDecls+
+              nNamespaces));
+  fprintf(stderr, "    %d namespace decls, %d each (%d bytes)\n", 
+          nNamespaces, (int)sizeof(NamespaceDecl), 
+          int(nNamespaces*sizeof(NamespaceDecl)));
   fprintf(stderr, "    %d function decls, %d each (%d bytes)\n", 
           nFuncs, (int)sizeof(FunctionDecl), int(nFuncs*sizeof(FunctionDecl)));
   fprintf(stderr, "    %d variable decls, %d each (%d bytes)\n", 
@@ -170,12 +176,14 @@
               nObjCPropertyDecl*sizeof(ObjCPropertyDecl)+
               nObjCPropertyImplDecl*sizeof(ObjCPropertyImplDecl)+
               nLinkageSpecDecl*sizeof(LinkageSpecDecl)+
-              nFileScopeAsmDecl*sizeof(FileScopeAsmDecl)));
+              nFileScopeAsmDecl*sizeof(FileScopeAsmDecl)+
+              nNamespaces*sizeof(NamespaceDecl)));
     
 }
 
 void Decl::addDeclKind(Kind k) {
   switch (k) {
+  case Namespace:           nNamespaces++; break;
   case Typedef:             nTypedef++; break;
   case Function:            nFuncs++; break;
   case Var:                 nVars++; break;
@@ -205,12 +213,18 @@
 //===----------------------------------------------------------------------===//
 // Decl Allocation/Deallocation Method Implementations
 //===----------------------------------------------------------------------===//
-
+ 
 TranslationUnitDecl *TranslationUnitDecl::Create(ASTContext &C) {
   void *Mem = C.getAllocator().Allocate<TranslationUnitDecl>();
   return new (Mem) TranslationUnitDecl();
 }
 
+NamespaceDecl *NamespaceDecl::Create(ASTContext &C, DeclContext *DC,
+                                     SourceLocation L, IdentifierInfo *Id) {
+  void *Mem = C.getAllocator().Allocate<NamespaceDecl>();
+  return new (Mem) NamespaceDecl(DC, L, Id);
+}
+
 VarDecl *VarDecl::Create(ASTContext &C, DeclContext *DC,
                          SourceLocation L,
                          IdentifierInfo *Id, QualType T,
@@ -342,6 +356,7 @@
   CASE(ObjCImplementation);
   CASE(ObjCProtocol);
   CASE(ObjCProperty);
+  CASE(Namespace);
   CASE(Typedef);
   CASE(Enum);
   CASE(EnumConstant);

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

==============================================================================
--- cfe/trunk/lib/AST/DeclSerialization.cpp (original)
+++ cfe/trunk/lib/AST/DeclSerialization.cpp Sun Apr 27 08:50:30 2008
@@ -44,6 +44,9 @@
     case TranslationUnit:
       return TranslationUnitDecl::CreateImpl(D, C);
 
+    case Namespace:
+      return NamespaceDecl::CreateImpl(D, C);
+
     case Var:
       return VarDecl::CreateImpl(D, C);
       
@@ -206,8 +209,7 @@
 TranslationUnitDecl* TranslationUnitDecl::CreateImpl(Deserializer& D,
                                                      ASTContext& C) {  
   void *Mem = C.getAllocator().Allocate<TranslationUnitDecl>();
-  TranslationUnitDecl* decl =
-    new (Mem) TranslationUnitDecl();
+  TranslationUnitDecl* decl = new (Mem) TranslationUnitDecl();
  
   decl->Decl::ReadInRec(D, C);
   
@@ -215,6 +217,30 @@
 }
 
 //===----------------------------------------------------------------------===//
+//      NamespaceDecl Serialization.
+//===----------------------------------------------------------------------===//
+
+void NamespaceDecl::EmitImpl(llvm::Serializer& S) const
+{
+  ScopedDecl::EmitInRec(S);
+  S.Emit(getLBracLoc());
+  S.Emit(getRBracLoc());
+  ScopedDecl::EmitOutRec(S);
+}
+
+NamespaceDecl* NamespaceDecl::CreateImpl(Deserializer& D, ASTContext& C) {  
+  void *Mem = C.getAllocator().Allocate<NamespaceDecl>();
+  NamespaceDecl* decl = new (Mem) NamespaceDecl(0, SourceLocation(), 0);
+ 
+  decl->ScopedDecl::ReadInRec(D, C);
+  decl->LBracLoc = SourceLocation::ReadVal(D);
+  decl->RBracLoc = SourceLocation::ReadVal(D);
+  decl->ScopedDecl::ReadOutRec(D, C);
+  
+  return decl;
+}
+
+//===----------------------------------------------------------------------===//
 //      VarDecl Serialization.
 //===----------------------------------------------------------------------===//
 

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

==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Sun Apr 27 08:50:30 2008
@@ -62,17 +62,25 @@
     // FIXME: Verify no attributes were present.
     // FIXME: parse this.
   } else if (Tok.is(tok::l_brace)) {
+
     SourceLocation LBrace = ConsumeBrace();
-    // FIXME: push a scope, push a namespace decl.
-    
-    while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
-      // FIXME capture the decls.
+
+    // Enter a scope for the namespace.
+    EnterScope(Scope::DeclScope);
+
+    DeclTy *NamespcDecl =
+      Actions.ActOnStartNamespaceDef(CurScope, IdentLoc, Ident, LBrace);
+
+    while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof))
       ParseExternalDeclaration();
-    }
     
     SourceLocation RBrace = MatchRHSPunctuation(tok::r_brace, LBrace);
+    Actions.ActOnFinishNamespaceDef(NamespcDecl, RBrace);
+
+    ExitScope();
+
+    return NamespcDecl;
     
-    // FIXME: act on this.
   } else {
     unsigned D = Ident ? diag::err_expected_lbrace : 
                          diag::err_expected_ident_lbrace;

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

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Sun Apr 27 08:50:30 2008
@@ -552,6 +552,12 @@
                                 ExprTy *expr, TypeTy *type,
                                 SourceLocation RPLoc);
   
+  // Act on C++ namespaces
+  virtual DeclTy *ActOnStartNamespaceDef(Scope *S, SourceLocation IdentLoc,
+                                        IdentifierInfo *Ident,
+                                        SourceLocation LBrace);
+  virtual void ActOnFinishNamespaceDef(DeclTy *Dcl, SourceLocation RBrace);
+
   /// ActOnCXXCasts - Parse {dynamic,static,reinterpret,const}_cast's.
   virtual ExprResult ActOnCXXCasts(SourceLocation OpLoc, tok::TokenKind Kind,
                                    SourceLocation LAngleBracketLoc, TypeTy *Ty,

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Sun Apr 27 08:50:30 2008
@@ -43,7 +43,7 @@
 }
 
 void Sema::PushDeclContext(DeclContext *DC) {
-  assert( ( (DC->isFunctionOrMethod() && isa<TranslationUnitDecl>(CurContext))
+  assert( ( (isa<ObjCMethodDecl>(DC) && isa<TranslationUnitDecl>(CurContext))
             || DC->getParent() == CurContext ) &&
       "The next DeclContext should be directly contained in the current one.");
   CurContext = DC;
@@ -52,7 +52,7 @@
 void Sema::PopDeclContext() {
   assert(CurContext && "DeclContext imbalance!");
   // If CurContext is a ObjC method, getParent() will return NULL.
-  CurContext = CurContext->isFunctionOrMethod()
+  CurContext = isa<ObjCMethodDecl>(CurContext)
                ? Context.getTranslationUnitDecl()
                  :  CurContext->getParent();
 }
@@ -1332,42 +1332,53 @@
   
   // If this is a named struct, check to see if there was a previous forward
   // declaration or definition.
-  if (TagDecl *PrevDecl = 
-          dyn_cast_or_null<TagDecl>(LookupDecl(Name, Decl::IDNS_Tag, S))) {
-    
-    // If this is a use of a previous tag, or if the tag is already declared in
-    // the same scope (so that the definition/declaration completes or
-    // rementions the tag), reuse the decl.
-    if (TK == TK_Reference || S->isDeclScope(PrevDecl)) {
-      // Make sure that this wasn't declared as an enum and now used as a struct
-      // or something similar.
-      if (PrevDecl->getKind() != Kind) {
-        Diag(KWLoc, diag::err_use_with_wrong_tag, Name->getName());
-        Diag(PrevDecl->getLocation(), diag::err_previous_use);
-      }
-      
-      // If this is a use or a forward declaration, we're good.
-      if (TK != TK_Definition)
-        return PrevDecl;
-
-      // Diagnose attempts to redefine a tag.
-      if (PrevDecl->isDefinition()) {
-        Diag(NameLoc, diag::err_redefinition, Name->getName());
-        Diag(PrevDecl->getLocation(), diag::err_previous_definition);
-        // If this is a redefinition, recover by making this struct be
-        // anonymous, which will make any later references get the previous
-        // definition.
-        Name = 0;
-      } else {
-        // Okay, this is definition of a previously declared or referenced tag.
-        // Move the location of the decl to be the definition site.
-        PrevDecl->setLocation(NameLoc);
-        return PrevDecl;
+  // Use ScopedDecl instead of TagDecl, because a NamespaceDecl may come up.
+  if (ScopedDecl *PrevDecl = 
+          dyn_cast_or_null<ScopedDecl>(LookupDecl(Name, Decl::IDNS_Tag, S))) {
+    
+    assert((isa<TagDecl>(PrevDecl) || isa<NamespaceDecl>(PrevDecl)) &&
+            "unexpected Decl type");
+    if (TagDecl *PrevTagDecl = dyn_cast<TagDecl>(PrevDecl)) {
+      // If this is a use of a previous tag, or if the tag is already declared in
+      // the same scope (so that the definition/declaration completes or
+      // rementions the tag), reuse the decl.
+      if (TK == TK_Reference || S->isDeclScope(PrevDecl)) {
+        // Make sure that this wasn't declared as an enum and now used as a struct
+        // or something similar.
+        if (PrevDecl->getKind() != Kind) {
+          Diag(KWLoc, diag::err_use_with_wrong_tag, Name->getName());
+          Diag(PrevDecl->getLocation(), diag::err_previous_use);
+        }
+        
+        // If this is a use or a forward declaration, we're good.
+        if (TK != TK_Definition)
+          return PrevDecl;
+
+        // Diagnose attempts to redefine a tag.
+        if (PrevTagDecl->isDefinition()) {
+          Diag(NameLoc, diag::err_redefinition, Name->getName());
+          Diag(PrevDecl->getLocation(), diag::err_previous_definition);
+          // If this is a redefinition, recover by making this struct be
+          // anonymous, which will make any later references get the previous
+          // definition.
+          Name = 0;
+        } else {
+          // Okay, this is definition of a previously declared or referenced tag.
+          // Move the location of the decl to be the definition site.
+          PrevDecl->setLocation(NameLoc);
+          return PrevDecl;
+        }
       }
+      // If we get here, this is a definition of a new struct type in a nested
+      // scope, e.g. "struct foo; void bar() { struct foo; }", just create a new
+      // type.
+    } else {
+      // The tag name clashes with a namespace name, issue an error and recover
+      // by making this tag be anonymous.
+      Diag(NameLoc, diag::err_redefinition_different_kind, Name->getName());
+      Diag(PrevDecl->getLocation(), diag::err_previous_definition);
+      Name = 0;
     }
-    // If we get here, this is a definition of a new struct type in a nested
-    // scope, e.g. "struct foo; void bar() { struct foo; }", just create a new
-    // type.
   }
   
   // If there is an identifier, use the location of the identifier as the

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Sun Apr 27 08:50:30 2008
@@ -17,6 +17,7 @@
 #include "clang/AST/Expr.h"
 #include "clang/AST/StmtVisitor.h"
 #include "clang/AST/Type.h"
+#include "clang/Parse/Scope.h"
 #include "llvm/ADT/OwningPtr.h"
 #include "llvm/Support/Compiler.h"
 
@@ -284,3 +285,79 @@
 
   // FIXME: Attach base class to the record.
 }
+
+
+//===----------------------------------------------------------------------===//
+// Namespace Handling
+//===----------------------------------------------------------------------===//
+
+/// ActOnStartNamespaceDef - This is called at the start of a namespace
+/// definition.
+Sema::DeclTy *Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
+                                           SourceLocation IdentLoc,
+                                           IdentifierInfo *II,
+                                           SourceLocation LBrace) {
+  NamespaceDecl *Namespc =
+      NamespaceDecl::Create(Context, CurContext, IdentLoc, II);
+  Namespc->setLBracLoc(LBrace);
+
+  Scope *DeclRegionScope = NamespcScope->getParent();
+
+  if (II) {
+    // C++ [namespace.def]p2:
+    // The identifier in an original-namespace-definition shall not have been
+    // previously defined in the declarative region in which the
+    // original-namespace-definition appears. The identifier in an
+    // original-namespace-definition is the name of the namespace. Subsequently
+    // in that declarative region, it is treated as an original-namespace-name.
+
+    Decl *PrevDecl =
+        LookupDecl(II, Decl::IDNS_Tag | Decl::IDNS_Ordinary, DeclRegionScope,
+                   /*enableLazyBuiltinCreation=*/false);
+
+    if (PrevDecl && DeclRegionScope->isDeclScope(PrevDecl)) {
+      if (NamespaceDecl *OrigNS = dyn_cast<NamespaceDecl>(PrevDecl)) {
+        // This is an extended namespace definition.
+        // Attach this namespace decl to the chain of extended namespace
+        // definitions.
+        NamespaceDecl *NextNS = OrigNS;
+        while (NextNS->getNextNamespace())
+          NextNS = NextNS->getNextNamespace();
+
+        NextNS->setNextNamespace(Namespc);
+        Namespc->setOriginalNamespace(OrigNS);
+
+        // We won't add this decl to the current scope. We want the namespace
+        // name to return the original namespace decl during a name lookup.
+      } else {
+        // This is an invalid name redefinition.
+        Diag(Namespc->getLocation(), diag::err_redefinition_different_kind,
+          Namespc->getName());
+        Diag(PrevDecl->getLocation(), diag::err_previous_definition);
+        Namespc->setInvalidDecl();
+        // Continue on to push Namespc as current DeclContext and return it.
+      }
+    } else {
+      // This namespace name is declared for the first time.
+      PushOnScopeChains(Namespc, DeclRegionScope);
+    }
+  }
+  else {
+    // FIXME: Handle anonymous namespaces
+  }
+
+  // Although we could have an invalid decl (i.e. the namespace name is a
+  // redefinition), push it as current DeclContext and try to continue parsing.
+  PushDeclContext(Namespc->getOriginalNamespace());
+  return Namespc;
+}
+
+/// ActOnFinishNamespaceDef - This callback is called after a namespace is
+/// exited. Decl is the DeclTy returned by ActOnStartNamespaceDef.
+void Sema::ActOnFinishNamespaceDef(DeclTy *D, SourceLocation RBrace) {
+  Decl *Dcl = static_cast<Decl *>(D);
+  NamespaceDecl *Namespc = dyn_cast_or_null<NamespaceDecl>(Dcl);
+  assert(Namespc && "Invalid parameter, expected NamespaceDecl");
+  Namespc->setRBracLoc(RBrace);
+  PopDeclContext();
+}

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Sun Apr 27 08:50:30 2008
@@ -128,6 +128,8 @@
     return Diag(Loc, diag::err_unexpected_typedef, II.getName());
   if (isa<ObjCInterfaceDecl>(D))
     return Diag(Loc, diag::err_unexpected_interface, II.getName());
+  if (isa<NamespaceDecl>(D))
+    return Diag(Loc, diag::err_unexpected_namespace, II.getName());
 
   assert(0 && "Invalid decl");
   abort();
@@ -2313,3 +2315,5 @@
   return isInvalid;
 }
 
+
+

Added: cfe/trunk/test/Sema/cxx-namespace.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/cxx-namespace.cpp?rev=50321&view=auto

==============================================================================
--- cfe/trunk/test/Sema/cxx-namespace.cpp (added)
+++ cfe/trunk/test/Sema/cxx-namespace.cpp Sun Apr 27 08:50:30 2008
@@ -0,0 +1,15 @@
+// RUN: clang -fsyntax-only -verify %s 
+namespace A { // expected-error {{error: previous definition is here}}
+  int A;
+  void f() { A = 0; }
+}
+
+void f() { A = 0; } // expected-error {{error: unexpected namespace name 'A': expected expression}}
+int A; // expected-error {{error: redefinition of 'A' as different kind of symbol}}
+class A; // expected-error {{error: redefinition of 'A' as different kind of symbol}}
+
+class B; // expected-error {{error: previous definition is here}}
+namespace B {} // expected-error {{error: redefinition of 'B' as different kind of symbol}}
+
+void C(); // expected-error {{error: previous definition is here}}
+namespace C {} // expected-error {{error: redefinition of 'C' as different kind of symbol}}





More information about the cfe-commits mailing list