Semantic analysis, ASTs, and unqualified name lookup support for C++
using directives, from Piotr Rak!
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@63646 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 0a3801a..6bc02e0 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/Expr.h"
@@ -146,6 +147,13 @@
bool NamedDecl::declarationReplaces(NamedDecl *OldD) const {
assert(getDeclName() == OldD->getDeclName() && "Declaration name mismatch");
+ // UsingDirectiveDecl's are not really NamedDecl's, and all have same name.
+ // We want to keep it, unless it nominates same namespace.
+ if (getKind() == Decl::UsingDirective) {
+ return cast<UsingDirectiveDecl>(this)->getNominatedNamespace() ==
+ cast<UsingDirectiveDecl>(OldD)->getNominatedNamespace();
+ }
+
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(this))
// For function declarations, we keep track of redeclarations.
return FD->getPreviousDeclaration() == OldD;
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index 6d0cda1..21e1e0c 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -499,8 +499,9 @@
// [FirstMatch, LastMatch) contains the set of declarations that
// have the same name as this declaration. Determine where the
- // declaration D will be inserted into this range.
- if (D->getIdentifierNamespace() == Decl::IDNS_Tag)
+ // declaration D will be inserted into this range.
+ if (D->getKind() == Decl::UsingDirective ||
+ D->getIdentifierNamespace() == Decl::IDNS_Tag)
InsertPos = LastMatch;
else if (Array[LastMatch-1]->getIdentifierNamespace() == Decl::IDNS_Tag)
InsertPos = LastMatch - 1;
@@ -549,7 +550,9 @@
}
// Put this declaration into the appropriate slot.
- if (D->getIdentifierNamespace() == Decl::IDNS_Tag || Pos->second.empty())
+ if (D->getKind() == Decl::UsingDirective ||
+ D->getIdentifierNamespace() == Decl::IDNS_Tag
+ || Pos->second.empty())
Pos->second.push_back(D);
else if (Pos->second.back()->getIdentifierNamespace() == Decl::IDNS_Tag) {
NamedDecl *TagD = Pos->second.back();
@@ -561,3 +564,12 @@
(*Map)[D->getDeclName()].push_back(D);
}
}
+
+/// Returns iterator range [First, Last) of UsingDirectiveDecls stored within
+/// this context.
+DeclContext::udir_iterator_range DeclContext::getUsingDirectives() const {
+ lookup_const_result Result = lookup(UsingDirectiveDecl::getName());
+ return udir_iterator_range(reinterpret_cast<udir_iterator>(Result.first),
+ reinterpret_cast<udir_iterator>(Result.second));
+}
+
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 39ca878..5e1875a 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -363,3 +363,14 @@
LanguageIDs Lang, bool Braces) {
return new (C) LinkageSpecDecl(DC, L, Lang, Braces);
}
+
+UsingDirectiveDecl *UsingDirectiveDecl::Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L,
+ SourceLocation NamespaceLoc,
+ SourceLocation IdentLoc,
+ NamespaceDecl *Used,
+ DeclContext *CommonAncestor) {
+ return new (C) UsingDirectiveDecl(DC, L, NamespaceLoc, IdentLoc,
+ Used, CommonAncestor);
+}
+
diff --git a/lib/AST/DeclSerialization.cpp b/lib/AST/DeclSerialization.cpp
index 5b881f2..a10b229 100644
--- a/lib/AST/DeclSerialization.cpp
+++ b/lib/AST/DeclSerialization.cpp
@@ -203,6 +203,10 @@
case DeclarationName::CXXOperatorName:
S.EmitInt(Name.getCXXOverloadedOperator());
break;
+
+ case DeclarationName::CXXUsingDirective:
+ // No extra data to emit
+ break;
}
}
@@ -242,6 +246,10 @@
Name = C.DeclarationNames.getCXXOperatorName(Op);
break;
}
+
+ case DeclarationName::CXXUsingDirective:
+ Name = DeclarationName::getUsingDirectiveName();
+ break;
}
}
diff --git a/lib/AST/DeclarationName.cpp b/lib/AST/DeclarationName.cpp
index ae579c2..0a6adef 100644
--- a/lib/AST/DeclarationName.cpp
+++ b/lib/AST/DeclarationName.cpp
@@ -95,10 +95,13 @@
case DeclarationNameExtra::CXXConversionFunction:
return CXXConversionFunctionName;
+ case DeclarationNameExtra::CXXUsingDirective:
+ return CXXUsingDirective;
+
default:
// Check if we have one of the CXXOperator* enumeration values.
if (getExtra()->ExtraKindOrNumArgs <
- DeclarationNameExtra::NUM_EXTRA_KINDS)
+ DeclarationNameExtra::CXXUsingDirective)
return CXXOperatorName;
return ObjCMultiArgSelector;
@@ -165,6 +168,8 @@
Result += Type.getAsString();
return Result;
}
+ case CXXUsingDirective:
+ return "<using-directive>";
}
assert(false && "Unexpected declaration name kind");
@@ -246,6 +251,17 @@
}
}
+DeclarationName DeclarationName::getUsingDirectiveName() {
+ // Single instance of DeclarationNameExtra for using-directive
+ static DeclarationNameExtra UDirExtra =
+ { DeclarationNameExtra::CXXUsingDirective };
+
+ uintptr_t Ptr = reinterpret_cast<uintptr_t>(&UDirExtra);
+ Ptr |= StoredDeclarationNameExtra;
+
+ return DeclarationName(Ptr);
+}
+
DeclarationNameTable::DeclarationNameTable() {
CXXSpecialNamesImpl = new llvm::FoldingSet<CXXSpecialName>;
diff --git a/lib/AST/StmtDumper.cpp b/lib/AST/StmtDumper.cpp
index 83313ed..87a9f8e 100644
--- a/lib/AST/StmtDumper.cpp
+++ b/lib/AST/StmtDumper.cpp
@@ -14,6 +14,7 @@
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/Support/Compiler.h"
#include <cstdio>
@@ -247,6 +248,14 @@
tagname = "<anonymous>";
fprintf(F, "\"%s %s;\"", TD->getKindName(), tagname);
// FIXME: print tag bodies.
+ } else if (UsingDirectiveDecl *UD = dyn_cast<UsingDirectiveDecl>(D)) {
+ // print using-directive decl (e.g. "using namespace x;")
+ const char *ns;
+ if (const IdentifierInfo *II = UD->getNominatedNamespace()->getIdentifier())
+ ns = II->getName();
+ else
+ ns = "<anonymous>";
+ fprintf(F, "\"%s %s;\"",UD->getDeclKindName(), ns);
} else {
assert(0 && "Unexpected decl");
}