[cfe-commits] r82954 - in /cfe/trunk: lib/Sema/Sema.h lib/Sema/SemaDecl.cpp test/SemaCXX/using-decl-1.cpp

Douglas Gregor dgregor at apple.com
Sun Sep 27 17:47:05 PDT 2009


Author: dgregor
Date: Sun Sep 27 19:47:05 2009
New Revision: 82954

URL: http://llvm.org/viewvc/llvm-project?rev=82954&view=rev
Log:
Teach Sema::isDeclInScope to handle overload sets constructed from
functions that occur in multiple declaration contexts, e.g., because
some were found via using declarations. Now, isDeclInScope will build
a new overload set (when needed) containing only those declarations
that are actually in scope. This eliminates a problem found with
libstdc++'s <iostream>, where the presence of using 

In the longer term, I'd like to eliminate Sema::isDeclInScope in favor
of better handling of the RedeclarationOnly flag in the name-lookup
routines. That way, name lookup only returns the entities that matter,
rather than taking the current two-pass approach of producing too many
results and then filtering our the wrong results. It's not efficient,
and I'm sure that we aren't filtering everywhere we should be.


Modified:
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/test/SemaCXX/using-decl-1.cpp

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=82954&r1=82953&r2=82954&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Sun Sep 27 19:47:05 2009
@@ -528,7 +528,7 @@
   void DiagnoseFunctionSpecifiers(Declarator& D);
   NamedDecl* ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
                                     QualType R, DeclaratorInfo *DInfo,
-                                    Decl* PrevDecl, bool &Redeclaration);
+                                    NamedDecl* PrevDecl, bool &Redeclaration);
   NamedDecl* ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
                                      QualType R, DeclaratorInfo *DInfo,
                                      NamedDecl* PrevDecl,
@@ -725,9 +725,7 @@
   /// isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true
   /// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns
   /// true if 'D' belongs to the given declaration context.
-  bool isDeclInScope(Decl *D, DeclContext *Ctx, Scope *S = 0) {
-    return IdResolver.isDeclInScope(D, Ctx, Context, S);
-  }
+  bool isDeclInScope(NamedDecl *&D, DeclContext *Ctx, Scope *S = 0);
 
   /// Finds the scope corresponding to the given decl context, if it
   /// happens to be an enclosing scope.  Otherwise return NULL.

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=82954&r1=82953&r2=82954&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Sun Sep 27 19:47:05 2009
@@ -311,9 +311,10 @@
       IdentifierResolver::iterator
         I = IdResolver.begin(TD->getDeclName()),
         IEnd = IdResolver.end();
-      if (I != IEnd && isDeclInScope(*I, CurContext, S)) {
+      NamedDecl *ID = *I;
+      if (I != IEnd && isDeclInScope(ID, CurContext, S)) {
         NamedDecl *PrevDecl = *I;
-        for (; I != IEnd && isDeclInScope(*I, CurContext, S);
+        for (; I != IEnd && isDeclInScope(ID, CurContext, S);
              PrevDecl = *I, ++I) {
           if (TD->declarationReplaces(*I)) {
             // This is a redeclaration. Remove it from the chain and
@@ -374,6 +375,41 @@
   IdResolver.AddDecl(D);
 }
 
+bool Sema::isDeclInScope(NamedDecl *&D, DeclContext *Ctx, Scope *S) {
+  if (OverloadedFunctionDecl *Ovl = dyn_cast<OverloadedFunctionDecl>(D)) {
+    // Look inside the overload set to determine if any of the declarations
+    // are in scope. (Possibly) build a new overload set containing only
+    // those declarations that are in scope.
+    OverloadedFunctionDecl *NewOvl = 0;
+    bool FoundInScope = false;
+    for (OverloadedFunctionDecl::function_iterator F = Ovl->function_begin(),
+         FEnd = Ovl->function_end();
+         F != FEnd; ++F) {
+      NamedDecl *FD = F->get();
+      if (!isDeclInScope(FD, Ctx, S)) {
+        if (!NewOvl && F != Ovl->function_begin()) {
+          NewOvl = OverloadedFunctionDecl::Create(Context, 
+                                                  F->get()->getDeclContext(),
+                                                  F->get()->getDeclName());
+          D = NewOvl;
+          for (OverloadedFunctionDecl::function_iterator 
+               First = Ovl->function_begin();
+               First != F; ++First)
+            NewOvl->addOverload(*First);
+        }
+      } else {
+        FoundInScope = true;
+        if (NewOvl)
+          NewOvl->addOverload(*F);
+      }
+    }
+    
+    return FoundInScope;
+  }
+  
+  return IdResolver.isDeclInScope(D, Ctx, Context, S);
+}
+
 void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {
   if (S->decl_empty()) return;
   assert((S->getFlags() & (Scope::DeclScope | Scope::TemplateParamScope)) &&
@@ -1971,7 +2007,7 @@
 NamedDecl*
 Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
                              QualType R,  DeclaratorInfo *DInfo,
-                             Decl* PrevDecl, bool &Redeclaration) {
+                             NamedDecl* PrevDecl, bool &Redeclaration) {
   // Typedef declarators cannot be qualified (C++ [dcl.meaning]p1).
   if (D.getCXXScopeSpec().isSet()) {
     Diag(D.getIdentifierLoc(), diag::err_qualified_typedef_declarator)
@@ -4411,7 +4447,8 @@
     if (Lookup.getKind() == LookupResult::Found)
       PrevTypedef = dyn_cast<TypedefDecl>(Lookup.getAsDecl());
 
-    if (PrevTypedef && isDeclInScope(PrevTypedef, SearchDC, S) &&
+    NamedDecl *PrevTypedefNamed = PrevTypedef;
+    if (PrevTypedef && isDeclInScope(PrevTypedefNamed, SearchDC, S) &&
         Context.getCanonicalType(Context.getTypeDeclType(PrevTypedef)) !=
           Context.getCanonicalType(Context.getTypeDeclType(New))) {
       Diag(Loc, diag::err_tag_definition_of_typedef)

Modified: cfe/trunk/test/SemaCXX/using-decl-1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/using-decl-1.cpp?rev=82954&r1=82953&r2=82954&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/using-decl-1.cpp (original)
+++ cfe/trunk/test/SemaCXX/using-decl-1.cpp Sun Sep 27 19:47:05 2009
@@ -6,3 +6,14 @@
   using ::f;
   inline void f() { return f(true); }
 }
+
+namespace M {
+  void f(float);
+}
+
+namespace N {
+  using M::f;
+  void f(int) { } // expected-note{{previous}}
+  
+  void f(int) { } // expected-error{{redefinition}}
+}





More information about the cfe-commits mailing list