diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp | 54 |
1 files changed, 51 insertions, 3 deletions
diff --git a/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp b/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp index b5f8c0f..378121c 100644 --- a/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp @@ -29,16 +29,64 @@ using namespace clang; namespace { +/// According to Itanium C++ ABI 5.1.2: +/// the name of an anonymous union is considered to be +/// the name of the first named data member found by a pre-order, +/// depth-first, declaration-order walk of the data members of +/// the anonymous union. +/// If there is no such data member (i.e., if all of the data members +/// in the union are unnamed), then there is no way for a program to +/// refer to the anonymous union, and there is therefore no need to mangle its name. +/// +/// Returns the name of anonymous union VarDecl or nullptr if it is not found. +static const IdentifierInfo *findAnonymousUnionVarDeclName(const VarDecl& VD) { + const RecordType *RT = VD.getType()->getAs<RecordType>(); + assert(RT && "type of VarDecl is expected to be RecordType."); + assert(RT->getDecl()->isUnion() && "RecordType is expected to be a union."); + if (const FieldDecl *FD = RT->getDecl()->findFirstNamedDataMember()) { + return FD->getIdentifier(); + } + + return nullptr; +} + /// \brief Keeps track of the mangled names of lambda expressions and block /// literals within a particular context. class ItaniumNumberingContext : public MangleNumberingContext { - llvm::DenseMap<IdentifierInfo*, unsigned> VarManglingNumbers; - llvm::DenseMap<IdentifierInfo*, unsigned> TagManglingNumbers; + llvm::DenseMap<const Type *, unsigned> ManglingNumbers; + llvm::DenseMap<const IdentifierInfo *, unsigned> VarManglingNumbers; + llvm::DenseMap<const IdentifierInfo *, unsigned> TagManglingNumbers; public: + unsigned getManglingNumber(const CXXMethodDecl *CallOperator) override { + const FunctionProtoType *Proto = + CallOperator->getType()->getAs<FunctionProtoType>(); + ASTContext &Context = CallOperator->getASTContext(); + + QualType Key = + Context.getFunctionType(Context.VoidTy, Proto->getParamTypes(), + FunctionProtoType::ExtProtoInfo()); + Key = Context.getCanonicalType(Key); + return ++ManglingNumbers[Key->castAs<FunctionProtoType>()]; + } + + unsigned getManglingNumber(const BlockDecl *BD) override { + const Type *Ty = nullptr; + return ++ManglingNumbers[Ty]; + } + + unsigned getStaticLocalNumber(const VarDecl *VD) override { + return 0; + } + /// Variable decls are numbered by identifier. unsigned getManglingNumber(const VarDecl *VD, unsigned) override { - return ++VarManglingNumbers[VD->getIdentifier()]; + const IdentifierInfo *Identifier = VD->getIdentifier(); + if (!Identifier) { + // VarDecl without an identifier represents an anonymous union declaration. + Identifier = findAnonymousUnionVarDeclName(*VD); + } + return ++VarManglingNumbers[Identifier]; } unsigned getManglingNumber(const TagDecl *TD, unsigned) override { |