diff options
author | Erik Pilkington <erik.pilkington@gmail.com> | 2018-02-14 01:08:20 +0000 |
---|---|---|
committer | Erik Pilkington <erik.pilkington@gmail.com> | 2018-02-14 01:08:20 +0000 |
commit | 0bae6d8c14028726e77738717a307b916e85d23d (patch) | |
tree | d97b3ab7a4cf46362fc56b8ddcd8f62b2d6bc597 /libcxxabi/src | |
parent | bb0e34558fff2d0beb24bd14b4b958c05af0e034 (diff) | |
download | bcm5719-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.cpp | 84 |
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> |