[libcxxabi] r325093 - [demangler] Support for exception specifications on function types.

Erik Pilkington via cfe-commits cfe-commits at lists.llvm.org
Tue Feb 13 17:08:20 PST 2018


Author: epilk
Date: Tue Feb 13 17:08:20 2018
New Revision: 325093

URL: http://llvm.org/viewvc/llvm-project?rev=325093&view=rev
Log:
[demangler] Support for exception specifications on function types.

Modified:
    libcxxabi/trunk/src/cxa_demangle.cpp
    libcxxabi/trunk/test/test_demangle.pass.cpp

Modified: libcxxabi/trunk/src/cxa_demangle.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/src/cxa_demangle.cpp?rev=325093&r1=325092&r2=325093&view=diff
==============================================================================
--- libcxxabi/trunk/src/cxa_demangle.cpp (original)
+++ libcxxabi/trunk/src/cxa_demangle.cpp Tue Feb 13 17:08:20 2018
@@ -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>

Modified: libcxxabi/trunk/test/test_demangle.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/test/test_demangle.pass.cpp?rev=325093&r1=325092&r2=325093&view=diff
==============================================================================
--- libcxxabi/trunk/test/test_demangle.pass.cpp (original)
+++ libcxxabi/trunk/test/test_demangle.pass.cpp Tue Feb 13 17:08:20 2018
@@ -29694,6 +29694,22 @@ const char* cases[][2] =
     // Inheriting constructors:
     {"_ZN1BCI21AEi", "B::B(int)"},
     {"_ZN1DCI21CIiEET_", "D::D(int)"},
+
+    // Exception specifiers:
+    {"_Z1bPDoFivE", "b(int (*)() noexcept)"},
+    {"_Z1fILb0EEvPDOT_EFivE", "void f<false>(int (*)() noexcept(false))"},
+    {"_Z1fILb1EEvPDOT_EFivE", "void f<true>(int (*)() noexcept(true))"},
+    {"_Z1gIJEEvPDwDpT_EFivE", "void g<>(int (*)() throw())"},
+    {"_Z1gIJfEEvPDwDpT_EFivE", "void g<float>(int (*)() throw(float))"},
+    {"_Z1hIJEEPDwDpT_iEFivEPDwiS1_EFivE", "int (*h<>(int (*)() throw(int)))() throw(int)"},
+    {"_Z1hIJfEEPDwDpT_iEFivEPDwiS1_EFivE", "int (*h<float>(int (*)() throw(int, float)))() throw(float, int)"},
+    {"_Z1iIJEEPDwiDpT_EFivEPS2_", "int (*i<>(int (*)() throw(int)))() throw(int)"},
+    {"_Z1iIJEEPDwiDpT_EFivES3_", "int (*i<>(int (*)() throw(int)))() throw(int)"},
+    {"_Z1iIJfEEPDwiDpT_EFivEPS2_", "int (*i<float>(int (*)() throw(int, float)))() throw(int, float)"},
+    {"_Z1iIJfEEPDwiDpT_EFivES3_", "int (*i<float>(int (*)() throw(int, float)))() throw(int, float)"},
+    {"_Z1pILb1EEiM1SKDOT_EFivRE", "int p<true>(int (S::*)() const & noexcept(true))"},
+    {"_Z1pIJicfEEiM1SVKDwDpT_EFivOE", "int p<int, char, float>(int (S::*)() const volatile && throw(int, char, float))"},
+    {"_Z1pM1SDoFivE", "p(int (S::*)() noexcept)"},
 };
 
 const unsigned N = sizeof(cases) / sizeof(cases[0]);




More information about the cfe-commits mailing list