[cfe-commits] r171925 - in /cfe/trunk: lib/Sema/SemaDecl.cpp test/Modules/Inputs/linkage-merge-sub.h test/Modules/Inputs/module.map test/Modules/linkage-merge.m

Douglas Gregor dgregor at apple.com
Tue Jan 8 16:47:57 PST 2013


Author: dgregor
Date: Tue Jan  8 18:47:56 2013
New Revision: 171925

URL: http://llvm.org/viewvc/llvm-project?rev=171925&view=rev
Log:
When name lookup for a redeclaration finds declarations that are known
(because they are part of some module) but have not been made visible
(because they are in a submodule that wasn't imported), filter out
those declarations unless both the old declaration and the new
declaration have external linkage. When one or both has internal
linkage, there should be no conflict unless both are imported.


Added:
    cfe/trunk/test/Modules/Inputs/linkage-merge-sub.h
    cfe/trunk/test/Modules/linkage-merge.m
Modified:
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/test/Modules/Inputs/module.map

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=171925&r1=171924&r2=171925&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue Jan  8 18:47:56 2013
@@ -1568,6 +1568,40 @@
   return New;
 }
 
+/// \brief Filter out any previous declarations that the given declaration
+/// should not consider because they are not permitted to conflict, e.g.,
+/// because they come from hidden sub-modules and do not refer to the same
+/// entity.
+static void filterNonConflictingPreviousDecls(ASTContext &context,
+                                              NamedDecl *decl,
+                                              LookupResult &previous){
+  // This is only interesting when modules are enabled.
+  if (!context.getLangOpts().Modules)
+    return;
+
+  // Empty sets are uninteresting.
+  if (previous.empty())
+    return;
+
+  // If this declaration has external
+  bool hasExternalLinkage = (decl->getLinkage() == ExternalLinkage);
+
+  LookupResult::Filter filter = previous.makeFilter();
+  while (filter.hasNext()) {
+    NamedDecl *old = filter.next();
+
+    // Non-hidden declarations are never ignored.
+    if (!old->isHidden())
+      continue;
+
+    // If either has no-external linkage, ignore the old declaration.
+    if (!hasExternalLinkage || old->getLinkage() != ExternalLinkage)
+      filter.erase();
+  }
+
+  filter.done();
+}
+
 bool Sema::isIncompatibleTypedef(TypeDecl *Old, TypedefNameDecl *New) {
   QualType OldType;
   if (TypedefNameDecl *OldTypedef = dyn_cast<TypedefNameDecl>(Old))
@@ -4139,6 +4173,7 @@
   // in an outer scope, it isn't the same thing.
   FilterLookupForScope(Previous, DC, S, /*ConsiderLinkage*/ false,
                        /*ExplicitInstantiationOrSpecialization=*/false);
+  filterNonConflictingPreviousDecls(Context, NewTD, Previous);
   if (!Previous.empty()) {
     Redeclaration = true;
     MergeTypedefNameDecl(NewTD, Previous);
@@ -4768,6 +4803,9 @@
       Previous.addDecl(Pos->second);
   }
 
+  // Filter out any non-conflicting previous declarations.
+  filterNonConflictingPreviousDecls(Context, NewVD, Previous);
+
   if (T->isVoidType() && !NewVD->hasExternalStorage()) {
     Diag(NewVD->getLocation(), diag::err_typecheck_decl_incomplete_type)
       << T;
@@ -6118,6 +6156,9 @@
       Previous.addDecl(Pos->second);
   }
 
+  // Filter out any non-conflicting previous declarations.
+  filterNonConflictingPreviousDecls(Context, NewFD, Previous);
+
   bool Redeclaration = false;
 
   // Merge or overload the declaration with an existing declaration of

Added: cfe/trunk/test/Modules/Inputs/linkage-merge-sub.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/linkage-merge-sub.h?rev=171925&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/linkage-merge-sub.h (added)
+++ cfe/trunk/test/Modules/Inputs/linkage-merge-sub.h Tue Jan  8 18:47:56 2013
@@ -0,0 +1,11 @@
+extern int f0(int);
+extern int f1(int);
+static int f2(int);
+static int f3(int);
+
+extern int v0;
+extern int v1;
+static int v2;
+static int v3;
+
+typedef int T0;

Modified: cfe/trunk/test/Modules/Inputs/module.map
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/module.map?rev=171925&r1=171924&r2=171925&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/module.map (original)
+++ cfe/trunk/test/Modules/Inputs/module.map Tue Jan  8 18:47:56 2013
@@ -118,3 +118,9 @@
 framework module * { 
   exclude NotAModule
 }
+
+module linkage_merge_left {
+  explicit module sub {
+    header "linkage-merge-sub.h"
+  }
+}

Added: cfe/trunk/test/Modules/linkage-merge.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/linkage-merge.m?rev=171925&view=auto
==============================================================================
--- cfe/trunk/test/Modules/linkage-merge.m (added)
+++ cfe/trunk/test/Modules/linkage-merge.m Tue Jan  8 18:47:56 2013
@@ -0,0 +1,27 @@
+// In module: expected-note{{previous declaration}}
+
+
+
+
+// In module: expected-note{{previous definition is here}}
+
+// Test redeclarations of functions where the original declaration is
+// still hidden.
+
+ at import linkage_merge_left; // excludes "sub"
+
+extern int f0(float); // expected-error{{conflicting types for 'f0'}}
+static int f1(float); // okay: considered distinct
+static int f2(float); // okay: considered distinct
+extern int f3(float); // okay: considered distinct
+
+extern float v0; // expected-error{{redefinition of 'v0' with a different type: 'float' vs 'int'}}
+static float v1;
+static float v2;
+extern float v3;
+
+typedef float T0;
+
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodules -x objective-c -fmodule-cache-path %t -emit-module -fmodule-name=linkage_merge_left %S/Inputs/module.map
+// RUN: %clang_cc1 -fmodules -fmodule-cache-path %t -w %s -verify





More information about the cfe-commits mailing list