Parser support for C++ using directives, from Piotr Rak

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@61486 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 3866390..ca15176 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -491,11 +491,25 @@
   void CheckCXXDefaultArguments(FunctionDecl *FD);
   void CheckExtraCXXDefaultArguments(Declarator &D);
 
+  // FIXME: NamespaceNameOnly parameter is added temporarily
+  // we will need a better way to specify lookup criteria for things
+  // like template specializations, explicit template instatatiation etc.
+
   /// More parsing and symbol table subroutines...
   Decl *LookupDecl(DeclarationName Name, unsigned NSI, Scope *S,
                    const DeclContext *LookupCtx = 0,
                    bool enableLazyBuiltinCreation = true,
-                  bool LookInParent = true);
+                   bool LookInParent = true,
+                   bool NamespaceNameOnly = false);
+
+  Decl *LookupNamespaceName(DeclarationName Name, Scope *S,
+                            const DeclContext *LookupCtx) {
+    return LookupDecl(Name, Decl::IDNS_Tag | Decl::IDNS_Ordinary, S,
+                      LookupCtx,
+                      /* enableLazyBuiltinCreation */ false,
+                      /* LookInParent */ true,
+                      /* NamespaceNameOnly */ true);
+  }
   ObjCInterfaceDecl *getObjCInterfaceDecl(IdentifierInfo *Id);
   ScopedDecl *LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID, 
                                   Scope *S);
@@ -807,6 +821,14 @@
                                         SourceLocation LBrace);
   virtual void ActOnFinishNamespaceDef(DeclTy *Dcl, SourceLocation RBrace);
 
+  virtual DeclTy *ActOnUsingDirective(Scope *CurScope,
+                                      SourceLocation UsingLoc,
+                                      SourceLocation NamespcLoc,
+                                      const CXXScopeSpec &SS,
+                                      SourceLocation IdentLoc,
+                                      IdentifierInfo *NamespcName,
+                                      AttributeList *AttrList);
+
   /// AddCXXDirectInitializerToDecl - This action is called immediately after 
   /// ActOnDeclarator, when a C++ direct initializer is present.
   /// e.g: "int x(1);"
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 875f0f1..21d3ad6 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -243,11 +243,15 @@
 }
 
 /// LookupDecl - Look up the inner-most declaration in the specified
-/// namespace.
+/// namespace. NamespaceNameOnly - during lookup only namespace names
+/// are considered as required in C++ [basic.lookup.udir] 3.4.6.p1
+/// 'When looking up a namespace-name in a using-directive or
+/// namespace-alias-definition, only namespace names are considered.'
 Decl *Sema::LookupDecl(DeclarationName Name, unsigned NSI, Scope *S,
                        const DeclContext *LookupCtx,
                        bool enableLazyBuiltinCreation,
-                       bool LookInParent) {
+                       bool LookInParent,
+                       bool NamespaceNameOnly) {
   if (!Name) return 0;
   unsigned NS = NSI;
   if (getLangOptions().CPlusPlus && (NS & Decl::IDNS_Ordinary))
@@ -259,6 +263,7 @@
     // labels in C++ is purely lexical, so search in the
     // declarations attached to the name.
     assert(!LookupCtx && "Can't perform qualified name lookup here");
+    assert(!NamespaceNameOnly && "Can't perform namespace name lookup here");
     IdentifierResolver::iterator I
       = IdResolver.begin(Name, CurContext, LookInParent);
     
@@ -268,14 +273,19 @@
     // deep shadowing is extremely uncommon.
     for (; I != IdResolver.end(); ++I)
       if ((*I)->getIdentifierNamespace() & NS)
-         return *I;
+        return *I;
   } else if (LookupCtx) {
     // Perform qualified name lookup into the LookupCtx.
     // FIXME: Will need to look into base classes and such.
     DeclContext::lookup_const_iterator I, E;
     for (llvm::tie(I, E) = LookupCtx->lookup(Context, Name); I != E; ++I)
-      if ((*I)->getIdentifierNamespace() & NS)
-        return MaybeConstructOverloadSet(Context, I, E);
+      if ((*I)->getIdentifierNamespace() & NS) {
+        if (NamespaceNameOnly && !isa<NamespaceDecl>(*I)) {
+          // Skip non-namespace name.
+        } else {
+          return MaybeConstructOverloadSet(Context, I, E);
+        }
+      }
   } else {
     // Name lookup for ordinary names and tag names in C++ requires
     // looking into scopes that aren't strictly lexical, and
@@ -289,17 +299,21 @@
       // FIXME: The isDeclScope check could be expensive. Can we do better?
       for (; I != IEnd && S->isDeclScope(*I); ++I) {
         if ((*I)->getIdentifierNamespace() & NS) {
-          // We found something. Look for anything else in our scope
-          // with this same name and in an acceptable identifier
-          // namespace, so that we can construct an overload set if we
-          // need to.
-          IdentifierResolver::iterator LastI = I;
-          for (++LastI; LastI != IEnd; ++LastI) {
-            if (((*LastI)->getIdentifierNamespace() & NS) == 0 ||
-                !S->isDeclScope(*LastI))
-              break;
+          if (NamespaceNameOnly && !isa<NamespaceDecl>(*I)) {
+            // Skip non-namespace name.
+          } else {
+            // We found something. Look for anything else in our scope
+            // with this same name and in an acceptable identifier
+            // namespace, so that we can construct an overload set if we
+            // need to.
+            IdentifierResolver::iterator LastI = I;
+            for (++LastI; LastI != IEnd; ++LastI) {
+              if (((*LastI)->getIdentifierNamespace() & NS) == 0 ||
+                  !S->isDeclScope(*LastI))
+                break;
+            }
+            return MaybeConstructOverloadSet(Context, I, LastI);
           }
-          return MaybeConstructOverloadSet(Context, I, LastI);
         }
       }
       
@@ -314,8 +328,10 @@
         DeclContext::lookup_const_iterator I, E;
         for (llvm::tie(I, E) = Ctx->lookup(Context, Name); I != E; ++I) {
           // FIXME: Cache this result in the IdResolver
-          if ((*I)->getIdentifierNamespace() & NS)
-            return MaybeConstructOverloadSet(Context, I, E);
+          if ((*I)->getIdentifierNamespace() & NS) {
+            if (NamespaceNameOnly && !isa<NamespaceDecl>(*I)) {}
+            else return MaybeConstructOverloadSet(Context, I, E);
+          }
         }
         
         Ctx = Ctx->getParent();
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 5ba2850..e3c8373 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -1349,6 +1349,34 @@
   PopDeclContext();
 }
 
+Sema::DeclTy *Sema::ActOnUsingDirective(Scope *S,
+                                        SourceLocation UsingLoc,
+                                        SourceLocation NamespcLoc,
+                                        const CXXScopeSpec &SS,
+                                        SourceLocation IdentLoc,
+                                        IdentifierInfo *NamespcName,
+                                        AttributeList *AttrList) {
+  assert(!SS.isInvalid() && "Invalid CXXScopeSpec.");
+  assert(NamespcName && "Invalid NamespcName.");
+  assert(IdentLoc.isValid() && "Invalid NamespceName location.");
+
+  // FIXME: This still requires lot more checks, and AST support.
+  // Lookup namespace name.
+  DeclContext *DC = static_cast<DeclContext*>(SS.getScopeRep());
+  Decl *NS = 0;
+
+  if ((NS = LookupNamespaceName(NamespcName, S, DC))) {
+    assert(isa<NamespaceDecl>(NS) && "expected namespace decl");
+  } else {
+    DiagnosticBuilder Builder = Diag(IdentLoc, diag::err_expected_namespace_name);
+    if (SS.isSet())
+      Builder << SS.getRange();
+  }
+
+  // FIXME: We ignore AttrList for now, and delete it to avoid leak.
+  delete AttrList;
+  return 0;
+}
 
 /// AddCXXDirectInitializerToDecl - This action is called immediately after 
 /// ActOnDeclarator, when a C++ direct initializer is present.