Skip to content

Commit

Permalink
[MS Demangler] Fix several issues related to templates.
Browse files Browse the repository at this point in the history
These were uncovered when porting the mangling tests in
ms-templates.cpp from clang/CodeGenCXX over to demangling
tests.  The main issues fixed here are surrounding integer
literal signed and unsignedness, empty array dimensions,
and pointer and reference non-type template parameters.

Differential Revision: https://reviews.llvm.org/D50512

llvm-svn: 339434
  • Loading branch information
Zachary Turner committed Aug 10, 2018
1 parent f337f5b commit dbefc6c
Show file tree
Hide file tree
Showing 2 changed files with 285 additions and 34 deletions.
124 changes: 90 additions & 34 deletions llvm/lib/Demangle/MicrosoftDemangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,15 @@ struct FunctionParams {
struct TemplateParams {
bool IsTemplateTemplate = false;
bool IsAliasTemplate = false;
bool IsIntegerLiteral = false;
bool IntegerLiteralIsNegative = false;
bool IsEmptyParameterPack = false;
bool PointerToSymbol = false;
bool ReferenceToSymbol = false;

// If IsIntegerLiteral is true, this is a non-type template parameter
// whose value is contained in this field.
uint64_t IntegralValue = 0;

// Type can be null if this is a template template parameter. In that case
// only Name will be valid.
Expand Down Expand Up @@ -340,14 +349,18 @@ struct UdtType : public Type {
Name *UdtName = nullptr;
};

struct ArrayDimension {
uint64_t Dim = 0;
ArrayDimension *Next = nullptr;
};

struct ArrayType : public Type {
Type *clone(ArenaAllocator &Arena) const override;
void outputPre(OutputStream &OS, NameResolver &Resolver) override;
void outputPost(OutputStream &OS, NameResolver &Resolver) override;

// Either NextDimension or ElementType will be valid.
ArrayType *NextDimension = nullptr;
uint32_t ArrayDimension = 0;
ArrayDimension *Dims = nullptr;

Type *ElementType = nullptr;
};
Expand Down Expand Up @@ -510,7 +523,7 @@ static void outputName(OutputStream &OS, const Name *TheName,

static void outputParameterList(OutputStream &OS, const TemplateParams &Params,
NameResolver &Resolver) {
if (!Params.ParamType && !Params.ParamName) {
if (Params.IsEmptyParameterPack) {
OS << "<>";
return;
}
Expand All @@ -521,9 +534,13 @@ static void outputParameterList(OutputStream &OS, const TemplateParams &Params,
// Type can be null if this is a template template parameter,
// and Name can be null if this is a simple type.

if (Head->ParamType && Head->ParamName) {
// Function pointer.
OS << "&";
if (Head->IsIntegerLiteral) {
if (Head->IntegerLiteralIsNegative)
OS << '-';
OS << Head->IntegralValue;
} else if (Head->PointerToSymbol || Head->ReferenceToSymbol) {
if (Head->PointerToSymbol)
OS << "&";
Type::outputPre(OS, *Head->ParamType, Resolver);
outputName(OS, Head->ParamName, Resolver);
Type::outputPost(OS, *Head->ParamType, Resolver);
Expand Down Expand Up @@ -867,12 +884,16 @@ void ArrayType::outputPre(OutputStream &OS, NameResolver &Resolver) {
}

void ArrayType::outputPost(OutputStream &OS, NameResolver &Resolver) {
if (ArrayDimension > 0)
OS << "[" << ArrayDimension << "]";
if (NextDimension)
Type::outputPost(OS, *NextDimension, Resolver);
else if (ElementType)
Type::outputPost(OS, *ElementType, Resolver);
ArrayDimension *D = Dims;
while (D) {
OS << "[";
if (D->Dim > 0)
OS << D->Dim;
OS << "]";
D = D->Next;
}

Type::outputPost(OS, *ElementType, Resolver);
}

struct Symbol {
Expand Down Expand Up @@ -938,7 +959,7 @@ class Demangler : public NameResolver {
TemplateParams *demangleTemplateParameterList(StringView &MangledName);
FunctionParams demangleFunctionParameterList(StringView &MangledName);

int demangleNumber(StringView &MangledName);
std::pair<uint64_t, bool> demangleNumber(StringView &MangledName);

void memorizeString(StringView s);

Expand Down Expand Up @@ -1091,21 +1112,21 @@ Type *Demangler::demangleVariableEncoding(StringView &MangledName) {
// ::= <hex digit>+ @ # when Numbrer == 0 or >= 10
//
// <hex-digit> ::= [A-P] # A = 0, B = 1, ...
int Demangler::demangleNumber(StringView &MangledName) {
bool neg = MangledName.consumeFront("?");
std::pair<uint64_t, bool> Demangler::demangleNumber(StringView &MangledName) {
bool IsNegative = MangledName.consumeFront('?');

if (startsWithDigit(MangledName)) {
int32_t Ret = MangledName[0] - '0' + 1;
uint64_t Ret = MangledName[0] - '0' + 1;
MangledName = MangledName.dropFront(1);
return neg ? -Ret : Ret;
return {Ret, IsNegative};
}

int Ret = 0;
uint64_t Ret = 0;
for (size_t i = 0; i < MangledName.size(); ++i) {
char C = MangledName[i];
if (C == '@') {
MangledName = MangledName.dropFront(i + 1);
return neg ? -Ret : Ret;
return {Ret, IsNegative};
}
if ('A' <= C && C <= 'P') {
Ret = (Ret << 4) + (C - 'A');
Expand All @@ -1115,7 +1136,7 @@ int Demangler::demangleNumber(StringView &MangledName) {
}

Error = true;
return 0;
return {0ULL, false};
}

// First 10 strings can be referenced by special BackReferences ?0, ?1, ..., ?9.
Expand Down Expand Up @@ -1346,7 +1367,8 @@ Name *Demangler::demangleLocallyScopedNamePiece(StringView &MangledName) {

Name *Node = Arena.alloc<Name>();
MangledName.consumeFront('?');
int ScopeIdentifier = demangleNumber(MangledName);
auto Number = demangleNumber(MangledName);
assert(!Number.second);

// One ? to terminate the number
MangledName.consumeFront('?');
Expand All @@ -1361,7 +1383,7 @@ Name *Demangler::demangleLocallyScopedNamePiece(StringView &MangledName) {
OS << '`';
output(Scope, OS);
OS << '\'';
OS << "::`" << ScopeIdentifier << "'";
OS << "::`" << Number.first << "'";
OS << '\0';
char *Result = OS.getBuffer();
Node->Str = copyString(Result);
Expand Down Expand Up @@ -1933,19 +1955,28 @@ ArrayType *Demangler::demangleArrayType(StringView &MangledName) {
assert(MangledName.front() == 'Y');
MangledName.popFront();

int Dimension = demangleNumber(MangledName);
if (Dimension <= 0) {
uint64_t Rank = 0;
bool IsNegative = false;
std::tie(Rank, IsNegative) = demangleNumber(MangledName);
if (IsNegative || Rank == 0) {
Error = true;
return nullptr;
}

ArrayType *ATy = Arena.alloc<ArrayType>();
ArrayType *Dim = ATy;
for (int I = 0; I < Dimension; ++I) {
Dim->Prim = PrimTy::Array;
Dim->ArrayDimension = demangleNumber(MangledName);
Dim->NextDimension = Arena.alloc<ArrayType>();
Dim = Dim->NextDimension;
ATy->Prim = PrimTy::Array;
ATy->Dims = Arena.alloc<ArrayDimension>();
ArrayDimension *Dim = ATy->Dims;
for (uint64_t I = 0; I < Rank; ++I) {
std::tie(Dim->Dim, IsNegative) = demangleNumber(MangledName);
if (IsNegative) {
Error = true;
return nullptr;
}
if (I + 1 < Rank) {
Dim->Next = Arena.alloc<ArrayDimension>();
Dim = Dim->Next;
}
}

if (MangledName.consumeFront("$$C")) {
Expand All @@ -1958,7 +1989,6 @@ ArrayType *Demangler::demangleArrayType(StringView &MangledName) {
}

ATy->ElementType = demangleType(MangledName, QualifierMangleMode::Drop);
Dim->ElementType = ATy->ElementType;
return ATy;
}

Expand Down Expand Up @@ -2034,16 +2064,42 @@ Demangler::demangleTemplateParameterList(StringView &MangledName) {
// Empty parameter pack.
if (MangledName.consumeFront("$S") || MangledName.consumeFront("$$V") ||
MangledName.consumeFront("$$$V")) {
(*Current)->IsEmptyParameterPack = true;
break;
}

if (MangledName.consumeFront("$$Y")) {
// Template alias
(*Current)->IsTemplateTemplate = true;
(*Current)->IsAliasTemplate = true;
(*Current)->ParamName = demangleFullyQualifiedTypeName(MangledName);
} else if (MangledName.consumeFront("$1?")) {
(*Current)->ParamName = demangleFullyQualifiedSymbolName(MangledName);
(*Current)->ParamType = demangleFunctionEncoding(MangledName);
} else if (MangledName.consumeFront("$$B")) {
// Array
(*Current)->ParamType =
demangleType(MangledName, QualifierMangleMode::Drop);
} else if (MangledName.startsWith("$1?")) {
MangledName.consumeFront("$1");
// Pointer to symbol
Symbol *S = parse(MangledName);
(*Current)->ParamName = S->SymbolName;
(*Current)->ParamType = S->SymbolType;
(*Current)->PointerToSymbol = true;
} else if (MangledName.startsWith("$E?")) {
MangledName.consumeFront("$E");
// Reference to symbol
Symbol *S = parse(MangledName);
(*Current)->ParamName = S->SymbolName;
(*Current)->ParamType = S->SymbolType;
(*Current)->ReferenceToSymbol = true;
} else if (MangledName.consumeFront("$0")) {
// Integral non-type template parameter
bool IsNegative = false;
uint64_t Value = 0;
std::tie(Value, IsNegative) = demangleNumber(MangledName);

(*Current)->IsIntegerLiteral = true;
(*Current)->IntegerLiteralIsNegative = IsNegative;
(*Current)->IntegralValue = Value;
} else {
(*Current)->ParamType =
demangleType(MangledName, QualifierMangleMode::Drop);
Expand Down

0 comments on commit dbefc6c

Please sign in to comment.