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");
   }