diff --git a/clang/lib/CodeGen/Mangle.cpp b/clang/lib/CodeGen/Mangle.cpp index 6c2a64898fee..4d98deec3d3b 100644 --- a/clang/lib/CodeGen/Mangle.cpp +++ b/clang/lib/CodeGen/Mangle.cpp @@ -125,19 +125,24 @@ class CXXNameMangler { const CXXMethodDecl *Structor; unsigned StructorType; + /// SeqID - The next subsitution sequence number. + unsigned SeqID; + llvm::DenseMap Substitutions; ASTContext &getASTContext() const { return Context.getASTContext(); } public: CXXNameMangler(MangleContext &C, llvm::SmallVectorImpl &Res) - : Context(C), Out(Res), Structor(0), StructorType(0) { } + : Context(C), Out(Res), Structor(0), StructorType(0), SeqID(0) { } CXXNameMangler(MangleContext &C, llvm::SmallVectorImpl &Res, const CXXConstructorDecl *D, CXXCtorType Type) - : Context(C), Out(Res), Structor(getStructor(D)), StructorType(Type) { } + : Context(C), Out(Res), Structor(getStructor(D)), StructorType(Type), + SeqID(0) { } CXXNameMangler(MangleContext &C, llvm::SmallVectorImpl &Res, const CXXDestructorDecl *D, CXXDtorType Type) - : Context(C), Out(Res), Structor(getStructor(D)), StructorType(Type) { } + : Context(C), Out(Res), Structor(getStructor(D)), StructorType(Type), + SeqID(0) { } #if MANGLE_CHECKER ~CXXNameMangler() { @@ -1204,6 +1209,22 @@ void CXXNameMangler::mangleType(const MemberPointerType *T) { if (const FunctionProtoType *FPT = dyn_cast(PointeeType)) { mangleQualifiers(Qualifiers::fromCVRMask(FPT->getTypeQuals())); mangleType(FPT); + + // Itanium C++ ABI 5.1.8: + // + // The type of a non-static member function is considered to be different, + // for the purposes of substitution, from the type of a namespace-scope or + // static member function whose type appears similar. The types of two + // non-static member functions are considered to be different, for the + // purposes of substitution, if the functions are members of different + // classes. In other words, for the purposes of substitution, the class of + // which the function is a member is considered part of the type of + // function. + + // We increment the SeqID here to emulate adding an entry to the + // substitution table. We can't actually add it because we don't want this + // particular function type to be substituted. + ++SeqID; } else mangleType(PointeeType); } @@ -2049,10 +2070,8 @@ void CXXNameMangler::addSubstitution(TemplateName Template) { } void CXXNameMangler::addSubstitution(uintptr_t Ptr) { - unsigned SeqID = Substitutions.size(); - assert(!Substitutions.count(Ptr) && "Substitution already exists!"); - Substitutions[Ptr] = SeqID; + Substitutions[Ptr] = SeqID++; } // diff --git a/clang/test/CodeGenCXX/mangle-subst.cpp b/clang/test/CodeGenCXX/mangle-subst.cpp index bd06869ff7f9..d83a081dd76a 100644 --- a/clang/test/CodeGenCXX/mangle-subst.cpp +++ b/clang/test/CodeGenCXX/mangle-subst.cpp @@ -67,3 +67,16 @@ namespace NS { // CHECK: @_ZN2NS1fERNS_1CE void f(C&) { } } + +namespace Test1 { + +struct A { }; +struct B { }; + +// CHECK: @_ZN5Test11fEMNS_1BEFvvENS_1AES3_ +void f(void (B::*)(), A, A) { } + +// CHECK: @_ZN5Test11fEMNS_1BEFvvENS_1AES3_MS0_FvS3_EMS3_FvvE +void f(void (B::*)(), A, A, void (B::*)(A), void (A::*)()) { } + +}