Index: lib/AST/MicrosoftMangle.cpp =================================================================== --- lib/AST/MicrosoftMangle.cpp +++ lib/AST/MicrosoftMangle.cpp @@ -66,6 +66,16 @@ } }; +static const DeclContext * +getLambdaDefaultArgumentDeclContext(const Decl *D) { + if (const auto *RD = dyn_cast(D)) + if (RD->isLambda()) + if (const auto *Parm = + dyn_cast_or_null(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 @@ // 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(D)) { - if (RD->isLambda()) - if (ParmVarDecl *ContextParam = - dyn_cast_or_null(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(D)) { @@ -112,14 +118,6 @@ return FD; } -static bool isLambda(const NamedDecl *ND) { - const CXXRecordDecl *Record = dyn_cast(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,12 @@ // Lambda closure types are already numbered, give out a phony number so // that they demangle nicely. - if (isLambda(ND)) { - disc = 1; - return true; + // Use scope zero for lambdas in default arguments, one for all other lambdas. + if (const auto *RD = dyn_cast(ND)) { + if (RD->isLambda()) { + disc = getLambdaDefaultArgumentDeclContext(RD) ? 0 : 1; + return true; + } } // Use the canonical number for externally visible decls. @@ -824,9 +825,19 @@ if (const CXXRecordDecl *Record = dyn_cast(TD)) { if (Record->isLambda()) { llvm::SmallString<10> Name("getLambdaContextDecl(); + unsigned LambdaManglingNumber = Record->getLambdaManglingNumber(); unsigned LambdaId; - if (Record->getLambdaManglingNumber()) - LambdaId = Record->getLambdaManglingNumber(); + const ParmVarDecl *Parm = + dyn_cast_or_null(LambdaContextDecl); + const FunctionDecl *Func = + Parm ? dyn_cast(Parm->getDeclContext()) : nullptr; + + if (Func) + LambdaId = Func->getNumParams() - Parm->getFunctionScopeIndex(); + else if (LambdaManglingNumber) + LambdaId = LambdaManglingNumber; else LambdaId = Context.getLambdaId(Record); @@ -834,6 +845,16 @@ 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(LambdaContextDecl) || + isa(LambdaContextDecl)) && + LambdaContextDecl->getDeclContext()->isRecord()) { + mangleUnqualifiedName(cast(LambdaContextDecl)); + } + } break; } } @@ -937,7 +958,6 @@ // for how this should be done. Out << "__block_invoke" << Context.getBlockId(BD, false); Out << '@'; - continue; } else if (const ObjCMethodDecl *Method = dyn_cast(DC)) { mangleObjCMethodName(Method); } else if (isa(DC)) { @@ -945,8 +965,15 @@ if (const FunctionDecl *FD = dyn_cast(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(); } Index: test/CodeGenCXX/mangle-ms-cxx11.cpp =================================================================== --- test/CodeGenCXX/mangle-ms-cxx11.cpp +++ test/CodeGenCXX/mangle-ms-cxx11.cpp @@ -318,3 +318,26 @@ // CHECK-DAG: @"\01?unaligned_foo8@unaligned_foo8_S@@QFCEXXZ" +namespace PR31197 { +struct A { + // CHECK-DAG: define linkonce_odr x86_thiscallcc i32* @"\01??R@x@A@PR31197@@QBE@XZ"( + int *x = []() { + static int white; + // CHECK-DAG: @"\01?white@?1???R@x@A@PR31197@@QBE@XZ@4HA" + return &white; + }(); + // CHECK-DAG: define linkonce_odr x86_thiscallcc i32* @"\01??R@y@A@PR31197@@QBE@XZ"( + int *y = []() { + static int black; + // CHECK-DAG: @"\01?black@?1???R@y@A@PR31197@@QBE@XZ@4HA" + return &black; + }(); + using FPtrTy = void(void); + static void default_args(FPtrTy x = [] {}, FPtrTy y = [] {}) {} + // CHECK-DAG: @"\01??R@?A@??default_args@A@PR31197@@SAXP6AXXZ0@Z@QBE@XZ"( + // CHECK-DAG: @"\01??R@?A@??default_args@A@PR31197@@SAXP6AXXZ0@Z@QBE@XZ"( +}; +A a; + +int call_it = (A::default_args(), 1); +}