mirror of
https://github.com/llvm/llvm-project.git
synced 2025-05-01 12:26:09 +00:00
[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 llvm-svn: 288826
This commit is contained in:
parent
4a2979ce12
commit
984498ff9d
@ -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) {
|
|||||||
// 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) {
|
|||||||
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:
|
|||||||
|
|
||||||
// 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,
|
|||||||
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,
|
|||||||
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) {
|
|||||||
// 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) {
|
|||||||
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 {}
|
|||||||
|
|
||||||
// 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);
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user