summaryrefslogtreecommitdiffstats
path: root/libcxxabi/src
diff options
context:
space:
mode:
authorErik Pilkington <erik.pilkington@gmail.com>2018-02-14 01:08:20 +0000
committerErik Pilkington <erik.pilkington@gmail.com>2018-02-14 01:08:20 +0000
commit0bae6d8c14028726e77738717a307b916e85d23d (patch)
treed97b3ab7a4cf46362fc56b8ddcd8f62b2d6bc597 /libcxxabi/src
parentbb0e34558fff2d0beb24bd14b4b958c05af0e034 (diff)
downloadbcm5719-llvm-0bae6d8c14028726e77738717a307b916e85d23d.tar.gz
bcm5719-llvm-0bae6d8c14028726e77738717a307b916e85d23d.zip
[demangler] Support for exception specifications on function types.
llvm-svn: 325093
Diffstat (limited to 'libcxxabi/src')
-rw-r--r--libcxxabi/src/cxa_demangle.cpp84
1 files changed, 80 insertions, 4 deletions
diff --git a/libcxxabi/src/cxa_demangle.cpp b/libcxxabi/src/cxa_demangle.cpp
index 82b9de087a1..2a004e6c7fa 100644
--- a/libcxxabi/src/cxa_demangle.cpp
+++ b/libcxxabi/src/cxa_demangle.cpp
@@ -175,6 +175,8 @@ public:
KPointerToMemberType,
KArrayType,
KFunctionType,
+ KNoexceptSpec,
+ KDynamicExceptionSpec,
KFunctionEncoding,
KLiteralOperator,
KSpecialName,
@@ -720,16 +722,21 @@ class FunctionType final : public Node {
NodeArray Params;
Qualifiers CVQuals;
FunctionRefQual RefQual;
+ Node *ExceptionSpec;
public:
FunctionType(Node *Ret_, NodeArray Params_, Qualifiers CVQuals_,
- FunctionRefQual RefQual_)
+ FunctionRefQual RefQual_, Node *ExceptionSpec_)
: Node(KFunctionType, Ret_->ParameterPackSize,
/*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No,
/*FunctionCache=*/Cache::Yes),
- Ret(Ret_), Params(Params_), CVQuals(CVQuals_), RefQual(RefQual_) {
+ 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);
}
bool hasRHSComponentSlow(OutputStream &) const override { return true; }
@@ -764,6 +771,39 @@ public:
S += " &";
else if (RefQual == FrefQualRValue)
S += " &&";
+
+ if (ExceptionSpec != nullptr) {
+ S += ' ';
+ ExceptionSpec->print(S);
+ }
+ }
+};
+
+class NoexceptSpec : public Node {
+ Node *E;
+public:
+ NoexceptSpec(Node *E_) : Node(KNoexceptSpec, E_->ParameterPackSize), E(E_) {}
+
+ void printLeft(OutputStream &S) const override {
+ S += "noexcept(";
+ E->print(S);
+ S += ")";
+ }
+};
+
+class DynamicExceptionSpec : public Node {
+ NodeArray Types;
+public:
+ DynamicExceptionSpec(NodeArray Types_)
+ : Node(KDynamicExceptionSpec), Types(Types_) {
+ for (Node *T : Types)
+ ParameterPackSize = std::min(ParameterPackSize, T->ParameterPackSize);
+ }
+
+ void printLeft(OutputStream &S) const override {
+ S += "throw(";
+ Types.printWithComma(S);
+ S += ')';
}
};
@@ -2370,6 +2410,29 @@ StringView Db::parseBareSourceName() {
// <ref-qualifier> ::= O # && ref-qualifier
Node *Db::parseFunctionType() {
Qualifiers CVQuals = parseCVQualifiers();
+
+ Node *ExceptionSpec = nullptr;
+ if (consumeIf("Do")) {
+ ExceptionSpec = make<NameType>("noexcept");
+ } else if (consumeIf("DO")) {
+ Node *E = parseExpr();
+ if (E == nullptr || !consumeIf('E'))
+ return nullptr;
+ ExceptionSpec = make<NoexceptSpec>(E);
+ } else if (consumeIf("Dw")) {
+ size_t SpecsBegin = Names.size();
+ while (!consumeIf('E')) {
+ Node *T = parseType();
+ if (T == nullptr)
+ return nullptr;
+ Names.push_back(T);
+ }
+ ExceptionSpec =
+ make<DynamicExceptionSpec>(popTrailingNodeArray(SpecsBegin));
+ }
+
+ consumeIf("Dx"); // transaction safe
+
if (!consumeIf('F'))
return nullptr;
consumeIf('Y'); // extern "C"
@@ -2399,7 +2462,8 @@ Node *Db::parseFunctionType() {
}
NodeArray Params = popTrailingNodeArray(ParamsBegin);
- return make<FunctionType>(ReturnType, Params, CVQuals, ReferenceQualifier);
+ return make<FunctionType>(ReturnType, Params, CVQuals,
+ ReferenceQualifier, ExceptionSpec);
}
// extension:
@@ -2599,7 +2663,11 @@ Node *Db::parseType() {
if (look(AfterQuals) == 'r') ++AfterQuals;
if (look(AfterQuals) == 'V') ++AfterQuals;
if (look(AfterQuals) == 'K') ++AfterQuals;
- if (look(AfterQuals) == 'F') {
+
+ if (look(AfterQuals) == 'F' ||
+ (look(AfterQuals) == 'D' &&
+ (look(AfterQuals + 1) == 'o' || look(AfterQuals + 1) == 'O' ||
+ look(AfterQuals + 1) == 'w' || look(AfterQuals + 1) == 'x'))) {
Result = parseFunctionType();
break;
}
@@ -2761,6 +2829,14 @@ Node *Db::parseType() {
Result = make<ParameterPackExpansion>(Child);
break;
}
+ // Exception specifier on a function type.
+ case 'o':
+ case 'O':
+ case 'w':
+ // Transaction safe function type.
+ case 'x':
+ Result = parseFunctionType();
+ break;
}
break;
// ::= <function-type>
OpenPOWER on IntegriCloud