]> granicus.if.org Git - clang/commitdiff
Just add global scope to the associated namespaces set instead of tracking it
authorJohn McCall <rjmccall@apple.com>
Fri, 7 Aug 2009 22:18:02 +0000 (22:18 +0000)
committerJohn McCall <rjmccall@apple.com>
Fri, 7 Aug 2009 22:18:02 +0000 (22:18 +0000)
separately.  Add the framework (currently unfed) for finding friend declarations
during argument-dependent lookup.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@78414 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/DeclBase.h
lib/Sema/Sema.h
lib/Sema/SemaLookup.cpp

index 5dd25d8a9c50f63804167c7796c079cb3203e26c..ea782c9a66acd6f2a390661f67e7dac4b7e50cfc 100644 (file)
@@ -87,7 +87,8 @@ public:
     IDNS_Ordinary = 0x8,
     IDNS_ObjCProtocol = 0x10,
     IDNS_ObjCImplementation = 0x20,
-    IDNS_ObjCCategoryImpl = 0x40
+    IDNS_ObjCCategoryImpl = 0x40,
+    IDNS_Friend = 0x80
   };
   
   /// ObjCDeclQualifier - Qualifier used on types in method declarations
index e9190fbbe914862c84f205c2f1d9f4dd57f07b31..e83fcf579fd9652fafd81c624d4013aafa96f714 100644 (file)
@@ -735,8 +735,11 @@ public:
     OR_Deleted              ///< Overload resoltuion refers to a deleted function.
   };
 
+  // Members have to be NamespaceDecl* or TranslationUnitDecl*.
+  // TODO: make this is a typesafe union.
+  typedef llvm::SmallPtrSet<DeclContext   *, 16> AssociatedNamespaceSet;
+
   typedef llvm::SmallPtrSet<AnyFunctionDecl, 16> FunctionSet;
-  typedef llvm::SmallPtrSet<NamespaceDecl *, 16> AssociatedNamespaceSet;
   typedef llvm::SmallPtrSet<CXXRecordDecl *, 16> AssociatedClassSet;
 
   void AddOverloadCandidate(FunctionDecl *Function, 
@@ -1214,8 +1217,7 @@ public:
 
   void FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs,
                                    AssociatedNamespaceSet &AssociatedNamespaces,
-                                   AssociatedClassSet &AssociatedClasses,
-                                          bool &GlobalScope);
+                                   AssociatedClassSet &AssociatedClasses);
 
   bool DiagnoseAmbiguousLookup(LookupResult &Result, DeclarationName Name,
                                SourceLocation NameLoc, 
index 43494cf4aaa53aa0f0f951aa4770ed36f6b21d48..ef105374fac63782b5dd549f8c0dac74f68a9742 100644 (file)
@@ -1246,8 +1246,13 @@ static void
 addAssociatedClassesAndNamespaces(QualType T, 
                                   ASTContext &Context,
                           Sema::AssociatedNamespaceSet &AssociatedNamespaces,
-                                  Sema::AssociatedClassSet &AssociatedClasses,
-                                  bool &GlobalScope);
+                                  Sema::AssociatedClassSet &AssociatedClasses);
+
+static void CollectNamespace(Sema::AssociatedNamespaceSet &Namespaces,
+                             DeclContext *Ctx) {
+  if (Ctx->isFileContext())
+    Namespaces.insert(Ctx);
+}
 
 // \brief Add the associated classes and namespaces for argument-dependent 
 // lookup that involves a template argument (C++ [basic.lookup.koenig]p2).
@@ -1255,8 +1260,7 @@ static void
 addAssociatedClassesAndNamespaces(const TemplateArgument &Arg, 
                                   ASTContext &Context,
                            Sema::AssociatedNamespaceSet &AssociatedNamespaces,
-                                  Sema::AssociatedClassSet &AssociatedClasses,
-                                  bool &GlobalScope) {
+                                  Sema::AssociatedClassSet &AssociatedClasses) {
   // C++ [basic.lookup.koenig]p2, last bullet:
   //   -- [...] ;  
   switch (Arg.getKind()) {
@@ -1269,8 +1273,7 @@ addAssociatedClassesAndNamespaces(const TemplateArgument &Arg,
       // template template parameters)
       addAssociatedClassesAndNamespaces(Arg.getAsType(), Context,
                                         AssociatedNamespaces,
-                                        AssociatedClasses,
-                                        GlobalScope);
+                                        AssociatedClasses);
       break;
       
     case TemplateArgument::Declaration:
@@ -1285,10 +1288,7 @@ addAssociatedClassesAndNamespaces(const TemplateArgument &Arg,
         // Add the associated namespace for this class.
         while (Ctx->isRecord())
           Ctx = Ctx->getParent();
-        if (NamespaceDecl *EnclosingNamespace = dyn_cast<NamespaceDecl>(Ctx))
-          AssociatedNamespaces.insert(EnclosingNamespace);
-        else if (Ctx->isTranslationUnit())
-          GlobalScope = true;
+        CollectNamespace(AssociatedNamespaces, Ctx);
       }
       break;
       
@@ -1304,8 +1304,7 @@ addAssociatedClassesAndNamespaces(const TemplateArgument &Arg,
            P != PEnd; ++P)
         addAssociatedClassesAndNamespaces(*P, Context,
                                           AssociatedNamespaces,
-                                          AssociatedClasses,
-                                          GlobalScope);
+                                          AssociatedClasses);
       break;
   }
 }
@@ -1317,8 +1316,7 @@ static void
 addAssociatedClassesAndNamespaces(CXXRecordDecl *Class, 
                                   ASTContext &Context,
                             Sema::AssociatedNamespaceSet &AssociatedNamespaces,
-                            Sema::AssociatedClassSet &AssociatedClasses,
-                                  bool &GlobalScope) {
+                            Sema::AssociatedClassSet &AssociatedClasses) {
   // C++ [basic.lookup.koenig]p2:
   //   [...]
   //     -- If T is a class type (including unions), its associated
@@ -1334,10 +1332,7 @@ addAssociatedClassesAndNamespaces(CXXRecordDecl *Class,
   // Add the associated namespace for this class.
   while (Ctx->isRecord())
     Ctx = Ctx->getParent();
-  if (NamespaceDecl *EnclosingNamespace = dyn_cast<NamespaceDecl>(Ctx))
-    AssociatedNamespaces.insert(EnclosingNamespace);
-  else if (Ctx->isTranslationUnit())
-    GlobalScope = true;
+  CollectNamespace(AssociatedNamespaces, Ctx);
   
   // Add the class itself. If we've already seen this class, we don't
   // need to visit base classes.
@@ -1361,17 +1356,13 @@ addAssociatedClassesAndNamespaces(CXXRecordDecl *Class,
     // Add the associated namespace for this class.
     while (Ctx->isRecord())
       Ctx = Ctx->getParent();
-    if (NamespaceDecl *EnclosingNamespace = dyn_cast<NamespaceDecl>(Ctx))
-      AssociatedNamespaces.insert(EnclosingNamespace);
-    else if (Ctx->isTranslationUnit())
-      GlobalScope = true;
+    CollectNamespace(AssociatedNamespaces, Ctx);
     
     const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
     for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
       addAssociatedClassesAndNamespaces(TemplateArgs[I], Context,
                                         AssociatedNamespaces,
-                                        AssociatedClasses,
-                                        GlobalScope);
+                                        AssociatedClasses);
   }
   
   // Add direct and indirect base classes along with their associated
@@ -1394,11 +1385,7 @@ addAssociatedClassesAndNamespaces(CXXRecordDecl *Class,
         DeclContext *BaseCtx = BaseDecl->getDeclContext();
         while (BaseCtx->isRecord())
           BaseCtx = BaseCtx->getParent();
-        if (NamespaceDecl *EnclosingNamespace 
-              = dyn_cast<NamespaceDecl>(BaseCtx))
-          AssociatedNamespaces.insert(EnclosingNamespace);
-        else if (BaseCtx->isTranslationUnit())
-          GlobalScope = true;
+        CollectNamespace(AssociatedNamespaces, BaseCtx);
 
         // Make sure we visit the bases of this base class.
         if (BaseDecl->bases_begin() != BaseDecl->bases_end())
@@ -1415,8 +1402,7 @@ static void
 addAssociatedClassesAndNamespaces(QualType T, 
                                   ASTContext &Context,
                             Sema::AssociatedNamespaceSet &AssociatedNamespaces,
-                                  Sema::AssociatedClassSet &AssociatedClasses,
-                                  bool &GlobalScope) {
+                                  Sema::AssociatedClassSet &AssociatedClasses) {
   // C++ [basic.lookup.koenig]p2:
   //
   //   For each argument type T in the function call, there is a set
@@ -1458,8 +1444,7 @@ addAssociatedClassesAndNamespaces(QualType T,
         = dyn_cast<CXXRecordDecl>(ClassType->getDecl())) {
       addAssociatedClassesAndNamespaces(ClassDecl, Context, 
                                         AssociatedNamespaces, 
-                                        AssociatedClasses,
-                                        GlobalScope);
+                                        AssociatedClasses);
       return;
     }
 
@@ -1477,10 +1462,7 @@ addAssociatedClassesAndNamespaces(QualType T,
     // Add the associated namespace for this class.
     while (Ctx->isRecord())
       Ctx = Ctx->getParent();
-    if (NamespaceDecl *EnclosingNamespace = dyn_cast<NamespaceDecl>(Ctx))
-      AssociatedNamespaces.insert(EnclosingNamespace);
-    else if (Ctx->isTranslationUnit())
-      GlobalScope = true;
+    CollectNamespace(AssociatedNamespaces, Ctx);
 
     return;
   }
@@ -1492,8 +1474,7 @@ addAssociatedClassesAndNamespaces(QualType T,
     // Return type
     addAssociatedClassesAndNamespaces(FunctionType->getResultType(), 
                                       Context,
-                                      AssociatedNamespaces, AssociatedClasses,
-                                      GlobalScope);
+                                      AssociatedNamespaces, AssociatedClasses);
 
     const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FunctionType);
     if (!Proto)
@@ -1504,8 +1485,7 @@ addAssociatedClassesAndNamespaces(QualType T,
                                            ArgEnd = Proto->arg_type_end(); 
          Arg != ArgEnd; ++Arg)
       addAssociatedClassesAndNamespaces(*Arg, Context,
-                                        AssociatedNamespaces, AssociatedClasses,
-                                        GlobalScope);
+                                        AssociatedNamespaces, AssociatedClasses);
       
     return;
   }
@@ -1523,15 +1503,15 @@ addAssociatedClassesAndNamespaces(QualType T,
     // Handle the type that the pointer to member points to.
     addAssociatedClassesAndNamespaces(MemberPtr->getPointeeType(),
                                       Context,
-                                      AssociatedNamespaces, AssociatedClasses,
-                                      GlobalScope);
+                                      AssociatedNamespaces,
+                                      AssociatedClasses);
 
     // Handle the class type into which this points.
     if (const RecordType *Class = MemberPtr->getClass()->getAs<RecordType>())
       addAssociatedClassesAndNamespaces(cast<CXXRecordDecl>(Class->getDecl()),
                                         Context,
-                                        AssociatedNamespaces, AssociatedClasses,
-                                        GlobalScope);
+                                        AssociatedNamespaces,
+                                        AssociatedClasses);
 
     return;
   }
@@ -1550,8 +1530,7 @@ addAssociatedClassesAndNamespaces(QualType T,
 void 
 Sema::FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs,
                                  AssociatedNamespaceSet &AssociatedNamespaces,
-                                 AssociatedClassSet &AssociatedClasses,
-                                         bool &GlobalScope) {
+                                 AssociatedClassSet &AssociatedClasses) {
   AssociatedNamespaces.clear();
   AssociatedClasses.clear();
 
@@ -1567,8 +1546,8 @@ Sema::FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs,
 
     if (Arg->getType() != Context.OverloadTy) {
       addAssociatedClassesAndNamespaces(Arg->getType(), Context,
-                                        AssociatedNamespaces, AssociatedClasses,
-                                        GlobalScope);
+                                        AssociatedNamespaces,
+                                        AssociatedClasses);
       continue;
     }
 
@@ -1611,16 +1590,13 @@ Sema::FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs,
       // that, if this is a member function, we do *not* consider the
       // enclosing namespace of its class.
       DeclContext *Ctx = FDecl->getDeclContext();
-      if (NamespaceDecl *EnclosingNamespace = dyn_cast<NamespaceDecl>(Ctx))
-        AssociatedNamespaces.insert(EnclosingNamespace);
-      else if (Ctx->isTranslationUnit())
-        GlobalScope = true;
+      CollectNamespace(AssociatedNamespaces, Ctx);
 
       // Add the classes and namespaces associated with the parameter
       // types and return type of this function.
       addAssociatedClassesAndNamespaces(FDecl->getType(), Context,
-                                        AssociatedNamespaces, AssociatedClasses,
-                                        GlobalScope);
+                                        AssociatedNamespaces,
+                                        AssociatedClasses);
     }
   }
 }
@@ -1736,6 +1712,14 @@ void Sema::LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S,
   }
 }
 
+static void CollectFunctionDecl(Sema::FunctionSet &Functions,
+                                Decl *D) {
+  if (FunctionDecl *Func = dyn_cast<FunctionDecl>(D))
+    Functions.insert(Func);
+  else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D))
+    Functions.insert(FunTmpl);
+}
+
 void Sema::ArgumentDependentLookup(DeclarationName Name,
                                    Expr **Args, unsigned NumArgs,
                                    FunctionSet &Functions) {
@@ -1743,10 +1727,9 @@ void Sema::ArgumentDependentLookup(DeclarationName Name,
   // arguments we have.
   AssociatedNamespaceSet AssociatedNamespaces;
   AssociatedClassSet AssociatedClasses;
-  bool GlobalScope = false;
   FindAssociatedClassesAndNamespaces(Args, NumArgs, 
-                                     AssociatedNamespaces, AssociatedClasses,
-                                     GlobalScope);
+                                     AssociatedNamespaces,
+                                     AssociatedClasses);
 
   // C++ [basic.lookup.argdep]p3:
   //   Let X be the lookup set produced by unqualified lookup (3.4.1)
@@ -1769,28 +1752,33 @@ void Sema::ArgumentDependentLookup(DeclarationName Name,
     //     -- Any using-directives in the associated namespace are
     //        ignored.
     //
-    //     -- FIXME: Any namespace-scope friend functions declared in
+    //     -- Any namespace-scope friend functions declared in
     //        associated classes are visible within their respective
     //        namespaces even if they are not visible during an ordinary
     //        lookup (11.4).
+    //
+    // We implement the second clause in the loop below.
     DeclContext::lookup_iterator I, E;
-    for (llvm::tie(I, E) = (*NS)->lookup(Name); I != E; ++I) {
-      if (FunctionDecl *Func = dyn_cast<FunctionDecl>(*I))
-        Functions.insert(Func);
-      else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(*I))
-        Functions.insert(FunTmpl);
-    }
+    for (llvm::tie(I, E) = (*NS)->lookup(Name); I != E; ++I)
+      CollectFunctionDecl(Functions, *I);
   }
-  
-  if (GlobalScope) {
+
+  // Look for friend function declarations in associated classes
+  // which name functions in associated namespaces.
+  for (AssociatedClassSet::iterator AC = AssociatedClasses.begin(),
+                                 ACEnd = AssociatedClasses.end();
+       AC != ACEnd; ++AC) {
     DeclContext::lookup_iterator I, E;
-    for (llvm::tie(I, E) 
-           = Context.getTranslationUnitDecl()->lookup(Name); 
-         I != E; ++I) {
-      if (FunctionDecl *Func = dyn_cast<FunctionDecl>(*I))
-        Functions.insert(Func);
-      else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(*I))
-        Functions.insert(FunTmpl);
+    for (llvm::tie(I, E) = (*AC)->lookup(Name); I != E; ++I) {
+      Decl *D = *I;
+      if (!D->isInIdentifierNamespace(Decl::IDNS_Friend))
+        continue;
+
+      DeclContext *DC = D->getDeclContext();
+      if (!AssociatedNamespaces.count(DC))
+        continue;
+
+      CollectFunctionDecl(Functions, D);
     }
   }
 }