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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@50321 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 373aace..61cfa79 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -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))) {
+ // 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))) {
- // 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;
+ 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 (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;
+ // 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