r250884 - [modules] libstdc++ defines some static inline functions in its internal

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Wed Oct 21 00:13:52 PDT 2015


Author: rsmith
Date: Wed Oct 21 02:13:52 2015
New Revision: 250884

URL: http://llvm.org/viewvc/llvm-project?rev=250884&view=rev
Log:
[modules] libstdc++ defines some static inline functions in its internal
headers. If those headers end up being textually included twice into the same
module, we get ambiguity errors.

Work around this by downgrading the ambiguity error to a warning if multiple
identical internal-linkage functions appear in an overload set, and just pick
one of those functions as the lookup result.

Added:
    cfe/trunk/test/Modules/Inputs/libstdcxx-ambiguous-internal/
    cfe/trunk/test/Modules/Inputs/libstdcxx-ambiguous-internal/a.h
    cfe/trunk/test/Modules/Inputs/libstdcxx-ambiguous-internal/b.h
    cfe/trunk/test/Modules/Inputs/libstdcxx-ambiguous-internal/c.h
    cfe/trunk/test/Modules/Inputs/libstdcxx-ambiguous-internal/d.h
    cfe/trunk/test/Modules/Inputs/libstdcxx-ambiguous-internal/module.modulemap
    cfe/trunk/test/Modules/libstdcxx-ambiguous-internal.cpp
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/SemaOverload.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=250884&r1=250883&r2=250884&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Oct 21 02:13:52 2015
@@ -2974,6 +2974,9 @@ def note_ovl_candidate : Note<"candidate
     "%select{none|const|restrict|const and restrict|volatile|const and volatile"
     "|volatile and restrict|const, volatile, and restrict}4)"
     "| made ineligible by enable_if}2">;
+def ext_ovl_equivalent_internal_linkage_functions_in_modules : ExtWarn<
+  "ambiguous use of internal linkage function %0 defined in multiple modules">,
+  InGroup<DiagGroup<"modules-ambiguous-internal-linkage-function">>;
 
 def note_ovl_candidate_inherited_constructor : Note<"inherited from here">;
 def note_ovl_candidate_illegal_constructor : Note<

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=250884&r1=250883&r2=250884&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Wed Oct 21 02:13:52 2015
@@ -8565,6 +8565,27 @@ bool clang::isBetterOverloadCandidate(Se
   return false;
 }
 
+/// Determine whether two function declarations are "equivalent" for overload
+/// resolution purposes. This applies when the same internal linkage function
+/// is defined by two modules (textually including the same header). In such
+/// a case, we don't consider the declarations to declare the same entity, but
+/// we also don't want lookups with both declarations visible to be ambiguous
+/// in some cases (this happens when using a modularized libstdc++).
+static bool isEquivalentCompatibleOverload(Sema &S,
+                                           const OverloadCandidate &Best,
+                                           const OverloadCandidate &Cand) {
+  return Best.Function && Cand.Function &&
+         Best.Function->getDeclContext()->getRedeclContext()->Equals(
+             Cand.Function->getDeclContext()->getRedeclContext()) &&
+         S.getOwningModule(Best.Function) != S.getOwningModule(Cand.Function) &&
+         !Best.Function->isExternallyVisible() &&
+         !Cand.Function->isExternallyVisible() &&
+         !S.IsOverload(Best.Function, Cand.Function, /*UsingDecl*/false);
+}
+
+static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
+                                  unsigned NumArgs);
+
 /// \brief Computes the best viable function (C++ 13.3.3)
 /// within an overload candidate set.
 ///
@@ -8592,6 +8613,8 @@ OverloadCandidateSet::BestViableFunction
   if (Best == end())
     return OR_No_Viable_Function;
 
+  llvm::SmallVector<const OverloadCandidate *, 4> EquivalentCands;
+
   // Make sure that this function is better than every other viable
   // function. If not, we have an ambiguity.
   for (iterator Cand = begin(); Cand != end(); ++Cand) {
@@ -8599,6 +8622,11 @@ OverloadCandidateSet::BestViableFunction
         Cand != Best &&
         !isBetterOverloadCandidate(S, *Best, *Cand, Loc,
                                    UserDefinedConversion)) {
+      if (isEquivalentCompatibleOverload(S, *Best, *Cand)) {
+        EquivalentCands.push_back(Cand);
+        continue;
+      }
+
       Best = end();
       return OR_Ambiguous;
     }
@@ -8610,6 +8638,14 @@ OverloadCandidateSet::BestViableFunction
        S.isFunctionConsideredUnavailable(Best->Function)))
     return OR_Deleted;
 
+  if (!EquivalentCands.empty()) {
+    S.Diag(Loc, diag::ext_ovl_equivalent_internal_linkage_functions_in_modules)
+      << Best->Function;
+    S.NoteOverloadCandidate(Best->Function);
+    for (auto *Cand : EquivalentCands)
+      S.NoteOverloadCandidate(Cand->Function);
+  }
+
   return OR_Success;
 }
 

Added: cfe/trunk/test/Modules/Inputs/libstdcxx-ambiguous-internal/a.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/libstdcxx-ambiguous-internal/a.h?rev=250884&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/libstdcxx-ambiguous-internal/a.h (added)
+++ cfe/trunk/test/Modules/Inputs/libstdcxx-ambiguous-internal/a.h Wed Oct 21 02:13:52 2015
@@ -0,0 +1,4 @@
+#ifndef A_H
+#define A_H
+static inline void f() {}
+#endif

Added: cfe/trunk/test/Modules/Inputs/libstdcxx-ambiguous-internal/b.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/libstdcxx-ambiguous-internal/b.h?rev=250884&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/libstdcxx-ambiguous-internal/b.h (added)
+++ cfe/trunk/test/Modules/Inputs/libstdcxx-ambiguous-internal/b.h Wed Oct 21 02:13:52 2015
@@ -0,0 +1,4 @@
+#ifndef B_H
+#define B_H
+#include "a.h"
+#endif

Added: cfe/trunk/test/Modules/Inputs/libstdcxx-ambiguous-internal/c.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/libstdcxx-ambiguous-internal/c.h?rev=250884&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/libstdcxx-ambiguous-internal/c.h (added)
+++ cfe/trunk/test/Modules/Inputs/libstdcxx-ambiguous-internal/c.h Wed Oct 21 02:13:52 2015
@@ -0,0 +1,4 @@
+#ifndef C_H
+#define C_H
+#include "a.h"
+#endif

Added: cfe/trunk/test/Modules/Inputs/libstdcxx-ambiguous-internal/d.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/libstdcxx-ambiguous-internal/d.h?rev=250884&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/libstdcxx-ambiguous-internal/d.h (added)
+++ cfe/trunk/test/Modules/Inputs/libstdcxx-ambiguous-internal/d.h Wed Oct 21 02:13:52 2015
@@ -0,0 +1,3 @@
+#include "b.h"
+#include "c.h"
+inline void g() { f(); }

Added: cfe/trunk/test/Modules/Inputs/libstdcxx-ambiguous-internal/module.modulemap
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/libstdcxx-ambiguous-internal/module.modulemap?rev=250884&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/libstdcxx-ambiguous-internal/module.modulemap (added)
+++ cfe/trunk/test/Modules/Inputs/libstdcxx-ambiguous-internal/module.modulemap Wed Oct 21 02:13:52 2015
@@ -0,0 +1,6 @@
+module std {
+  module A { textual header "a.h" }
+  module B { header "b.h" }
+  module C { header "c.h" }
+  module D { header "d.h" export * }
+}

Added: cfe/trunk/test/Modules/libstdcxx-ambiguous-internal.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/libstdcxx-ambiguous-internal.cpp?rev=250884&view=auto
==============================================================================
--- cfe/trunk/test/Modules/libstdcxx-ambiguous-internal.cpp (added)
+++ cfe/trunk/test/Modules/libstdcxx-ambiguous-internal.cpp Wed Oct 21 02:13:52 2015
@@ -0,0 +1,7 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -x c++ -std=c++11 -fmodules -emit-module -fmodule-name=std -fmodules-cache-path=%t %S/Inputs/libstdcxx-ambiguous-internal/module.modulemap -Werror
+// RUN: %clang_cc1 -x c++ -std=c++11 -fmodules -emit-module -fmodule-name=std -fmodules-cache-path=%t %S/Inputs/libstdcxx-ambiguous-internal/module.modulemap -fmodules-local-submodule-visibility -DAMBIGUOUS 2>&1| FileCheck %s
+
+// CHECK-NOT: error
+// CHECK: warning: ambiguous use of internal linkage function 'f' defined in multiple modules
+// CHECK-NOT: error




More information about the cfe-commits mailing list