From a04ca5c4e091f567230fc95c6b2715576ad0893b Mon Sep 17 00:00:00 2001 From: Timur Iskhodzhanov Date: Mon, 3 Sep 2012 09:08:10 +0000 Subject: [PATCH] Fix PR13444 - wrong mangling of "const char * const *" and friends with "-cxx-abi microsoft" git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@163110 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/MicrosoftMangle.cpp | 142 ++++++++++-------- .../mangle-ms-return-qualifiers.cpp | 5 +- test/CodeGenCXX/mangle-ms.cpp | 33 +++- 3 files changed, 105 insertions(+), 75 deletions(-) diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp index bf72b506b6..380c737e7e 100644 --- a/lib/AST/MicrosoftMangle.cpp +++ b/lib/AST/MicrosoftMangle.cpp @@ -56,7 +56,7 @@ public: void mangleVariableEncoding(const VarDecl *VD); void mangleNumber(int64_t Number); void mangleNumber(const llvm::APSInt &Value); - void mangleType(QualType T, SourceRange Range); + void mangleType(QualType T, SourceRange Range, bool MangleQualifiers = true); private: void disableBackReferences() { UseNameBackReferences = false; } @@ -68,6 +68,7 @@ private: void manglePostfix(const DeclContext *DC, bool NoFunction=false); void mangleOperatorName(OverloadedOperatorKind OO, SourceLocation Loc); void mangleQualifiers(Qualifiers Quals, bool IsMember); + void manglePointerQualifiers(Qualifiers Quals); void mangleUnscopedTemplateName(const TemplateDecl *ND); void mangleTemplateInstantiationName(const TemplateDecl *TD, @@ -75,7 +76,7 @@ private: void mangleObjCMethodName(const ObjCMethodDecl *MD); void mangleLocalName(const FunctionDecl *FD); - void mangleTypeRepeated(QualType T, SourceRange Range); + void mangleArgumentType(QualType T, SourceRange Range); // Declare manglers for every type class. #define ABSTRACT_TYPE(CLASS, PARENT) @@ -266,18 +267,18 @@ void MicrosoftCXXNameMangler::mangleVariableEncoding(const VarDecl *VD) { Out << '4'; // Now mangle the type. // ::= - // ::= A # pointers, references, arrays + // ::= # pointers, references // Pointers and references are odd. The type of 'int * const foo;' gets // mangled as 'QAHA' instead of 'PAHB', for example. TypeLoc TL = VD->getTypeSourceInfo()->getTypeLoc(); QualType Ty = TL.getType(); if (Ty->isPointerType() || Ty->isReferenceType()) { mangleType(Ty, TL.getSourceRange()); - Out << 'A'; + mangleQualifiers(Ty->getPointeeType().getQualifiers(), false); } else if (const ArrayType *AT = getASTContext().getAsArrayType(Ty)) { // Global arrays are funny, too. mangleType(AT, true); - Out << 'A'; + mangleQualifiers(Ty.getQualifiers(), false); } else { mangleType(Ty.getLocalUnqualifiedType(), TL.getSourceRange()); mangleQualifiers(Ty.getLocalQualifiers(), false); @@ -879,43 +880,60 @@ void MicrosoftCXXNameMangler::mangleQualifiers(Qualifiers Quals, // ::= 3 # ? // ::= 4 # ? // ::= 5 # not really based + bool HasConst = Quals.hasConst(), + HasVolatile = Quals.hasVolatile(); if (!IsMember) { - if (!Quals.hasVolatile()) { - if (!Quals.hasConst()) - Out << 'A'; - else - Out << 'B'; + if (HasConst && HasVolatile) { + Out << 'D'; + } else if (HasVolatile) { + Out << 'C'; + } else if (HasConst) { + Out << 'B'; } else { - if (!Quals.hasConst()) - Out << 'C'; - else - Out << 'D'; + Out << 'A'; } } else { - if (!Quals.hasVolatile()) { - if (!Quals.hasConst()) - Out << 'Q'; - else - Out << 'R'; + if (HasConst && HasVolatile) { + Out << 'T'; + } else if (HasVolatile) { + Out << 'S'; + } else if (HasConst) { + Out << 'R'; } else { - if (!Quals.hasConst()) - Out << 'S'; - else - Out << 'T'; + Out << 'Q'; } } // FIXME: For now, just drop all extension qualifiers on the floor. } -void MicrosoftCXXNameMangler::mangleTypeRepeated(QualType T, SourceRange Range) { +void MicrosoftCXXNameMangler::manglePointerQualifiers(Qualifiers Quals) { + // ::= P # no qualifiers + // ::= Q # const + // ::= R # volatile + // ::= S # const volatile + bool HasConst = Quals.hasConst(), + HasVolatile = Quals.hasVolatile(); + if (HasConst && HasVolatile) { + Out << 'S'; + } else if (HasVolatile) { + Out << 'R'; + } else if (HasConst) { + Out << 'Q'; + } else { + Out << 'P'; + } +} + +void MicrosoftCXXNameMangler::mangleArgumentType(QualType T, + SourceRange Range) { void *TypePtr = getASTContext().getCanonicalType(T).getAsOpaquePtr(); ArgBackRefMap::iterator Found = TypeBackReferences.find(TypePtr); if (Found == TypeBackReferences.end()) { size_t OutSizeBefore = Out.GetNumBytesInBuffer(); - mangleType(T,Range); + mangleType(T, Range, false); // See if it's worth creating a back reference. // Only types longer than 1 character are considered @@ -930,38 +948,30 @@ void MicrosoftCXXNameMangler::mangleTypeRepeated(QualType T, SourceRange Range) } } -void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range) { +void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range, + bool MangleQualifiers) { // Only operate on the canonical type! T = getASTContext().getCanonicalType(T); - + Qualifiers Quals = T.getLocalQualifiers(); - if (Quals) { - // We have to mangle these now, while we still have enough information. - // ::= P # pointer - // ::= Q # const pointer - // ::= R # volatile pointer - // ::= S # const volatile pointer - if (T->isAnyPointerType() || T->isMemberPointerType() || - T->isBlockPointerType()) { - if (!Quals.hasVolatile()) - Out << 'Q'; - else { - if (!Quals.hasConst()) - Out << 'R'; - else - Out << 'S'; - } - } else - // Just emit qualifiers like normal. - // NB: When we mangle a pointer/reference type, and the pointee - // type has no qualifiers, the lack of qualifier gets mangled - // in there. - mangleQualifiers(Quals, false); - } else if (T->isAnyPointerType() || T->isMemberPointerType() || - T->isBlockPointerType()) { - Out << 'P'; + // We have to mangle these now, while we still have enough information. + if (T->isAnyPointerType() || T->isMemberPointerType() || + T->isBlockPointerType()) { + manglePointerQualifiers(Quals); + } else if (Quals && MangleQualifiers) { + mangleQualifiers(Quals, false); } - switch (T->getTypeClass()) { + + SplitQualType split = T.split(); + const Type *ty = split.Ty; + + // If we're mangling a qualified array type, push the qualifiers to + // the element type. + if (split.Quals && isa(T)) { + ty = Context.getASTContext().getAsArrayType(T); + } + + switch (ty->getTypeClass()) { #define ABSTRACT_TYPE(CLASS, PARENT) #define NON_CANONICAL_TYPE(CLASS, PARENT) \ case Type::CLASS: \ @@ -969,7 +979,7 @@ void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range) { return; #define TYPE(CLASS, PARENT) \ case Type::CLASS: \ - mangleType(cast(T), Range); \ + mangleType(cast(ty), Range); \ break; #include "clang/AST/TypeNodes.def" #undef ABSTRACT_TYPE @@ -1119,14 +1129,14 @@ void MicrosoftCXXNameMangler::mangleType(const FunctionType *T, ParmEnd = D->param_end(); Parm != ParmEnd; ++Parm) { TypeSourceInfo *TSI = (*Parm)->getTypeSourceInfo(); QualType Type = TSI ? TSI->getType() : (*Parm)->getType(); - mangleTypeRepeated(Type, (*Parm)->getSourceRange()); + 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) - mangleTypeRepeated(*Arg, SourceRange()); + mangleArgumentType(*Arg, SourceRange()); } // ::= Z # ellipsis if (Proto->isVariadic()) @@ -1289,20 +1299,22 @@ void MicrosoftCXXNameMangler::mangleType(const TagType *T) { } // ::= -// ::= P [Y +] -// # as global +// ::= +// [Y +] +// # as global // ::= Q [Y +] -// # as param +// # as param // 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::mangleType(const ArrayType *T, bool IsGlobal) { // This isn't a recursive mangling, so now we have to do it all in this // one call. - if (IsGlobal) - Out << 'P'; - else + if (IsGlobal) { + manglePointerQualifiers(T->getElementType().getQualifiers()); + } else { Out << 'Q'; + } mangleExtraDimensions(T->getElementType()); } void MicrosoftCXXNameMangler::mangleType(const ConstantArrayType *T, @@ -1412,10 +1424,8 @@ void MicrosoftCXXNameMangler::mangleType(const PointerType *T, Out << '6'; mangleType(FT, NULL, false, false); } else { - if (!PointeeTy.hasQualifiers()) - // Lack of qualifiers is mangled as 'A'. - Out << 'A'; - mangleType(PointeeTy, Range); + mangleQualifiers(PointeeTy.getQualifiers(), false); + mangleType(PointeeTy, Range, false); } } void MicrosoftCXXNameMangler::mangleType(const ObjCObjectPointerType *T, diff --git a/test/CodeGenCXX/mangle-ms-return-qualifiers.cpp b/test/CodeGenCXX/mangle-ms-return-qualifiers.cpp index a5d03b3435..63bc4a9eb3 100644 --- a/test/CodeGenCXX/mangle-ms-return-qualifiers.cpp +++ b/test/CodeGenCXX/mangle-ms-return-qualifiers.cpp @@ -167,7 +167,4 @@ function_pointer* g3() { return 0; } // CHECK: "\01?g3@@YAPAP6AHH@ZXZ" const function_pointer* g4() { return 0; } -// The mangling of g4 is currently "\01?g4@@YAPQ6AHH@ZXZ" which is wrong. -// This looks related to http://llvm.org/PR13444 -// FIXME: replace CHECK-NOT with CHECK once it is fixed. -// CHECK-NOT: "\01?g4@@YAPBQ6AHH@ZXZ" +// CHECK: "\01?g4@@YAPBQ6AHH@ZXZ" diff --git a/test/CodeGenCXX/mangle-ms.cpp b/test/CodeGenCXX/mangle-ms.cpp index ef210f54cd..6964581f92 100644 --- a/test/CodeGenCXX/mangle-ms.cpp +++ b/test/CodeGenCXX/mangle-ms.cpp @@ -7,16 +7,17 @@ // CHECK: @"\01?e@foo@@1JC" // CHECK: @"\01?f@foo@@2DD" // CHECK: @"\01?g@bar@@2HA" -// CHECK: @"\01?h@@3QAHA" +// CHECK: @"\01?h1@@3QAHA" +// CHECK: @"\01?h2@@3QBHB" // CHECK: @"\01?i@@3PAY0BE@HA" // CHECK: @"\01?j@@3P6GHCE@ZA" // CHECK: @"\01?k@@3PTfoo@@DA" // CHECK: @"\01?l@@3P8foo@@AEHH@ZA" // CHECK: @"\01?color1@@3PANA" +// CHECK: @"\01?color2@@3QBNB" -// FIXME: The following three tests currently fail, see PR13182. +// FIXME: The following three tests currently fail, see http://llvm.org/PR13182 // Replace "CHECK-NOT" with "CHECK" when it is fixed. -// CHECK-NOT: @"\01?color2@@3QBNB" // CHECK-NOT: @"\01?color3@@3QAY02$$CBNA" // CHECK-NOT: @"\01?color4@@3QAY02$$CBNA" @@ -87,7 +88,8 @@ const volatile char foo::f = 'C'; int bar::g; -extern int * const h = &a; +extern int * const h1 = &a; +extern const int * const h2 = &a; int i[10][20]; @@ -151,7 +153,7 @@ void (redundant_parens)(); void redundant_parens_use() { redundant_parens(); } // CHECK: @"\01?redundant_parens@@YAXXZ" -// PR13182, PR13047 +// PR13047 typedef double RGB[3]; RGB color1; extern const RGB color2 = {}; @@ -166,3 +168,24 @@ E fooE() { return E(); } class X {}; // CHECK: "\01?fooX@@YA?AVX@@XZ" X fooX() { return X(); } + +namespace PR13182 { + extern char s0[]; + // CHECK: @"\01?s0@PR13182@@3PADA" + extern char s1[42]; + // CHECK: @"\01?s1@PR13182@@3PADA" + extern const char s2[]; + // CHECK: @"\01?s2@PR13182@@3QBDB" + extern const char s3[42]; + // CHECK: @"\01?s3@PR13182@@3QBDB" + extern volatile char s4[]; + // CHECK: @"\01?s4@PR13182@@3RCDC" + extern const volatile char s5[]; + // CHECK: @"\01?s5@PR13182@@3SDDD" + extern const char* const* s6; + // CHECK: @"\01?s6@PR13182@@3PBQBDB" + + char foo() { + return s0[0] + s1[0] + s2[0] + s3[0] + s4[0] + s5[0] + s6[0][0]; + } +}