diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp | 387 |
1 files changed, 307 insertions, 80 deletions
diff --git a/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp b/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp index acedf70..d7b6354 100644 --- a/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp @@ -40,14 +40,38 @@ using namespace clang; namespace { +/// \brief Retrieve the declaration context that should be used when mangling +/// the given declaration. +static const DeclContext *getEffectiveDeclContext(const Decl *D) { + // The ABI assumes that lambda closure types that occur within + // default arguments live in the context of the function. However, due to + // the way in which Clang parses and creates function declarations, this is + // 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(); + } + + return D->getDeclContext(); +} + +static const DeclContext *getEffectiveParentContext(const DeclContext *DC) { + return getEffectiveDeclContext(cast<Decl>(DC)); +} + static const CXXRecordDecl *GetLocalClassDecl(const NamedDecl *ND) { const DeclContext *DC = dyn_cast<DeclContext>(ND); if (!DC) - DC = ND->getDeclContext(); + DC = getEffectiveDeclContext(ND); while (!DC->isNamespace() && !DC->isTranslationUnit()) { - if (isa<FunctionDecl>(DC->getParent())) + const DeclContext *Parent = getEffectiveDeclContext(cast<Decl>(DC)); + if (isa<FunctionDecl>(Parent)) return dyn_cast<CXXRecordDecl>(DC); - DC = DC->getParent(); + DC = Parent; } return 0; } @@ -63,7 +87,7 @@ static const NamedDecl *getStructor(const NamedDecl *decl) { const FunctionDecl *fn = dyn_cast_or_null<FunctionDecl>(decl); return (fn ? getStructor(fn) : decl); } - + static const unsigned UnknownArity = ~0U; class ItaniumMangleContext : public MangleContext { @@ -122,6 +146,13 @@ public: } bool getNextDiscriminator(const NamedDecl *ND, unsigned &disc) { + // Lambda closure types with external linkage (indicated by a + // non-zero lambda mangling number) have their own numbering scheme, so + // they do not need a discriminator. + if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(ND)) + if (RD->isLambda() && RD->getLambdaManglingNumber() > 0) + return false; + unsigned &discriminator = Uniquifier[ND]; if (!discriminator) discriminator = ++Discriminator; @@ -272,6 +303,7 @@ private: void mangleUnscopedTemplateName(TemplateName); void mangleSourceName(const IdentifierInfo *II); void mangleLocalName(const NamedDecl *ND); + void mangleLambda(const CXXRecordDecl *Lambda); void mangleNestedName(const NamedDecl *ND, const DeclContext *DC, bool NoFunction=false); void mangleNestedName(const TemplateDecl *TD, @@ -332,8 +364,8 @@ private: static bool isInCLinkageSpecification(const Decl *D) { D = D->getCanonicalDecl(); - for (const DeclContext *DC = D->getDeclContext(); - !DC->isTranslationUnit(); DC = DC->getParent()) { + for (const DeclContext *DC = getEffectiveDeclContext(D); + !DC->isTranslationUnit(); DC = getEffectiveParentContext(DC)) { if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC)) return Linkage->getLanguage() == LinkageSpecDecl::lang_c; } @@ -343,7 +375,7 @@ static bool isInCLinkageSpecification(const Decl *D) { bool ItaniumMangleContext::shouldMangleDeclName(const NamedDecl *D) { // In C, functions with no attributes never need to be mangled. Fastpath them. - if (!getASTContext().getLangOptions().CPlusPlus && !D->hasAttrs()) + if (!getASTContext().getLangOpts().CPlusPlus && !D->hasAttrs()) return false; // Any decl can be declared with __asm("foo") on it, and this takes precedence @@ -360,22 +392,22 @@ bool ItaniumMangleContext::shouldMangleDeclName(const NamedDecl *D) { return true; // Otherwise, no mangling is done outside C++ mode. - if (!getASTContext().getLangOptions().CPlusPlus) + if (!getASTContext().getLangOpts().CPlusPlus) return false; // Variables at global scope with non-internal linkage are not mangled if (!FD) { - const DeclContext *DC = D->getDeclContext(); + const DeclContext *DC = getEffectiveDeclContext(D); // Check for extern variable declared locally. if (DC->isFunctionOrMethod() && D->hasLinkage()) while (!DC->isNamespace() && !DC->isTranslationUnit()) - DC = DC->getParent(); + DC = getEffectiveParentContext(DC); if (DC->isTranslationUnit() && D->getLinkage() != InternalLinkage) return false; } // Class members are always mangled. - if (D->getDeclContext()->isRecord()) + if (getEffectiveDeclContext(D)->isRecord()) return true; // C functions and "main" are not mangled. @@ -458,7 +490,7 @@ void CXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) { static const DeclContext *IgnoreLinkageSpecDecls(const DeclContext *DC) { while (isa<LinkageSpecDecl>(DC)) { - DC = DC->getParent(); + DC = getEffectiveParentContext(DC); } return DC; @@ -466,7 +498,8 @@ static const DeclContext *IgnoreLinkageSpecDecls(const DeclContext *DC) { /// isStd - Return whether a given namespace is the 'std' namespace. static bool isStd(const NamespaceDecl *NS) { - if (!IgnoreLinkageSpecDecls(NS->getParent())->isTranslationUnit()) + if (!IgnoreLinkageSpecDecls(getEffectiveParentContext(NS)) + ->isTranslationUnit()) return false; const IdentifierInfo *II = NS->getOriginalNamespace()->getIdentifier(); @@ -502,26 +535,35 @@ isTemplate(const NamedDecl *ND, const TemplateArgumentList *&TemplateArgs) { return 0; } +static bool isLambda(const NamedDecl *ND) { + const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(ND); + if (!Record) + return false; + + return Record->isLambda(); +} + void CXXNameMangler::mangleName(const NamedDecl *ND) { // <name> ::= <nested-name> // ::= <unscoped-name> // ::= <unscoped-template-name> <template-args> // ::= <local-name> // - const DeclContext *DC = ND->getDeclContext(); + const DeclContext *DC = getEffectiveDeclContext(ND); // If this is an extern variable declared locally, the relevant DeclContext // is that of the containing namespace, or the translation unit. - if (isa<FunctionDecl>(DC) && ND->hasLinkage()) + // FIXME: This is a hack; extern variables declared locally should have + // a proper semantic declaration context! + if (isa<FunctionDecl>(DC) && ND->hasLinkage() && !isLambda(ND)) while (!DC->isNamespace() && !DC->isTranslationUnit()) - DC = DC->getParent(); + DC = getEffectiveParentContext(DC); else if (GetLocalClassDecl(ND)) { mangleLocalName(ND); return; } - while (isa<LinkageSpecDecl>(DC)) - DC = DC->getParent(); + DC = IgnoreLinkageSpecDecls(DC); if (DC->isTranslationUnit() || isStdNamespace(DC)) { // Check if we have a template. @@ -547,7 +589,7 @@ void CXXNameMangler::mangleName(const NamedDecl *ND) { void CXXNameMangler::mangleName(const TemplateDecl *TD, const TemplateArgument *TemplateArgs, unsigned NumTemplateArgs) { - const DeclContext *DC = IgnoreLinkageSpecDecls(TD->getDeclContext()); + const DeclContext *DC = IgnoreLinkageSpecDecls(getEffectiveDeclContext(TD)); if (DC->isTranslationUnit() || isStdNamespace(DC)) { mangleUnscopedTemplateName(TD); @@ -561,7 +603,8 @@ void CXXNameMangler::mangleName(const TemplateDecl *TD, void CXXNameMangler::mangleUnscopedName(const NamedDecl *ND) { // <unscoped-name> ::= <unqualified-name> // ::= St <unqualified-name> # ::std:: - if (isStdNamespace(ND->getDeclContext())) + + if (isStdNamespace(IgnoreLinkageSpecDecls(getEffectiveDeclContext(ND)))) Out << "St"; mangleUnqualifiedName(ND); @@ -610,17 +653,41 @@ void CXXNameMangler::mangleFloat(const llvm::APFloat &f) { // representation (IEEE on Itanium), high-order bytes first, // without leading zeroes. For example: "Lf bf800000 E" is -1.0f // on Itanium. - // APInt::toString uses uppercase hexadecimal, and it's not really - // worth embellishing that interface for this use case, so we just - // do a second pass to lowercase things. - typedef llvm::SmallString<20> buffer_t; - buffer_t buffer; - f.bitcastToAPInt().toString(buffer, 16, false); + // The 'without leading zeroes' thing seems to be an editorial + // mistake; see the discussion on cxx-abi-dev beginning on + // 2012-01-16. + + // Our requirements here are just barely wierd enough to justify + // using a custom algorithm instead of post-processing APInt::toString(). + + llvm::APInt valueBits = f.bitcastToAPInt(); + unsigned numCharacters = (valueBits.getBitWidth() + 3) / 4; + assert(numCharacters != 0); - for (buffer_t::iterator i = buffer.begin(), e = buffer.end(); i != e; ++i) - if (isupper(*i)) *i = tolower(*i); + // Allocate a buffer of the right number of characters. + llvm::SmallVector<char, 20> buffer; + buffer.set_size(numCharacters); - Out.write(buffer.data(), buffer.size()); + // Fill the buffer left-to-right. + for (unsigned stringIndex = 0; stringIndex != numCharacters; ++stringIndex) { + // The bit-index of the next hex digit. + unsigned digitBitIndex = 4 * (numCharacters - stringIndex - 1); + + // Project out 4 bits starting at 'digitIndex'. + llvm::integerPart hexDigit + = valueBits.getRawData()[digitBitIndex / llvm::integerPartWidth]; + hexDigit >>= (digitBitIndex % llvm::integerPartWidth); + hexDigit &= 0xF; + + // Map that over to a lowercase hex digit. + static const char charForHex[16] = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' + }; + buffer[stringIndex] = charForHex[hexDigit]; + } + + Out.write(buffer.data(), numCharacters); } void CXXNameMangler::mangleNumber(const llvm::APSInt &Value) { @@ -997,7 +1064,7 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, // This naming convention is the same as that followed by GCC, // though it shouldn't actually matter. if (ND && ND->getLinkage() == InternalLinkage && - ND->getDeclContext()->isFileContext()) + getEffectiveDeclContext(ND)->isFileContext()) Out << 'L'; mangleSourceName(II); @@ -1052,13 +1119,24 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, break; } + // <unnamed-type-name> ::= <closure-type-name> + // + // <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _ + // <lambda-sig> ::= <parameter-type>+ # Parameter types or 'v' for 'void'. + if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(TD)) { + if (Record->isLambda() && Record->getLambdaManglingNumber()) { + mangleLambda(Record); + break; + } + } + // Get a unique id for the anonymous struct. uint64_t AnonStructId = Context.getAnonymousStructId(TD); // Mangle it as a source name in the form // [n] $_<id> // where n is the length of the string. - llvm::SmallString<8> Str; + SmallString<8> Str; Str += "$_"; Str += llvm::utostr(AnonStructId); @@ -1180,8 +1258,10 @@ void CXXNameMangler::mangleNestedName(const TemplateDecl *TD, void CXXNameMangler::mangleLocalName(const NamedDecl *ND) { // <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 DeclContext *DC = ND->getDeclContext(); + const DeclContext *DC = getEffectiveDeclContext(ND); if (isa<ObjCMethodDecl>(DC) && isa<FunctionDecl>(ND)) { // Don't add objc method name mangling to locally declared function mangleUnqualifiedName(ND); @@ -1193,23 +1273,46 @@ void CXXNameMangler::mangleLocalName(const NamedDecl *ND) { if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(DC)) { mangleObjCMethodName(MD); } else if (const CXXRecordDecl *RD = GetLocalClassDecl(ND)) { - mangleFunctionEncoding(cast<FunctionDecl>(RD->getDeclContext())); + mangleFunctionEncoding(cast<FunctionDecl>(getEffectiveDeclContext(RD))); Out << 'E'; + // The parameter number is omitted for the last parameter, 0 for the + // second-to-last parameter, 1 for the third-to-last parameter, etc. The + // <entity name> will of course contain a <closure-type-name>: Its + // numbering will be local to the particular argument in which it appears + // -- other default arguments do not affect its encoding. + bool SkipDiscriminator = false; + if (RD->isLambda()) { + if (const ParmVarDecl *Parm + = dyn_cast_or_null<ParmVarDecl>(RD->getLambdaContextDecl())) { + if (const FunctionDecl *Func + = dyn_cast<FunctionDecl>(Parm->getDeclContext())) { + Out << 'd'; + unsigned Num = Func->getNumParams() - Parm->getFunctionScopeIndex(); + if (Num > 1) + mangleNumber(Num - 2); + Out << '_'; + SkipDiscriminator = true; + } + } + } + // Mangle the name relative to the closest enclosing function. if (ND == RD) // equality ok because RD derived from ND above mangleUnqualifiedName(ND); else mangleNestedName(ND, DC, true /*NoFunction*/); - unsigned disc; - if (Context.getNextDiscriminator(RD, disc)) { - if (disc < 10) - Out << '_' << disc; - else - Out << "__" << disc << '_'; + if (!SkipDiscriminator) { + unsigned disc; + if (Context.getNextDiscriminator(RD, disc)) { + if (disc < 10) + Out << '_' << disc; + else + Out << "__" << disc << '_'; + } } - + return; } else @@ -1219,6 +1322,48 @@ void CXXNameMangler::mangleLocalName(const NamedDecl *ND) { mangleUnqualifiedName(ND); } +void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) { + // If the context of a closure type is an initializer for a class member + // (static or nonstatic), it is encoded in a qualified name with a final + // <prefix> of the form: + // + // <data-member-prefix> := <member source-name> M + // + // Technically, the data-member-prefix is part of the <prefix>. However, + // since a closure type will always be mangled with a prefix, it's easier + // to emit that last part of the prefix here. + if (Decl *Context = Lambda->getLambdaContextDecl()) { + if ((isa<VarDecl>(Context) || isa<FieldDecl>(Context)) && + Context->getDeclContext()->isRecord()) { + if (const IdentifierInfo *Name + = cast<NamedDecl>(Context)->getIdentifier()) { + mangleSourceName(Name); + Out << 'M'; + } + } + } + + Out << "Ul"; + DeclarationName Name + = getASTContext().DeclarationNames.getCXXOperatorName(OO_Call); + const FunctionProtoType *Proto + = cast<CXXMethodDecl>(*Lambda->lookup(Name).first)->getType()-> + getAs<FunctionProtoType>(); + mangleBareFunctionType(Proto, /*MangleReturnType=*/false); + Out << "E"; + + // The number is omitted for the first closure type with a given + // <lambda-sig> in a given context; it is n-2 for the nth closure type + // (in lexical order) with that same <lambda-sig> and context. + // + // The AST keeps track of the number for us. + unsigned Number = Lambda->getLambdaManglingNumber(); + assert(Number > 0 && "Lambda should be mangled as an unnamed class"); + if (Number > 1) + mangleNumber(Number - 2); + Out << '_'; +} + void CXXNameMangler::manglePrefix(NestedNameSpecifier *qualifier) { switch (qualifier->getKind()) { case NestedNameSpecifier::Global: @@ -1258,15 +1403,14 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) { // ::= # empty // ::= <substitution> - while (isa<LinkageSpecDecl>(DC)) - DC = DC->getParent(); + DC = IgnoreLinkageSpecDecls(DC); if (DC->isTranslationUnit()) return; if (const BlockDecl *Block = dyn_cast<BlockDecl>(DC)) { - manglePrefix(DC->getParent(), NoFunction); - llvm::SmallString<64> Name; + manglePrefix(getEffectiveParentContext(DC), NoFunction); + SmallString<64> Name; llvm::raw_svector_ostream NameStream(Name); Context.mangleBlock(Block, NameStream); NameStream.flush(); @@ -1274,26 +1418,27 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) { return; } - if (mangleSubstitution(cast<NamedDecl>(DC))) + const NamedDecl *ND = cast<NamedDecl>(DC); + if (mangleSubstitution(ND)) return; - + // Check if we have a template. const TemplateArgumentList *TemplateArgs = 0; - if (const TemplateDecl *TD = isTemplate(cast<NamedDecl>(DC), TemplateArgs)) { + if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) { mangleTemplatePrefix(TD); TemplateParameterList *TemplateParameters = TD->getTemplateParameters(); mangleTemplateArgs(*TemplateParameters, *TemplateArgs); } - else if(NoFunction && (isa<FunctionDecl>(DC) || isa<ObjCMethodDecl>(DC))) + else if(NoFunction && (isa<FunctionDecl>(ND) || isa<ObjCMethodDecl>(ND))) return; - else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC)) + else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) mangleObjCMethodName(Method); else { - manglePrefix(DC->getParent(), NoFunction); - mangleUnqualifiedName(cast<NamedDecl>(DC)); + manglePrefix(getEffectiveDeclContext(ND), NoFunction); + mangleUnqualifiedName(ND); } - addSubstitution(cast<NamedDecl>(DC)); + addSubstitution(ND); } void CXXNameMangler::mangleTemplatePrefix(TemplateName Template) { @@ -1336,7 +1481,7 @@ void CXXNameMangler::mangleTemplatePrefix(const TemplateDecl *ND) { return; } - manglePrefix(ND->getDeclContext()); + manglePrefix(getEffectiveDeclContext(ND)); mangleUnqualifiedName(ND->getTemplatedDecl()); addSubstitution(ND); } @@ -1370,7 +1515,6 @@ void CXXNameMangler::mangleType(TemplateName TN) { case TemplateName::OverloadedTemplate: llvm_unreachable("can't mangle an overloaded template name as a <type>"); - break; case TemplateName::DependentTemplate: { const DependentTemplateName *Dependent = TN.getAsDependentTemplateName(); @@ -1531,7 +1675,7 @@ void CXXNameMangler::mangleQualifiers(Qualifiers Quals) { // // where <address-space-number> is a source name consisting of 'AS' // followed by the address space <number>. - llvm::SmallString<64> ASString; + SmallString<64> ASString; ASString = "AS" + llvm::utostr_32(Quals.getAddressSpace()); Out << 'U' << ASString.size() << ASString; } @@ -1632,8 +1776,8 @@ void CXXNameMangler::mangleType(QualType T) { } while (true); } SplitQualType split = T.split(); - Qualifiers quals = split.second; - const Type *ty = split.first; + Qualifiers quals = split.Quals; + const Type *ty = split.Ty; bool isSubstitutable = quals || !isa<BuiltinType>(T); if (isSubstitutable && mangleSubstitution(T)) @@ -1735,12 +1879,12 @@ void CXXNameMangler::mangleType(const BuiltinType *T) { case BuiltinType::LongDouble: Out << 'e'; break; case BuiltinType::NullPtr: Out << "Dn"; break; - case BuiltinType::Overload: +#define BUILTIN_TYPE(Id, SingletonId) +#define PLACEHOLDER_TYPE(Id, SingletonId) \ + case BuiltinType::Id: +#include "clang/AST/BuiltinTypes.def" case BuiltinType::Dependent: - case BuiltinType::BoundMember: - case BuiltinType::UnknownAny: llvm_unreachable("mangling a placeholder type"); - break; case BuiltinType::ObjCId: Out << "11objc_object"; break; case BuiltinType::ObjCClass: Out << "10objc_class"; break; case BuiltinType::ObjCSel: Out << "13objc_selector"; break; @@ -2217,15 +2361,12 @@ recurse: // These all can only appear in local or variable-initialization // contexts and so should never appear in a mangling. case Expr::AddrLabelExprClass: - case Expr::BlockDeclRefExprClass: case Expr::CXXThisExprClass: case Expr::DesignatedInitExprClass: case Expr::ImplicitValueInitExprClass: - case Expr::InitListExprClass: case Expr::ParenListExprClass: - case Expr::CXXScalarValueInitExprClass: + case Expr::LambdaExprClass: llvm_unreachable("unexpected statement kind"); - break; // FIXME: invent manglings for all these. case Expr::BlockExprClass: @@ -2242,6 +2383,10 @@ recurse: case Expr::ObjCProtocolExprClass: case Expr::ObjCSelectorExprClass: case Expr::ObjCStringLiteralClass: + case Expr::ObjCNumericLiteralClass: + case Expr::ObjCArrayLiteralClass: + case Expr::ObjCDictionaryLiteralClass: + case Expr::ObjCSubscriptRefExprClass: case Expr::ObjCIndirectCopyRestoreExprClass: case Expr::OffsetOfExprClass: case Expr::PredefinedExprClass: @@ -2249,6 +2394,7 @@ recurse: case Expr::StmtExprClass: case Expr::UnaryTypeTraitExprClass: case Expr::BinaryTypeTraitExprClass: + case Expr::TypeTraitExprClass: case Expr::ArrayTypeTraitExprClass: case Expr::ExpressionTraitExprClass: case Expr::VAArgExprClass: @@ -2256,6 +2402,7 @@ recurse: case Expr::CXXNoexceptExprClass: case Expr::CUDAKernelCallExprClass: case Expr::AsTypeExprClass: + case Expr::PseudoObjectExprClass: case Expr::AtomicExprClass: { // As bad as this diagnostic is, it's better than crashing. @@ -2282,6 +2429,16 @@ recurse: case Expr::OpaqueValueExprClass: llvm_unreachable("cannot mangle opaque value; mangling wrong thing?"); + case Expr::InitListExprClass: { + // Proposal by Jason Merrill, 2012-01-03 + Out << "il"; + const InitListExpr *InitList = cast<InitListExpr>(E); + for (unsigned i = 0, e = InitList->getNumInits(); i != e; ++i) + mangleExpression(InitList->getInit(i)); + Out << "E"; + break; + } + case Expr::CXXDefaultArgExprClass: mangleExpression(cast<CXXDefaultArgExpr>(E)->getExpr(), Arity); break; @@ -2291,6 +2448,9 @@ recurse: Arity); break; + case Expr::UserDefinedLiteralClass: + // We follow g++'s approach of mangling a UDL as a call to the literal + // operator. case Expr::CXXMemberCallExprClass: // fallthrough case Expr::CallExprClass: { const CallExpr *CE = cast<CallExpr>(E); @@ -2318,7 +2478,6 @@ recurse: } case Expr::CXXNewExprClass: { - // Proposal from David Vandervoorde, 2010.06.30 const CXXNewExpr *New = cast<CXXNewExpr>(E); if (New->isGlobalNew()) Out << "gs"; Out << (New->isArray() ? "na" : "nw"); @@ -2328,10 +2487,29 @@ recurse: Out << '_'; mangleType(New->getAllocatedType()); if (New->hasInitializer()) { - Out << "pi"; - for (CXXNewExpr::const_arg_iterator I = New->constructor_arg_begin(), - E = New->constructor_arg_end(); I != E; ++I) - mangleExpression(*I); + // Proposal by Jason Merrill, 2012-01-03 + if (New->getInitializationStyle() == CXXNewExpr::ListInit) + Out << "il"; + else + Out << "pi"; + const Expr *Init = New->getInitializer(); + if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(Init)) { + // Directly inline the initializers. + for (CXXConstructExpr::const_arg_iterator I = CCE->arg_begin(), + E = CCE->arg_end(); + I != E; ++I) + mangleExpression(*I); + } else if (const ParenListExpr *PLE = dyn_cast<ParenListExpr>(Init)) { + for (unsigned i = 0, e = PLE->getNumExprs(); i != e; ++i) + mangleExpression(PLE->getExpr(i)); + } else if (New->getInitializationStyle() == CXXNewExpr::ListInit && + isa<InitListExpr>(Init)) { + // Only take InitListExprs apart for list-initialization. + const InitListExpr *InitList = cast<InitListExpr>(Init); + for (unsigned i = 0, e = InitList->getNumInits(); i != e; ++i) + mangleExpression(InitList->getInit(i)); + } else + mangleExpression(Init); } Out << 'E'; break; @@ -2395,7 +2573,11 @@ recurse: const CXXConstructExpr *CE = cast<CXXConstructExpr>(E); unsigned N = CE->getNumArgs(); - Out << "cv"; + // Proposal by Jason Merrill, 2012-01-03 + if (CE->isListInitialization()) + Out << "tl"; + else + Out << "cv"; mangleType(CE->getType()); if (N != 1) Out << '_'; for (unsigned I = 0; I != N; ++I) mangleExpression(CE->getArg(I)); @@ -2403,6 +2585,12 @@ recurse: break; } + case Expr::CXXScalarValueInitExprClass: + Out <<"cv"; + mangleType(E->getType()); + Out <<"_E"; + break; + case Expr::UnaryExprOrTypeTraitExprClass: { const UnaryExprOrTypeTraitExpr *SAE = cast<UnaryExprOrTypeTraitExpr>(E); @@ -2642,6 +2830,13 @@ recurse: Out << 'E'; break; + // FIXME. __objc_yes/__objc_no are mangled same as true/false + case Expr::ObjCBoolLiteralExprClass: + Out << "Lb"; + Out << (cast<ObjCBoolLiteralExpr>(E)->getValue() ? '1' : '0'); + Out << 'E'; + break; + case Expr::CXXBoolLiteralExprClass: Out << "Lb"; Out << (cast<CXXBoolLiteralExpr>(E)->getValue() ? '1' : '0'); @@ -2897,23 +3092,48 @@ void CXXNameMangler::mangleTemplateArg(const NamedDecl *P, Out << "Dp"; mangleType(A.getAsTemplateOrTemplatePattern()); break; - case TemplateArgument::Expression: + case TemplateArgument::Expression: { + // It's possible to end up with a DeclRefExpr here in certain + // dependent cases, in which case we should mangle as a + // declaration. + const Expr *E = A.getAsExpr()->IgnoreParens(); + if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) { + const ValueDecl *D = DRE->getDecl(); + if (isa<VarDecl>(D) || isa<FunctionDecl>(D)) { + Out << "L"; + mangle(D, "_Z"); + Out << 'E'; + break; + } + } + Out << 'X'; - mangleExpression(A.getAsExpr()); + mangleExpression(E); Out << 'E'; break; + } case TemplateArgument::Integral: mangleIntegerLiteral(A.getIntegralType(), *A.getAsIntegral()); break; case TemplateArgument::Declaration: { assert(P && "Missing template parameter for declaration argument"); // <expr-primary> ::= L <mangled-name> E # external name - + // <expr-primary> ::= L <type> 0 E // Clang produces AST's where pointer-to-member-function expressions // and pointer-to-function expressions are represented as a declaration not // an expression. We compensate for it here to produce the correct mangling. - NamedDecl *D = cast<NamedDecl>(A.getAsDecl()); const NonTypeTemplateParmDecl *Parameter = cast<NonTypeTemplateParmDecl>(P); + + // Handle NULL pointer arguments. + if (!A.getAsDecl()) { + Out << "L"; + mangleType(Parameter->getType()); + Out << "0E"; + break; + } + + + NamedDecl *D = cast<NamedDecl>(A.getAsDecl()); bool compensateMangling = !Parameter->getType()->isReferenceType(); if (compensateMangling) { Out << 'X'; @@ -2982,8 +3202,15 @@ bool CXXNameMangler::mangleSubstitution(const NamedDecl *ND) { return mangleSubstitution(reinterpret_cast<uintptr_t>(ND)); } +/// \brief Determine whether the given type has any qualifiers that are +/// relevant for substitutions. +static bool hasMangledSubstitutionQualifiers(QualType T) { + Qualifiers Qs = T.getQualifiers(); + return Qs.getCVRQualifiers() || Qs.hasAddressSpace(); +} + bool CXXNameMangler::mangleSubstitution(QualType T) { - if (!T.getCVRQualifiers()) { + if (!hasMangledSubstitutionQualifiers(T)) { if (const RecordType *RT = T->getAs<RecordType>()) return mangleSubstitution(RT->getDecl()); } @@ -3059,7 +3286,7 @@ static bool isCharSpecialization(QualType T, const char *Name) { if (!SD) return false; - if (!isStdNamespace(SD->getDeclContext())) + if (!isStdNamespace(getEffectiveDeclContext(SD))) return false; const TemplateArgumentList &TemplateArgs = SD->getTemplateArgs(); @@ -3101,7 +3328,7 @@ bool CXXNameMangler::mangleStandardSubstitution(const NamedDecl *ND) { } if (const ClassTemplateDecl *TD = dyn_cast<ClassTemplateDecl>(ND)) { - if (!isStdNamespace(TD->getDeclContext())) + if (!isStdNamespace(getEffectiveDeclContext(TD))) return false; // <substitution> ::= Sa # ::std::allocator @@ -3119,7 +3346,7 @@ bool CXXNameMangler::mangleStandardSubstitution(const NamedDecl *ND) { if (const ClassTemplateSpecializationDecl *SD = dyn_cast<ClassTemplateSpecializationDecl>(ND)) { - if (!isStdNamespace(SD->getDeclContext())) + if (!isStdNamespace(getEffectiveDeclContext(SD))) return false; // <substitution> ::= Ss # ::std::basic_string<char, @@ -3169,7 +3396,7 @@ bool CXXNameMangler::mangleStandardSubstitution(const NamedDecl *ND) { } void CXXNameMangler::addSubstitution(QualType T) { - if (!T.getCVRQualifiers()) { + if (!hasMangledSubstitutionQualifiers(T)) { if (const RecordType *RT = T->getAs<RecordType>()) { addSubstitution(RT->getDecl()); return; |