Merge 1839f48 for LLVM update to 339409

Change-Id: I6c070048b836fef72d3d13531dadebc68a775707
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1488737..0eeb4b3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -21,7 +21,7 @@
   project(libcxxabi CXX C)
 
   set(PACKAGE_NAME libcxxabi)
-  set(PACKAGE_VERSION 7.0.0svn)
+  set(PACKAGE_VERSION 8.0.0svn)
   set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}")
   set(PACKAGE_BUGREPORT "llvm-bugs@lists.llvm.org")
 
@@ -84,6 +84,20 @@
 option(LIBCXXABI_ENABLE_SHARED "Build libc++abi as a shared library." ON)
 option(LIBCXXABI_ENABLE_STATIC "Build libc++abi as a static library." ON)
 
+cmake_dependent_option(LIBCXXABI_INSTALL_STATIC_LIBRARY
+  "Install the static libc++abi library." ON
+  "LIBCXXABI_ENABLE_STATIC;LIBCXXABI_INSTALL_LIBRARY" OFF)
+cmake_dependent_option(LIBCXXABI_INSTALL_SHARED_LIBRARY
+  "Install the shared libc++abi library." ON
+  "LIBCXXABI_ENABLE_SHARED;LIBCXXABI_INSTALL_LIBRARY" OFF)
+
+cmake_dependent_option(LIBCXXABI_STATICALLY_LINK_UNWINDER_IN_STATIC_LIBRARY
+  "Statically link the LLVM unwinder to static library" ON
+  "LIBCXXABI_ENABLE_STATIC_UNWINDER;LIBCXXABI_ENABLE_STATIC" OFF)
+cmake_dependent_option(LIBCXXABI_STATICALLY_LINK_UNWINDER_IN_SHARED_LIBRARY
+  "Statically link the LLVM unwinder to shared library" ON
+  "LIBCXXABI_ENABLE_STATIC_UNWINDER;LIBCXXABI_ENABLE_SHARED" OFF)
+
 option(LIBCXXABI_BAREMETAL "Build libc++abi for baremetal targets." OFF)
 # The default terminate handler attempts to demangle uncaught exceptions, which
 # causes extra I/O and demangling code to be pulled in.
@@ -110,12 +124,13 @@
 
 find_path(
   LIBCXXABI_LIBCXX_INCLUDES
-  vector
+  __config
   PATHS ${LIBCXXABI_LIBCXX_INCLUDES}
         ${LIBCXXABI_LIBCXX_PATH}/include
         ${CMAKE_BINARY_DIR}/${LIBCXXABI_LIBCXX_INCLUDES}
         ${LIBCXXABI_LIBCXX_INCLUDE_DIRS}
         ${LLVM_INCLUDE_DIR}/c++/v1
+  NO_DEFAULT_PATH
   NO_CMAKE_FIND_ROOT_PATH
   )
 
@@ -154,19 +169,22 @@
 set(LIBCXXABI_COMPILER    ${CMAKE_CXX_COMPILER})
 set(LIBCXXABI_SOURCE_DIR  ${CMAKE_CURRENT_SOURCE_DIR})
 set(LIBCXXABI_BINARY_DIR  ${CMAKE_CURRENT_BINARY_DIR})
-if (LLVM_LIBRARY_OUTPUT_INTDIR)
+
+string(REGEX MATCH "[0-9]+\\.[0-9]+(\\.[0-9]+)?" CLANG_VERSION
+       ${PACKAGE_VERSION})
+
+if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE)
+  set(DEFAULT_INSTALL_PREFIX lib${LLVM_LIBDIR_SUFFIX}/clang/${CLANG_VERSION}/${LLVM_DEFAULT_TARGET_TRIPLE}/)
+  set(LIBCXXABI_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/clang/${CLANG_VERSION}/${LLVM_DEFAULT_TARGET_TRIPLE}/lib${LIBCXXABI_LIBDIR_SUFFIX})
+elseif(LLVM_LIBRARY_OUTPUT_INTDIR)
   set(LIBCXXABI_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR})
 else()
   set(LIBCXXABI_LIBRARY_DIR ${CMAKE_BINARY_DIR}/lib${LIBCXXABI_LIBDIR_SUFFIX})
 endif()
 
-set(LIBCXXABI_INSTALL_PREFIX "" CACHE STRING
+set(LIBCXXABI_INSTALL_PREFIX ${DEFAULT_INSTALL_PREFIX} CACHE STRING
     "Define libc++abi destination prefix.")
 
-if (NOT LIBCXXABI_INSTALL_PREFIX MATCHES "^$|.*/")
-  message(FATAL_ERROR "LIBCXXABI_INSTALL_PREFIX has to end with \"/\".")
-endif()
-
 set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${LIBCXXABI_LIBRARY_DIR})
 set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${LIBCXXABI_LIBRARY_DIR})
 set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${LIBCXXABI_LIBRARY_DIR})
diff --git a/LICENSE.TXT b/LICENSE.TXT
index f333f1f..f1f163f 100644
--- a/LICENSE.TXT
+++ b/LICENSE.TXT
@@ -14,7 +14,7 @@
 University of Illinois/NCSA
 Open Source License
 
-Copyright (c) 2009-2017 by the contributors listed in CREDITS.TXT
+Copyright (c) 2009-2018 by the contributors listed in CREDITS.TXT
 
 All rights reserved.
 
diff --git a/cmake/Modules/HandleCompilerRT.cmake b/cmake/Modules/HandleCompilerRT.cmake
index 395c21a..945de58 100644
--- a/cmake/Modules/HandleCompilerRT.cmake
+++ b/cmake/Modules/HandleCompilerRT.cmake
@@ -14,6 +14,7 @@
       OUTPUT_VARIABLE LIBRARY_FILE
   )
   string(STRIP "${LIBRARY_FILE}" LIBRARY_FILE)
+  file(TO_CMAKE_PATH "${LIBRARY_FILE}" LIBRARY_FILE)
   string(REPLACE "builtins" "${name}" LIBRARY_FILE "${LIBRARY_FILE}")
   if (NOT HAD_ERROR AND EXISTS "${LIBRARY_FILE}")
     message(STATUS "Found compiler-rt library: ${LIBRARY_FILE}")
@@ -37,6 +38,7 @@
         OUTPUT_VARIABLE LIBRARY_DIR
     )
     string(STRIP "${LIBRARY_DIR}" LIBRARY_DIR)
+    file(TO_CMAKE_PATH "${LIBRARY_DIR}" LIBRARY_DIR)
     set(LIBRARY_DIR "${LIBRARY_DIR}/darwin")
   else()
     set(CLANG_COMMAND ${CMAKE_CXX_COMPILER} ${LIBCXXABI_COMPILE_FLAGS}
@@ -47,6 +49,7 @@
         OUTPUT_VARIABLE LIBRARY_FILE
     )
     string(STRIP "${LIBRARY_FILE}" LIBRARY_FILE)
+    file(TO_CMAKE_PATH "${LIBRARY_FILE}" LIBRARY_FILE)
     get_filename_component(LIBRARY_DIR "${LIBRARY_FILE}" DIRECTORY)
   endif()
   if (NOT HAD_ERROR AND EXISTS "${LIBRARY_DIR}")
diff --git a/cmake/Modules/HandleOutOfTreeLLVM.cmake b/cmake/Modules/HandleOutOfTreeLLVM.cmake
index ed0b527..e50d026 100644
--- a/cmake/Modules/HandleOutOfTreeLLVM.cmake
+++ b/cmake/Modules/HandleOutOfTreeLLVM.cmake
@@ -46,10 +46,11 @@
       OUTPUT_VARIABLE CONFIG_OUTPUT
       ERROR_QUIET)
     if(NOT HAD_ERROR)
-      string(STRIP "${CONFIG_OUTPUT}" LLVM_CMAKE_PATH)
+      string(STRIP "${CONFIG_OUTPUT}" LLVM_CMAKE_PATH_FROM_LLVM_CONFIG)
+      file(TO_CMAKE_PATH "${LLVM_CMAKE_PATH_FROM_LLVM_CONFIG}" LLVM_CMAKE_PATH)
     else()
-      set(LLVM_CMAKE_PATH
-          "${LLVM_BINARY_DIR}/lib${LLVM_LIBDIR_SUFFIX}/cmake/llvm")
+      file(TO_CMAKE_PATH "${LLVM_BINARY_DIR}" LLVM_BINARY_DIR_CMAKE_STYLE)
+      set(LLVM_CMAKE_PATH "${LLVM_BINARY_DIR_CMAKE_STYLE}/lib${LLVM_LIBDIR_SUFFIX}/cmake/llvm")
     endif()
   else()
     set(LLVM_FOUND OFF)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 5a929cf..776c512 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -61,12 +61,19 @@
   # Prefer using the in-tree version of libunwind, either shared or static. If
   # none are found fall back to using -lunwind.
   # FIXME: Is it correct to prefer the static version of libunwind?
-  if (NOT LIBCXXABI_ENABLE_STATIC_UNWINDER AND (TARGET unwind_shared OR HAVE_LIBUNWIND))
-    list(APPEND LIBCXXABI_LIBRARIES unwind_shared)
-  elseif (LIBCXXABI_ENABLE_STATIC_UNWINDER AND (TARGET unwind_static OR HAVE_LIBUNWIND))
-    list(APPEND LIBCXXABI_LIBRARIES unwind_static)
+  if (NOT LIBCXXABI_STATICALLY_LINK_UNWINDER_IN_SHARED_LIBRARY AND (TARGET unwind_shared OR HAVE_LIBUNWIND))
+    list(APPEND LIBCXXABI_SHARED_LIBRARIES unwind_shared)
+  elseif (LIBCXXABI_STATICALLY_LINK_UNWINDER_IN_SHARED_LIBRARY AND (TARGET unwind_static OR HAVE_LIBUNWIND))
+    list(APPEND LIBCXXABI_SHARED_LIBRARIES unwind_static)
   else()
-    list(APPEND LIBCXXABI_LIBRARIES unwind)
+    list(APPEND LIBCXXABI_SHARED_LIBRARIES unwind)
+  endif()
+  if (NOT LIBCXXABI_STATICALLY_LINK_UNWINDER_IN_STATIC_LIBRARY AND (TARGET unwind_shared OR HAVE_LIBUNWIND))
+    list(APPEND LIBCXXABI_STATIC_LIBRARIES unwind_shared)
+  elseif (LIBCXXABI_STATICALLY_LINK_UNWINDER_IN_STATIC_LIBRARY AND (TARGET unwind_static OR HAVE_LIBUNWIND))
+      # We handle this by directly merging libunwind objects into libc++abi.
+  else()
+    list(APPEND LIBCXXABI_STATIC_LIBRARIES unwind)
   endif()
 else()
   add_library_flags_if(LIBCXXABI_HAS_GCC_S_LIB gcc_s)
@@ -122,15 +129,13 @@
                         POSITION_INDEPENDENT_CODE
                           ON)
 
-set(LIBCXXABI_TARGETS)
-
 # Build the shared library.
 if (LIBCXXABI_ENABLE_SHARED)
   add_library(cxxabi_shared SHARED $<TARGET_OBJECTS:cxxabi_objects>)
   if(COMMAND llvm_setup_rpath)
     llvm_setup_rpath(cxxabi_shared)
   endif()
-  target_link_libraries(cxxabi_shared ${LIBCXXABI_LIBRARIES})
+  target_link_libraries(cxxabi_shared ${LIBCXXABI_LIBRARIES} ${LIBCXXABI_SHARED_LIBRARIES})
   set_target_properties(cxxabi_shared
                         PROPERTIES
                           CXX_EXTENSIONS
@@ -149,19 +154,22 @@
                             "1"
                           VERSION
                             "1.0")
-  list(APPEND LIBCXXABI_TARGETS "cxxabi_shared")
+  list(APPEND LIBCXXABI_BUILD_TARGETS "cxxabi_shared")
+  if (LIBCXXABI_INSTALL_SHARED_LIBRARY)
+    list(APPEND LIBCXXABI_INSTALL_TARGETS "cxxabi_shared")
+  endif()
 endif()
 
 # Build the static library.
 if (LIBCXXABI_ENABLE_STATIC)
   set(cxxabi_static_sources $<TARGET_OBJECTS:cxxabi_objects>)
-  if (LIBCXXABI_USE_LLVM_UNWINDER AND LIBCXXABI_ENABLE_STATIC_UNWINDER)
+  if (LIBCXXABI_USE_LLVM_UNWINDER AND LIBCXXABI_STATICALLY_LINK_UNWINDER_IN_STATIC_LIBRARY)
     if (TARGET unwind_static OR HAVE_LIBUNWIND)
       list(APPEND cxxabi_static_sources $<TARGET_OBJECTS:unwind_objects>)
     endif()
   endif()
   add_library(cxxabi_static STATIC ${cxxabi_static_sources})
-  target_link_libraries(cxxabi_static ${LIBCXXABI_LIBRARIES})
+  target_link_libraries(cxxabi_static ${LIBCXXABI_LIBRARIES} ${LIBCXXABI_STATIC_LIBRARIES})
   set_target_properties(cxxabi_static
                         PROPERTIES
                           CXX_EXTENSIONS
@@ -176,14 +184,17 @@
                             "c++abi"
                           POSITION_INDEPENDENT_CODE
                             ON)
-  list(APPEND LIBCXXABI_TARGETS "cxxabi_static")
+  list(APPEND LIBCXXABI_BUILD_TARGETS "cxxabi_static")
+  if (LIBCXXABI_INSTALL_STATIC_LIBRARY)
+    list(APPEND LIBCXXABI_INSTALL_TARGETS "cxxabi_static")
+  endif()
 endif()
 
 # Add a meta-target for both libraries.
-add_custom_target(cxxabi DEPENDS ${LIBCXXABI_TARGETS})
+add_custom_target(cxxabi DEPENDS ${LIBCXXABI_BUILD_TARGETS})
 
 if (LIBCXXABI_INSTALL_LIBRARY)
-  install(TARGETS ${LIBCXXABI_TARGETS}
+  install(TARGETS ${LIBCXXABI_INSTALL_TARGETS}
     LIBRARY DESTINATION ${LIBCXXABI_INSTALL_PREFIX}lib${LIBCXXABI_LIBDIR_SUFFIX} COMPONENT cxxabi
     ARCHIVE DESTINATION ${LIBCXXABI_INSTALL_PREFIX}lib${LIBCXXABI_LIBDIR_SUFFIX} COMPONENT cxxabi
     )
diff --git a/src/cxa_demangle.cpp b/src/cxa_demangle.cpp
index d70ffdf..3a7ee06 100644
--- a/src/cxa_demangle.cpp
+++ b/src/cxa_demangle.cpp
@@ -15,150 +15,26 @@
 
 #include "__cxxabi_config.h"
 
-#include <vector>
-#include <algorithm>
-#include <numeric>
+#include "demangle/Compiler.h"
+#include "demangle/StringView.h"
+#include "demangle/Utility.h"
+
 #include <cassert>
+#include <cctype>
 #include <cstdio>
 #include <cstdlib>
 #include <cstring>
-#include <cctype>
-
-#ifdef _MSC_VER
-// snprintf is implemented in VS 2015
-#if _MSC_VER < 1900
-#define snprintf _snprintf_s
-#endif
-#endif
-
-#ifndef NDEBUG
-#if __has_attribute(noinline) && __has_attribute(used)
-#define DUMP_METHOD __attribute__((noinline,used))
-#else
-#define DUMP_METHOD
-#endif
-#endif
+#include <numeric>
+#include <utility>
+#include <vector>
 
 namespace {
-
-class StringView {
-  const char *First;
-  const char *Last;
-
-public:
-  template <size_t N>
-  StringView(const char (&Str)[N]) : First(Str), Last(Str + N - 1) {}
-  StringView(const char *First_, const char *Last_) : First(First_), Last(Last_) {}
-  StringView() : First(nullptr), Last(nullptr) {}
-
-  StringView substr(size_t From, size_t To) {
-    if (To >= size())
-      To = size() - 1;
-    if (From >= size())
-      From = size() - 1;
-    return StringView(First + From, First + To);
-  }
-
-  StringView dropFront(size_t N) const {
-    if (N >= size())
-      N = size() - 1;
-    return StringView(First + N, Last);
-  }
-
-  bool startsWith(StringView Str) const {
-    if (Str.size() > size())
-      return false;
-    return std::equal(Str.begin(), Str.end(), begin());
-  }
-
-  const char &operator[](size_t Idx) const { return *(begin() + Idx); }
-
-  const char *begin() const { return First; }
-  const char *end() const { return Last; }
-  size_t size() const { return static_cast<size_t>(Last - First); }
-  bool empty() const { return First == Last; }
-};
-
-bool operator==(const StringView &LHS, const StringView &RHS) {
-  return LHS.size() == RHS.size() &&
-         std::equal(LHS.begin(), LHS.end(), RHS.begin());
-}
-
-// Stream that AST nodes write their string representation into after the AST
-// has been parsed.
-class OutputStream {
-  char *Buffer;
-  size_t CurrentPosition;
-  size_t BufferCapacity;
-
-  // Ensure there is at least n more positions in buffer.
-  void grow(size_t N) {
-    if (N + CurrentPosition >= BufferCapacity) {
-      BufferCapacity *= 2;
-      if (BufferCapacity < N + CurrentPosition)
-        BufferCapacity = N + CurrentPosition;
-      Buffer = static_cast<char *>(std::realloc(Buffer, BufferCapacity));
-    }
-  }
-
-public:
-  OutputStream(char *StartBuf, size_t Size)
-      : Buffer(StartBuf), CurrentPosition(0), BufferCapacity(Size) {}
-  OutputStream() = default;
-  void reset(char *Buffer_, size_t BufferCapacity_) {
-    CurrentPosition = 0;
-    Buffer = Buffer_;
-    BufferCapacity = BufferCapacity_;
-  }
-
-  /// 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();
-    if (Size == 0)
-      return *this;
-    grow(Size);
-    memmove(Buffer + CurrentPosition, R.begin(), Size);
-    CurrentPosition += Size;
-    return *this;
-  }
-
-  OutputStream &operator+=(char C) {
-    grow(1);
-    Buffer[CurrentPosition++] = C;
-    return *this;
-  }
-
-  size_t getCurrentPosition() const { return CurrentPosition; }
-  void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; }
-
-  char back() const {
-    return CurrentPosition ? Buffer[CurrentPosition - 1] : '\0';
-  }
-
-  bool empty() const { return CurrentPosition == 0; }
-
-  char *getBuffer() { return Buffer; }
-  char *getBufferEnd() { return Buffer + CurrentPosition - 1; }
-  size_t getBufferCapacity() { return BufferCapacity; }
-};
-
-template <class T>
-class SwapAndRestore {
-  T &Restore;
-  T OriginalValue;
-public:
-  SwapAndRestore(T& Restore_, T NewVal)
-      : Restore(Restore_), OriginalValue(Restore) {
-    Restore = std::move(NewVal);
-  }
-  ~SwapAndRestore() { Restore = std::move(OriginalValue); }
-
-  SwapAndRestore(const SwapAndRestore &) = delete;
-  SwapAndRestore &operator=(const SwapAndRestore &) = delete;
+enum : int {
+  demangle_unknown_error = -4,
+  demangle_invalid_args = -3,
+  demangle_invalid_mangled_name = -2,
+  demangle_memory_alloc_failure = -1,
+  demangle_success = 0,
 };
 
 // Base class of all AST nodes. The AST is built by the parser, then is
@@ -178,8 +54,7 @@
     KEnableIfAttr,
     KObjCProtoName,
     KPointerType,
-    KLValueReferenceType,
-    KRValueReferenceType,
+    KReferenceType,
     KPointerToMemberType,
     KArrayType,
     KFunctionType,
@@ -260,6 +135,12 @@
   virtual bool hasArraySlow(OutputStream &) const { return false; }
   virtual bool hasFunctionSlow(OutputStream &) const { return false; }
 
+  // Dig through "glue" nodes like ParameterPack and ForwardTemplateReference to
+  // get at a node that actually represents some concrete syntax.
+  virtual const Node *getSyntaxNode(OutputStream &) const {
+    return this;
+  }
+
   void print(OutputStream &S) const {
     printLeft(S);
     if (RHSComponentCache != Cache::No)
@@ -272,7 +153,7 @@
   // Print the "right". This distinction is necessary to represent C++ types
   // that appear on the RHS of their subtype, such as arrays or functions.
   // Since most types don't have such a component, provide a default
-  // implemenation.
+  // implementation.
   virtual void printRight(OutputStream &) const {}
 
   virtual StringView getBaseName() const { return StringView(); }
@@ -570,60 +451,64 @@
   }
 };
 
-class LValueReferenceType final : public Node {
-  const Node *Pointee;
-
-public:
-  LValueReferenceType(Node *Pointee_)
-      : Node(KLValueReferenceType, Pointee_->RHSComponentCache),
-        Pointee(Pointee_) {}
-
-  bool hasRHSComponentSlow(OutputStream &S) const override {
-    return Pointee->hasRHSComponent(S);
-  }
-
-  void printLeft(OutputStream &s) const override {
-    Pointee->printLeft(s);
-    if (Pointee->hasArray(s))
-      s += " ";
-    if (Pointee->hasArray(s) || Pointee->hasFunction(s))
-      s += "(&";
-    else
-      s += "&";
-  }
-  void printRight(OutputStream &s) const override {
-    if (Pointee->hasArray(s) || Pointee->hasFunction(s))
-      s += ")";
-    Pointee->printRight(s);
-  }
+enum class ReferenceKind {
+  LValue,
+  RValue,
 };
 
-class RValueReferenceType final : public Node {
+// Represents either a LValue or an RValue reference type.
+class ReferenceType : public Node {
   const Node *Pointee;
+  ReferenceKind RK;
+
+  mutable bool Printing = false;
+
+  // Dig through any refs to refs, collapsing the ReferenceTypes as we go. The
+  // rule here is rvalue ref to rvalue ref collapses to a rvalue ref, and any
+  // other combination collapses to a lvalue ref.
+  std::pair<ReferenceKind, const Node *> collapse(OutputStream &S) const {
+    auto SoFar = std::make_pair(RK, Pointee);
+    for (;;) {
+      const Node *SN = SoFar.second->getSyntaxNode(S);
+      if (SN->getKind() != KReferenceType)
+        break;
+      auto *RT = static_cast<const ReferenceType *>(SN);
+      SoFar.second = RT->Pointee;
+      SoFar.first = std::min(SoFar.first, RT->RK);
+    }
+    return SoFar;
+  }
 
 public:
-  RValueReferenceType(Node *Pointee_)
-      : Node(KRValueReferenceType, Pointee_->RHSComponentCache),
-        Pointee(Pointee_) {}
+  ReferenceType(Node *Pointee_, ReferenceKind RK_)
+      : Node(KReferenceType, Pointee_->RHSComponentCache),
+        Pointee(Pointee_), RK(RK_) {}
 
   bool hasRHSComponentSlow(OutputStream &S) const override {
     return Pointee->hasRHSComponent(S);
   }
 
   void printLeft(OutputStream &s) const override {
-    Pointee->printLeft(s);
-    if (Pointee->hasArray(s))
+    if (Printing)
+      return;
+    SwapAndRestore<bool> SavePrinting(Printing, true);
+    std::pair<ReferenceKind, const Node *> Collapsed = collapse(s);
+    Collapsed.second->printLeft(s);
+    if (Collapsed.second->hasArray(s))
       s += " ";
-    if (Pointee->hasArray(s) || Pointee->hasFunction(s))
-      s += "(&&";
-    else
-      s += "&&";
-  }
+    if (Collapsed.second->hasArray(s) || Collapsed.second->hasFunction(s))
+      s += "(";
 
+    s += (Collapsed.first == ReferenceKind::LValue ? "&" : "&&");
+  }
   void printRight(OutputStream &s) const override {
-    if (Pointee->hasArray(s) || Pointee->hasFunction(s))
+    if (Printing)
+      return;
+    SwapAndRestore<bool> SavePrinting(Printing, true);
+    std::pair<ReferenceKind, const Node *> Collapsed = collapse(s);
+    if (Collapsed.second->hasArray(s) || Collapsed.second->hasFunction(s))
       s += ")";
-    Pointee->printRight(s);
+    Collapsed.second->printRight(s);
   }
 };
 
@@ -748,7 +633,7 @@
   bool hasRHSComponentSlow(OutputStream &) const override { return true; }
   bool hasFunctionSlow(OutputStream &) const override { return true; }
 
-  // Handle C++'s ... quirky decl grammer by using the left & right
+  // Handle C++'s ... quirky decl grammar by using the left & right
   // distinction. Consider:
   //   int (*f(float))(char) {}
   // f is a function that takes a float and returns a pointer to a function
@@ -1042,6 +927,11 @@
     size_t Idx = S.CurrentPackIndex;
     return Idx < Data.size() && Data[Idx]->hasFunction(S);
   }
+  const Node *getSyntaxNode(OutputStream &S) const override {
+    initializePackExpansion(S);
+    size_t Idx = S.CurrentPackIndex;
+    return Idx < Data.size() ? Data[Idx]->getSyntaxNode(S) : this;
+  }
 
   void printLeft(OutputStream &S) const override {
     initializePackExpansion(S);
@@ -1057,7 +947,7 @@
   }
 };
 
-/// A variadic template argument. This node represents an occurance of
+/// A variadic template argument. This node represents an occurrence of
 /// J<something>E in some <template-args>. It isn't itself unexpanded, unless
 /// one of it's Elements is. The parser inserts a ParameterPack into the
 /// TemplateParams table if the <template-args> this pack belongs to apply to an
@@ -1169,6 +1059,12 @@
     SwapAndRestore<bool> SavePrinting(Printing, true);
     return Ref->hasFunction(S);
   }
+  const Node *getSyntaxNode(OutputStream &S) const override {
+    if (Printing)
+      return this;
+    SwapAndRestore<bool> SavePrinting(Printing, true);
+    return Ref->getSyntaxNode(S);
+  }
 
   void printLeft(OutputStream &S) const override {
     if (Printing)
@@ -1890,17 +1786,21 @@
   static constexpr size_t AllocSize = 4096;
   static constexpr size_t UsableAllocSize = AllocSize - sizeof(BlockMeta);
 
-  alignas(16) char InitialBuffer[AllocSize];
+  alignas(long double) char InitialBuffer[AllocSize];
   BlockMeta* BlockList = nullptr;
 
   void grow() {
-    char* NewMeta = new char[AllocSize];
+    char* NewMeta = static_cast<char *>(std::malloc(AllocSize));
+    if (NewMeta == nullptr)
+      std::terminate();
     BlockList = new (NewMeta) BlockMeta{BlockList, 0};
   }
 
   void* allocateMassive(size_t NBytes) {
     NBytes += sizeof(BlockMeta);
-    BlockMeta* NewMeta = reinterpret_cast<BlockMeta*>(new char[NBytes]);
+    BlockMeta* NewMeta = reinterpret_cast<BlockMeta*>(std::malloc(NBytes));
+    if (NewMeta == nullptr)
+      std::terminate();
     BlockList->Next = new (NewMeta) BlockMeta{BlockList->Next, 0};
     return static_cast<void*>(NewMeta + 1);
   }
@@ -1926,7 +1826,7 @@
       BlockMeta* Tmp = BlockList;
       BlockList = BlockList->Next;
       if (reinterpret_cast<char*>(Tmp) != InitialBuffer)
-        delete[] reinterpret_cast<char*>(Tmp);
+        std::free(Tmp);
     }
     BlockList = new (InitialBuffer) BlockMeta{nullptr, 0};
   }
@@ -1956,10 +1856,15 @@
     size_t S = size();
     if (isInline()) {
       auto* Tmp = static_cast<T*>(std::malloc(NewCap * sizeof(T)));
+      if (Tmp == nullptr)
+        std::terminate();
       std::copy(First, Last, Tmp);
       First = Tmp;
-    } else
+    } else {
       First = static_cast<T*>(std::realloc(First, NewCap * sizeof(T)));
+      if (First == nullptr)
+        std::terminate();
+    }
     Last = First + S;
     Cap = First + NewCap;
   }
@@ -2053,7 +1958,7 @@
   const char *Last;
 
   // Name stack, this is used by the parser to hold temporary names that were
-  // parsed. The parser colapses multiple names into new nodes to construct
+  // parsed. The parser collapses multiple names into new nodes to construct
   // the AST. Once the parser is finished, names.size() == 1.
   PODSmallVector<Node *, 32> Names;
 
@@ -2927,7 +2832,7 @@
 // <unresolved-name>
 //  extension        ::= srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
 //                   ::= [gs] <base-unresolved-name>                     # x or (with "gs") ::x
-//                   ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>  
+//                   ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
 //                                                                       # A::x, N::y, A<T>::z; "gs" means leading "::"
 //                   ::= sr <unresolved-type> <base-unresolved-name>     # T::x / decltype(p)::x
 //  extension        ::= sr <unresolved-type> <template-args> <base-unresolved-name>
@@ -2977,7 +2882,7 @@
     return SoFar;
   }
 
-  // [gs] sr <unresolved-qualifier-level>+ E   <base-unresolved-name>  
+  // [gs] sr <unresolved-qualifier-level>+ E   <base-unresolved-name>
   if (std::isdigit(look())) {
     do {
       Node *Qual = parseSimpleId();
@@ -3558,7 +3463,7 @@
     Node *Ref = parseType();
     if (Ref == nullptr)
       return nullptr;
-    Result = make<LValueReferenceType>(Ref);
+    Result = make<ReferenceType>(Ref, ReferenceKind::LValue);
     break;
   }
   //             ::= O <type>        # r-value reference (C++11)
@@ -3567,7 +3472,7 @@
     Node *Ref = parseType();
     if (Ref == nullptr)
       return nullptr;
-    Result = make<RValueReferenceType>(Ref);
+    Result = make<ReferenceType>(Ref, ReferenceKind::RValue);
     break;
   }
   //             ::= C <type>        # complex pair (C99)
@@ -5030,6 +4935,8 @@
     bool RequireNumber = consumeIf('_');
     if (parseNumber().empty() && RequireNumber)
       return nullptr;
+    if (look() == '.')
+      First = Last;
     if (numLeft() != 0)
       return nullptr;
     return make<SpecialName>("invocation function for block in ", Encoding);
@@ -5058,33 +4965,25 @@
 
 }  // unnamed namespace
 
-enum {
-  unknown_error = -4,
-  invalid_args = -3,
-  invalid_mangled_name = -2,
-  memory_alloc_failure = -1,
-  success = 0,
-};
-
 namespace __cxxabiv1 {
 extern "C" _LIBCXXABI_FUNC_VIS char *
 __cxa_demangle(const char *MangledName, char *Buf, size_t *N, int *Status) {
   if (MangledName == nullptr || (Buf != nullptr && N == nullptr)) {
     if (Status)
-      *Status = invalid_args;
+      *Status = demangle_invalid_args;
     return nullptr;
   }
 
-  int InternalStatus = success;
+  int InternalStatus = demangle_success;
   Db Parser(MangledName, MangledName + std::strlen(MangledName));
   OutputStream S;
 
   Node *AST = Parser.parse();
 
   if (AST == nullptr)
-    InternalStatus = invalid_mangled_name;
+    InternalStatus = demangle_invalid_mangled_name;
   else if (initializeOutputStream(Buf, N, S, 1024))
-    InternalStatus = memory_alloc_failure;
+    InternalStatus = demangle_memory_alloc_failure;
   else {
     assert(Parser.ForwardTemplateRefs.empty());
     AST->print(S);
@@ -5096,6 +4995,6 @@
 
   if (Status)
     *Status = InternalStatus;
-  return InternalStatus == success ? Buf : nullptr;
+  return InternalStatus == demangle_success ? Buf : nullptr;
 }
 }  // __cxxabiv1
diff --git a/src/cxa_personality.cpp b/src/cxa_personality.cpp
index 7f857fa..6759d8a 100644
--- a/src/cxa_personality.cpp
+++ b/src/cxa_personality.cpp
@@ -23,6 +23,16 @@
 #include "private_typeinfo.h"
 #include "unwind.h"
 
+#if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
+#include <windows.h>
+#include <winnt.h>
+
+extern "C" EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD,
+                                                       void *, PCONTEXT,
+                                                       PDISPATCHER_CONTEXT,
+                                                       _Unwind_Personality_Fn);
+#endif
+
 /*
     Exception Header Layout:
 
@@ -934,12 +944,16 @@
 */
 
 #if !defined(_LIBCXXABI_ARM_EHABI)
+#if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
+static _Unwind_Reason_Code __gxx_personality_imp
+#else
 _LIBCXXABI_FUNC_VIS _Unwind_Reason_Code
 #ifdef __USING_SJLJ_EXCEPTIONS__
 __gxx_personality_sj0
 #else
 __gxx_personality_v0
 #endif
+#endif
                     (int version, _Unwind_Action actions, uint64_t exceptionClass,
                      _Unwind_Exception* unwind_exception, _Unwind_Context* context)
 {
@@ -1022,6 +1036,17 @@
     // We were called improperly: neither a phase 1 or phase 2 search
     return _URC_FATAL_PHASE1_ERROR;
 }
+
+#if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
+extern "C" EXCEPTION_DISPOSITION
+__gxx_personality_seh0(PEXCEPTION_RECORD ms_exc, void *this_frame,
+                       PCONTEXT ms_orig_context, PDISPATCHER_CONTEXT ms_disp)
+{
+  return _GCC_specific_handler(ms_exc, this_frame, ms_orig_context, ms_disp,
+                               __gxx_personality_imp);
+}
+#endif
+
 #else
 
 extern "C" _Unwind_Reason_Code __gnu_unwind_frame(_Unwind_Exception*,
diff --git a/src/demangle/Compiler.h b/src/demangle/Compiler.h
new file mode 100644
index 0000000..e5f3c72
--- /dev/null
+++ b/src/demangle/Compiler.h
@@ -0,0 +1,34 @@
+//===--- Compiler.h ---------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+// This file is contains a subset of macros copied from
+// llvm/lib/Demangle/Compiler.h.
+//===----------------------------------------------------------------------===//
+
+#ifndef LIBCXX_DEMANGLE_COMPILER_H
+#define LIBCXX_DEMANGLE_COMPILER_H
+
+#ifdef _MSC_VER
+// snprintf is implemented in VS 2015
+#if _MSC_VER < 1900
+#define snprintf _snprintf_s
+#endif
+#endif
+
+#ifndef __has_attribute
+#define __has_attribute(x) 0
+#endif
+
+#ifndef NDEBUG
+#if __has_attribute(noinline) && __has_attribute(used)
+#define DUMP_METHOD __attribute__((noinline, used))
+#else
+#define DUMP_METHOD
+#endif
+#endif
+
+#endif
diff --git a/src/demangle/StringView.h b/src/demangle/StringView.h
new file mode 100644
index 0000000..986f2de
--- /dev/null
+++ b/src/demangle/StringView.h
@@ -0,0 +1,98 @@
+//===--- StringView.h -------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//
+// This file is copied from llvm/lib/Demangle/StringView.h.
+//===----------------------------------------------------------------------===//
+
+#ifndef LIBCXX_DEMANGLE_STRINGVIEW_H
+#define LIBCXX_DEMANGLE_STRINGVIEW_H
+
+#include <algorithm>
+#include <cassert>
+#include <cstring>
+
+namespace {
+class StringView {
+  const char *First;
+  const char *Last;
+
+public:
+  template <size_t N>
+  StringView(const char (&Str)[N]) : First(Str), Last(Str + N - 1) {}
+  StringView(const char *First_, const char *Last_)
+      : First(First_), Last(Last_) {}
+  StringView(const char *First_, size_t Len)
+      : First(First_), Last(First_ + Len) {}
+  StringView(const char *Str) : First(Str), Last(Str + std::strlen(Str)) {}
+  StringView() : First(nullptr), Last(nullptr) {}
+
+  StringView substr(size_t From) const {
+    return StringView(begin() + From, size() - From);
+  }
+
+  StringView substr(size_t From, size_t To) const {
+    if (To >= size())
+      To = size() - 1;
+    if (From >= size())
+      From = size() - 1;
+    return StringView(First + From, First + To);
+  }
+
+  StringView dropFront(size_t N = 1) const {
+    if (N >= size())
+      N = size() - 1;
+    return StringView(First + N, Last);
+  }
+
+  char front() const {
+    assert(!empty());
+    return *begin();
+  }
+
+  char popFront() {
+    assert(!empty());
+    return *First++;
+  }
+
+  bool consumeFront(char C) {
+    if (!startsWith(C))
+      return false;
+    *this = dropFront(1);
+    return true;
+  }
+
+  bool consumeFront(StringView S) {
+    if (!startsWith(S))
+      return false;
+    *this = dropFront(S.size());
+    return true;
+  }
+
+  bool startsWith(char C) const { return !empty() && *begin() == C; }
+
+  bool startsWith(StringView Str) const {
+    if (Str.size() > size())
+      return false;
+    return std::equal(Str.begin(), Str.end(), begin());
+  }
+
+  const char &operator[](size_t Idx) const { return *(begin() + Idx); }
+
+  const char *begin() const { return First; }
+  const char *end() const { return Last; }
+  size_t size() const { return static_cast<size_t>(Last - First); }
+  bool empty() const { return First == Last; }
+};
+
+inline bool operator==(const StringView &LHS, const StringView &RHS) {
+  return LHS.size() == RHS.size() &&
+         std::equal(LHS.begin(), LHS.end(), RHS.begin());
+}
+} // namespace
+
+#endif
diff --git a/src/demangle/Utility.h b/src/demangle/Utility.h
new file mode 100644
index 0000000..3909243
--- /dev/null
+++ b/src/demangle/Utility.h
@@ -0,0 +1,191 @@
+//===--- Utility.h ----------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//
+// This file is copied from llvm/lib/Demangle/Utility.h.
+//===----------------------------------------------------------------------===//
+
+#ifndef LIBCXX_DEMANGLE_UTILITY_H
+#define LIBCXX_DEMANGLE_UTILITY_H
+
+#include "StringView.h"
+
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+#include <iterator>
+#include <limits>
+
+namespace {
+// Stream that AST nodes write their string representation into after the AST
+// has been parsed.
+class OutputStream {
+  char *Buffer;
+  size_t CurrentPosition;
+  size_t BufferCapacity;
+
+  // Ensure there is at least n more positions in buffer.
+  void grow(size_t N) {
+    if (N + CurrentPosition >= BufferCapacity) {
+      BufferCapacity *= 2;
+      if (BufferCapacity < N + CurrentPosition)
+        BufferCapacity = N + CurrentPosition;
+      Buffer = static_cast<char *>(std::realloc(Buffer, BufferCapacity));
+      if (Buffer == nullptr)
+        std::terminate();
+    }
+  }
+
+  void writeUnsigned(uint64_t N, bool isNeg = false) {
+    // Handle special case...
+    if (N == 0) {
+      *this << '0';
+      return;
+    }
+
+    char Temp[21];
+    char *TempPtr = std::end(Temp);
+
+    while (N) {
+      *--TempPtr = '0' + char(N % 10);
+      N /= 10;
+    }
+
+    // Add negative sign...
+    if (isNeg)
+      *--TempPtr = '-';
+    this->operator<<(StringView(TempPtr, std::end(Temp)));
+  }
+
+public:
+  OutputStream(char *StartBuf, size_t Size)
+      : Buffer(StartBuf), CurrentPosition(0), BufferCapacity(Size) {}
+  OutputStream() = default;
+  void reset(char *Buffer_, size_t BufferCapacity_) {
+    CurrentPosition = 0;
+    Buffer = Buffer_;
+    BufferCapacity = BufferCapacity_;
+  }
+
+  /// Create an OutputStream from a buffer and a size.  If either of these are
+  /// null a buffer is allocated.
+  static OutputStream create(char *StartBuf, size_t *Size, size_t AllocSize) {
+    OutputStream Result;
+
+    if (!StartBuf || !Size) {
+      StartBuf = static_cast<char *>(std::malloc(AllocSize));
+      if (StartBuf == nullptr)
+        std::terminate();
+      Size = &AllocSize;
+    }
+
+    Result.reset(StartBuf, *Size);
+    return Result;
+  }
+
+  /// 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();
+    if (Size == 0)
+      return *this;
+    grow(Size);
+    std::memmove(Buffer + CurrentPosition, R.begin(), Size);
+    CurrentPosition += Size;
+    return *this;
+  }
+
+  OutputStream &operator+=(char C) {
+    grow(1);
+    Buffer[CurrentPosition++] = C;
+    return *this;
+  }
+
+  OutputStream &operator<<(StringView R) { return (*this += R); }
+
+  OutputStream &operator<<(char C) { return (*this += C); }
+
+  OutputStream &operator<<(long long N) {
+    if (N < 0)
+      writeUnsigned(static_cast<unsigned long long>(-N), true);
+    else
+      writeUnsigned(static_cast<unsigned long long>(N));
+    return *this;
+  }
+
+  OutputStream &operator<<(unsigned long long N) {
+    writeUnsigned(N, false);
+    return *this;
+  }
+
+  OutputStream &operator<<(long N) {
+    return this->operator<<(static_cast<long long>(N));
+  }
+
+  OutputStream &operator<<(unsigned long N) {
+    return this->operator<<(static_cast<unsigned long long>(N));
+  }
+
+  OutputStream &operator<<(int N) {
+    return this->operator<<(static_cast<long long>(N));
+  }
+
+  OutputStream &operator<<(unsigned int N) {
+    return this->operator<<(static_cast<unsigned long long>(N));
+  }
+
+  size_t getCurrentPosition() const { return CurrentPosition; }
+  void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; }
+
+  char back() const {
+    return CurrentPosition ? Buffer[CurrentPosition - 1] : '\0';
+  }
+
+  bool empty() const { return CurrentPosition == 0; }
+
+  char *getBuffer() { return Buffer; }
+  char *getBufferEnd() { return Buffer + CurrentPosition - 1; }
+  size_t getBufferCapacity() { return BufferCapacity; }
+};
+
+template <class T> class SwapAndRestore {
+  T &Restore;
+  T OriginalValue;
+  bool ShouldRestore = true;
+
+public:
+  SwapAndRestore(T &Restore_) : SwapAndRestore(Restore_, Restore_) {}
+
+  SwapAndRestore(T &Restore_, T NewVal)
+      : Restore(Restore_), OriginalValue(Restore) {
+    Restore = std::move(NewVal);
+  }
+  ~SwapAndRestore() {
+    if (ShouldRestore)
+      Restore = std::move(OriginalValue);
+  }
+
+  void shouldRestore(bool ShouldRestore_) { ShouldRestore = ShouldRestore_; }
+
+  void restoreNow(bool Force) {
+    if (!Force && !ShouldRestore)
+      return;
+
+    Restore = std::move(OriginalValue);
+    ShouldRestore = false;
+  }
+
+  SwapAndRestore(const SwapAndRestore &) = delete;
+  SwapAndRestore &operator=(const SwapAndRestore &) = delete;
+};
+
+} // namespace
+
+#endif
diff --git a/src/stdlib_exception.cpp b/src/stdlib_exception.cpp
index a8f71ab..6c09102 100644
--- a/src/stdlib_exception.cpp
+++ b/src/stdlib_exception.cpp
@@ -8,7 +8,6 @@
 //===----------------------------------------------------------------------===//
 
 #define _LIBCPP_BUILDING_LIBRARY
-#define _LIBCPP_BUILDING_NEW
 #include <new>
 #include <exception>
 
diff --git a/src/stdlib_new_delete.cpp b/src/stdlib_new_delete.cpp
index 0e85f6a..686ad07 100644
--- a/src/stdlib_new_delete.cpp
+++ b/src/stdlib_new_delete.cpp
@@ -9,7 +9,6 @@
 // This file implements the new and delete operators.
 //===----------------------------------------------------------------------===//
 
-#define _LIBCPP_BUILDING_NEW
 #define _LIBCPP_BUILDING_LIBRARY
 #include "__cxxabi_config.h"
 #include <new>
diff --git a/test/catch_member_function_pointer_02.pass.cpp b/test/catch_member_function_pointer_02.pass.cpp
index 6bd9e6f..29f02bd 100644
--- a/test/catch_member_function_pointer_02.pass.cpp
+++ b/test/catch_member_function_pointer_02.pass.cpp
@@ -13,7 +13,7 @@
 
 // GCC 7 and 8 support noexcept function types but this test still fails.
 // This is likely a bug in their implementation. Investigation needed.
-// XFAIL: gcc-7, gcc-8
+// XFAIL: gcc-7, gcc-8, gcc-9
 
 #include <cassert>
 
diff --git a/test/cxa_bad_cast.pass.cpp b/test/cxa_bad_cast.pass.cpp
index d2c3bf9..9b6bff4 100644
--- a/test/cxa_bad_cast.pass.cpp
+++ b/test/cxa_bad_cast.pass.cpp
@@ -21,7 +21,7 @@
 
 class Derived : public Base {};
 
-Derived &test_bad_cast(Base b) {
+Derived &test_bad_cast(Base& b) {
   return dynamic_cast<Derived&>(b);
 }
 
diff --git a/test/libcxxabi/test/config.py b/test/libcxxabi/test/config.py
index f294c8b..abec67f 100644
--- a/test/libcxxabi/test/config.py
+++ b/test/libcxxabi/test/config.py
@@ -10,6 +10,7 @@
 import sys
 
 from libcxx.test.config import Configuration as LibcxxConfiguration
+from libcxx.test.config import intMacroValue
 
 
 class Configuration(LibcxxConfiguration):
@@ -34,7 +35,7 @@
         super(Configuration, self).configure_obj_root()
 
     def has_cpp_feature(self, feature, required_value):
-        return int(self.cxx.dumpMacros().get('__cpp_' + feature, 0)) >= required_value
+        return intMacroValue(self.cxx.dumpMacros().get('__cpp_' + feature, '0')) >= required_value
 
     def configure_features(self):
         super(Configuration, self).configure_features()
diff --git a/test/test_demangle.pass.cpp b/test/test_demangle.pass.cpp
index ea7a0fa..7c1fd2d 100644
--- a/test/test_demangle.pass.cpp
+++ b/test/test_demangle.pass.cpp
@@ -29749,6 +29749,12 @@
     {"_Z5foldlIJLi1ELi2ELi3EEEv1AIXflplT_EE", "void foldl<1, 2, 3>(A<(... + (1, 2, 3))>)"},
     {"_Z5foldrIJLi1ELi2ELi3EEEv1AIXfrplT_EE", "void foldr<1, 2, 3>(A<((1, 2, 3) + ...)>)"},
     {"_ZN7PartialIJLi1ELi2EEE5foldrIJLi3ELi4EEEEv1AIXplLi1EplLi2EfRplT_plLi1EplLi2EfrplT_EE", "void Partial<1, 2>::foldr<3, 4>(A<(1) + ((2) + (((3, 4) + ... + (1) + ((2) + (((3, 4) + ...))))))>)"},
+
+    // reference collapsing:
+    {"_Z1fIR1SEiOT_", "int f<S&>(S&)"},
+    {"_Z1fIJR1SS0_EEiDpOT_", "int f<S&, S>(S&, S&&)"},
+
+    {"___Z3foo_block_invoke.25", "invocation function for block in foo"},
 };
 
 const unsigned N = sizeof(cases) / sizeof(cases[0]);