зеркало из 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 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.
|
||||
// <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
|
||||
// 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) {
|
||||
// <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();
|
||||
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.
|
||||
// <pointer-cvr-qualifiers> ::= 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<ArrayType>(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<CLASS##Type>(T), Range); \
|
||||
mangleType(cast<CLASS##Type>(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());
|
||||
}
|
||||
// <builtin-type> ::= Z # ellipsis
|
||||
if (Proto->isVariadic())
|
||||
|
@ -1289,20 +1299,22 @@ void MicrosoftCXXNameMangler::mangleType(const TagType *T) {
|
|||
}
|
||||
|
||||
// <type> ::= <array-type>
|
||||
// <array-type> ::= P <cvr-qualifiers> [Y <dimension-count> <dimension>+]
|
||||
// <element-type> # as global
|
||||
// <array-type> ::= <pointer-cvr-qualifiers> <cvr-qualifiers>
|
||||
// [Y <dimension-count> <dimension>+]
|
||||
// <element-type> # as global
|
||||
// ::= 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
|
||||
// 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,
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче