diff options
author | David Majnemer <david.majnemer@gmail.com> | 2016-12-06 17:01:02 +0000 |
---|---|---|
committer | David Majnemer <david.majnemer@gmail.com> | 2016-12-06 17:01:02 +0000 |
commit | 984498ff9de8f6d89911485faac3e8c203461ff3 (patch) | |
tree | da73bdde7a01d3402b6c3b005e9aa2c4d394166f /clang/lib/AST/MicrosoftMangle.cpp | |
parent | 4a2979ce12da345e98b8d96be30eb4e0efa9efb7 (diff) | |
download | bcm5719-llvm-984498ff9de8f6d89911485faac3e8c203461ff3.tar.gz bcm5719-llvm-984498ff9de8f6d89911485faac3e8c203461ff3.zip |
[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
Diffstat (limited to 'clang/lib/AST/MicrosoftMangle.cpp')
-rw-r--r-- | clang/lib/AST/MicrosoftMangle.cpp | 73 |
1 files changed, 52 insertions, 21 deletions
diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index 9268017222f..27806a7d9e2 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -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 /// the given declaration. 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 // 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(const NamedDecl *ND) { 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::mangleUnqualifiedName(const NamedDecl *ND, 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::mangleUnqualifiedName(const NamedDecl *ND, 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::mangleNestedName(const NamedDecl *ND) { // 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::mangleNestedName(const NamedDecl *ND) { 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(); } |