Skip to content

Commit f9e111c

Browse files
committed
[cxx-interop] Re-implement template mangling.
Instead of mangling class template specializations with the prefix "__CxxTemplateInst," simply set the decl name as the class templates plus the types that it is specialized on (so `vector<Int>` rather than `__CxxTemplateInstNSt3__16vectorIi...`). This is mainly to improve diagnostics. As a side effect of this change, if anyone copies the name of a class template specializaiton from an error/warning and uses it in source code, the compiler will error (that class templates aren't available in swift) rather than silently passing only to cause serailization failures down the road.
1 parent 8e0e51a commit f9e111c

File tree

6 files changed

+93
-74
lines changed

6 files changed

+93
-74
lines changed

include/swift/AST/ASTContext.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1455,6 +1455,8 @@ class ASTContext final {
14551455
/// Finds the address of the given symbol. If `libraryHandleHint` is non-null,
14561456
/// search within the library.
14571457
void *getAddressOfSymbol(const char *name, void *libraryHandleHint = nullptr);
1458+
1459+
Type getNamedSwiftType(ModuleDecl *module, StringRef name);
14581460

14591461
private:
14601462
friend Decl;

lib/AST/ASTContext.cpp

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
#include "swift/Basic/SourceManager.h"
5656
#include "swift/Basic/Statistic.h"
5757
#include "swift/Basic/StringExtras.h"
58+
#include "swift/ClangImporter/ClangModule.h"
5859
#include "swift/Strings.h"
5960
#include "swift/Subsystems.h"
6061
#include "swift/SymbolGraphGen/SymbolGraphOptions.h"
@@ -5306,8 +5307,6 @@ ASTContext::getForeignRepresentationInfo(NominalTypeDecl *nominal,
53065307
}
53075308

53085309
// Pull SIMD types of size 2...4 from the SIMD module, if it exists.
5309-
// FIXME: Layering violation to use the ClangImporter's define.
5310-
const unsigned SWIFT_MAX_IMPORTED_SIMD_ELEMENTS = 4;
53115310
if (auto simd = getLoadedModule(Id_simd)) {
53125311
#define MAP_SIMD_TYPE(BASENAME, _, __) \
53135312
{ \
@@ -5354,7 +5353,6 @@ ASTContext::getForeignRepresentationInfo(NominalTypeDecl *nominal,
53545353
conditionallyAddTrivial(nominal, getSwiftId(KnownFoundationEntity::NSZone), Id_ObjectiveC, true);
53555354
conditionallyAddTrivial(nominal, Id_CGFloat, getIdentifier("CoreGraphics"));
53565355
conditionallyAddTrivial(nominal, Id_CGFloat, getIdentifier("CoreFoundation"));
5357-
const unsigned SWIFT_MAX_IMPORTED_SIMD_ELEMENTS = 4;
53585356
#define MAP_SIMD_TYPE(BASENAME, _, __) \
53595357
{ \
53605358
char name[] = #BASENAME "0"; \
@@ -6252,3 +6250,39 @@ void *ASTContext::getAddressOfSymbol(const char *name,
62526250
#endif
62536251
return address;
62546252
}
6253+
6254+
Type ASTContext::getNamedSwiftType(ModuleDecl *module, StringRef name) {
6255+
if (!module)
6256+
return Type();
6257+
6258+
// Look for the type.
6259+
Identifier identifier = getIdentifier(name);
6260+
SmallVector<ValueDecl *, 2> results;
6261+
6262+
// Check if the lookup we're about to perform a lookup within is
6263+
// a Clang module.
6264+
for (auto *file : module->getFiles()) {
6265+
if (auto clangUnit = dyn_cast<ClangModuleUnit>(file)) {
6266+
// If we have an overlay, look in the overlay. Otherwise, skip
6267+
// the lookup to avoid infinite recursion.
6268+
if (auto module = clangUnit->getOverlayModule())
6269+
module->lookupValue(identifier, NLKind::UnqualifiedLookup, results);
6270+
} else {
6271+
file->lookupValue(identifier, NLKind::UnqualifiedLookup, results);
6272+
}
6273+
}
6274+
6275+
if (results.size() != 1)
6276+
return Type();
6277+
6278+
auto decl = dyn_cast<TypeDecl>(results.front());
6279+
if (!decl)
6280+
return Type();
6281+
6282+
assert(!decl->hasClangNode() && "picked up the original type?");
6283+
6284+
if (auto *nominalDecl = dyn_cast<NominalTypeDecl>(decl))
6285+
return nominalDecl->getDeclaredType();
6286+
return decl->getDeclaredInterfaceType();
6287+
}
6288+

lib/AST/ClangTypeConverter.cpp

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -43,22 +43,7 @@ using namespace swift;
4343
namespace {
4444

4545
static Type getNamedSwiftType(ModuleDecl *stdlib, StringRef name) {
46-
auto &ctx = stdlib->getASTContext();
47-
SmallVector<ValueDecl*, 1> results;
48-
stdlib->lookupValue(ctx.getIdentifier(name), NLKind::QualifiedLookup,
49-
results);
50-
51-
// If we have one single type decl, and that decl has been
52-
// type-checked, return its declared type.
53-
//
54-
// ...non-type-checked types should only ever show up here because
55-
// of test cases using -enable-source-import, but unfortunately
56-
// that's a real thing.
57-
if (results.size() == 1) {
58-
if (auto typeDecl = dyn_cast<TypeDecl>(results[0]))
59-
return typeDecl->getDeclaredInterfaceType();
60-
}
61-
return Type();
46+
return stdlib->getASTContext().getNamedSwiftType(stdlib, name);
6247
}
6348

6449
static clang::QualType

lib/ClangImporter/ImportName.cpp

Lines changed: 50 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2179,29 +2179,58 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,
21792179
return importNameImpl(classTemplateSpecDecl->getSpecializedTemplate(),
21802180
version, givenName);
21812181
if (!isa<clang::ClassTemplatePartialSpecializationDecl>(D)) {
2182-
2183-
auto &astContext = classTemplateSpecDecl->getASTContext();
2184-
// Itanium mangler produces valid Swift identifiers, use it to generate a name for
2185-
// this instantiation.
2186-
std::unique_ptr<clang::MangleContext> mangler{
2187-
clang::ItaniumMangleContext::create(astContext,
2188-
astContext.getDiagnostics())};
2182+
// When constructing the name of a C++ template, don't expand all the
2183+
// template, only expand one layer. Here we want to prioritize
2184+
// readability over total completeness.
21892185
llvm::SmallString<128> storage;
21902186
llvm::raw_svector_ostream buffer(storage);
2191-
mangler->mangleTypeName(astContext.getRecordType(classTemplateSpecDecl),
2192-
buffer);
2193-
2194-
// The Itanium mangler does not provide a way to get the mangled
2195-
// representation of a type. Instead, we call mangleTypeName() that
2196-
// returns the name of the RTTI typeinfo symbol, and remove the _ZTS
2197-
// prefix. Then we prepend __CxxTemplateInst to reduce chances of conflict
2198-
// with regular C and C++ structs.
2199-
llvm::SmallString<128> mangledNameStorage;
2200-
llvm::raw_svector_ostream mangledName(mangledNameStorage);
2201-
assert(buffer.str().take_front(4) == "_ZTS");
2202-
mangledName << CXX_TEMPLATE_INST_PREFIX << buffer.str().drop_front(4);
2203-
2204-
baseName = swiftCtx.getIdentifier(mangledName.str()).get();
2187+
D->printName(buffer);
2188+
buffer << "<";
2189+
llvm::interleaveComma(classTemplateSpecDecl->getTemplateArgs().asArray(),
2190+
buffer,
2191+
[&buffer, this, version](const clang::TemplateArgument& arg) {
2192+
// Use import name here so builtin types such as "int" map to their
2193+
// Swift equivalent ("Int32").
2194+
if (arg.getKind() == clang::TemplateArgument::Type) {
2195+
auto ty = arg.getAsType().getTypePtr();
2196+
if (auto builtin = dyn_cast<clang::BuiltinType>(ty)) {
2197+
auto &ctx = swiftCtx;
2198+
Type swiftType = nullptr;
2199+
switch (builtin->getKind()) {
2200+
case clang::BuiltinType::Void:
2201+
swiftType = ctx.getNamedSwiftType(ctx.getStdlibModule(), "Void");
2202+
break;
2203+
#define MAP_BUILTIN_TYPE(CLANG_BUILTIN_KIND, SWIFT_TYPE_NAME) \
2204+
case clang::BuiltinType::CLANG_BUILTIN_KIND: \
2205+
swiftType = ctx.getNamedSwiftType(ctx.getStdlibModule(), \
2206+
#SWIFT_TYPE_NAME); \
2207+
break;
2208+
#define MAP_BUILTIN_CCHAR_TYPE(CLANG_BUILTIN_KIND, SWIFT_TYPE_NAME) \
2209+
case clang::BuiltinType::CLANG_BUILTIN_KIND: \
2210+
swiftType = ctx.getNamedSwiftType(ctx.getStdlibModule(), \
2211+
#SWIFT_TYPE_NAME); \
2212+
break;
2213+
#include "swift/ClangImporter/BuiltinMappedTypes.def"
2214+
default:
2215+
break;
2216+
}
2217+
2218+
if (swiftType) {
2219+
if (auto nominal = dyn_cast<NominalType>(swiftType->getCanonicalType())) {
2220+
buffer << nominal->getDecl()->getNameStr();
2221+
return;
2222+
}
2223+
}
2224+
} else if (auto namedArg = dyn_cast_or_null<clang::NamedDecl>(ty->getAsTagDecl())) {
2225+
importNameImpl(namedArg, version, clang::DeclarationName()).getDeclName().print(buffer);
2226+
return;
2227+
}
2228+
}
2229+
buffer << "_";
2230+
});
2231+
buffer << ">";
2232+
2233+
baseName = swiftCtx.getIdentifier(buffer.str()).get();
22052234
}
22062235
}
22072236

lib/ClangImporter/ImportType.cpp

Lines changed: 1 addition & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3251,38 +3251,7 @@ bool ClangImporter::Implementation::canImportFoundationModule() {
32513251

32523252
Type ClangImporter::Implementation::getNamedSwiftType(ModuleDecl *module,
32533253
StringRef name) {
3254-
if (!module)
3255-
return Type();
3256-
3257-
// Look for the type.
3258-
Identifier identifier = SwiftContext.getIdentifier(name);
3259-
SmallVector<ValueDecl *, 2> results;
3260-
3261-
// Check if the lookup we're about to perform a lookup within is
3262-
// a Clang module.
3263-
for (auto *file : module->getFiles()) {
3264-
if (auto clangUnit = dyn_cast<ClangModuleUnit>(file)) {
3265-
// If we have an overlay, look in the overlay. Otherwise, skip
3266-
// the lookup to avoid infinite recursion.
3267-
if (auto module = clangUnit->getOverlayModule())
3268-
module->lookupValue(identifier, NLKind::UnqualifiedLookup, results);
3269-
} else {
3270-
file->lookupValue(identifier, NLKind::UnqualifiedLookup, results);
3271-
}
3272-
}
3273-
3274-
if (results.size() != 1)
3275-
return Type();
3276-
3277-
auto decl = dyn_cast<TypeDecl>(results.front());
3278-
if (!decl)
3279-
return Type();
3280-
3281-
assert(!decl->hasClangNode() && "picked up the original type?");
3282-
3283-
if (auto *nominalDecl = dyn_cast<NominalTypeDecl>(decl))
3284-
return nominalDecl->getDeclaredType();
3285-
return decl->getDeclaredInterfaceType();
3254+
return SwiftContext.getNamedSwiftType(module, name);
32863255
}
32873256

32883257
Type ClangImporter::Implementation::getNamedSwiftType(StringRef moduleName,

lib/Parse/Parser.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1360,8 +1360,8 @@ DeclNameRef swift::formDeclNameRef(ASTContext &ctx,
13601360
// We cannot import when the base name is not an identifier.
13611361
if (baseName.empty())
13621362
return DeclNameRef();
1363-
if (!Lexer::isIdentifier(baseName) && !Lexer::isOperator(baseName))
1364-
return DeclNameRef();
1363+
// if (!Lexer::isIdentifier(baseName) && !Lexer::isOperator(baseName))
1364+
// return DeclNameRef();
13651365

13661366
// Get the identifier for the base name. Special-case `init`.
13671367
DeclBaseName baseNameId;

0 commit comments

Comments
 (0)