diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index 24bd2a5a365f..53c2d3ce52fb 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -87,6 +87,7 @@ class MicrosoftMangleContextImpl : public MicrosoftMangleContext { typedef std::pair DiscriminatorKeyTy; llvm::DenseMap Discriminator; llvm::DenseMap Uniquifier; + llvm::DenseMap LambdaIds; public: MicrosoftMangleContextImpl(ASTContext &Context, DiagnosticsEngine &Diags) @@ -148,6 +149,16 @@ public: return true; } + unsigned getLambdaId(const CXXRecordDecl *RD) { + assert(RD->isLambda() && "RD must be a lambda!"); + assert(!RD->isExternallyVisible() && "RD must not be visible!"); + assert(RD->getLambdaManglingNumber() == 0 && + "RD must not have a mangling number!"); + std::pair::iterator, bool> + Result = LambdaIds.insert(std::make_pair(RD, LambdaIds.size())); + return Result.first->second; + } + private: void mangleInitFiniStub(const VarDecl *D, raw_ostream &Out, char CharCode); }; @@ -704,6 +715,23 @@ MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, break; } + if (const CXXRecordDecl *Record = dyn_cast(TD)) { + if (Record->isLambda()) { + llvm::SmallString<10> Name("getLambdaManglingNumber()) + LambdaId = Record->getLambdaManglingNumber(); + else + LambdaId = Context.getLambdaId(Record); + + Name += llvm::utostr(LambdaId); + Name += ">"; + + mangleSourceName(Name); + break; + } + } + llvm::SmallString<64> Name("hasDeclaratorForAnonDecl()) { // Anonymous types with no tag or typedef get the name of their @@ -712,7 +740,7 @@ MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, } else { // Otherwise, number the types using a $S prefix. Name += "$S"; - Name += llvm::utostr(Context.getAnonymousStructId(TD) + 1); + Name += llvm::utostr(Context.getAnonymousStructId(TD)); } Name += ">"; mangleSourceName(Name.str()); @@ -770,6 +798,9 @@ MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, void MicrosoftCXXNameMangler::mangleNestedName(const NamedDecl *ND) { // ::= [] // ::= [] + if (isLambda(ND)) + return; + const DeclContext *DC = ND->getDeclContext(); while (!DC->isTranslationUnit()) { diff --git a/clang/test/CodeGenCXX/mangle-ms-cxx11.cpp b/clang/test/CodeGenCXX/mangle-ms-cxx11.cpp index c5da330a40d7..3acd7a21001e 100644 --- a/clang/test/CodeGenCXX/mangle-ms-cxx11.cpp +++ b/clang/test/CodeGenCXX/mangle-ms-cxx11.cpp @@ -101,3 +101,21 @@ decltype(a) fun(decltype(a) x, decltype(a)) { return x; } // CHECK-DAG: ?fun@PR18022@@YA?AU@1@U21@0@Z } + +inline int define_lambda() { + static auto lambda = [] { static int local; ++local; return local; }; +// First, we have the static local variable of type "" inside of +// "define_lambda". +// CHECK-DAG: ?lambda@?1??define_lambda@@YAHXZ@4V@@A +// Next, we have the "operator()" for "" which is inside of +// "define_lambda". +// CHECK-DAG: ??R@?define_lambda@@YAHXZ@QBEHXZ +// Finally, we have the local which is inside of "" which is inside of +// "define_lambda". Hooray. +// CHECK-DAG: ?local@?2???R@?define_lambda@@YAHXZ@QBEHXZ@4HA + return lambda(); +} + +int call_lambda() { + return define_lambda(); +}