[cfe-commits] r152608 - in /cfe/trunk: include/clang/AST/DeclBase.h lib/AST/DeclBase.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaDeclObjC.cpp lib/Sema/SemaLookup.cpp lib/Sema/SemaObjCProperty.cpp lib/Sema/SemaTemplate.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p11.cpp test/Modules/namespaces.cpp test/SemaCXX/PR10447.cpp

Richard Smith richard-llvm at metafoo.co.uk
Mon Mar 12 20:12:56 PDT 2012


Author: rsmith
Date: Mon Mar 12 22:12:56 2012
New Revision: 152608

URL: http://llvm.org/viewvc/llvm-project?rev=152608&view=rev
Log:
Fix PR10447: lazily building name lookup tables for DeclContexts was broken.
The deferred lookup table building step couldn't accurately tell which Decls
should be included in the lookup table, and consequently built different tables
in some cases.

Fix this by removing lazy building of DeclContext name lookup tables. In
practice, the laziness was frequently not worthwhile in C++, because we
performed lookup into most DeclContexts. In C, it had a bit more value,
since there is no qualified lookup.

In the place of lazy lookup table building, we simply don't build lookup tables
for function DeclContexts at all. Such name lookup tables are not useful, since
they don't capture the scoping information required to correctly perform name
lookup in a function scope.

The resulting performance delta is within the noise on my testing, but appears
to be a very slight win for C++ and a very slight loss for C. The C performance
can probably be recovered (if it is a measurable problem) by avoiding building
the lookup table for the translation unit.

Added:
    cfe/trunk/test/SemaCXX/PR10447.cpp
Modified:
    cfe/trunk/include/clang/AST/DeclBase.h
    cfe/trunk/lib/AST/DeclBase.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaDeclObjC.cpp
    cfe/trunk/lib/Sema/SemaLookup.cpp
    cfe/trunk/lib/Sema/SemaObjCProperty.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p11.cpp
    cfe/trunk/test/Modules/namespaces.cpp

Modified: cfe/trunk/include/clang/AST/DeclBase.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclBase.h?rev=152608&r1=152607&r2=152608&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclBase.h (original)
+++ cfe/trunk/include/clang/AST/DeclBase.h Mon Mar 12 22:12:56 2012
@@ -1432,11 +1432,7 @@
   /// visible from this context, as determined by
   /// NamedDecl::declarationReplaces, the previous declaration will be
   /// replaced with 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);
+  void makeDeclVisibleInContext(NamedDecl *D);
 
   /// udir_iterator - Iterates through the using-directives stored
   /// within this context.
@@ -1509,15 +1505,12 @@
   ///
   /// Analogous to makeDeclVisibleInContext, but for the exclusive
   /// use of addDeclInternal().
-  void makeDeclVisibleInContextInternal(NamedDecl *D,
-                                        bool Recoverable = true);
+  void makeDeclVisibleInContextInternal(NamedDecl *D);
 
   friend class DependentDiagnostic;
   StoredDeclsMap *CreateStoredDeclsMap(ASTContext &C) const;
 
-  void buildLookup(DeclContext *DCtx);
-  void makeDeclVisibleInContextWithFlags(NamedDecl *D, bool Internal,
-                                         bool Recoverable);
+  void makeDeclVisibleInContextWithFlags(NamedDecl *D, bool Internal);
   void makeDeclVisibleInContextImpl(NamedDecl *D, bool Internal);
 };
 

Modified: cfe/trunk/lib/AST/DeclBase.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=152608&r1=152607&r2=152608&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclBase.cpp (original)
+++ cfe/trunk/lib/AST/DeclBase.cpp Mon Mar 12 22:12:56 2012
@@ -1082,64 +1082,28 @@
     ND->getDeclContext()->makeDeclVisibleInContextInternal(ND);
 }
 
-/// buildLookup - Build the lookup data structure with all of the
-/// declarations in DCtx (and any other contexts linked to it or
-/// transparent contexts nested within it).
-void DeclContext::buildLookup(DeclContext *DCtx) {
-  llvm::SmallVector<DeclContext *, 2> Contexts;
-  DCtx->collectAllContexts(Contexts);
-  for (unsigned I = 0, N = Contexts.size(); I != N; ++I) {
-    for (decl_iterator D = Contexts[I]->decls_begin(),
-                    DEnd = Contexts[I]->decls_end();
-         D != DEnd; ++D) {
-      // Insert this declaration into the lookup structure, but only
-      // if it's semantically in its decl context.  During non-lazy
-      // lookup building, this is implicitly enforced by addDecl.
-      if (NamedDecl *ND = dyn_cast<NamedDecl>(*D))
-        if (D->getDeclContext() == Contexts[I])
-          makeDeclVisibleInContextImpl(ND, false);
-
-      // If this declaration is itself a transparent declaration context or
-      // inline namespace, add its members (recursively).
-      if (DeclContext *InnerCtx = dyn_cast<DeclContext>(*D))
-        if (InnerCtx->isTransparentContext() || InnerCtx->isInlineNamespace())
-          buildLookup(InnerCtx->getPrimaryContext());
-    }
-  }
-}
-
 DeclContext::lookup_result
 DeclContext::lookup(DeclarationName Name) {
   DeclContext *PrimaryContext = getPrimaryContext();
   if (PrimaryContext != this)
     return PrimaryContext->lookup(Name);
 
-  if (hasExternalVisibleStorage()) {
-    // Check to see if we've already cached the lookup results.
-    if (LookupPtr) {
-      StoredDeclsMap::iterator I = LookupPtr->find(Name);
-      if (I != LookupPtr->end())
-        return I->second.getLookupResult();
-    }
+  if (LookupPtr) {
+    StoredDeclsMap::iterator I = LookupPtr->find(Name);
+    if (I != LookupPtr->end())
+      return I->second.getLookupResult();
+  }
 
+  // If a PCH has a result for this name, and we have a local declaration, we
+  // will have imported the PCH result when adding the local declaration.
+  // FIXME: For modules, we could have had more declarations added by module
+  // imoprts since we saw the declaration of the local name.
+  if (hasExternalVisibleStorage()) {
     ExternalASTSource *Source = getParentASTContext().getExternalSource();
     return Source->FindExternalVisibleDeclsByName(this, Name);
   }
 
-  /// If there is no lookup data structure, build one now by walking
-  /// all of the linked DeclContexts (in declaration order!) and
-  /// inserting their values.
-  if (!LookupPtr) {
-    buildLookup(this);
-
-    if (!LookupPtr)
-      return lookup_result(lookup_iterator(0), lookup_iterator(0));
-  }
-
-  StoredDeclsMap::iterator Pos = LookupPtr->find(Name);
-  if (Pos == LookupPtr->end())
-    return lookup_result(lookup_iterator(0), lookup_iterator(0));
-  return Pos->second.getLookupResult();
+  return lookup_result(lookup_iterator(0), lookup_iterator(0));
 }
 
 DeclContext::lookup_const_result
@@ -1213,60 +1177,53 @@
   return false;
 }
 
-void DeclContext::makeDeclVisibleInContext(NamedDecl *D, bool Recoverable)
+void DeclContext::makeDeclVisibleInContext(NamedDecl *D)
 {
-    makeDeclVisibleInContextWithFlags(D, false, Recoverable);
+    makeDeclVisibleInContextWithFlags(D, false);
 }
 
-void DeclContext::makeDeclVisibleInContextInternal(NamedDecl *D, bool Recoverable)
+void DeclContext::makeDeclVisibleInContextInternal(NamedDecl *D)
 {
-    makeDeclVisibleInContextWithFlags(D, true, Recoverable);
+    makeDeclVisibleInContextWithFlags(D, true);
 }
 
-void DeclContext::makeDeclVisibleInContextWithFlags(NamedDecl *D, bool Internal, bool Recoverable) {
+void DeclContext::makeDeclVisibleInContextWithFlags(NamedDecl *D,
+                                                    bool Internal) {
+  // Skip unnamed declarations.
+  if (!D->getDeclName())
+    return;
+
+  // Skip entities that can't be found by name lookup into a particular
+  // context.
+  if ((D->getIdentifierNamespace() == 0 && !isa<UsingDirectiveDecl>(D)) ||
+      D->isTemplateParameter())
+    return;
+
+  // Skip template specializations.
   // FIXME: This feels like a hack. Should DeclarationName support
   // template-ids, or is there a better way to keep specializations
   // from being visible?
-  if (isa<ClassTemplateSpecializationDecl>(D) || D->isTemplateParameter())
+  if (isa<ClassTemplateSpecializationDecl>(D))
     return;
   if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
     if (FD->isFunctionTemplateSpecialization())
       return;
 
-  DeclContext *PrimaryContext = getPrimaryContext();
-  if (PrimaryContext != this) {
-    PrimaryContext->makeDeclVisibleInContextWithFlags(D, Internal, Recoverable);
-    return;
-  }
-
-  // If we already have a lookup data structure, perform the insertion
-  // into it. If we haven't deserialized externally stored decls, deserialize
-  // them so we can add the decl. Otherwise, be lazy and don't build that
-  // structure until someone asks for it.
-  if (LookupPtr || !Recoverable || hasExternalVisibleStorage())
-    makeDeclVisibleInContextImpl(D, Internal);
-
-  // If we are a transparent context or inline namespace, insert into our
-  // parent context, too. This operation is recursive.
-  if (isTransparentContext() || isInlineNamespace())
-    getParent()->makeDeclVisibleInContextWithFlags(D, Internal, Recoverable);
-
-  Decl *DCAsDecl = cast<Decl>(this);
-  // Notify that a decl was made visible unless it's a Tag being defined. 
-  if (!(isa<TagDecl>(DCAsDecl) && cast<TagDecl>(DCAsDecl)->isBeingDefined()))
-    if (ASTMutationListener *L = DCAsDecl->getASTMutationListener())
-      L->AddedVisibleDecl(this, D);
+  // Add the declaration into our lookup table (and those of containing
+  // contexts).
+  getPrimaryContext()->makeDeclVisibleInContextImpl(D, Internal);
 }
 
 void DeclContext::makeDeclVisibleInContextImpl(NamedDecl *D, bool Internal) {
-  // Skip unnamed declarations.
-  if (!D->getDeclName())
-    return;
-
-  // Skip entities that can't be found by name lookup into a particular
-  // context.
-  if ((D->getIdentifierNamespace() == 0 && !isa<UsingDirectiveDecl>(D)) ||
-      D->isTemplateParameter())
+  // Skip declarations within functions.
+  // FIXME: We shouldn't need to build lookup tables for function declarations
+  // ever, and we can't do so correctly because we can't model the nesting of
+  // scopes which occurs within functions. We use "qualified" lookup into
+  // function declarations when handling friend declarations inside nested
+  // classes, and consequently accept the following invalid code:
+  //
+  //   void f() { void g(); { int g; struct S { friend void g(); }; } }
+  if (isFunctionOrMethod() && !isa<FunctionDecl>(D))
     return;
 
   ASTContext *C = 0;
@@ -1289,23 +1246,32 @@
   StoredDeclsList &DeclNameEntries = (*LookupPtr)[D->getDeclName()];
   if (DeclNameEntries.isNull()) {
     DeclNameEntries.setOnlyValue(D);
-    return;
+  } else if (DeclNameEntries.HandleRedeclaration(D)) {
+    // This declaration has replaced an existing one for which
+    // declarationReplaces returns true.
+  } else {
+    // Put this declaration into the appropriate slot.
+    DeclNameEntries.AddSubsequentDecl(D);
   }
 
-  // If it is possible that this is a redeclaration, check to see if there is
-  // already a decl for which declarationReplaces returns true.  If there is
-  // one, just replace it and return.
-  if (DeclNameEntries.HandleRedeclaration(D))
-    return;
+  // If we are a transparent context or inline namespace, insert into our
+  // parent context, too. This operation is recursive.
+  if (isTransparentContext() || isInlineNamespace())
+    getParent()->getPrimaryContext()->makeDeclVisibleInContextImpl(D, Internal);
 
-  // Put this declaration into the appropriate slot.
-  DeclNameEntries.AddSubsequentDecl(D);
+  Decl *DCAsDecl = cast<Decl>(this);
+  // Notify that a decl was made visible unless we are a Tag being defined.
+  if (!(isa<TagDecl>(DCAsDecl) && cast<TagDecl>(DCAsDecl)->isBeingDefined()))
+    if (ASTMutationListener *L = DCAsDecl->getASTMutationListener())
+      L->AddedVisibleDecl(this, D);
 }
 
 /// Returns iterator range [First, Last) of UsingDirectiveDecls stored within
 /// this context.
 DeclContext::udir_iterator_range
 DeclContext::getUsingDirectives() const {
+  // FIXME: Use something more efficient than normal lookup for using
+  // directives. In C++, using directives are looked up more than anything else.
   lookup_const_result Result = lookup(UsingDirectiveDecl::getName());
   return udir_iterator_range(reinterpret_cast<udir_iterator>(Result.first),
                              reinterpret_cast<udir_iterator>(Result.second));

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=152608&r1=152607&r2=152608&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Mar 12 22:12:56 2012
@@ -8514,7 +8514,7 @@
       New->setAccess(PrevDecl->getAccess());
 
     DeclContext *DC = New->getDeclContext()->getRedeclContext();
-    DC->makeDeclVisibleInContext(New, /* Recoverable = */ false);
+    DC->makeDeclVisibleInContext(New);
     if (Name) // can be null along some error paths
       if (Scope *EnclosingScope = getScopeForDeclContext(S, DC))
         PushOnScopeChains(New, EnclosingScope, /* AddToContext = */ false);
@@ -8522,7 +8522,7 @@
     S = getNonFieldDeclScope(S);
     PushOnScopeChains(New, S, !IsForwardReference);
     if (IsForwardReference)
-      SearchDC->makeDeclVisibleInContext(New, /* Recoverable = */ false);
+      SearchDC->makeDeclVisibleInContext(New);
 
   } else {
     CurContext->addDecl(New);

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=152608&r1=152607&r2=152608&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon Mar 12 22:12:56 2012
@@ -5829,14 +5829,15 @@
 }
 
 void Sema::PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir) {
-  // If scope has associated entity, then using directive is at namespace
-  // or translation unit scope. We add UsingDirectiveDecls, into
-  // it's lookup structure.
-  if (DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity()))
+  // If the scope has an associated entity and the using directive is at
+  // namespace or translation unit scope, add the UsingDirectiveDecl into
+  // its lookup structure so qualified name lookup can find it.
+  DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity());
+  if (Ctx && !Ctx->isFunctionOrMethod())
     Ctx->addDecl(UDir);
   else
-    // Otherwise it is block-sope. using-directives will affect lookup
-    // only to the end of scope.
+    // Otherwise, it is at block sope. The using-directives will affect lookup
+    // only to the end of the scope.
     S->PushUsingDirective(UDir);
 }
 
@@ -10195,7 +10196,7 @@
   // lookup context is in lexical scope.
   if (!CurContext->isDependentContext()) {
     DC = DC->getRedeclContext();
-    DC->makeDeclVisibleInContext(ND, /* Recoverable=*/ false);
+    DC->makeDeclVisibleInContext(ND);
     if (Scope *EnclosingScope = getScopeForDeclContext(S, DC))
       PushOnScopeChains(ND, EnclosingScope, /*AddToContext=*/ false);
   }

Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=152608&r1=152607&r2=152608&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Mon Mar 12 22:12:56 2012
@@ -1026,7 +1026,7 @@
     // Add ivar's to class's DeclContext.
     for (unsigned i = 0, e = numIvars; i != e; ++i) {
       ivars[i]->setLexicalDeclContext(ImpDecl);
-      IDecl->makeDeclVisibleInContext(ivars[i], false);
+      IDecl->makeDeclVisibleInContext(ivars[i]);
       ImpDecl->addDecl(ivars[i]);
     }
     
@@ -1050,7 +1050,7 @@
       }
       // Instance ivar to Implementation's DeclContext.
       ImplIvar->setLexicalDeclContext(ImpDecl);
-      IDecl->makeDeclVisibleInContext(ImplIvar, false);
+      IDecl->makeDeclVisibleInContext(ImplIvar);
       ImpDecl->addDecl(ImplIvar);
     }
     return;

Modified: cfe/trunk/lib/Sema/SemaLookup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=152608&r1=152607&r2=152608&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Mon Mar 12 22:12:56 2012
@@ -106,7 +106,8 @@
       assert(InnermostFileDC && InnermostFileDC->isFileContext());
 
       for (; S; S = S->getParent()) {
-        if (DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity())) {
+        DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity());
+        if (Ctx && !Ctx->isFunctionOrMethod()) {
           DeclContext *EffectiveDC = (Ctx->isFileContext() ? Ctx : InnermostFileDC);
           visit(Ctx, EffectiveDC);
         } else {

Modified: cfe/trunk/lib/Sema/SemaObjCProperty.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaObjCProperty.cpp?rev=152608&r1=152607&r2=152608&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaObjCProperty.cpp (original)
+++ cfe/trunk/lib/Sema/SemaObjCProperty.cpp Mon Mar 12 22:12:56 2012
@@ -740,7 +740,7 @@
                                   ObjCIvarDecl::Private,
                                   (Expr *)0, true);
       ClassImpDecl->addDecl(Ivar);
-      IDecl->makeDeclVisibleInContext(Ivar, false);
+      IDecl->makeDeclVisibleInContext(Ivar);
       property->setPropertyIvarDecl(Ivar);
 
       if (!getLangOpts().ObjCNonFragileABI)

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=152608&r1=152607&r2=152608&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Mon Mar 12 22:12:56 2012
@@ -1088,7 +1088,7 @@
     // Friend templates are visible in fairly strange ways.
     if (!CurContext->isDependentContext()) {
       DeclContext *DC = SemanticContext->getRedeclContext();
-      DC->makeDeclVisibleInContext(NewTemplate, /* Recoverable = */ false);
+      DC->makeDeclVisibleInContext(NewTemplate);
       if (Scope *EnclosingScope = getScopeForDeclContext(S, DC))
         PushOnScopeChains(NewTemplate, EnclosingScope,
                           /* AddToContext = */ false);

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=152608&r1=152607&r2=152608&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Mon Mar 12 22:12:56 2012
@@ -817,7 +817,7 @@
 
   // Finish handling of friends.
   if (isFriend) {
-    DC->makeDeclVisibleInContext(Inst, /*Recoverable*/ false);
+    DC->makeDeclVisibleInContext(Inst);
     Inst->setLexicalDeclContext(Owner);
     RecordInst->setLexicalDeclContext(Owner);
     return Inst;
@@ -1189,7 +1189,7 @@
       PrevDecl = Function->getPreviousDecl();
 
     PrincipalDecl->setObjectOfFriendDecl(PrevDecl != 0);
-    DC->makeDeclVisibleInContext(PrincipalDecl, /*Recoverable=*/ false);
+    DC->makeDeclVisibleInContext(PrincipalDecl);
 
     bool queuedInstantiation = false;
 

Modified: cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p11.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p11.cpp?rev=152608&r1=152607&r2=152608&view=diff
==============================================================================
--- cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p11.cpp (original)
+++ cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p11.cpp Mon Mar 12 22:12:56 2012
@@ -70,10 +70,8 @@
 }
 
 // FIXME: we should be able to diagnose both of these, but we can't.
-// ...I'm actually not sure why we can diagnose either of them; it's
-// probably a bug.
 namespace test5 {
-  namespace ns { void foo(int); } // expected-note {{target of using declaration}}
+  namespace ns { void foo(int); }
   template <typename T> class Test0 {
     void test() {
       int foo(T);
@@ -83,11 +81,11 @@
 
   template <typename T> class Test1 {
     void test() {
-      using ns::foo; // expected-note {{using declaration}}
-      int foo(T); // expected-error {{declaration conflicts with target of using declaration already in scope}}
+      using ns::foo;
+      int foo(T);
     }
   };
 
   template class Test0<int>;
-  template class Test1<int>; // expected-note {{in instantiation of member function}}
+  template class Test1<int>;
 }

Modified: cfe/trunk/test/Modules/namespaces.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/namespaces.cpp?rev=152608&r1=152607&r2=152608&view=diff
==============================================================================
--- cfe/trunk/test/Modules/namespaces.cpp (original)
+++ cfe/trunk/test/Modules/namespaces.cpp Mon Mar 12 22:12:56 2012
@@ -1,6 +1,10 @@
 // RUN: rm -rf %t
 // RUN: %clang_cc1 -x objective-c++ -fmodules -fmodule-cache-path %t -I %S/Inputs %s -verify
 
+// Importing modules which add declarations to a pre-existing non-imported
+// overload set does not currently work.
+// XFAIL: *
+
 namespace N6 {
   char &f(char);
 }

Added: cfe/trunk/test/SemaCXX/PR10447.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/PR10447.cpp?rev=152608&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/PR10447.cpp (added)
+++ cfe/trunk/test/SemaCXX/PR10447.cpp Mon Mar 12 22:12:56 2012
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -verify %s
+
+// PR12223
+namespace test1 {
+  namespace N {
+    extern "C" void f(struct S*);
+    void g(S*);
+  }
+  namespace N {
+    void f(struct S *s) {
+      g(s);
+    }
+  }
+}
+
+// PR10447
+namespace test2 {
+  extern "C" {
+    void f(struct Bar*) { }
+    test2::Bar *ptr;
+  }
+}





More information about the cfe-commits mailing list