зеркало из https://github.com/microsoft/clang-1.git
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:
Родитель
1d01afe4d5
Коммит
a04ca5c4e0
|
@ -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';
|
||||||
Out << 'B';
|
} else if (HasConst) {
|
||||||
|
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';
|
||||||
Out << 'R';
|
} else if (HasConst) {
|
||||||
|
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.
|
if (T->isAnyPointerType() || T->isMemberPointerType() ||
|
||||||
// <pointer-cvr-qualifiers> ::= P # pointer
|
T->isBlockPointerType()) {
|
||||||
// ::= Q # const pointer
|
manglePointerQualifiers(Quals);
|
||||||
// ::= R # volatile pointer
|
} else if (Quals && MangleQualifiers) {
|
||||||
// ::= S # const volatile pointer
|
mangleQualifiers(Quals, false);
|
||||||
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';
|
|
||||||
}
|
}
|
||||||
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,20 +1299,22 @@ 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>
|
||||||
// <element-type> # as global
|
// [Y <dimension-count> <dimension>+]
|
||||||
|
// <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
|
||||||
// It's supposed to be the other way around, but for some strange reason, it
|
// 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
|
// isn't. Today this behavior is retained for the sole purpose of backwards
|
||||||
// compatibility.
|
// compatibility.
|
||||||
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];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче