Skip to content
Snippets Groups Projects
Commit d3feba18 authored by David Majnemer's avatar David Majnemer
Browse files

[MS ABI] Implement more of the Itanium mangling rules

We didn't implement handle corner cases like:
 - lambdas used to initialize a field
 - lambdas in default argument initializers

This fixes PR31197.

Differential Revision: https://reviews.llvm.org/D27226

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@288826 91177308-0d34-0410-b5e6-96231b3b80d8
parent c083b0c2
No related branches found
No related tags found
No related merge requests found
...@@ -66,6 +66,16 @@ struct msvc_hashing_ostream : public llvm::raw_svector_ostream { ...@@ -66,6 +66,16 @@ struct msvc_hashing_ostream : public llvm::raw_svector_ostream {
} }
}; };
static const DeclContext *
getLambdaDefaultArgumentDeclContext(const Decl *D) {
if (const auto *RD = dyn_cast<CXXRecordDecl>(D))
if (RD->isLambda())
if (const auto *Parm =
dyn_cast_or_null<ParmVarDecl>(RD->getLambdaContextDecl()))
return Parm->getDeclContext();
return nullptr;
}
/// \brief Retrieve the declaration context that should be used when mangling /// \brief Retrieve the declaration context that should be used when mangling
/// the given declaration. /// the given declaration.
static const DeclContext *getEffectiveDeclContext(const Decl *D) { static const DeclContext *getEffectiveDeclContext(const Decl *D) {
...@@ -75,12 +85,8 @@ static const DeclContext *getEffectiveDeclContext(const Decl *D) { ...@@ -75,12 +85,8 @@ static const DeclContext *getEffectiveDeclContext(const Decl *D) {
// not the case: the lambda closure type ends up living in the context // not the case: the lambda closure type ends up living in the context
// where the function itself resides, because the function declaration itself // where the function itself resides, because the function declaration itself
// had not yet been created. Fix the context here. // had not yet been created. Fix the context here.
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) { if (const auto *LDADC = getLambdaDefaultArgumentDeclContext(D))
if (RD->isLambda()) return LDADC;
if (ParmVarDecl *ContextParam =
dyn_cast_or_null<ParmVarDecl>(RD->getLambdaContextDecl()))
return ContextParam->getDeclContext();
}
// Perform the same check for block literals. // Perform the same check for block literals.
if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) { if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
...@@ -112,14 +118,6 @@ static const FunctionDecl *getStructor(const NamedDecl *ND) { ...@@ -112,14 +118,6 @@ static const FunctionDecl *getStructor(const NamedDecl *ND) {
return FD; return FD;
} }
static bool isLambda(const NamedDecl *ND) {
const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(ND);
if (!Record)
return false;
return Record->isLambda();
}
/// MicrosoftMangleContextImpl - Overrides the default MangleContext for the /// MicrosoftMangleContextImpl - Overrides the default MangleContext for the
/// Microsoft Visual C++ ABI. /// Microsoft Visual C++ ABI.
class MicrosoftMangleContextImpl : public MicrosoftMangleContext { class MicrosoftMangleContextImpl : public MicrosoftMangleContext {
...@@ -200,9 +198,11 @@ public: ...@@ -200,9 +198,11 @@ public:
// Lambda closure types are already numbered, give out a phony number so // Lambda closure types are already numbered, give out a phony number so
// that they demangle nicely. // that they demangle nicely.
if (isLambda(ND)) { if (const auto *RD = dyn_cast<CXXRecordDecl>(ND)) {
disc = 1; if (RD->isLambda()) {
return true; disc = 1;
return true;
}
} }
// Use the canonical number for externally visible decls. // Use the canonical number for externally visible decls.
...@@ -824,9 +824,24 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, ...@@ -824,9 +824,24 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(TD)) { if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(TD)) {
if (Record->isLambda()) { if (Record->isLambda()) {
llvm::SmallString<10> Name("<lambda_"); llvm::SmallString<10> Name("<lambda_");
Decl *LambdaContextDecl = Record->getLambdaContextDecl();
unsigned LambdaManglingNumber = Record->getLambdaManglingNumber();
unsigned LambdaId; unsigned LambdaId;
if (Record->getLambdaManglingNumber()) const ParmVarDecl *Parm =
LambdaId = Record->getLambdaManglingNumber(); dyn_cast_or_null<ParmVarDecl>(LambdaContextDecl);
const FunctionDecl *Func =
Parm ? dyn_cast<FunctionDecl>(Parm->getDeclContext()) : nullptr;
if (Func) {
unsigned DefaultArgNo =
Func->getNumParams() - Parm->getFunctionScopeIndex();
Name += llvm::utostr(DefaultArgNo);
Name += "_";
}
if (LambdaManglingNumber)
LambdaId = LambdaManglingNumber;
else else
LambdaId = Context.getLambdaId(Record); LambdaId = Context.getLambdaId(Record);
...@@ -834,6 +849,16 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, ...@@ -834,6 +849,16 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
Name += ">"; Name += ">";
mangleSourceName(Name); mangleSourceName(Name);
// If the context of a closure type is an initializer for a class
// member (static or nonstatic), it is encoded in a qualified name.
if (LambdaManglingNumber && LambdaContextDecl) {
if ((isa<VarDecl>(LambdaContextDecl) ||
isa<FieldDecl>(LambdaContextDecl)) &&
LambdaContextDecl->getDeclContext()->isRecord()) {
mangleUnqualifiedName(cast<NamedDecl>(LambdaContextDecl));
}
}
break; break;
} }
} }
...@@ -937,7 +962,6 @@ void MicrosoftCXXNameMangler::mangleNestedName(const NamedDecl *ND) { ...@@ -937,7 +962,6 @@ void MicrosoftCXXNameMangler::mangleNestedName(const NamedDecl *ND) {
// for how this should be done. // for how this should be done.
Out << "__block_invoke" << Context.getBlockId(BD, false); Out << "__block_invoke" << Context.getBlockId(BD, false);
Out << '@'; Out << '@';
continue;
} else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC)) { } else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC)) {
mangleObjCMethodName(Method); mangleObjCMethodName(Method);
} else if (isa<NamedDecl>(DC)) { } else if (isa<NamedDecl>(DC)) {
...@@ -945,8 +969,15 @@ void MicrosoftCXXNameMangler::mangleNestedName(const NamedDecl *ND) { ...@@ -945,8 +969,15 @@ void MicrosoftCXXNameMangler::mangleNestedName(const NamedDecl *ND) {
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) { if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
mangle(FD, "?"); mangle(FD, "?");
break; break;
} else } else {
mangleUnqualifiedName(ND); mangleUnqualifiedName(ND);
// Lambdas in default arguments conceptually belong to the function the
// parameter corresponds to.
if (const auto *LDADC = getLambdaDefaultArgumentDeclContext(ND)) {
DC = LDADC;
continue;
}
}
} }
DC = DC->getParent(); DC = DC->getParent();
} }
......
...@@ -318,3 +318,28 @@ void unaligned_foo8_S::unaligned_foo8() volatile __unaligned {} ...@@ -318,3 +318,28 @@ void unaligned_foo8_S::unaligned_foo8() volatile __unaligned {}
// CHECK-DAG: @"\01?unaligned_foo8@unaligned_foo8_S@@QFCEXXZ" // CHECK-DAG: @"\01?unaligned_foo8@unaligned_foo8_S@@QFCEXXZ"
namespace PR31197 {
struct A {
// CHECK-DAG: define linkonce_odr x86_thiscallcc i32* @"\01??R<lambda_1>@x@A@PR31197@@QBE@XZ"(
int *x = []() {
static int white;
// CHECK-DAG: @"\01?white@?1???R<lambda_1>@x@A@PR31197@@QBE@XZ@4HA"
return &white;
}();
// CHECK-DAG: define linkonce_odr x86_thiscallcc i32* @"\01??R<lambda_1>@y@A@PR31197@@QBE@XZ"(
int *y = []() {
static int black;
// CHECK-DAG: @"\01?black@?1???R<lambda_1>@y@A@PR31197@@QBE@XZ@4HA"
return &black;
}();
using FPtrTy = void(void);
static void default_args(FPtrTy x = [] {}, FPtrTy y = [] {}, int z = [] { return 1; }() + [] { return 2; }()) {}
// CHECK-DAG: @"\01??R<lambda_1_1>@?0??default_args@A@PR31197@@SAXP6AXXZ0H@Z@QBE@XZ"(
// CHECK-DAG: @"\01??R<lambda_1_2>@?0??default_args@A@PR31197@@SAXP6AXXZ0H@Z@QBE@XZ"(
// CHECK-DAG: @"\01??R<lambda_2_1>@?0??default_args@A@PR31197@@SAXP6AXXZ0H@Z@QBE@XZ"(
// CHECK-DAG: @"\01??R<lambda_3_1>@?0??default_args@A@PR31197@@SAXP6AXXZ0H@Z@QBE@XZ"(
};
A a;
int call_it = (A::default_args(), 1);
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment