Merge commit 565ba0415b6b
- upstream svn@328507
Test: git diff 565ba0415b6b == git diff 89cdbc2e15cc f26c8d18976
Change-Id: I631ab42bb70c97b7b90b68e2b773d584ebc603a1
diff --git a/src/cxa_demangle.cpp b/src/cxa_demangle.cpp
index d0362dc..9253e83 100644
--- a/src/cxa_demangle.cpp
+++ b/src/cxa_demangle.cpp
@@ -9,7 +9,6 @@
// FIXME: (possibly) incomplete list of features that clang mangles that this
// file does not yet support:
-// - enable_if attribute
// - C++ modules TS
// - All C++14 and C++17 features
@@ -110,6 +109,7 @@
/// If a ParameterPackExpansion (or similar type) is encountered, the offset
/// into the pack that we're currently printing.
unsigned CurrentPackIndex = std::numeric_limits<unsigned>::max();
+ unsigned CurrentPackMax = std::numeric_limits<unsigned>::max();
OutputStream &operator+=(StringView R) {
size_t Size = R.size();
@@ -127,7 +127,8 @@
return *this;
}
- size_t getCurrentPosition() const { return CurrentPosition; };
+ size_t getCurrentPosition() const { return CurrentPosition; }
+ void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; }
char back() const {
return CurrentPosition ? Buffer[CurrentPosition - 1] : '\0';
@@ -168,6 +169,7 @@
KElaboratedTypeSpefType,
KNameType,
KAbiTagAttr,
+ KEnableIfAttr,
KObjCProtoName,
KPointerType,
KLValueReferenceType,
@@ -188,6 +190,7 @@
KTemplateArgumentPack,
KParameterPackExpansion,
KTemplateArgs,
+ KForwardTemplateReference,
KNameWithTemplateArgs,
KGlobalQualifiedName,
KStdQualifiedName,
@@ -197,15 +200,12 @@
KDtorName,
KUnnamedTypeName,
KClosureTypeName,
+ KStructuredBindingName,
KExpr,
KBracedExpr,
KBracedRangeExpr,
};
- static constexpr unsigned NoParameterPack =
- std::numeric_limits<unsigned>::max();
- unsigned ParameterPackSize = NoParameterPack;
-
Kind K;
/// Three-way bool to track a cached value. Unknown is possible if this node
@@ -224,17 +224,11 @@
/// affect how we format the output string.
Cache FunctionCache;
- Node(Kind K_, unsigned ParameterPackSize_ = NoParameterPack,
- Cache RHSComponentCache_ = Cache::No, Cache ArrayCache_ = Cache::No,
- Cache FunctionCache_ = Cache::No)
- : ParameterPackSize(ParameterPackSize_), K(K_),
- RHSComponentCache(RHSComponentCache_), ArrayCache(ArrayCache_),
+ Node(Kind K_, Cache RHSComponentCache_ = Cache::No,
+ Cache ArrayCache_ = Cache::No, Cache FunctionCache_ = Cache::No)
+ : K(K_), RHSComponentCache(RHSComponentCache_), ArrayCache(ArrayCache_),
FunctionCache(FunctionCache_) {}
- bool containsUnexpandedParameterPack() const {
- return ParameterPackSize != NoParameterPack;
- }
-
bool hasRHSComponent(OutputStream &S) const {
if (RHSComponentCache != Cache::Unknown)
return RHSComponentCache == Cache::Yes;
@@ -259,10 +253,6 @@
virtual bool hasArraySlow(OutputStream &) const { return false; }
virtual bool hasFunctionSlow(OutputStream &) const { return false; }
- /// If this node is a pack expansion that expands to 0 elements. This can have
- /// an effect on how we should format the output.
- bool isEmptyPackExpansion() const;
-
void print(OutputStream &S) const {
printLeft(S);
if (RHSComponentCache != Cache::No)
@@ -315,12 +305,20 @@
void printWithComma(OutputStream &S) const {
bool FirstElement = true;
for (size_t Idx = 0; Idx != NumElements; ++Idx) {
- if (Elements[Idx]->isEmptyPackExpansion())
- continue;
+ size_t BeforeComma = S.getCurrentPosition();
if (!FirstElement)
S += ", ";
- FirstElement = false;
+ size_t AfterComma = S.getCurrentPosition();
Elements[Idx]->print(S);
+
+ // Elements[Idx] is an empty parameter pack expansion, we should erase the
+ // comma we just printed.
+ if (AfterComma == S.getCurrentPosition()) {
+ S.setCurrentPosition(BeforeComma);
+ continue;
+ }
+
+ FirstElement = false;
}
}
};
@@ -347,8 +345,7 @@
public:
VendorExtQualType(Node *Ty_, StringView Ext_)
- : Node(KVendorExtQualType, Ty_->ParameterPackSize),
- Ty(Ty_), Ext(Ext_) {}
+ : Node(KVendorExtQualType), Ty(Ty_), Ext(Ext_) {}
void printLeft(OutputStream &S) const override {
Ty->print(S);
@@ -390,7 +387,7 @@
public:
QualType(Node *Child_, Qualifiers Quals_)
- : Node(KQualType, Child_->ParameterPackSize, Child_->RHSComponentCache,
+ : Node(KQualType, Child_->RHSComponentCache,
Child_->ArrayCache, Child_->FunctionCache),
Quals(Quals_), Child(Child_) {}
@@ -417,7 +414,7 @@
public:
ConversionOperatorType(Node *Ty_)
- : Node(KConversionOperatorType, Ty_->ParameterPackSize), Ty(Ty_) {}
+ : Node(KConversionOperatorType), Ty(Ty_) {}
void printLeft(OutputStream &S) const override {
S += "operator ";
@@ -431,8 +428,7 @@
public:
PostfixQualifiedType(Node *Ty_, StringView Postfix_)
- : Node(KPostfixQualifiedType, Ty_->ParameterPackSize),
- Ty(Ty_), Postfix(Postfix_) {}
+ : Node(KPostfixQualifiedType), Ty(Ty_), Postfix(Postfix_) {}
void printLeft(OutputStream &s) const override {
Ty->printLeft(s);
@@ -457,9 +453,7 @@
Node *Child;
public:
ElaboratedTypeSpefType(StringView Kind_, Node *Child_)
- : Node(KElaboratedTypeSpefType), Kind(Kind_), Child(Child_) {
- ParameterPackSize = Child->ParameterPackSize;
- }
+ : Node(KElaboratedTypeSpefType), Kind(Kind_), Child(Child_) {}
void printLeft(OutputStream &S) const override {
S += Kind;
@@ -473,7 +467,7 @@
StringView Tag;
public:
AbiTagAttr(const Node* Base_, StringView Tag_)
- : Node(KAbiTagAttr, Base_->ParameterPackSize, Base_->RHSComponentCache,
+ : Node(KAbiTagAttr, Base_->RHSComponentCache,
Base_->ArrayCache, Base_->FunctionCache),
Base(Base_), Tag(Tag_) {}
@@ -485,6 +479,19 @@
}
};
+class EnableIfAttr : public Node {
+ NodeArray Conditions;
+public:
+ EnableIfAttr(NodeArray Conditions_)
+ : Node(KEnableIfAttr), Conditions(Conditions_) {}
+
+ void printLeft(OutputStream &S) const override {
+ S += " [enable_if:";
+ Conditions.printWithComma(S);
+ S += ']';
+ }
+};
+
class ObjCProtoName : public Node {
Node *Ty;
StringView Protocol;
@@ -513,8 +520,7 @@
public:
PointerType(Node *Pointee_)
- : Node(KPointerType, Pointee_->ParameterPackSize,
- Pointee_->RHSComponentCache),
+ : Node(KPointerType, Pointee_->RHSComponentCache),
Pointee(Pointee_) {}
bool hasRHSComponentSlow(OutputStream &S) const override {
@@ -554,8 +560,7 @@
public:
LValueReferenceType(Node *Pointee_)
- : Node(KLValueReferenceType, Pointee_->ParameterPackSize,
- Pointee_->RHSComponentCache),
+ : Node(KLValueReferenceType, Pointee_->RHSComponentCache),
Pointee(Pointee_) {}
bool hasRHSComponentSlow(OutputStream &S) const override {
@@ -583,8 +588,7 @@
public:
RValueReferenceType(Node *Pointee_)
- : Node(KRValueReferenceType, Pointee_->ParameterPackSize,
- Pointee_->RHSComponentCache),
+ : Node(KRValueReferenceType, Pointee_->RHSComponentCache),
Pointee(Pointee_) {}
bool hasRHSComponentSlow(OutputStream &S) const override {
@@ -614,10 +618,7 @@
public:
PointerToMemberType(Node *ClassType_, Node *MemberType_)
- : Node(KPointerToMemberType,
- std::min(MemberType_->ParameterPackSize,
- ClassType_->ParameterPackSize),
- MemberType_->RHSComponentCache),
+ : Node(KPointerToMemberType, MemberType_->RHSComponentCache),
ClassType(ClassType_), MemberType(MemberType_) {}
bool hasRHSComponentSlow(OutputStream &S) const override {
@@ -683,18 +684,14 @@
public:
ArrayType(Node *Base_, NodeOrString Dimension_)
- : Node(KArrayType, Base_->ParameterPackSize,
+ : Node(KArrayType,
/*RHSComponentCache=*/Cache::Yes,
/*ArrayCache=*/Cache::Yes),
- Base(Base_), Dimension(Dimension_) {
- if (Dimension.isNode())
- ParameterPackSize =
- std::min(ParameterPackSize, Dimension.asNode()->ParameterPackSize);
- }
+ Base(Base_), Dimension(Dimension_) {}
// Incomplete array type.
ArrayType(Node *Base_)
- : Node(KArrayType, Base_->ParameterPackSize,
+ : Node(KArrayType,
/*RHSComponentCache=*/Cache::Yes,
/*ArrayCache=*/Cache::Yes),
Base(Base_) {}
@@ -727,17 +724,11 @@
public:
FunctionType(Node *Ret_, NodeArray Params_, Qualifiers CVQuals_,
FunctionRefQual RefQual_, Node *ExceptionSpec_)
- : Node(KFunctionType, Ret_->ParameterPackSize,
+ : Node(KFunctionType,
/*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No,
/*FunctionCache=*/Cache::Yes),
Ret(Ret_), Params(Params_), CVQuals(CVQuals_), RefQual(RefQual_),
- ExceptionSpec(ExceptionSpec_) {
- for (Node *P : Params)
- ParameterPackSize = std::min(ParameterPackSize, P->ParameterPackSize);
- if (ExceptionSpec != nullptr)
- ParameterPackSize =
- std::min(ParameterPackSize, ExceptionSpec->ParameterPackSize);
- }
+ ExceptionSpec(ExceptionSpec_) {}
bool hasRHSComponentSlow(OutputStream &) const override { return true; }
bool hasFunctionSlow(OutputStream &) const override { return true; }
@@ -782,7 +773,7 @@
class NoexceptSpec : public Node {
Node *E;
public:
- NoexceptSpec(Node *E_) : Node(KNoexceptSpec, E_->ParameterPackSize), E(E_) {}
+ NoexceptSpec(Node *E_) : Node(KNoexceptSpec), E(E_) {}
void printLeft(OutputStream &S) const override {
S += "noexcept(";
@@ -795,10 +786,7 @@
NodeArray Types;
public:
DynamicExceptionSpec(NodeArray Types_)
- : Node(KDynamicExceptionSpec), Types(Types_) {
- for (Node *T : Types)
- ParameterPackSize = std::min(ParameterPackSize, T->ParameterPackSize);
- }
+ : Node(KDynamicExceptionSpec), Types(Types_) {}
void printLeft(OutputStream &S) const override {
S += "throw(";
@@ -811,22 +799,18 @@
const Node *Ret;
const Node *Name;
NodeArray Params;
+ Node *Attrs;
Qualifiers CVQuals;
FunctionRefQual RefQual;
public:
FunctionEncoding(Node *Ret_, Node *Name_, NodeArray Params_,
- Qualifiers CVQuals_, FunctionRefQual RefQual_)
- : Node(KFunctionEncoding, NoParameterPack,
+ Node *Attrs_, Qualifiers CVQuals_, FunctionRefQual RefQual_)
+ : Node(KFunctionEncoding,
/*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No,
/*FunctionCache=*/Cache::Yes),
- Ret(Ret_), Name(Name_), Params(Params_), CVQuals(CVQuals_),
- RefQual(RefQual_) {
- for (Node *P : Params)
- ParameterPackSize = std::min(ParameterPackSize, P->ParameterPackSize);
- if (Ret)
- ParameterPackSize = std::min(ParameterPackSize, Ret->ParameterPackSize);
- }
+ Ret(Ret_), Name(Name_), Params(Params_), Attrs(Attrs_),
+ CVQuals(CVQuals_), RefQual(RefQual_) {}
bool hasRHSComponentSlow(OutputStream &) const override { return true; }
bool hasFunctionSlow(OutputStream &) const override { return true; }
@@ -860,6 +844,9 @@
S += " &";
else if (RefQual == FrefQualRValue)
S += " &&";
+
+ if (Attrs != nullptr)
+ Attrs->print(S);
}
};
@@ -867,8 +854,7 @@
const Node *OpName;
public:
- LiteralOperator(Node *OpName_)
- : Node(KLiteralOperator, OpName_->ParameterPackSize), OpName(OpName_) {}
+ LiteralOperator(Node *OpName_) : Node(KLiteralOperator), OpName(OpName_) {}
void printLeft(OutputStream &S) const override {
S += "operator\"\" ";
@@ -882,8 +868,7 @@
public:
SpecialName(StringView Special_, Node* Child_)
- : Node(KSpecialName, Child_->ParameterPackSize), Special(Special_),
- Child(Child_) {}
+ : Node(KSpecialName), Special(Special_), Child(Child_) {}
void printLeft(OutputStream &S) const override {
S += Special;
@@ -897,8 +882,7 @@
public:
CtorVtableSpecialName(Node *FirstType_, Node *SecondType_)
- : Node(KCtorVtableSpecialName, std::min(FirstType_->ParameterPackSize,
- SecondType_->ParameterPackSize)),
+ : Node(KCtorVtableSpecialName),
FirstType(FirstType_), SecondType(SecondType_) {}
void printLeft(OutputStream &S) const override {
@@ -916,9 +900,7 @@
public:
QualifiedName(Node* Qualifier_, Node* Name_)
- : Node(KQualifiedName,
- std::min(Qualifier_->ParameterPackSize, Name_->ParameterPackSize)),
- Qualifier(Qualifier_), Name(Name_) {}
+ : Node(KQualifiedName), Qualifier(Qualifier_), Name(Name_) {}
StringView getBaseName() const override { return Name->getBaseName(); }
@@ -943,17 +925,10 @@
public:
VectorType(NodeOrString Dimension_)
: Node(KVectorType), BaseType(nullptr), Dimension(Dimension_),
- IsPixel(true) {
- if (Dimension.isNode())
- ParameterPackSize = Dimension.asNode()->ParameterPackSize;
- }
+ IsPixel(true) {}
VectorType(Node *BaseType_, NodeOrString Dimension_)
- : Node(KVectorType, BaseType_->ParameterPackSize), BaseType(BaseType_),
- Dimension(Dimension_), IsPixel(false) {
- if (Dimension.isNode())
- ParameterPackSize =
- std::min(ParameterPackSize, Dimension.asNode()->ParameterPackSize);
- }
+ : Node(KVectorType), BaseType(BaseType_),
+ Dimension(Dimension_), IsPixel(false) {}
void printLeft(OutputStream &S) const override {
if (IsPixel) {
@@ -982,9 +957,17 @@
/// T_).
class ParameterPack final : public Node {
NodeArray Data;
+
+ // Setup OutputStream for a pack expansion unless we're already expanding one.
+ void initializePackExpansion(OutputStream &S) const {
+ if (S.CurrentPackMax == std::numeric_limits<unsigned>::max()) {
+ S.CurrentPackMax = static_cast<unsigned>(Data.size());
+ S.CurrentPackIndex = 0;
+ }
+ }
+
public:
- ParameterPack(NodeArray Data_)
- : Node(KParameterPack, static_cast<unsigned>(Data_.size())), Data(Data_) {
+ ParameterPack(NodeArray Data_) : Node(KParameterPack), Data(Data_) {
ArrayCache = FunctionCache = RHSComponentCache = Cache::Unknown;
if (std::all_of(Data.begin(), Data.end(), [](Node* P) {
return P->ArrayCache == Cache::No;
@@ -1001,24 +984,29 @@
}
bool hasRHSComponentSlow(OutputStream &S) const override {
+ initializePackExpansion(S);
size_t Idx = S.CurrentPackIndex;
return Idx < Data.size() && Data[Idx]->hasRHSComponent(S);
}
bool hasArraySlow(OutputStream &S) const override {
+ initializePackExpansion(S);
size_t Idx = S.CurrentPackIndex;
return Idx < Data.size() && Data[Idx]->hasArray(S);
}
bool hasFunctionSlow(OutputStream &S) const override {
+ initializePackExpansion(S);
size_t Idx = S.CurrentPackIndex;
return Idx < Data.size() && Data[Idx]->hasFunction(S);
}
void printLeft(OutputStream &S) const override {
+ initializePackExpansion(S);
size_t Idx = S.CurrentPackIndex;
if (Idx < Data.size())
Data[Idx]->printLeft(S);
}
void printRight(OutputStream &S) const override {
+ initializePackExpansion(S);
size_t Idx = S.CurrentPackIndex;
if (Idx < Data.size())
Data[Idx]->printRight(S);
@@ -1034,10 +1022,7 @@
NodeArray Elements;
public:
TemplateArgumentPack(NodeArray Elements_)
- : Node(KTemplateArgumentPack), Elements(Elements_) {
- for (Node *E : Elements)
- ParameterPackSize = std::min(E->ParameterPackSize, ParameterPackSize);
- }
+ : Node(KTemplateArgumentPack), Elements(Elements_) {}
NodeArray getElements() const { return Elements; }
@@ -1058,66 +1043,103 @@
const Node *getChild() const { return Child; }
void printLeft(OutputStream &S) const override {
- unsigned PackSize = Child->ParameterPackSize;
- if (PackSize == NoParameterPack) {
- Child->print(S);
+ constexpr unsigned Max = std::numeric_limits<unsigned>::max();
+ SwapAndRestore<unsigned> SavePackIdx(S.CurrentPackIndex, Max);
+ SwapAndRestore<unsigned> SavePackMax(S.CurrentPackMax, Max);
+ size_t StreamPos = S.getCurrentPosition();
+
+ // Print the first element in the pack. If Child contains a ParameterPack,
+ // it will set up S.CurrentPackMax and print the first element.
+ Child->print(S);
+
+ // No ParameterPack was found in Child. This can occur if we've found a pack
+ // expansion on a <function-param>.
+ if (S.CurrentPackMax == Max) {
S += "...";
return;
}
- SwapAndRestore<unsigned> SavePackIndex(S.CurrentPackIndex, 0);
- for (unsigned I = 0; I != PackSize; ++I) {
- if (I != 0)
- S += ", ";
+ // We found a ParameterPack, but it has no elements. Erase whatever we may
+ // of printed.
+ if (S.CurrentPackMax == 0) {
+ S.setCurrentPosition(StreamPos);
+ return;
+ }
+
+ // Else, iterate through the rest of the elements in the pack.
+ for (unsigned I = 1, E = S.CurrentPackMax; I < E; ++I) {
+ S += ", ";
S.CurrentPackIndex = I;
Child->print(S);
}
}
};
-inline bool Node::isEmptyPackExpansion() const {
- if (getKind() == KParameterPackExpansion) {
- auto *AsPack = static_cast<const ParameterPackExpansion *>(this);
- return AsPack->getChild()->isEmptyPackExpansion();
- }
- if (getKind() == KTemplateArgumentPack) {
- auto *AsTemplateArg = static_cast<const TemplateArgumentPack *>(this);
- for (Node *E : AsTemplateArg->getElements())
- if (!E->isEmptyPackExpansion())
- return false;
- return true;
- }
- return ParameterPackSize == 0;
-}
-
class TemplateArgs final : public Node {
NodeArray Params;
public:
- TemplateArgs(NodeArray Params_) : Node(KTemplateArgs), Params(Params_) {
- for (Node *P : Params)
- ParameterPackSize = std::min(ParameterPackSize, P->ParameterPackSize);
- }
+ TemplateArgs(NodeArray Params_) : Node(KTemplateArgs), Params(Params_) {}
NodeArray getParams() { return Params; }
void printLeft(OutputStream &S) const override {
S += "<";
- bool FirstElement = true;
- for (size_t Idx = 0, E = Params.size(); Idx != E; ++Idx) {
- if (Params[Idx]->isEmptyPackExpansion())
- continue;
- if (!FirstElement)
- S += ", ";
- FirstElement = false;
- Params[Idx]->print(S);
- }
+ Params.printWithComma(S);
if (S.back() == '>')
S += " ";
S += ">";
}
};
+struct ForwardTemplateReference : Node {
+ size_t Index;
+ Node *Ref = nullptr;
+
+ // If we're currently printing this node. It is possible (though invalid) for
+ // a forward template reference to refer to itself via a substitution. This
+ // creates a cyclic AST, which will stack overflow printing. To fix this, bail
+ // out if more than one print* function is active.
+ mutable bool Printing = false;
+
+ ForwardTemplateReference(size_t Index_)
+ : Node(KForwardTemplateReference, Cache::Unknown, Cache::Unknown,
+ Cache::Unknown),
+ Index(Index_) {}
+
+ bool hasRHSComponentSlow(OutputStream &S) const override {
+ if (Printing)
+ return false;
+ SwapAndRestore<bool> SavePrinting(Printing, true);
+ return Ref->hasRHSComponent(S);
+ }
+ bool hasArraySlow(OutputStream &S) const override {
+ if (Printing)
+ return false;
+ SwapAndRestore<bool> SavePrinting(Printing, true);
+ return Ref->hasArray(S);
+ }
+ bool hasFunctionSlow(OutputStream &S) const override {
+ if (Printing)
+ return false;
+ SwapAndRestore<bool> SavePrinting(Printing, true);
+ return Ref->hasFunction(S);
+ }
+
+ void printLeft(OutputStream &S) const override {
+ if (Printing)
+ return;
+ SwapAndRestore<bool> SavePrinting(Printing, true);
+ Ref->printLeft(S);
+ }
+ void printRight(OutputStream &S) const override {
+ if (Printing)
+ return;
+ SwapAndRestore<bool> SavePrinting(Printing, true);
+ Ref->printRight(S);
+ }
+};
+
class NameWithTemplateArgs final : public Node {
// name<template_args>
Node *Name;
@@ -1125,9 +1147,7 @@
public:
NameWithTemplateArgs(Node *Name_, Node *TemplateArgs_)
- : Node(KNameWithTemplateArgs, std::min(Name_->ParameterPackSize,
- TemplateArgs_->ParameterPackSize)),
- Name(Name_), TemplateArgs(TemplateArgs_) {}
+ : Node(KNameWithTemplateArgs), Name(Name_), TemplateArgs(TemplateArgs_) {}
StringView getBaseName() const override { return Name->getBaseName(); }
@@ -1142,7 +1162,7 @@
public:
GlobalQualifiedName(Node* Child_)
- : Node(KGlobalQualifiedName, Child_->ParameterPackSize), Child(Child_) {}
+ : Node(KGlobalQualifiedName), Child(Child_) {}
StringView getBaseName() const override { return Child->getBaseName(); }
@@ -1156,8 +1176,7 @@
Node *Child;
public:
- StdQualifiedName(Node *Child_)
- : Node(KStdQualifiedName, Child_->ParameterPackSize), Child(Child_) {}
+ StdQualifiedName(Node *Child_) : Node(KStdQualifiedName), Child(Child_) {}
StringView getBaseName() const override { return Child->getBaseName(); }
@@ -1280,8 +1299,7 @@
public:
CtorDtorName(Node *Basename_, bool IsDtor_)
- : Node(KCtorDtorName, Basename_->ParameterPackSize),
- Basename(Basename_), IsDtor(IsDtor_) {}
+ : Node(KCtorDtorName), Basename(Basename_), IsDtor(IsDtor_) {}
void printLeft(OutputStream &S) const override {
if (IsDtor)
@@ -1294,9 +1312,7 @@
const Node *Base;
public:
- DtorName(Node *Base_) : Node(KDtorName), Base(Base_) {
- ParameterPackSize = Base->ParameterPackSize;
- }
+ DtorName(Node *Base_) : Node(KDtorName), Base(Base_) {}
void printLeft(OutputStream &S) const override {
S += "~";
@@ -1323,10 +1339,7 @@
public:
ClosureTypeName(NodeArray Params_, StringView Count_)
- : Node(KClosureTypeName), Params(Params_), Count(Count_) {
- for (Node *P : Params)
- ParameterPackSize = std::min(ParameterPackSize, P->ParameterPackSize);
- }
+ : Node(KClosureTypeName), Params(Params_), Count(Count_) {}
void printLeft(OutputStream &S) const override {
S += "\'lambda";
@@ -1337,6 +1350,19 @@
}
};
+class StructuredBindingName : public Node {
+ NodeArray Bindings;
+public:
+ StructuredBindingName(NodeArray Bindings_)
+ : Node(KStructuredBindingName), Bindings(Bindings_) {}
+
+ void printLeft(OutputStream &S) const override {
+ S += '[';
+ Bindings.printWithComma(S);
+ S += ']';
+ }
+};
+
// -- Expression Nodes --
struct Expr : public Node {
@@ -1350,10 +1376,7 @@
public:
BinaryExpr(Node *LHS_, StringView InfixOperator_, Node *RHS_)
- : LHS(LHS_), InfixOperator(InfixOperator_), RHS(RHS_) {
- ParameterPackSize =
- std::min(LHS->ParameterPackSize, RHS->ParameterPackSize);
- }
+ : LHS(LHS_), InfixOperator(InfixOperator_), RHS(RHS_) {}
void printLeft(OutputStream &S) const override {
// might be a template argument expression, then we need to disambiguate
@@ -1379,10 +1402,7 @@
const Node *Op2;
public:
- ArraySubscriptExpr(Node *Op1_, Node *Op2_) : Op1(Op1_), Op2(Op2_) {
- ParameterPackSize =
- std::min(Op1->ParameterPackSize, Op2->ParameterPackSize);
- }
+ ArraySubscriptExpr(Node *Op1_, Node *Op2_) : Op1(Op1_), Op2(Op2_) {}
void printLeft(OutputStream &S) const override {
S += "(";
@@ -1399,9 +1419,7 @@
public:
PostfixExpr(Node *Child_, StringView Operand_)
- : Child(Child_), Operand(Operand_) {
- ParameterPackSize = Child->ParameterPackSize;
- }
+ : Child(Child_), Operand(Operand_) {}
void printLeft(OutputStream &S) const override {
S += "(";
@@ -1418,11 +1436,7 @@
public:
ConditionalExpr(Node *Cond_, Node *Then_, Node *Else_)
- : Cond(Cond_), Then(Then_), Else(Else_) {
- ParameterPackSize =
- std::min(Cond->ParameterPackSize,
- std::min(Then->ParameterPackSize, Else->ParameterPackSize));
- }
+ : Cond(Cond_), Then(Then_), Else(Else_) {}
void printLeft(OutputStream &S) const override {
S += "(";
@@ -1442,10 +1456,7 @@
public:
MemberExpr(Node *LHS_, StringView Kind_, Node *RHS_)
- : LHS(LHS_), Kind(Kind_), RHS(RHS_) {
- ParameterPackSize =
- std::min(LHS->ParameterPackSize, RHS->ParameterPackSize);
- }
+ : LHS(LHS_), Kind(Kind_), RHS(RHS_) {}
void printLeft(OutputStream &S) const override {
LHS->print(S);
@@ -1461,9 +1472,7 @@
public:
EnclosingExpr(StringView Prefix_, Node *Infix_, StringView Postfix_)
- : Prefix(Prefix_), Infix(Infix_), Postfix(Postfix_) {
- ParameterPackSize = Infix->ParameterPackSize;
- }
+ : Prefix(Prefix_), Infix(Infix_), Postfix(Postfix_) {}
void printLeft(OutputStream &S) const override {
S += Prefix;
@@ -1480,10 +1489,7 @@
public:
CastExpr(StringView CastKind_, Node *To_, Node *From_)
- : CastKind(CastKind_), To(To_), From(From_) {
- ParameterPackSize =
- std::min(To->ParameterPackSize, From->ParameterPackSize);
- }
+ : CastKind(CastKind_), To(To_), From(From_) {}
void printLeft(OutputStream &S) const override {
S += CastKind;
@@ -1514,11 +1520,7 @@
NodeArray Args;
public:
- CallExpr(Node *Callee_, NodeArray Args_) : Callee(Callee_), Args(Args_) {
- for (Node *P : Args)
- ParameterPackSize = std::min(ParameterPackSize, P->ParameterPackSize);
- ParameterPackSize = std::min(ParameterPackSize, Callee->ParameterPackSize);
- }
+ CallExpr(Node *Callee_, NodeArray Args_) : Callee(Callee_), Args(Args_) {}
void printLeft(OutputStream &S) const override {
Callee->print(S);
@@ -1539,14 +1541,7 @@
NewExpr(NodeArray ExprList_, Node *Type_, NodeArray InitList_, bool IsGlobal_,
bool IsArray_)
: ExprList(ExprList_), Type(Type_), InitList(InitList_),
- IsGlobal(IsGlobal_), IsArray(IsArray_) {
- for (Node *E : ExprList)
- ParameterPackSize = std::min(ParameterPackSize, E->ParameterPackSize);
- for (Node *I : InitList)
- ParameterPackSize = std::min(ParameterPackSize, I->ParameterPackSize);
- if (Type)
- ParameterPackSize = std::min(ParameterPackSize, Type->ParameterPackSize);
- }
+ IsGlobal(IsGlobal_), IsArray(IsArray_) {}
void printLeft(OutputStream &S) const override {
if (IsGlobal)
@@ -1577,9 +1572,7 @@
public:
DeleteExpr(Node *Op_, bool IsGlobal_, bool IsArray_)
- : Op(Op_), IsGlobal(IsGlobal_), IsArray(IsArray_) {
- ParameterPackSize = Op->ParameterPackSize;
- }
+ : Op(Op_), IsGlobal(IsGlobal_), IsArray(IsArray_) {}
void printLeft(OutputStream &S) const override {
if (IsGlobal)
@@ -1596,9 +1589,7 @@
Node *Child;
public:
- PrefixExpr(StringView Prefix_, Node *Child_) : Prefix(Prefix_), Child(Child_) {
- ParameterPackSize = Child->ParameterPackSize;
- }
+ PrefixExpr(StringView Prefix_, Node *Child_) : Prefix(Prefix_), Child(Child_) {}
void printLeft(OutputStream &S) const override {
S += Prefix;
@@ -1626,11 +1617,7 @@
public:
ConversionExpr(const Node *Type_, NodeArray Expressions_)
- : Type(Type_), Expressions(Expressions_) {
- for (Node *E : Expressions)
- ParameterPackSize = std::min(ParameterPackSize, E->ParameterPackSize);
- ParameterPackSize = std::min(ParameterPackSize, Type->ParameterPackSize);
- }
+ : Type(Type_), Expressions(Expressions_) {}
void printLeft(OutputStream &S) const override {
S += "(";
@@ -1645,13 +1632,7 @@
Node *Ty;
NodeArray Inits;
public:
- InitListExpr(Node *Ty_, NodeArray Inits_)
- : Ty(Ty_), Inits(Inits_) {
- if (Ty)
- ParameterPackSize = Ty->ParameterPackSize;
- for (Node *I : Inits)
- ParameterPackSize = std::min(I->ParameterPackSize, ParameterPackSize);
- }
+ InitListExpr(Node *Ty_, NodeArray Inits_) : Ty(Ty_), Inits(Inits_) {}
void printLeft(OutputStream &S) const override {
if (Ty)
@@ -1709,9 +1690,7 @@
const Node *Op;
public:
- ThrowExpr(Node *Op_) : Op(Op_) {
- ParameterPackSize = Op->ParameterPackSize;
- }
+ ThrowExpr(Node *Op_) : Op(Op_) {}
void printLeft(OutputStream &S) const override {
S += "throw ";
@@ -1736,9 +1715,8 @@
StringView Integer;
public:
- IntegerCastExpr(Node *Ty_, StringView Integer_) : Ty(Ty_), Integer(Integer_) {
- ParameterPackSize = Ty->ParameterPackSize;
- }
+ IntegerCastExpr(Node *Ty_, StringView Integer_)
+ : Ty(Ty_), Integer(Integer_) {}
void printLeft(OutputStream &S) const override {
S += "(";
@@ -1995,10 +1973,13 @@
// stored on the stack.
PODSmallVector<Node *, 8> TemplateParams;
- unsigned EncodingDepth = 0;
- bool TagTemplates = true;
- bool FixForwardReferences = false;
+ // Set of unresolved forward <template-param> references. These can occur in a
+ // conversion operator's type, and are resolved in the enclosing <encoding>.
+ PODSmallVector<ForwardTemplateReference *, 4> ForwardTemplateRefs;
+
bool TryToParseTemplateArgs = true;
+ bool PermitForwardTemplateReferences = false;
+ bool ParsingLambdaParams = false;
BumpPointerAllocator ASTAllocator;
@@ -2059,7 +2040,7 @@
bool parseSeqId(size_t *Out);
Node *parseSubstitution();
Node *parseTemplateParam();
- Node *parseTemplateArgs();
+ Node *parseTemplateArgs(bool TagTemplates = false);
Node *parseTemplateArg();
/// Parse the <expr> production.
@@ -2095,8 +2076,25 @@
bool EndsWithTemplateArgs = false;
Qualifiers CVQualifiers = QualNone;
FunctionRefQual ReferenceQualifier = FrefQualNone;
+ size_t ForwardTemplateRefsBegin;
+
+ NameState(Db *Enclosing)
+ : ForwardTemplateRefsBegin(Enclosing->ForwardTemplateRefs.size()) {}
};
+ bool resolveForwardTemplateRefs(NameState &State) {
+ size_t I = State.ForwardTemplateRefsBegin;
+ size_t E = ForwardTemplateRefs.size();
+ for (; I < E; ++I) {
+ size_t Idx = ForwardTemplateRefs[I]->Index;
+ if (Idx >= TemplateParams.size())
+ return true;
+ ForwardTemplateRefs[I]->Ref = TemplateParams[Idx];
+ }
+ ForwardTemplateRefs.dropBack(State.ForwardTemplateRefsBegin);
+ return false;
+ }
+
/// Parse the <name> production>
Node *parseName(NameState *State = nullptr);
Node *parseLocalName(NameState *State);
@@ -2145,7 +2143,7 @@
return nullptr;
if (look() != 'I')
return nullptr;
- Node *TA = parseTemplateArgs();
+ Node *TA = parseTemplateArgs(State != nullptr);
if (TA == nullptr)
return nullptr;
if (State) State->EndsWithTemplateArgs = true;
@@ -2158,7 +2156,7 @@
// ::= <unscoped-template-name> <template-args>
if (look() == 'I') {
Subs.push_back(N);
- Node *TA = parseTemplateArgs();
+ Node *TA = parseTemplateArgs(State != nullptr);
if (TA == nullptr)
return nullptr;
if (State) State->EndsWithTemplateArgs = true;
@@ -2217,7 +2215,7 @@
// ::= <ctor-dtor-name>
// ::= <source-name>
// ::= <unnamed-type-name>
-// FIXME: ::= DC <source-name>+ E # structured binding declaration
+// ::= DC <source-name>+ E # structured binding declaration
Node *Db::parseUnqualifiedName(NameState *State) {
// <ctor-dtor-name>s are special-cased in parseNestedName().
Node *Result;
@@ -2225,7 +2223,16 @@
Result = parseUnnamedTypeName(State);
else if (look() >= '1' && look() <= '9')
Result = parseSourceName(State);
- else
+ else if (consumeIf("DC")) {
+ size_t BindingsBegin = Names.size();
+ do {
+ Node *Binding = parseSourceName(State);
+ if (Binding == nullptr)
+ return nullptr;
+ Names.push_back(Binding);
+ } while (!consumeIf('E'));
+ Result = make<StructuredBindingName>(popTrailingNodeArray(BindingsBegin));
+ } else
Result = parseOperatorName(State);
if (Result != nullptr)
Result = parseAbiTags(Result);
@@ -2247,6 +2254,7 @@
}
if (consumeIf("Ul")) {
NodeArray Params;
+ SwapAndRestore<bool> SwapParams(ParsingLambdaParams, true);
if (!consumeIf("vE")) {
size_t ParamsBegin = Names.size();
do {
@@ -2362,9 +2370,15 @@
return make<NameType>("operator~");
// ::= cv <type> # (cast)
case 'v': {
- SwapAndRestore<bool> SaveTemplate(TryToParseTemplateArgs, false);
First += 2;
- Node *Ty = parseType();
+ SwapAndRestore<bool> SaveTemplate(TryToParseTemplateArgs, false);
+ // If we're parsing an encoding, State != nullptr and the conversion
+ // operators' <type> could have a <template-param> that refers to some
+ // <template-arg>s further ahead in the mangled name.
+ SwapAndRestore<bool> SavePermit(PermitForwardTemplateReferences,
+ PermitForwardTemplateReferences ||
+ State != nullptr);
+ Node* Ty = parseType();
if (Ty == nullptr)
return nullptr;
if (State) State->CtorDtorConversion = true;
@@ -2588,7 +2602,7 @@
++First;
if (State) State->CtorDtorConversion = true;
if (IsInherited) {
- if (parseName() == nullptr)
+ if (parseName(State) == nullptr)
return nullptr;
}
return make<CtorDtorName>(SoFar, false);
@@ -2658,7 +2672,7 @@
// ::= <template-prefix> <template-args>
if (look() == 'I') {
- Node *TA = parseTemplateArgs();
+ Node *TA = parseTemplateArgs(State != nullptr);
if (TA == nullptr || SoFar == nullptr)
return nullptr;
SoFar = make<NameWithTemplateArgs>(SoFar, TA);
@@ -2689,7 +2703,7 @@
}
// Parse an <unqualified-name> thats actually a <ctor-dtor-name>.
- if (look() == 'C' || look() == 'D') {
+ if (look() == 'C' || (look() == 'D' && look(1) != 'C')) {
if (SoFar == nullptr)
return nullptr;
Node *CtorDtor = parseCtorDtorName(SoFar, State);
@@ -4301,6 +4315,8 @@
// # No <type>
// ::= TW <object name> # Thread-local wrapper
// ::= TH <object name> # Thread-local initialization
+// ::= GR <object name> _ # First temporary
+// ::= GR <object name> <seq-id> _ # Subsequent temporaries
// extension ::= TC <first type> <number> _ <second type> # construction vtable for second-in-first
// extension ::= GR <object name> # reference temporary for object
Node *Db::parseSpecialName() {
@@ -4405,11 +4421,17 @@
return make<SpecialName>("guard variable for ", Name);
}
// GR <object name> # reference temporary for object
+ // GR <object name> _ # First temporary
+ // GR <object name> <seq-id> _ # Subsequent temporaries
case 'R': {
First += 2;
Node *Name = parseName();
if (Name == nullptr)
return nullptr;
+ size_t Count;
+ bool ParsedSeqId = !parseSeqId(&Count);
+ if (!consumeIf('_') && ParsedSeqId)
+ return nullptr;
return make<SpecialName>("reference temporary for ", Name);
}
}
@@ -4421,15 +4443,6 @@
// ::= <data name>
// ::= <special-name>
Node *Db::parseEncoding() {
- // Always "tag" templates (insert them into Db::TemplateParams) unless we're
- // doing a second parse to resolve a forward template reference, in which case
- // we only tag templates if EncodingDepth > 1.
- // FIXME: This is kinda broken; it would be better to make a forward reference
- // and patch it all in one pass.
- SwapAndRestore<bool> SaveTagTemplates(TagTemplates,
- TagTemplates || EncodingDepth);
- SwapAndRestore<unsigned> SaveEncodingDepth(EncodingDepth, EncodingDepth + 1);
-
if (look() == 'G' || look() == 'T')
return parseSpecialName();
@@ -4440,12 +4453,28 @@
return numLeft() == 0 || look() == 'E' || look() == '.' || look() == '_';
};
- NameState NameInfo;
+ NameState NameInfo(this);
Node *Name = parseName(&NameInfo);
- if (Name == nullptr || IsEndOfEncoding())
+ if (Name == nullptr)
+ return nullptr;
+
+ if (resolveForwardTemplateRefs(NameInfo))
+ return nullptr;
+
+ if (IsEndOfEncoding())
return Name;
- TagTemplates = false;
+ Node *Attrs = nullptr;
+ if (consumeIf("Ua9enable_ifI")) {
+ size_t BeforeArgs = Names.size();
+ while (!consumeIf('E')) {
+ Node *Arg = parseTemplateArg();
+ if (Arg == nullptr)
+ return nullptr;
+ Names.push_back(Arg);
+ }
+ Attrs = make<EnableIfAttr>(popTrailingNodeArray(BeforeArgs));
+ }
Node *ReturnType = nullptr;
if (!NameInfo.CtorDtorConversion && NameInfo.EndsWithTemplateArgs) {
@@ -4456,7 +4485,7 @@
if (consumeIf('v'))
return make<FunctionEncoding>(ReturnType, Name, NodeArray(),
- NameInfo.CVQualifiers,
+ Attrs, NameInfo.CVQualifiers,
NameInfo.ReferenceQualifier);
size_t ParamsBegin = Names.size();
@@ -4469,7 +4498,7 @@
return make<FunctionEncoding>(ReturnType, Name,
popTrailingNodeArray(ParamsBegin),
- NameInfo.CVQualifiers,
+ Attrs, NameInfo.CVQualifiers,
NameInfo.ReferenceQualifier);
}
@@ -4627,24 +4656,30 @@
if (!consumeIf('T'))
return nullptr;
- if (consumeIf('_')) {
- if (TemplateParams.empty()) {
- FixForwardReferences = true;
- return make<NameType>("FORWARD_REFERENCE");
- }
- return TemplateParams[0];
+ size_t Index = 0;
+ if (!consumeIf('_')) {
+ if (parsePositiveInteger(&Index))
+ return nullptr;
+ ++Index;
+ if (!consumeIf('_'))
+ return nullptr;
}
- size_t Index;
- if (parsePositiveInteger(&Index))
- return nullptr;
- ++Index;
- if (!consumeIf('_'))
- return nullptr;
- if (Index >= TemplateParams.size()) {
- FixForwardReferences = true;
- return make<NameType>("FORWARD_REFERENCE");
+ // Itanium ABI 5.1.8: In a generic lambda, uses of auto in the parameter list
+ // are mangled as the corresponding artificial template type parameter.
+ if (ParsingLambdaParams)
+ return make<NameType>("auto");
+
+ // If we're in a context where this <template-param> refers to a
+ // <template-arg> further ahead in the mangled name (currently just conversion
+ // operator types), then we should only look it up in the right context.
+ if (PermitForwardTemplateReferences) {
+ ForwardTemplateRefs.push_back(make<ForwardTemplateReference>(Index));
+ return ForwardTemplateRefs.back();
}
+
+ if (Index >= TemplateParams.size())
+ return nullptr;
return TemplateParams[Index];
}
@@ -4693,7 +4728,7 @@
// <template-args> ::= I <template-arg>* E
// extension, the abi says <template-arg>+
-Node *Db::parseTemplateArgs() {
+Node *Db::parseTemplateArgs(bool TagTemplates) {
if (!consumeIf('I'))
return nullptr;
@@ -4788,8 +4823,8 @@
Node *Encoding = parseEncoding();
if (Encoding == nullptr || !consumeIf("_block_invoke"))
return nullptr;
- consumeIf('_');
- if (parseNumber().empty())
+ bool RequireNumber = consumeIf('_');
+ if (parseNumber().empty() && RequireNumber)
return nullptr;
if (numLeft() != 0)
return nullptr;
@@ -4830,23 +4865,9 @@
if (AST == nullptr)
InternalStatus = invalid_mangled_name;
- if (InternalStatus == success && Parser.FixForwardReferences &&
- !Parser.TemplateParams.empty()) {
- Parser.FixForwardReferences = false;
- Parser.TagTemplates = false;
- Parser.Names.clear();
- Parser.Subs.clear();
- Parser.First = MangledName;
- Parser.Last = MangledName + MangledNameLength;
- AST = Parser.parse();
- if (AST == nullptr || Parser.FixForwardReferences)
- InternalStatus = invalid_mangled_name;
- }
-
- if (InternalStatus == success && AST->containsUnexpandedParameterPack())
- InternalStatus = invalid_mangled_name;
-
if (InternalStatus == success) {
+ assert(Parser.ForwardTemplateRefs.empty());
+
if (Buf == nullptr) {
BufSize = 1024;
Buf = static_cast<char*>(std::malloc(BufSize));
diff --git a/test/test_demangle.pass.cpp b/test/test_demangle.pass.cpp
index b54f8d3..98921c2 100644
--- a/test/test_demangle.pass.cpp
+++ b/test/test_demangle.pass.cpp
@@ -29604,7 +29604,7 @@
{"PFvRmOE", "void (*)(unsigned long&) &&"},
{"_ZTW1x", "thread-local wrapper routine for x"},
{"_ZTHN3fooE", "thread-local initialization routine for foo"},
- {"_Z4algoIJiiiEEvZ1gEUlDpT_E_", "void algo<int, int, int>(g::'lambda'(int, int, int))"},
+
// attribute abi_tag
{"_Z1fB3foov", "f[abi:foo]()"},
{"_Z1fB3fooB3barv", "f[abi:foo][abi:bar]()"},
@@ -29716,6 +29716,28 @@
// ABI tags can apply to built-in substitutions.
{"_Z1fSsB1XS_", "f(std::string[abi:X], std::string[abi:X])"},
+
+ {"___Z10blocksNRVOv_block_invoke", "invocation function for block in blocksNRVO()"},
+
+ // Structured bindings:
+ {"_ZDC2a12a2E", "[a1, a2]"},
+ {"_ZN2NSDC1x1yEE", "NS::[x, y]"},
+
+ {"_ZGRDC1x1yE_", "reference temporary for [x, y]"},
+ {"_ZGR1bIvE2_", "reference temporary for b<void>"},
+
+ {"_ZZ18test_assign_throwsI20small_throws_on_copyLb0EEvvENKUlRNSt3__13anyEOT_E_clIRS0_EEDaS3_S5_", "auto void test_assign_throws<small_throws_on_copy, false>()::'lambda'(std::__1::any&, auto&&)::operator()<small_throws_on_copy&>(std::__1::any&, auto&&) const"},
+
+ // enable_if attributes:
+ {"_Z1fUa9enable_ifIXLi1EEEv", "f() [enable_if:1]"},
+ {"_ZN5test4IdE1fEUa9enable_ifIXeqfL0p_Li1EEXeqfL0p0_Li2EEEi", "test4<double>::f(int) [enable_if:(fp) == (1), (fp0) == (2)]"},
+ {"_Z3quxUa9enable_ifIXLi1EEXL_Z9TRUEFACTSEEEi", "qux(int) [enable_if:1, TRUEFACTS]"},
+
+ // Conversion operators:
+ {"_ZN5OuterI4MarpEcv7MuncherIJT_T0_DpT1_EEI4MerpS0_JicfEEEv", "Outer<Marp>::operator Muncher<Merp, Marp, int, char, float><Merp, Marp, int, char, float>()"},
+ {"_ZN5OuterI4MarpEcvT_I4MerpEEv", "Outer<Marp>::operator Merp<Merp>()"},
+ {"_ZZN5OuterI4MarpEcv7MuncherIJT_T0_DpT1_EEI4MerpS0_JicfEEEvEN1ScvS9_Ev", "Outer<Marp>::operator Muncher<Merp, Marp, int, char, float><Merp, Marp, int, char, float>()::S::operator Merp()"},
+ {"_ZN1Scv7MuncherIJDpPT_EEIJFivEA_iEEEv", "S::operator Muncher<int (*)(), int (*) []><int (), int []>()"},
};
const unsigned N = sizeof(cases) / sizeof(cases[0]);
@@ -29787,7 +29809,6 @@
"AT__ZSiIJEEAnwscT_T__",
"FSiIJEENT_IoE ",
"ZTVSiIZTVSiIZTVSiIZTVSiINIJEET_T_T_T_T_ ",
- "_ZSiIJEvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvttvvvvvvET_v",
"Ana_T_E_T_IJEffffffffffffffersfffffrsrsffffffbgE",
};
@@ -29797,22 +29818,25 @@
{
std::size_t len = 0;
char* buf = nullptr;
+ bool failed = false;
for (unsigned i = 0; i < N; ++i)
{
int status;
char* demang = __cxxabiv1::__cxa_demangle(cases[i][0], buf, &len, &status);
if (demang == 0 || std::strcmp(demang, cases[i][1]) != 0)
{
- std::cout << cases[i][0] << " -> " << cases[i][1] << '\n';
+ std::cout << "ERROR demangling " << cases[i][0] << '\n'
+ << "expected: " << cases[i][1] << std::endl;
if (demang)
{
- std::cout << "Got instead: " << demang << '\n';
- assert(std::strcmp(demang, cases[i][1]) == 0);
+ std::cout << " reality: " << demang << '\n' << std::endl;
+ buf = demang;
+ failed = true;
}
else
{
std::cout << "Got instead: NULL, " << status << '\n';
- assert(demang != 0);
+ failed = true;
}
}
else
@@ -29820,6 +29844,7 @@
buf = demang;
}
}
+ assert(!failed);
free(buf);
}
@@ -29845,8 +29870,6 @@
}
const char *xfail_cases[] = {
- "_Z1fUa9enable_ifIXLi1EEEv", // enable_if attribute
- "_ZDC2a12a2E", // decomposition decl
"_ZW6FooBarE2f3v", // C++ modules TS
// FIXME: Why does clang generate the "cp" expr?