Skip to content

Commit 0bd992a

Browse files
[clang AST] move mangling API to namespace clang to allow calls from swift-frontend (#137884)
When implementing `@objcDirect` in Swift, Swift needs to mangle a native `Decl` that is not a clang Node, which in turn don't have access to `clang::MangleContext`. Reimplementing mangling logic in Swift is redundant. This patch moves mangling logic from `clang::MangleContext` to `clang` using only basic types (`StringRef`, `std::optional`, etc.), such that Swift can we can just call Clang API: Swift depends on Clang already. We are separating this from #126639 so we can draft the proposal on the Swift side. #126639 will be worked to depend on this PR. Tests: No new tests, old ones should pass with no problem. --------- Signed-off-by: Peter Rong <PeterRong@meta.com>
1 parent d7f096e commit 0bd992a

File tree

2 files changed

+34
-10
lines changed

2 files changed

+34
-10
lines changed

clang/include/clang/AST/Mangle.h

+7
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,13 @@ struct ThisAdjustment;
4040
struct ThunkInfo;
4141
class VarDecl;
4242

43+
/// Extract mangling function name from MangleContext such that swift can call
44+
/// it to prepare for ObjCDirect in swift.
45+
void mangleObjCMethodName(raw_ostream &OS, bool includePrefixByte,
46+
bool isInstanceMethod, StringRef ClassName,
47+
std::optional<StringRef> CategoryName,
48+
StringRef MethodName);
49+
4350
/// MangleContext - Context for tracking state which persists across multiple
4451
/// calls to the C++ name mangler.
4552
class MangleContext {

clang/lib/AST/Mangle.cpp

+27-10
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,23 @@
2929

3030
using namespace clang;
3131

32+
void clang::mangleObjCMethodName(raw_ostream &OS, bool includePrefixByte,
33+
bool isInstanceMethod, StringRef ClassName,
34+
std::optional<StringRef> CategoryName,
35+
StringRef MethodName) {
36+
// \01+[ContainerName(CategoryName) SelectorName]
37+
if (includePrefixByte)
38+
OS << "\01";
39+
OS << (isInstanceMethod ? '-' : '+');
40+
OS << '[';
41+
OS << ClassName;
42+
if (CategoryName)
43+
OS << "(" << *CategoryName << ")";
44+
OS << " ";
45+
OS << MethodName;
46+
OS << ']';
47+
}
48+
3249
// FIXME: For blocks we currently mimic GCC's mangling scheme, which leaves
3350
// much to be desired. Come up with a better mangling scheme.
3451

@@ -362,26 +379,26 @@ void MangleContext::mangleObjCMethodName(const ObjCMethodDecl *MD,
362379
}
363380

364381
// \01+[ContainerName(CategoryName) SelectorName]
365-
if (includePrefixByte) {
366-
OS << '\01';
367-
}
368-
OS << (MD->isInstanceMethod() ? '-' : '+') << '[';
382+
auto CategoryName = std::optional<StringRef>();
383+
StringRef ClassName = "";
369384
if (const auto *CID = MD->getCategory()) {
370385
if (const auto *CI = CID->getClassInterface()) {
371-
OS << CI->getName();
386+
ClassName = CI->getName();
372387
if (includeCategoryNamespace) {
373-
OS << '(' << *CID << ')';
388+
CategoryName = CID->getName();
374389
}
375390
}
376391
} else if (const auto *CD =
377392
dyn_cast<ObjCContainerDecl>(MD->getDeclContext())) {
378-
OS << CD->getName();
393+
ClassName = CD->getName();
379394
} else {
380395
llvm_unreachable("Unexpected ObjC method decl context");
381396
}
382-
OS << ' ';
383-
MD->getSelector().print(OS);
384-
OS << ']';
397+
std::string MethodName;
398+
llvm::raw_string_ostream MethodNameOS(MethodName);
399+
MD->getSelector().print(MethodNameOS);
400+
clang::mangleObjCMethodName(OS, includePrefixByte, MD->isInstanceMethod(),
401+
ClassName, CategoryName, MethodName);
385402
}
386403

387404
void MangleContext::mangleObjCMethodNameAsSourceName(const ObjCMethodDecl *MD,

0 commit comments

Comments
 (0)