Skip to content

Commit 5c40660

Browse files
Merge pull request #82106 from swiftlang/gaborh/ambiguous-overloads-on-6.2
[6.2][cxx-interop] Support _LIBCPP_PREFERRED_OVERLOAD
2 parents dd2f521 + e700c6b commit 5c40660

File tree

6 files changed

+76
-0
lines changed

6 files changed

+76
-0
lines changed

lib/AST/ModuleNameLookup.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
#include "swift/AST/NameLookup.h"
1818
#include "swift/AST/NameLookupRequests.h"
1919
#include "swift/Basic/Assertions.h"
20+
#include "clang/AST/Attr.h"
21+
#include "clang/AST/ExprCXX.h"
2022
#include "llvm/Support/raw_ostream.h"
2123

2224
using namespace swift;
@@ -278,6 +280,43 @@ void ModuleNameLookup<LookupStrategy>::lookupInModule(
278280
if (decls.size() - initialCount <= 1)
279281
return;
280282

283+
// Some functions like `memchr` are defined both in libc and in libc++.
284+
// Importing both would result in ambiguities, but there are some attributes
285+
// that mark the preferred overloads. See _LIBCPP_PREFERRED_OVERLOAD.
286+
llvm::SmallPtrSet<ValueDecl *, 4> declsToRemove;
287+
bool hasPreferredOverload = false;
288+
for (auto decl : decls)
289+
if (const auto *clangDecl = decl->getClangDecl()) {
290+
if (clangDecl->hasAttr<clang::EnableIfAttr>()) {
291+
// FIXME: at some point we might want to call into Clang to implement
292+
// the full enable_if semantics including the constant evaluation of the
293+
// conditions. For now, just look for the first enable_if(true, "...")
294+
// and assume all the rest of the enable_ifs evaluate to true.
295+
bool thisDeclHasPreferredOverload = false;
296+
for (auto clangAttr :
297+
clangDecl->specific_attrs<clang::EnableIfAttr>()) {
298+
if (auto litExpr =
299+
dyn_cast<clang::CXXBoolLiteralExpr>(clangAttr->getCond())) {
300+
if (litExpr->getValue()) {
301+
thisDeclHasPreferredOverload = hasPreferredOverload = true;
302+
break;
303+
}
304+
}
305+
}
306+
if (!thisDeclHasPreferredOverload)
307+
declsToRemove.insert(decl);
308+
} else
309+
declsToRemove.insert(decl);
310+
}
311+
312+
if (hasPreferredOverload) {
313+
decls.erase(std::remove_if(decls.begin() + initialCount, decls.end(),
314+
[&](ValueDecl *d) -> bool {
315+
return declsToRemove.contains(d);
316+
}),
317+
decls.end());
318+
}
319+
281320
// Remove duplicated declarations, which can happen when the same module is
282321
// imported with multiple access paths.
283322
llvm::SmallPtrSet<ValueDecl *, 4> knownDecls;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#pragma once
2+
3+
void f(int a);
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#pragma once
2+
3+
void f(int a) __attribute__((enable_if(a > 0, ""))) __attribute__((enable_if(true, "")));

test/Interop/Cxx/modules/Inputs/module.modulemap

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,13 @@ module TopLevelModule {
1717
}
1818
export *
1919
}
20+
21+
module AmbiguousA {
22+
header "ambiguous_a.h"
23+
requires cplusplus
24+
}
25+
26+
module AmbiguousB {
27+
header "ambiguous_a.h"
28+
requires cplusplus
29+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// RUN: %target-typecheck-verify-swift -I %S/Inputs -cxx-interoperability-mode=default
2+
3+
import AmbiguousA
4+
import AmbiguousB
5+
6+
func g(_ x: CInt) {
7+
f(x)
8+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// RUN: %target-swift-frontend -cxx-interoperability-mode=default -typecheck -verify -I %S/Inputs %s
2+
3+
// REQUIRES: objc_interop
4+
// REQUIRES: VENDOR=apple
5+
6+
import Darwin
7+
8+
func test_memchr() {
9+
var src = "hello"
10+
var _ = src.withUTF8 { srcBuf in
11+
Darwin.memchr(srcBuf.baseAddress!, 137, src.count)
12+
}
13+
}

0 commit comments

Comments
 (0)