Author: majnemer Date: Tue Dec 6 11:01:02 2016 New Revision: 288826 URL: http://llvm.org/viewvc/llvm-project?rev=288826&view=rev Log: [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 Modified: cfe/trunk/lib/AST/MicrosoftMangle.cpp cfe/trunk/test/CodeGenCXX/mangle-ms-cxx11.cpp Modified: cfe/trunk/lib/AST/MicrosoftMangle.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/MicrosoftMangle.cpp?rev=288826&r1=288825&r2=288826&view=diff ============================================================================== --- cfe/trunk/lib/AST/MicrosoftMangle.cpp (original) +++ cfe/trunk/lib/AST/MicrosoftMangle.cpp Tue Dec 6 11:01:02 2016 @@ -66,6 +66,16 @@ struct msvc_hashing_ostream : public llv } }; +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 /// the given declaration. static const DeclContext *getEffectiveDeclContext(const Decl *D) { @@ -75,12 +85,8 @@ static const DeclContext *getEffectiveDe // not the case: the lambda closure type ends up living in the context // where the function itself resides, because the function declaration itself // had not yet been created. Fix the context here. - if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) { - if (RD->isLambda()) - if (ParmVarDecl *ContextParam = - dyn_cast_or_null<ParmVarDecl>(RD->getLambdaContextDecl())) - return ContextParam->getDeclContext(); - } + if (const auto *LDADC = getLambdaDefaultArgumentDeclContext(D)) + return LDADC; // Perform the same check for block literals. if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) { @@ -112,14 +118,6 @@ static const FunctionDecl *getStructor(c 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 /// Microsoft Visual C++ ABI. class MicrosoftMangleContextImpl : public MicrosoftMangleContext { @@ -200,9 +198,11 @@ public: // Lambda closure types are already numbered, give out a phony number so // that they demangle nicely. - if (isLambda(ND)) { - disc = 1; - return true; + if (const auto *RD = dyn_cast<CXXRecordDecl>(ND)) { + if (RD->isLambda()) { + disc = 1; + return true; + } } // Use the canonical number for externally visible decls. @@ -824,9 +824,24 @@ void MicrosoftCXXNameMangler::mangleUnqu if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(TD)) { if (Record->isLambda()) { llvm::SmallString<10> Name("<lambda_"); + + Decl *LambdaContextDecl = Record->getLambdaContextDecl(); + unsigned LambdaManglingNumber = Record->getLambdaManglingNumber(); unsigned LambdaId; - if (Record->getLambdaManglingNumber()) - LambdaId = Record->getLambdaManglingNumber(); + const ParmVarDecl *Parm = + 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 LambdaId = Context.getLambdaId(Record); @@ -834,6 +849,16 @@ void MicrosoftCXXNameMangler::mangleUnqu 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; } } @@ -937,7 +962,6 @@ void MicrosoftCXXNameMangler::mangleNest // for how this should be done. Out << "__block_invoke" << Context.getBlockId(BD, false); Out << '@'; - continue; } else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC)) { mangleObjCMethodName(Method); } else if (isa<NamedDecl>(DC)) { @@ -945,8 +969,15 @@ void MicrosoftCXXNameMangler::mangleNest if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) { mangle(FD, "?"); break; - } else + } else { 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(); } Modified: cfe/trunk/test/CodeGenCXX/mangle-ms-cxx11.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/mangle-ms-cxx11.cpp?rev=288826&r1=288825&r2=288826&view=diff ============================================================================== --- cfe/trunk/test/CodeGenCXX/mangle-ms-cxx11.cpp (original) +++ cfe/trunk/test/CodeGenCXX/mangle-ms-cxx11.cpp Tue Dec 6 11:01:02 2016 @@ -318,3 +318,28 @@ void unaligned_foo8_S::unaligned_foo8() // 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); +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits