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
This commit is contained in:
Timur Iskhodzhanov 2012-09-03 09:08:10 +00:00
Родитель 1d01afe4d5
Коммит a04ca5c4e0
3 изменённых файлов: 105 добавлений и 75 удалений

Просмотреть файл

@ -56,7 +56,7 @@ public:
void mangleVariableEncoding(const VarDecl *VD); void mangleVariableEncoding(const VarDecl *VD);
void mangleNumber(int64_t Number); void mangleNumber(int64_t Number);
void mangleNumber(const llvm::APSInt &Value); void mangleNumber(const llvm::APSInt &Value);
void mangleType(QualType T, SourceRange Range); void mangleType(QualType T, SourceRange Range, bool MangleQualifiers = true);
private: private:
void disableBackReferences() { UseNameBackReferences = false; } void disableBackReferences() { UseNameBackReferences = false; }
@ -68,6 +68,7 @@ private:
void manglePostfix(const DeclContext *DC, bool NoFunction=false); void manglePostfix(const DeclContext *DC, bool NoFunction=false);
void mangleOperatorName(OverloadedOperatorKind OO, SourceLocation Loc); void mangleOperatorName(OverloadedOperatorKind OO, SourceLocation Loc);
void mangleQualifiers(Qualifiers Quals, bool IsMember); void mangleQualifiers(Qualifiers Quals, bool IsMember);
void manglePointerQualifiers(Qualifiers Quals);
void mangleUnscopedTemplateName(const TemplateDecl *ND); void mangleUnscopedTemplateName(const TemplateDecl *ND);
void mangleTemplateInstantiationName(const TemplateDecl *TD, void mangleTemplateInstantiationName(const TemplateDecl *TD,
@ -75,7 +76,7 @@ private:
void mangleObjCMethodName(const ObjCMethodDecl *MD); void mangleObjCMethodName(const ObjCMethodDecl *MD);
void mangleLocalName(const FunctionDecl *FD); void mangleLocalName(const FunctionDecl *FD);
void mangleTypeRepeated(QualType T, SourceRange Range); void mangleArgumentType(QualType T, SourceRange Range);
// Declare manglers for every type class. // Declare manglers for every type class.
#define ABSTRACT_TYPE(CLASS, PARENT) #define ABSTRACT_TYPE(CLASS, PARENT)
@ -266,18 +267,18 @@ void MicrosoftCXXNameMangler::mangleVariableEncoding(const VarDecl *VD) {
Out << '4'; Out << '4';
// Now mangle the type. // Now mangle the type.
// <variable-type> ::= <type> <cvr-qualifiers> // <variable-type> ::= <type> <cvr-qualifiers>
// ::= <type> A # pointers, references, arrays // ::= <type> <pointee-cvr-qualifiers> # pointers, references
// Pointers and references are odd. The type of 'int * const foo;' gets // Pointers and references are odd. The type of 'int * const foo;' gets
// mangled as 'QAHA' instead of 'PAHB', for example. // mangled as 'QAHA' instead of 'PAHB', for example.
TypeLoc TL = VD->getTypeSourceInfo()->getTypeLoc(); TypeLoc TL = VD->getTypeSourceInfo()->getTypeLoc();
QualType Ty = TL.getType(); QualType Ty = TL.getType();
if (Ty->isPointerType() || Ty->isReferenceType()) { if (Ty->isPointerType() || Ty->isReferenceType()) {
mangleType(Ty, TL.getSourceRange()); mangleType(Ty, TL.getSourceRange());
Out << 'A'; mangleQualifiers(Ty->getPointeeType().getQualifiers(), false);
} else if (const ArrayType *AT = getASTContext().getAsArrayType(Ty)) { } else if (const ArrayType *AT = getASTContext().getAsArrayType(Ty)) {
// Global arrays are funny, too. // Global arrays are funny, too.
mangleType(AT, true); mangleType(AT, true);
Out << 'A'; mangleQualifiers(Ty.getQualifiers(), false);
} else { } else {
mangleType(Ty.getLocalUnqualifiedType(), TL.getSourceRange()); mangleType(Ty.getLocalUnqualifiedType(), TL.getSourceRange());
mangleQualifiers(Ty.getLocalQualifiers(), false); mangleQualifiers(Ty.getLocalQualifiers(), false);
@ -879,43 +880,60 @@ void MicrosoftCXXNameMangler::mangleQualifiers(Qualifiers Quals,
// ::= 3 # ? // ::= 3 # ?
// ::= 4 # ? // ::= 4 # ?
// ::= 5 # not really based // ::= 5 # not really based
bool HasConst = Quals.hasConst(),
HasVolatile = Quals.hasVolatile();
if (!IsMember) { if (!IsMember) {
if (!Quals.hasVolatile()) { if (HasConst && HasVolatile) {
if (!Quals.hasConst()) Out << 'D';
Out << 'A'; } else if (HasVolatile) {
else Out << 'C';
} else if (HasConst) {
Out << 'B'; Out << 'B';
} else { } else {
if (!Quals.hasConst()) Out << 'A';
Out << 'C';
else
Out << 'D';
} }
} else { } else {
if (!Quals.hasVolatile()) { if (HasConst && HasVolatile) {
if (!Quals.hasConst()) Out << 'T';
Out << 'Q'; } else if (HasVolatile) {
else Out << 'S';
} else if (HasConst) {
Out << 'R'; Out << 'R';
} else { } else {
if (!Quals.hasConst()) Out << 'Q';
Out << 'S';
else
Out << 'T';
} }
} }
// FIXME: For now, just drop all extension qualifiers on the floor. // FIXME: For now, just drop all extension qualifiers on the floor.
} }
void MicrosoftCXXNameMangler::mangleTypeRepeated(QualType T, SourceRange Range) { void MicrosoftCXXNameMangler::manglePointerQualifiers(Qualifiers Quals) {
// <pointer-cvr-qualifiers> ::= 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(); void *TypePtr = getASTContext().getCanonicalType(T).getAsOpaquePtr();
ArgBackRefMap::iterator Found = TypeBackReferences.find(TypePtr); ArgBackRefMap::iterator Found = TypeBackReferences.find(TypePtr);
if (Found == TypeBackReferences.end()) { if (Found == TypeBackReferences.end()) {
size_t OutSizeBefore = Out.GetNumBytesInBuffer(); size_t OutSizeBefore = Out.GetNumBytesInBuffer();
mangleType(T,Range); mangleType(T, Range, false);
// See if it's worth creating a back reference. // See if it's worth creating a back reference.
// Only types longer than 1 character are considered // 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! // Only operate on the canonical type!
T = getASTContext().getCanonicalType(T); T = getASTContext().getCanonicalType(T);
Qualifiers Quals = T.getLocalQualifiers(); Qualifiers Quals = T.getLocalQualifiers();
if (Quals) {
// We have to mangle these now, while we still have enough information. // We have to mangle these now, while we still have enough information.
// <pointer-cvr-qualifiers> ::= P # pointer
// ::= Q # const pointer
// ::= R # volatile pointer
// ::= S # const volatile pointer
if (T->isAnyPointerType() || T->isMemberPointerType() || if (T->isAnyPointerType() || T->isMemberPointerType() ||
T->isBlockPointerType()) { T->isBlockPointerType()) {
if (!Quals.hasVolatile()) manglePointerQualifiers(Quals);
Out << 'Q'; } else if (Quals && MangleQualifiers) {
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); mangleQualifiers(Quals, false);
} else if (T->isAnyPointerType() || T->isMemberPointerType() ||
T->isBlockPointerType()) {
Out << 'P';
} }
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<ArrayType>(T)) {
ty = Context.getASTContext().getAsArrayType(T);
}
switch (ty->getTypeClass()) {
#define ABSTRACT_TYPE(CLASS, PARENT) #define ABSTRACT_TYPE(CLASS, PARENT)
#define NON_CANONICAL_TYPE(CLASS, PARENT) \ #define NON_CANONICAL_TYPE(CLASS, PARENT) \
case Type::CLASS: \ case Type::CLASS: \
@ -969,7 +979,7 @@ void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range) {
return; return;
#define TYPE(CLASS, PARENT) \ #define TYPE(CLASS, PARENT) \
case Type::CLASS: \ case Type::CLASS: \
mangleType(cast<CLASS##Type>(T), Range); \ mangleType(cast<CLASS##Type>(ty), Range); \
break; break;
#include "clang/AST/TypeNodes.def" #include "clang/AST/TypeNodes.def"
#undef ABSTRACT_TYPE #undef ABSTRACT_TYPE
@ -1119,14 +1129,14 @@ void MicrosoftCXXNameMangler::mangleType(const FunctionType *T,
ParmEnd = D->param_end(); Parm != ParmEnd; ++Parm) { ParmEnd = D->param_end(); Parm != ParmEnd; ++Parm) {
TypeSourceInfo *TSI = (*Parm)->getTypeSourceInfo(); TypeSourceInfo *TSI = (*Parm)->getTypeSourceInfo();
QualType Type = TSI ? TSI->getType() : (*Parm)->getType(); QualType Type = TSI ? TSI->getType() : (*Parm)->getType();
mangleTypeRepeated(Type, (*Parm)->getSourceRange()); mangleArgumentType(Type, (*Parm)->getSourceRange());
} }
} else { } else {
// Happens for function pointer type arguments for example. // Happens for function pointer type arguments for example.
for (FunctionProtoType::arg_type_iterator Arg = Proto->arg_type_begin(), for (FunctionProtoType::arg_type_iterator Arg = Proto->arg_type_begin(),
ArgEnd = Proto->arg_type_end(); ArgEnd = Proto->arg_type_end();
Arg != ArgEnd; ++Arg) Arg != ArgEnd; ++Arg)
mangleTypeRepeated(*Arg, SourceRange()); mangleArgumentType(*Arg, SourceRange());
} }
// <builtin-type> ::= Z # ellipsis // <builtin-type> ::= Z # ellipsis
if (Proto->isVariadic()) if (Proto->isVariadic())
@ -1289,7 +1299,8 @@ void MicrosoftCXXNameMangler::mangleType(const TagType *T) {
} }
// <type> ::= <array-type> // <type> ::= <array-type>
// <array-type> ::= P <cvr-qualifiers> [Y <dimension-count> <dimension>+] // <array-type> ::= <pointer-cvr-qualifiers> <cvr-qualifiers>
// [Y <dimension-count> <dimension>+]
// <element-type> # as global // <element-type> # as global
// ::= Q <cvr-qualifiers> [Y <dimension-count> <dimension>+] // ::= Q <cvr-qualifiers> [Y <dimension-count> <dimension>+]
// <element-type> # as param // <element-type> # as param
@ -1299,10 +1310,11 @@ void MicrosoftCXXNameMangler::mangleType(const TagType *T) {
void MicrosoftCXXNameMangler::mangleType(const ArrayType *T, bool IsGlobal) { void MicrosoftCXXNameMangler::mangleType(const ArrayType *T, bool IsGlobal) {
// This isn't a recursive mangling, so now we have to do it all in this // This isn't a recursive mangling, so now we have to do it all in this
// one call. // one call.
if (IsGlobal) if (IsGlobal) {
Out << 'P'; manglePointerQualifiers(T->getElementType().getQualifiers());
else } else {
Out << 'Q'; Out << 'Q';
}
mangleExtraDimensions(T->getElementType()); mangleExtraDimensions(T->getElementType());
} }
void MicrosoftCXXNameMangler::mangleType(const ConstantArrayType *T, void MicrosoftCXXNameMangler::mangleType(const ConstantArrayType *T,
@ -1412,10 +1424,8 @@ void MicrosoftCXXNameMangler::mangleType(const PointerType *T,
Out << '6'; Out << '6';
mangleType(FT, NULL, false, false); mangleType(FT, NULL, false, false);
} else { } else {
if (!PointeeTy.hasQualifiers()) mangleQualifiers(PointeeTy.getQualifiers(), false);
// Lack of qualifiers is mangled as 'A'. mangleType(PointeeTy, Range, false);
Out << 'A';
mangleType(PointeeTy, Range);
} }
} }
void MicrosoftCXXNameMangler::mangleType(const ObjCObjectPointerType *T, void MicrosoftCXXNameMangler::mangleType(const ObjCObjectPointerType *T,

Просмотреть файл

@ -167,7 +167,4 @@ function_pointer* g3() { return 0; }
// CHECK: "\01?g3@@YAPAP6AHH@ZXZ" // CHECK: "\01?g3@@YAPAP6AHH@ZXZ"
const function_pointer* g4() { return 0; } const function_pointer* g4() { return 0; }
// The mangling of g4 is currently "\01?g4@@YAPQ6AHH@ZXZ" which is wrong. // CHECK: "\01?g4@@YAPBQ6AHH@ZXZ"
// This looks related to http://llvm.org/PR13444
// FIXME: replace CHECK-NOT with CHECK once it is fixed.
// CHECK-NOT: "\01?g4@@YAPBQ6AHH@ZXZ"

Просмотреть файл

@ -7,16 +7,17 @@
// CHECK: @"\01?e@foo@@1JC" // CHECK: @"\01?e@foo@@1JC"
// CHECK: @"\01?f@foo@@2DD" // CHECK: @"\01?f@foo@@2DD"
// CHECK: @"\01?g@bar@@2HA" // CHECK: @"\01?g@bar@@2HA"
// CHECK: @"\01?h@@3QAHA" // CHECK: @"\01?h1@@3QAHA"
// CHECK: @"\01?h2@@3QBHB"
// CHECK: @"\01?i@@3PAY0BE@HA" // CHECK: @"\01?i@@3PAY0BE@HA"
// CHECK: @"\01?j@@3P6GHCE@ZA" // CHECK: @"\01?j@@3P6GHCE@ZA"
// CHECK: @"\01?k@@3PTfoo@@DA" // CHECK: @"\01?k@@3PTfoo@@DA"
// CHECK: @"\01?l@@3P8foo@@AEHH@ZA" // CHECK: @"\01?l@@3P8foo@@AEHH@ZA"
// CHECK: @"\01?color1@@3PANA" // 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. // Replace "CHECK-NOT" with "CHECK" when it is fixed.
// CHECK-NOT: @"\01?color2@@3QBNB"
// CHECK-NOT: @"\01?color3@@3QAY02$$CBNA" // CHECK-NOT: @"\01?color3@@3QAY02$$CBNA"
// CHECK-NOT: @"\01?color4@@3QAY02$$CBNA" // CHECK-NOT: @"\01?color4@@3QAY02$$CBNA"
@ -87,7 +88,8 @@ const volatile char foo::f = 'C';
int bar::g; int bar::g;
extern int * const h = &a; extern int * const h1 = &a;
extern const int * const h2 = &a;
int i[10][20]; int i[10][20];
@ -151,7 +153,7 @@ void (redundant_parens)();
void redundant_parens_use() { redundant_parens(); } void redundant_parens_use() { redundant_parens(); }
// CHECK: @"\01?redundant_parens@@YAXXZ" // CHECK: @"\01?redundant_parens@@YAXXZ"
// PR13182, PR13047 // PR13047
typedef double RGB[3]; typedef double RGB[3];
RGB color1; RGB color1;
extern const RGB color2 = {}; extern const RGB color2 = {};
@ -166,3 +168,24 @@ E fooE() { return E(); }
class X {}; class X {};
// CHECK: "\01?fooX@@YA?AVX@@XZ" // CHECK: "\01?fooX@@YA?AVX@@XZ"
X fooX() { return X(); } 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];
}
}