From 58e4cd09cc71893798282833806f4205b37dc828 Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Wed, 11 Sep 2013 04:44:30 +0000 Subject: [PATCH] [-cxx-abi microsoft] Canonicalize array parameters better Summary: More accurately characterize the nature of array parameters. Doing this removes false back-reference opportunities. Remove some hacks now that we characterize these better. Reviewers: rnk, timurrrr, whunt, cdavis5x CC: cfe-commits Differential Revision: http://llvm-reviews.chandlerc.com/D1626 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@190488 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/MicrosoftMangle.cpp | 50 +++++++++----------- test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp | 34 +++++++++++++ 2 files changed, 57 insertions(+), 27 deletions(-) diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp index 3ccc2bddf6..b60aad1371 100644 --- a/lib/AST/MicrosoftMangle.cpp +++ b/lib/AST/MicrosoftMangle.cpp @@ -125,7 +125,7 @@ private: #undef TYPE void mangleType(const TagDecl *TD); - void mangleDecayedArrayType(const ArrayType *T, bool IsGlobal); + void mangleDecayedArrayType(const ArrayType *T); void mangleArrayType(const ArrayType *T); void mangleFunctionClass(const FunctionDecl *FD); void mangleCallingConvention(const FunctionType *T, bool IsInstMethod = false); @@ -337,7 +337,7 @@ void MicrosoftCXXNameMangler::mangleVariableEncoding(const VarDecl *VD) { mangleQualifiers(Ty->getPointeeType().getQualifiers(), false); } else if (const ArrayType *AT = getASTContext().getAsArrayType(Ty)) { // Global arrays are funny, too. - mangleDecayedArrayType(AT, true); + mangleDecayedArrayType(AT); if (AT->getElementType()->isArrayType()) Out << 'A'; else @@ -1057,25 +1057,30 @@ 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(); + + // Decayed types do not match up with non-decayed versions of the same type. + // + // e.g. + // void (*x)(void) will not form a backreference with void x(void) + void *TypePtr; + if (const DecayedType *DT = T->getAs()) { + TypePtr = DT->getOriginalType().getCanonicalType().getAsOpaquePtr(); + // If the original parameter was textually written as an array, + // instead treat the decayed parameter like it's const. + // + // e.g. + // int [] -> int * const + if (DT->getOriginalType()->isArrayType()) + T = T.withConst(); + } else + TypePtr = T.getCanonicalType().getAsOpaquePtr(); + ArgBackRefMap::iterator Found = TypeBackReferences.find(TypePtr); if (Found == TypeBackReferences.end()) { size_t OutSizeBefore = Out.GetNumBytesInBuffer(); - 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); - } + mangleType(T, Range, QMM_Drop); // See if it's worth creating a back reference. // Only types longer than 1 character are considered @@ -1467,22 +1472,13 @@ void MicrosoftCXXNameMangler::mangleType(const TagDecl *TD) { // ::= // [Y +] // # as global, E is never required -// ::= Q E? [Y +] -// # as param, E is required for 64-bit // It's supposed to be the other way around, but for some strange reason, it // isn't. Today this behavior is retained for the sole purpose of backwards // compatibility. -void MicrosoftCXXNameMangler::mangleDecayedArrayType(const ArrayType *T, - bool IsGlobal) { +void MicrosoftCXXNameMangler::mangleDecayedArrayType(const ArrayType *T) { // This isn't a recursive mangling, so now we have to do it all in this // one call. - if (IsGlobal) { - manglePointerQualifiers(T->getElementType().getQualifiers()); - } else { - Out << 'Q'; - if (PointersAre64Bit) - Out << 'E'; - } + manglePointerQualifiers(T->getElementType().getQualifiers()); mangleType(T->getElementType(), SourceRange()); } void MicrosoftCXXNameMangler::mangleType(const ConstantArrayType *T, diff --git a/test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp b/test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp index 672a48641c..50a238340e 100644 --- a/test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp +++ b/test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp @@ -204,3 +204,37 @@ void mangle_fwd(char * x) {} void mangle_no_fwd(char * x) {} // CHECK: "\01?mangle_no_fwd@@YAXPAD@Z" // X64: "\01?mangle_no_fwd@@YAXPEAD@Z" + +// The first argument gets mangled as-if it were written "int *const" +// The second arg should not form a backref because it isn't qualified +void mangle_no_backref0(int[], int *) {} +// CHECK: "\01?mangle_no_backref0@@YAXQAHPAH@Z" +// X64: "\01?mangle_no_backref0@@YAXQEAHPEAH@Z" + +void mangle_no_backref1(int[], int *const) {} +// CHECK: "\01?mangle_no_backref1@@YAXQAHQAH@Z" +// X64: "\01?mangle_no_backref1@@YAXQEAHQEAH@Z" + +typedef void fun_type(void); +typedef void (*ptr_to_fun_type)(void); + +// Pointer to function types don't backref with function types +void mangle_no_backref2(fun_type, ptr_to_fun_type) {} +// CHECK: "\01?mangle_no_backref2@@YAXP6AXXZP6AXXZ@Z" +// X64: "\01?mangle_no_backref2@@YAXP6AXXZP6AXXZ@Z" + +void mangle_yes_backref0(int[], int []) {} +// CHECK: "\01?mangle_yes_backref0@@YAXQAH0@Z" +// X64: "\01?mangle_yes_backref0@@YAXQEAH0@Z" + +void mangle_yes_backref1(int *const, int *const) {} +// CHECK: "\01?mangle_yes_backref1@@YAXQAH0@Z" +// X64: "\01?mangle_yes_backref1@@YAXQEAH0@Z" + +void mangle_yes_backref2(fun_type *const[], ptr_to_fun_type const[]) {} +// CHECK: "\01?mangle_yes_backref2@@YAXQBQ6AXXZ0@Z" +// X64: "\01?mangle_yes_backref2@@YAXQEBQ6AXXZ0@Z" + +void mangle_yes_backref3(ptr_to_fun_type *const, void (**const)(void)) {} +// CHECK: "\01?mangle_yes_backref3@@YAXQAP6AXXZ0@Z" +// X64: "\01?mangle_yes_backref3@@YAXQEAP6AXXZ0@Z" -- 2.40.0