[cfe-commits] r80636 - in /cfe/trunk: include/clang/AST/DeclBase.h lib/AST/DeclBase.cpp lib/Sema/Sema.h lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp test/CXX/class/class.friend/p1-ambiguous.cpp

John McCall rjmccall at apple.com
Mon Aug 31 15:39:49 PDT 2009


Author: rjmccall
Date: Mon Aug 31 17:39:49 2009
New Revision: 80636

URL: http://llvm.org/viewvc/llvm-project?rev=80636&view=rev
Log:
Fix bug 4784 and allow friend declarations to properly extend
existing declaration chains.


Added:
    cfe/trunk/test/CXX/class/class.friend/p1-ambiguous.cpp
Modified:
    cfe/trunk/include/clang/AST/DeclBase.h
    cfe/trunk/lib/AST/DeclBase.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp

Modified: cfe/trunk/include/clang/AST/DeclBase.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclBase.h?rev=80636&r1=80635&r2=80636&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/DeclBase.h (original)
+++ cfe/trunk/include/clang/AST/DeclBase.h Mon Aug 31 17:39:49 2009
@@ -905,7 +905,11 @@
   /// visible from this context, as determined by
   /// NamedDecl::declarationReplaces, the previous declaration will be
   /// replaced with D.
-  void makeDeclVisibleInContext(NamedDecl *D);
+  ///
+  /// @param Recoverable true if it's okay to not add this decl to
+  /// the lookup tables because it can be easily recovered by walking
+  /// the declaration chains.
+  void makeDeclVisibleInContext(NamedDecl *D, bool Recoverable = true);
 
   /// udir_iterator - Iterates through the using-directives stored
   /// within this context.

Modified: cfe/trunk/lib/AST/DeclBase.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=80636&r1=80635&r2=80636&view=diff

==============================================================================
--- cfe/trunk/lib/AST/DeclBase.cpp (original)
+++ cfe/trunk/lib/AST/DeclBase.cpp Mon Aug 31 17:39:49 2009
@@ -697,7 +697,7 @@
   return Ctx->getPrimaryContext();
 }
 
-void DeclContext::makeDeclVisibleInContext(NamedDecl *D) {
+void DeclContext::makeDeclVisibleInContext(NamedDecl *D, bool Recoverable) {
   // FIXME: This feels like a hack. Should DeclarationName support
   // template-ids, or is there a better way to keep specializations
   // from being visible?
@@ -706,20 +706,20 @@
 
   DeclContext *PrimaryContext = getPrimaryContext();
   if (PrimaryContext != this) {
-    PrimaryContext->makeDeclVisibleInContext(D);
+    PrimaryContext->makeDeclVisibleInContext(D, Recoverable);
     return;
   }
 
   // If we already have a lookup data structure, perform the insertion
   // into it. Otherwise, be lazy and don't build that structure until
   // someone asks for it.
-  if (LookupPtr)
+  if (LookupPtr || !Recoverable)
     makeDeclVisibleInContextImpl(D);
 
   // If we are a transparent context, insert into our parent context,
   // too. This operation is recursive.
   if (isTransparentContext())
-    getParent()->makeDeclVisibleInContext(D);
+    getParent()->makeDeclVisibleInContext(D, Recoverable);
 }
 
 void DeclContext::makeDeclVisibleInContextImpl(NamedDecl *D) {

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

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Mon Aug 31 17:39:49 2009
@@ -703,7 +703,7 @@
   NamedDecl *getCurFunctionOrMethodDecl();
 
   /// Add this decl to the scope shadowed decl chains.
-  void PushOnScopeChains(NamedDecl *D, Scope *S);
+  void PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext = true);
 
   /// isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true
   /// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns
@@ -712,6 +712,18 @@
     return IdResolver.isDeclInScope(D, Ctx, Context, S);
   }
 
+  /// Finds the scope corresponding to the given decl context, if it
+  /// happens to be an enclosing scope.  Otherwise return NULL.
+  Scope *getScopeForDeclContext(Scope *S, DeclContext *DC) {
+    DC = DC->getPrimaryContext();
+    do {
+      if (((DeclContext*) S->getEntity())->getPrimaryContext() == DC)
+        return S;
+    } while ((S = S->getParent()));
+
+    return NULL;
+  }
+
 
   /// Subroutines of ActOnDeclarator().
   TypedefDecl *ParseTypedefDecl(Scope *S, Declarator &D, QualType T);

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Aug 31 17:39:49 2009
@@ -280,7 +280,7 @@
 }
 
 /// Add this decl to the scope shadowed decl chains.
-void Sema::PushOnScopeChains(NamedDecl *D, Scope *S) {
+void Sema::PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext) {
   // Move up the scope chain until we find the nearest enclosing
   // non-transparent context. The declaration will be introduced into this
   // scope.
@@ -293,7 +293,8 @@
   // Add scoped declarations into their context, so that they can be
   // found later. Declarations without a context won't be inserted
   // into any context.
-  CurContext->addDecl(D);
+  if (AddToContext)
+    CurContext->addDecl(D);
 
   // C++ [basic.scope]p4:
   //   -- exactly one declaration shall declare a class name or

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon Aug 31 17:39:49 2009
@@ -3820,15 +3820,27 @@
                                           IsDefinition,
                                           Redeclaration);
   if (!ND) return DeclPtrTy();
+
+  assert(cast<FunctionDecl>(ND)->getPreviousDeclaration() == FD &&
+         "lost reference to previous declaration");
+
   FD = cast<FunctionDecl>(ND);
 
   assert(FD->getDeclContext() == DC);
   assert(FD->getLexicalDeclContext() == CurContext);
 
-  // We only add the function declaration to the lookup tables, not
-  // the decl list, and only if the context isn't dependent.
-  if (!CurContext->isDependentContext())
-    DC->makeDeclVisibleInContext(FD);
+  // Add the function declaration to the appropriate lookup tables,
+  // adjusting the redeclarations list as necessary.  We don't
+  // want to do this yet if the friending class is dependent.
+  // 
+  // Also update the scope-based lookup if the target context's
+  // lookup context is in lexical scope.
+  if (!CurContext->isDependentContext()) {
+    DC = DC->getLookupContext();
+    DC->makeDeclVisibleInContext(FD, /* Recoverable=*/ false);
+    if (Scope *EnclosingScope = getScopeForDeclContext(S, DC))
+      PushOnScopeChains(FD, EnclosingScope, /*AddToContext=*/ false);
+  }
 
   FriendDecl *FrD = FriendDecl::Create(Context, CurContext,
                                        D.getIdentifierLoc(), FD,

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Mon Aug 31 17:39:49 2009
@@ -498,7 +498,7 @@
     bool WasDeclared = (FOK == Decl::FOK_Declared);
     Function->setObjectOfFriendDecl(WasDeclared);
     if (!Owner->isDependentContext())
-      DC->makeDeclVisibleInContext(Function);
+      DC->makeDeclVisibleInContext(Function, /* Recoverable = */ false);
 
     Function->setInstantiationOfMemberFunction(D);
   }

Added: cfe/trunk/test/CXX/class/class.friend/p1-ambiguous.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class/class.friend/p1-ambiguous.cpp?rev=80636&view=auto

==============================================================================
--- cfe/trunk/test/CXX/class/class.friend/p1-ambiguous.cpp (added)
+++ cfe/trunk/test/CXX/class/class.friend/p1-ambiguous.cpp Mon Aug 31 17:39:49 2009
@@ -0,0 +1,37 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// Make sure that friend declarations don't introduce ambiguous
+// declarations.
+
+// Test case courtesy of Shantonu Sen.
+// Bug 4784.
+
+class foo;
+
+extern "C" {
+  int c_func(foo *a);
+};
+int cpp_func(foo *a);
+
+class foo {
+public:
+  friend int c_func(foo *a);
+  friend int cpp_func(foo *a);
+  int caller();
+private:
+  int x;
+};
+
+int c_func(foo *a) {
+  return a->x;
+}
+
+int cpp_func(foo *a) {
+  return a->x;
+}
+
+int foo::caller() {
+    c_func(this);
+    cpp_func(this);
+    return 0;
+}





More information about the cfe-commits mailing list