[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