diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index 5e488e042e71..e2b42e7e30c4 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -125,7 +125,7 @@ private: void mangleFunctionType(const FunctionType *T, const FunctionDecl *D, bool IsStructor, bool IsInstMethod); void mangleDecayedArrayType(const ArrayType *T, bool IsGlobal); - void mangleArrayType(const ArrayType *T, Qualifiers Quals); + void mangleArrayType(const ArrayType *T); void mangleFunctionClass(const FunctionDecl *FD); void mangleCallingConvention(const FunctionType *T, bool IsInstMethod = false); void mangleIntegerLiteral(const llvm::APSInt &Number, bool IsBoolean); @@ -257,13 +257,20 @@ void MicrosoftCXXNameMangler::mangle(const NamedDecl *D, void MicrosoftCXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) { // ::= + // Since MSVC operates on the type as written and not the canonical type, it + // actually matters which decl we have here. MSVC appears to choose the + // first, since it is most likely to be the declaration in a header file. + FD = FD->getFirstDeclaration(); + // Don't mangle in the type if this isn't a decl we should typically mangle. if (!Context.shouldMangleDeclName(FD)) return; // We should never ever see a FunctionNoProtoType at this point. // We don't even know how to mangle their types anyway :). - const FunctionProtoType *FT = FD->getType()->castAs(); + TypeSourceInfo *TSI = FD->getTypeSourceInfo(); + QualType T = TSI ? TSI->getType() : FD->getType(); + const FunctionProtoType *FT = T->castAs(); bool InStructor = false, InInstMethod = false; const CXXMethodDecl *MD = dyn_cast(FD); @@ -980,17 +987,24 @@ void MicrosoftCXXNameMangler::manglePointerQualifiers(Qualifiers Quals) { void MicrosoftCXXNameMangler::mangleArgumentType(QualType T, SourceRange Range) { + // MSVC will backreference two canonically equivalent types that have slightly + // different manglings when mangled alone. void *TypePtr = getASTContext().getCanonicalType(T).getAsOpaquePtr(); ArgBackRefMap::iterator Found = TypeBackReferences.find(TypePtr); if (Found == TypeBackReferences.end()) { size_t OutSizeBefore = Out.GetNumBytesInBuffer(); - if (const ArrayType *AT = getASTContext().getAsArrayType(T)) { - mangleDecayedArrayType(AT, false); - } else if (const FunctionType *FT = T->getAs()) { - Out << "P6"; - mangleFunctionType(FT, 0, false, false); + if (const DecayedType *DT = T->getAs()) { + QualType OT = DT->getOriginalType(); + if (const ArrayType *AT = getASTContext().getAsArrayType(OT)) { + mangleDecayedArrayType(AT, false); + } else if (const FunctionType *FT = OT->getAs()) { + Out << "P6"; + mangleFunctionType(FT, 0, false, false); + } else { + llvm_unreachable("unexpected decayed type"); + } } else { mangleType(T, Range, QMM_Drop); } @@ -1010,16 +1024,18 @@ void MicrosoftCXXNameMangler::mangleArgumentType(QualType T, void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range, QualifierMangleMode QMM) { - // Only operate on the canonical type! - T = getASTContext().getCanonicalType(T); + // Don't use the canonical types. MSVC includes things like 'const' on + // pointer arguments to function pointers that canonicalization strips away. + T = T.getDesugaredType(getASTContext()); Qualifiers Quals = T.getLocalQualifiers(); - - if (const ArrayType *AT = dyn_cast(T)) { + if (const ArrayType *AT = getASTContext().getAsArrayType(T)) { + // If there were any Quals, getAsArrayType() pushed them onto the array + // element type. if (QMM == QMM_Mangle) Out << 'A'; else if (QMM == QMM_Escape || QMM == QMM_Result) Out << "$$B"; - mangleArrayType(AT, Quals); + mangleArrayType(AT); return; } @@ -1180,6 +1196,9 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T, // const FunctionProtoType *Proto = cast(T); + SourceRange Range; + if (D) Range = D->getSourceRange(); + // If this is a C++ instance method, mangle the CVR qualifiers for the // this pointer. if (IsInstMethod) @@ -1201,7 +1220,7 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T, } Out << '@'; } else { - mangleType(Proto->getResultType(), SourceRange(), QMM_Result); + mangleType(Proto->getResultType(), Range, QMM_Result); } // ::= X # void @@ -1210,23 +1229,11 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T, if (Proto->getNumArgs() == 0 && !Proto->isVariadic()) { Out << 'X'; } else { - if (D) { - // If we got a decl, use the type-as-written to make sure arrays - // get mangled right. Note that we can't rely on the TSI - // existing if (for example) the parameter was synthesized. - for (FunctionDecl::param_const_iterator Parm = D->param_begin(), - ParmEnd = D->param_end(); Parm != ParmEnd; ++Parm) { - TypeSourceInfo *TSI = (*Parm)->getTypeSourceInfo(); - QualType Type = TSI ? TSI->getType() : (*Parm)->getType(); - mangleArgumentType(Type, (*Parm)->getSourceRange()); - } - } else { - // Happens for function pointer type arguments for example. - for (FunctionProtoType::arg_type_iterator Arg = Proto->arg_type_begin(), - ArgEnd = Proto->arg_type_end(); - Arg != ArgEnd; ++Arg) - mangleArgumentType(*Arg, SourceRange()); - } + // Happens for function pointer type arguments for example. + for (FunctionProtoType::arg_type_iterator Arg = Proto->arg_type_begin(), + ArgEnd = Proto->arg_type_end(); + Arg != ArgEnd; ++Arg) + mangleArgumentType(*Arg, Range); // ::= Z # ellipsis if (Proto->isVariadic()) Out << 'Z'; @@ -1431,8 +1438,7 @@ void MicrosoftCXXNameMangler::mangleType(const IncompleteArrayType *T, SourceRange) { llvm_unreachable("Should have been special cased"); } -void MicrosoftCXXNameMangler::mangleArrayType(const ArrayType *T, - Qualifiers Quals) { +void MicrosoftCXXNameMangler::mangleArrayType(const ArrayType *T) { QualType ElementTy(T, 0); SmallVector Dimensions; for (;;) { @@ -1471,8 +1477,7 @@ void MicrosoftCXXNameMangler::mangleArrayType(const ArrayType *T, mangleNumber(Dimensions.size()); for (unsigned Dim = 0; Dim < Dimensions.size(); ++Dim) mangleNumber(Dimensions[Dim].getLimitedValue()); - mangleType(getASTContext().getQualifiedType(ElementTy.getTypePtr(), Quals), - SourceRange(), QMM_Escape); + mangleType(ElementTy, SourceRange(), QMM_Escape); } // ::= diff --git a/clang/test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp b/clang/test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp index ed7027d975dd..672a48641ca0 100644 --- a/clang/test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp +++ b/clang/test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp @@ -162,3 +162,45 @@ void foo_volatile(volatile Vector) {} void foo(Vector*, const Vector, const double) {} // CHECK: "\01?foo@@YAXPAY02NQBNN@Z" // X64: "\01?foo@@YAXPEAY02NQEBNN@Z" + +typedef void (*ConstFunPtr)(int *const d); +void foo_fnptrconst(ConstFunPtr f) { } +// CHECK: "\01?foo_fnptrconst@@YAXP6AXQAH@Z@Z" +// X64: "\01?foo_fnptrconst@@YAXP6AXQEAH@Z@Z" + +typedef void (*ArrayFunPtr)(int d[1]); +void foo_fnptrarray(ArrayFunPtr f) { } +// CHECK: "\01?foo_fnptrarray@@YAXP6AXQAH@Z@Z" +// X64: "\01?foo_fnptrarray@@YAXP6AXQEAH@Z@Z" + +void foo_fnptrbackref1(ArrayFunPtr f1, ArrayFunPtr f2) { } +// CHECK: "\01?foo_fnptrbackref1@@YAXP6AXQAH@Z1@Z" +// X64: "\01?foo_fnptrbackref1@@YAXP6AXQEAH@Z1@Z" + +void foo_fnptrbackref2(ArrayFunPtr f1, ConstFunPtr f2) { } +// CHECK: "\01?foo_fnptrbackref2@@YAXP6AXQAH@Z1@Z" +// X64: "\01?foo_fnptrbackref2@@YAXP6AXQEAH@Z1@Z" + +typedef void (*NormalFunPtr)(int *d); +void foo_fnptrbackref3(ArrayFunPtr f1, NormalFunPtr f2) { } +// CHECK: "\01?foo_fnptrbackref3@@YAXP6AXQAH@Z1@Z" +// X64: "\01?foo_fnptrbackref3@@YAXP6AXQEAH@Z1@Z" + +void foo_fnptrbackref4(NormalFunPtr f1, ArrayFunPtr f2) { } +// CHECK: "\01?foo_fnptrbackref4@@YAXP6AXPAH@Z1@Z" +// X64: "\01?foo_fnptrbackref4@@YAXP6AXPEAH@Z1@Z" + +ArrayFunPtr ret_fnptrarray() { return 0; } +// CHECK: "\01?ret_fnptrarray@@YAP6AXQAH@ZXZ" +// X64: "\01?ret_fnptrarray@@YAP6AXQEAH@ZXZ" + +// Test that we mangle the forward decl when we have a redeclaration with a +// slightly different type. +void mangle_fwd(char * const x); +void mangle_fwd(char * x) {} +// CHECK: "\01?mangle_fwd@@YAXQAD@Z" +// X64: "\01?mangle_fwd@@YAXQEAD@Z" + +void mangle_no_fwd(char * x) {} +// CHECK: "\01?mangle_no_fwd@@YAXPAD@Z" +// X64: "\01?mangle_no_fwd@@YAXPEAD@Z"