diff options
Diffstat (limited to 'clang/lib/AST/ItaniumMangle.cpp')
-rw-r--r-- | clang/lib/AST/ItaniumMangle.cpp | 121 |
1 files changed, 77 insertions, 44 deletions
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 7948ef7de06..419cb32e45a 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -57,17 +57,25 @@ static const DeclContext *getEffectiveDeclContext(const Decl *D) { return ContextParam->getDeclContext(); } - return D->getDeclContext(); + const DeclContext *DC = D->getDeclContext(); + if (const CapturedDecl *CD = dyn_cast<CapturedDecl>(DC)) + return getEffectiveDeclContext(CD); + + return DC; } static const DeclContext *getEffectiveParentContext(const DeclContext *DC) { return getEffectiveDeclContext(cast<Decl>(DC)); } - + +static bool isLocalContainerContext(const DeclContext *DC) { + return isa<FunctionDecl>(DC) || isa<ObjCMethodDecl>(DC) || isa<BlockDecl>(DC); +} + static const CXXRecordDecl *GetLocalClassDecl(const Decl *D) { const DeclContext *DC = getEffectiveDeclContext(D); while (!DC->isNamespace() && !DC->isTranslationUnit()) { - if (isa<FunctionDecl>(DC) || isa<ObjCMethodDecl>(DC) || isa<BlockDecl>(DC)) + if (isLocalContainerContext(DC)) return dyn_cast<CXXRecordDecl>(D); D = cast<Decl>(DC); DC = getEffectiveDeclContext(D); @@ -306,7 +314,9 @@ private: void mangleUnscopedTemplateName(const TemplateDecl *ND); void mangleUnscopedTemplateName(TemplateName); void mangleSourceName(const IdentifierInfo *II); - void mangleLocalName(const NamedDecl *ND); + void mangleLocalName(const Decl *D); + void mangleBlockForPrefix(const BlockDecl *Block); + void mangleUnqualifiedBlock(const BlockDecl *Block); void mangleLambda(const CXXRecordDecl *Lambda); void mangleNestedName(const NamedDecl *ND, const DeclContext *DC, bool NoFunction=false); @@ -551,8 +561,7 @@ void CXXNameMangler::mangleName(const NamedDecl *ND) { // is that of the containing namespace, or the translation unit. // FIXME: This is a hack; extern variables declared locally should have // a proper semantic declaration context! - if ((isa<FunctionDecl>(DC) || isa<ObjCMethodDecl>(DC)) && - ND->hasLinkage() && !isLambda(ND)) + if (isLocalContainerContext(DC) && ND->hasLinkage() && !isLambda(ND)) while (!DC->isNamespace() && !DC->isTranslationUnit()) DC = getEffectiveParentContext(DC); else if (GetLocalClassDecl(ND)) { @@ -575,7 +584,7 @@ void CXXNameMangler::mangleName(const NamedDecl *ND) { return; } - if (isa<FunctionDecl>(DC) || isa<ObjCMethodDecl>(DC)) { + if (isLocalContainerContext(DC)) { mangleLocalName(ND); return; } @@ -1264,21 +1273,22 @@ void CXXNameMangler::mangleNestedName(const TemplateDecl *TD, Out << 'E'; } -void CXXNameMangler::mangleLocalName(const NamedDecl *ND) { +void CXXNameMangler::mangleLocalName(const Decl *D) { // <local-name> := Z <function encoding> E <entity name> [<discriminator>] // := Z <function encoding> E s [<discriminator>] // <local-name> := Z <function encoding> E d [ <parameter number> ] // _ <entity name> // <discriminator> := _ <non-negative number> - const CXXRecordDecl *RD = GetLocalClassDecl(ND); - const DeclContext *DC = getEffectiveDeclContext(RD ? RD : ND); + assert(isa<NamedDecl>(D) || isa<BlockDecl>(D)); + const CXXRecordDecl *RD = GetLocalClassDecl(D); + const DeclContext *DC = getEffectiveDeclContext(RD ? RD : D); Out << 'Z'; if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(DC)) mangleObjCMethodName(MD); else if (const BlockDecl *BD = dyn_cast<BlockDecl>(DC)) - manglePrefix(BD); // FIXME: This isn't right. + mangleBlockForPrefix(BD); else mangleFunctionEncoding(cast<FunctionDecl>(DC)); @@ -1307,10 +1317,16 @@ void CXXNameMangler::mangleLocalName(const NamedDecl *ND) { } // Mangle the name relative to the closest enclosing function. - if (ND == RD) // equality ok because RD derived from ND above - mangleUnqualifiedName(ND); - else + // equality ok because RD derived from ND above + if (D == RD) { + mangleUnqualifiedName(RD); + } else if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) { + manglePrefix(getEffectiveDeclContext(BD), true /*NoFunction*/); + mangleUnqualifiedBlock(BD); + } else { + const NamedDecl *ND = cast<NamedDecl>(D); mangleNestedName(ND, getEffectiveDeclContext(ND), true /*NoFunction*/); + } if (!SkipDiscriminator) { unsigned disc; @@ -1325,7 +1341,48 @@ void CXXNameMangler::mangleLocalName(const NamedDecl *ND) { return; } - mangleUnqualifiedName(ND); + if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) + mangleUnqualifiedBlock(BD); + else + mangleUnqualifiedName(cast<NamedDecl>(D)); +} + +void CXXNameMangler::mangleBlockForPrefix(const BlockDecl *Block) { + if (GetLocalClassDecl(Block)) { + mangleLocalName(Block); + return; + } + const DeclContext *DC = getEffectiveDeclContext(Block); + if (isLocalContainerContext(DC)) { + mangleLocalName(Block); + return; + } + manglePrefix(getEffectiveDeclContext(Block)); + mangleUnqualifiedBlock(Block); +} + +void CXXNameMangler::mangleUnqualifiedBlock(const BlockDecl *Block) { + if (Decl *Context = Block->getBlockManglingContextDecl()) { + if ((isa<VarDecl>(Context) || isa<FieldDecl>(Context)) && + Context->getDeclContext()->isRecord()) { + if (const IdentifierInfo *Name + = cast<NamedDecl>(Context)->getIdentifier()) { + mangleSourceName(Name); + Out << 'M'; + } + } + } + + // If we have a block mangling number, use it. + unsigned Number = Block->getBlockManglingNumber(); + // Otherwise, just make up a number. It doesn't matter what it is because + // the symbol in question isn't externally visible. + if (!Number) + Number = Context.getBlockId(Block, false); + Out << "Ub"; + if (Number > 1) + Out << Number - 2; + Out << '_'; } void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) { @@ -1411,30 +1468,11 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) { if (DC->isTranslationUnit()) return; - if (const BlockDecl *Block = dyn_cast<BlockDecl>(DC)) { - // Reflect the lambda mangling rules, except that we don't have an - // actual function declaration. - if (NoFunction) - return; - - manglePrefix(getEffectiveParentContext(DC), NoFunction); - // If we have a block mangling number, use it. - unsigned Number = Block->getBlockManglingNumber(); - // Otherwise, just make up a number. It doesn't matter what it is because - // the symbol in question isn't externally visible. - if (!Number) - Number = Context.getBlockId(Block, false); - Out << "Ub"; - if (Number > 1) - Out << Number - 2; - Out << '_'; - return; - } else if (isa<CapturedDecl>(DC)) { - // Skip CapturedDecl context. - manglePrefix(getEffectiveParentContext(DC), NoFunction); + if (NoFunction && isLocalContainerContext(DC)) return; - } - + + assert(!isLocalContainerContext(DC)); + const NamedDecl *ND = cast<NamedDecl>(DC); if (mangleSubstitution(ND)) return; @@ -1444,12 +1482,7 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) { if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) { mangleTemplatePrefix(TD); mangleTemplateArgs(*TemplateArgs); - } - else if(NoFunction && (isa<FunctionDecl>(ND) || isa<ObjCMethodDecl>(ND))) - return; - else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) - mangleObjCMethodName(Method); - else { + } else { manglePrefix(getEffectiveDeclContext(ND), NoFunction); mangleUnqualifiedName(ND); } |