zoecarver updated this revision to Diff 221014.
zoecarver added a comment.
Herald added a subscriber: erik.pilkington.

- address review comments
- fix warnings in build


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D67052/new/

https://reviews.llvm.org/D67052

Files:
  clang/include/clang/AST/Type.h
  clang/include/clang/Basic/Specifiers.h
  clang/include/clang/Basic/TokenKinds.def
  clang/include/clang/Parse/Parser.h
  clang/include/clang/Sema/DeclSpec.h
  clang/lib/AST/ItaniumMangle.cpp
  clang/lib/AST/JSONNodeDumper.cpp
  clang/lib/AST/TextNodeDumper.cpp
  clang/lib/AST/TypePrinter.cpp
  clang/lib/Format/FormatToken.cpp
  clang/lib/Lex/PPMacroExpansion.cpp
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Parse/ParseDeclCXX.cpp
  clang/lib/Sema/DeclSpec.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Sema/SemaTemplateVariadic.cpp
  clang/lib/Sema/SemaType.cpp
  clang/test/SemaCXX/add_reference.cpp
  
libcxx/test/libcxx/utilities/meta/stress_tests/stress_test_add_lvalue_reference.sh.cpp
  
libcxx/test/libcxx/utilities/meta/stress_tests/stress_test_add_rvalue_reference.sh.cpp
  
libcxx/test/libcxx/utilities/meta/stress_tests/stress_test_remove_reference.sh.cpp

Index: libcxx/test/libcxx/utilities/meta/stress_tests/stress_test_remove_reference.sh.cpp
===================================================================
--- /dev/null
+++ libcxx/test/libcxx/utilities/meta/stress_tests/stress_test_remove_reference.sh.cpp
@@ -0,0 +1,63 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This is a dummy feature that prevents this test from running by default.
+
+// The table below compares the compile time and object size for each of the
+// variants listed in the RUN script.
+//
+//  Impl                       Compile Time      Object Size
+// ----------------------------------------------------------
+// new_remove_reference:       22.849 s          121 K
+// std::remove_reference:      25.643 s          121 K
+//
+// RUN: %cxx %flags %compile_flags -c %s -o %S/orig.o -ggdb  -ggnu-pubnames -ftemplate-depth=5000 -ftime-trace -std=c++17
+// RUN: %cxx %flags %compile_flags -c %s -o %S/new.o -ggdb  -ggnu-pubnames -ftemplate-depth=5000 -ftime-trace -std=c++17 -DTEST_NEW
+
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "template_cost_testing.h"
+
+template <int N> struct Arg { enum { value = 1 }; };
+
+#ifdef TEST_NEW
+
+template <class T>
+struct new_remove_reference
+{
+  typedef __remove_reference(T) type;
+};
+
+#define TEST_CASE_NOP()  new_remove_reference< Arg< __COUNTER__ > >{},
+#define TEST_CASE_TYPE() typename new_remove_reference< Arg< __COUNTER__ > >::type,
+
+#else
+
+#define TEST_CASE_NOP()  std::remove_reference< Arg< __COUNTER__ > >{},
+#define TEST_CASE_TYPE() typename std::remove_reference< Arg< __COUNTER__ > >::type,
+
+#endif
+
+int sink(...);
+
+int x = sink(
+  REPEAT_10000(TEST_CASE_NOP)
+  REPEAT_10000(TEST_CASE_NOP) 42
+);
+
+void Foo( REPEAT_10000(TEST_CASE_TYPE) int) { }
+
+void escape() {
+
+sink(&x);
+sink(&Foo);
+}
+
+
Index: libcxx/test/libcxx/utilities/meta/stress_tests/stress_test_add_rvalue_reference.sh.cpp
===================================================================
--- /dev/null
+++ libcxx/test/libcxx/utilities/meta/stress_tests/stress_test_add_rvalue_reference.sh.cpp
@@ -0,0 +1,63 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This is a dummy feature that prevents this test from running by default.
+
+// The table below compares the compile time and object size for each of the
+// variants listed in the RUN script.
+//
+//  Impl                       Compile Time      Object Size
+// ----------------------------------------------------------
+// new_add_rvalue_reference:   56.398 s          171 K
+// std::add_rvalue_reference:  114.59 s          271 K
+//
+// RUN: %cxx %flags %compile_flags -c %s -o %S/orig.o -ggdb  -ggnu-pubnames -ftemplate-depth=5000 -ftime-trace -std=c++17
+// RUN: %cxx %flags %compile_flags -c %s -o %S/new.o -ggdb  -ggnu-pubnames -ftemplate-depth=5000 -ftime-trace -std=c++17 -DTEST_NEW
+
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "template_cost_testing.h"
+
+template <int N> struct Arg { enum { value = 1 }; };
+
+#ifdef TEST_NEW
+
+template <class T>
+struct new_add_rvalue_reference
+{
+  typedef __add_rvalue_reference(T) type;
+};
+
+#define TEST_CASE_NOP()  new_add_rvalue_reference< Arg< __COUNTER__ > >{},
+#define TEST_CASE_TYPE() typename new_add_rvalue_reference< Arg< __COUNTER__ > >::type,
+
+#else
+
+#define TEST_CASE_NOP()  std::add_rvalue_reference< Arg< __COUNTER__ > >{},
+#define TEST_CASE_TYPE() typename std::add_rvalue_reference< Arg< __COUNTER__ > >::type,
+
+#endif
+
+int sink(...);
+
+int x = sink(
+  REPEAT_10000(TEST_CASE_NOP)
+  REPEAT_10000(TEST_CASE_NOP) 42
+);
+
+void Foo( REPEAT_10000(TEST_CASE_TYPE) int) { }
+
+void escape() {
+
+sink(&x);
+sink(&Foo);
+}
+
+
Index: libcxx/test/libcxx/utilities/meta/stress_tests/stress_test_add_lvalue_reference.sh.cpp
===================================================================
--- /dev/null
+++ libcxx/test/libcxx/utilities/meta/stress_tests/stress_test_add_lvalue_reference.sh.cpp
@@ -0,0 +1,63 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This is a dummy feature that prevents this test from running by default.
+
+// The table below compares the compile time and object size for each of the
+// variants listed in the RUN script.
+//
+//  Impl                       Compile Time      Object Size
+// ----------------------------------------------------------
+// new_add_lvalue_reference:   23,359.202 ms     171 K
+// std::add_lvalue_reference:  73,160.138 ms     201 K
+//
+// RUN: %cxx %flags %compile_flags -c %s -o %S/orig.o -ggdb  -ggnu-pubnames -ftemplate-depth=5000 -ftime-trace -std=c++17
+// RUN: %cxx %flags %compile_flags -c %s -o %S/new.o -ggdb  -ggnu-pubnames -ftemplate-depth=5000 -ftime-trace -std=c++17 -DTEST_NEW
+
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "template_cost_testing.h"
+
+template <int N> struct Arg { enum { value = 1 }; };
+
+#ifdef TEST_NEW
+
+template <class T>
+struct new_add_lvalue_reference
+{
+  typedef __add_lvalue_reference(T) type;
+};
+
+#define TEST_CASE_NOP()  new_add_lvalue_reference< Arg< __COUNTER__ > >{},
+#define TEST_CASE_TYPE() typename new_add_lvalue_reference< Arg< __COUNTER__ > >::type,
+
+#else
+
+#define TEST_CASE_NOP()  std::add_lvalue_reference< Arg< __COUNTER__ > >{},
+#define TEST_CASE_TYPE() typename std::add_lvalue_reference< Arg< __COUNTER__ > >::type,
+
+#endif
+
+int sink(...);
+
+int x = sink(
+  REPEAT_10000(TEST_CASE_NOP)
+  REPEAT_10000(TEST_CASE_NOP) 42
+);
+
+void Foo( REPEAT_10000(TEST_CASE_TYPE) int) { }
+
+void escape() {
+
+sink(&x);
+sink(&Foo);
+}
+
+
Index: clang/test/SemaCXX/add_reference.cpp
===================================================================
--- /dev/null
+++ clang/test/SemaCXX/add_reference.cpp
@@ -0,0 +1,69 @@
+// RUN: %clang_cc1 -std=c++11 %s
+
+template<class T>
+struct test_lval_trait
+{
+  typedef __add_lvalue_reference(T) type;
+};
+
+template<class T>
+struct test_lval
+{
+  static const bool value = __is_same(typename test_lval_trait<T>::type, T&)  &&
+                            __is_same(typename test_lval_trait<T&>::type, T&) &&
+                            __is_same(typename test_lval_trait<T&&>::type, T&);
+};
+
+template<class T>
+struct test_rval_trait
+{
+  typedef __add_rvalue_reference(T) type;
+};
+
+template<class T>
+struct test_rval
+{
+  static const bool value = __is_same(typename test_rval_trait<T>::type, T&&)  &&
+                            __is_same(typename test_rval_trait<T&>::type, T&&) &&
+                            __is_same(typename test_rval_trait<T&&>::type, T&&);
+};
+
+template<class T>
+struct test_remove_ref_trait
+{
+  typedef __remove_reference(T) type;
+};
+
+template<class T>
+struct test_remove_ref
+{
+  static const bool value = __is_same(typename test_remove_ref_trait<T>::type, T)  &&
+                            __is_same(typename test_remove_ref_trait<T&>::type, T) &&
+                            __is_same(typename test_remove_ref_trait<T&&>::type, T);
+};
+
+template<class T>
+struct test
+{
+  static const bool value = test_remove_ref<T>::value &&
+                            test_rval<T>::value &&
+                            test_lval<T>::value;
+};
+
+struct Foo { };
+
+template<class T>
+struct Bar { };
+
+template<class T>
+class Baz { };
+
+static_assert(test<int>::value, "");
+static_assert(test<int[]>::value, "");
+static_assert(test<int[8]>::value, "");
+static_assert(test<Foo>::value, "");
+static_assert(test<Bar<int>>::value, "");
+static_assert(test<Baz<int>>::value, "");
+static_assert(test<int*>::value, "");
+static_assert(test<int const>::value, "");
+static_assert(test<int(int)>::value, "");
Index: clang/lib/Sema/SemaType.cpp
===================================================================
--- clang/lib/Sema/SemaType.cpp
+++ clang/lib/Sema/SemaType.cpp
@@ -1251,6 +1251,22 @@
   return OpenCLAccessAttr::Keyword_read_only;
 }
 
+static UnaryTransformType::UTTKind
+TSTToUnaryTransformType(DeclSpec::TST SwitchTST) {
+  switch (SwitchTST) {
+  case TST_addLValueReferenceType:
+    return UnaryTransformType::AddLValueRefType;
+  case TST_addRValueReferenceType:
+    return UnaryTransformType::AddRValueRefType;
+  case TST_removeReferenceType:
+    return UnaryTransformType::RemoveReferenceType;
+  case TST_underlyingType:
+    return UnaryTransformType::EnumUnderlyingType;
+  default:
+    llvm_unreachable("Cannot map TST to unary transform type");
+  }
+}
+
 /// Convert the specified declspec to the appropriate type
 /// object.
 /// \param state Specifies the declarator containing the declaration specifier
@@ -1593,6 +1609,20 @@
       declarator.setInvalidType(true);
     }
     break;
+  case DeclSpec::TST_addLValueReferenceType:
+  case DeclSpec::TST_addRValueReferenceType:
+  case DeclSpec::TST_removeReferenceType:
+    Result = S.GetTypeFromParser(DS.getRepAsType());
+    assert(!Result.isNull() &&
+           "Reference manipulation type transform may not have received a type.");
+    Result = S.BuildUnaryTransformType(Result,
+                                       TSTToUnaryTransformType(DS.getTypeSpecType()),
+                                       DS.getTypeSpecTypeLoc());
+    if (Result.isNull()) {
+      declarator.setInvalidType(true);
+    }
+    break;
+
 
   case DeclSpec::TST_auto:
     Result = Context.getAutoType(QualType(), AutoTypeKeyword::Auto, false);
@@ -5462,8 +5492,11 @@
       TL.setUnderlyingTInfo(TInfo);
     }
     void VisitUnaryTransformTypeLoc(UnaryTransformTypeLoc TL) {
-      // FIXME: This holds only because we only have one unary transform.
-      assert(DS.getTypeSpecType() == DeclSpec::TST_underlyingType);
+      // Make sure it is a unary transform type
+      assert(DS.getTypeSpecType() >= DeclSpec::TST_underlyingType &&
+             DS.getTypeSpecType() <= TST_removeReferenceType);
+
+      // assert(DS.getTypeSpecType() == DeclSpec::TST_underlyingType);
       TL.setKWLoc(DS.getTypeSpecTypeLoc());
       TL.setParensRange(DS.getTypeofParensRange());
       assert(DS.getRepAsType());
@@ -7927,7 +7960,7 @@
       break;
     }
 
-    SourceRange Loc = 
+    SourceRange Loc =
     S.ImplicitMSInheritanceAttrLoc.isValid()
                                  ? S.ImplicitMSInheritanceAttrLoc
                                  : RD->getSourceRange();
@@ -8380,6 +8413,21 @@
       return Context.getUnaryTransformType(BaseType, Underlying,
                                         UnaryTransformType::EnumUnderlyingType);
     }
+  case UnaryTransformType::AddLValueRefType: {
+    QualType Underlying = Context.getLValueReferenceType(BaseType.getCanonicalType());
+    return Context.getUnaryTransformType(BaseType, Underlying,
+                                         UnaryTransformType::AddLValueRefType);
+  }
+  case UnaryTransformType::AddRValueRefType: {
+    QualType Underlying = Context.getRValueReferenceType(BaseType.getCanonicalType());
+    return Context.getUnaryTransformType(BaseType, Underlying,
+                                         UnaryTransformType::AddRValueRefType);
+  }
+  case UnaryTransformType::RemoveReferenceType: {
+    QualType Underlying = BaseType.getNonReferenceType();
+    return Context.getUnaryTransformType(BaseType, Underlying,
+                                         UnaryTransformType::RemoveReferenceType);
+  }
   }
   llvm_unreachable("unknown unary transform type");
 }
Index: clang/lib/Sema/SemaTemplateVariadic.cpp
===================================================================
--- clang/lib/Sema/SemaTemplateVariadic.cpp
+++ clang/lib/Sema/SemaTemplateVariadic.cpp
@@ -838,6 +838,9 @@
   case TST_typename:
   case TST_typeofType:
   case TST_underlyingType:
+  case TST_addLValueReferenceType:
+  case TST_addRValueReferenceType:
+  case TST_removeReferenceType:
   case TST_atomic: {
     QualType T = DS.getRepAsType().get();
     if (!T.isNull() && T->containsUnexpandedParameterPack())
Index: clang/lib/Sema/SemaDecl.cpp
===================================================================
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -141,6 +141,9 @@
   case tok::kw_wchar_t:
   case tok::kw_bool:
   case tok::kw___underlying_type:
+  case tok::kw___add_lvalue_reference:
+  case tok::kw___add_rvalue_reference:
+  case tok::kw___remove_reference:
   case tok::kw___auto_type:
     return true;
 
@@ -5287,6 +5290,9 @@
   case DeclSpec::TST_typename:
   case DeclSpec::TST_typeofType:
   case DeclSpec::TST_underlyingType:
+  case DeclSpec::TST_addLValueReferenceType:
+  case DeclSpec::TST_addRValueReferenceType:
+  case DeclSpec::TST_removeReferenceType:
   case DeclSpec::TST_atomic: {
     // Grab the type from the parser.
     TypeSourceInfo *TSI = nullptr;
Index: clang/lib/Sema/DeclSpec.cpp
===================================================================
--- clang/lib/Sema/DeclSpec.cpp
+++ clang/lib/Sema/DeclSpec.cpp
@@ -374,6 +374,9 @@
       return false;
 
     case TST_underlyingType:
+    case TST_addLValueReferenceType:
+    case TST_addRValueReferenceType:
+    case TST_removeReferenceType:
     case TST_typename:
     case TST_typeofType: {
       QualType QT = DS.getRepAsType().get();
@@ -553,6 +556,9 @@
   case DeclSpec::TST_decltype:    return "(decltype)";
   case DeclSpec::TST_decltype_auto: return "decltype(auto)";
   case DeclSpec::TST_underlyingType: return "__underlying_type";
+  case DeclSpec::TST_addLValueReferenceType: return "__add_lvalue_reference";
+  case DeclSpec::TST_addRValueReferenceType: return "__add_rvalue_reference";
+  case DeclSpec::TST_removeReferenceType: return "__remove_reference";
   case DeclSpec::TST_unknown_anytype: return "__unknown_anytype";
   case DeclSpec::TST_atomic: return "_Atomic";
 #define GENERIC_IMAGE_TYPE(ImgType, Id) \
Index: clang/lib/Parse/ParseDeclCXX.cpp
===================================================================
--- clang/lib/Parse/ParseDeclCXX.cpp
+++ clang/lib/Parse/ParseDeclCXX.cpp
@@ -1083,6 +1083,48 @@
   DS.setTypeofParensRange(T.getRange());
 }
 
+DeclSpec::TST Parser::ReferenceTransformTokToDeclSpec() {
+  switch (Tok.getKind()) {
+  case tok::kw___add_lvalue_reference:
+    return DeclSpec::TST_addLValueReferenceType;
+  case tok::kw___add_rvalue_reference:
+    return DeclSpec::TST_addRValueReferenceType;
+  case tok::kw___remove_reference:
+    return DeclSpec::TST_removeReferenceType;
+  default:
+    llvm_unreachable("Not a reference type specifier");
+  }
+}
+
+void Parser::ParseAddReferenceTypeSpecifier(DeclSpec &DS) {
+  DeclSpec::TST ReferenceTransformTST = ReferenceTransformTokToDeclSpec();
+
+  SourceLocation StartLoc = ConsumeToken();
+  BalancedDelimiterTracker T(*this, tok::l_paren);
+  if (T.expectAndConsume(diag::err_expected_lparen_after,
+                         "reference manipulation builtin",
+                         tok::r_paren)) return;
+
+  TypeResult BaseTyResult = ParseTypeName();
+  if (BaseTyResult.isInvalid()) {
+    SkipUntil(tok::r_paren, StopAtSemi);
+    return;
+  }
+
+  T.consumeClose();
+  if (T.getCloseLocation().isInvalid()) return;
+
+  const char *PrevSpec;
+  unsigned DiagID;
+  if (DS.SetTypeSpecType(ReferenceTransformTST,
+                         StartLoc, PrevSpec,
+                         DiagID, BaseTyResult.get(),
+                         Actions.getASTContext().getPrintingPolicy())) {
+    Diag(StartLoc, DiagID) << PrevSpec;
+  }
+  DS.setTypeofParensRange(T.getRange());
+}
+
 /// ParseBaseTypeSpecifier - Parse a C++ base-type-specifier which is either a
 /// class name or decltype-specifier. Note that we only check that the result
 /// names a type; semantic analysis will need to verify that the type names a
Index: clang/lib/Parse/ParseDecl.cpp
===================================================================
--- clang/lib/Parse/ParseDecl.cpp
+++ clang/lib/Parse/ParseDecl.cpp
@@ -3919,6 +3919,12 @@
       ParseUnderlyingTypeSpecifier(DS);
       continue;
 
+    case tok::kw___remove_reference:
+    case tok::kw___add_rvalue_reference:
+    case tok::kw___add_lvalue_reference:
+      ParseAddReferenceTypeSpecifier(DS);
+      continue;
+
     case tok::kw__Atomic:
       // C11 6.7.2.4/4:
       //   If the _Atomic keyword is immediately followed by a left parenthesis,
Index: clang/lib/Lex/PPMacroExpansion.cpp
===================================================================
--- clang/lib/Lex/PPMacroExpansion.cpp
+++ clang/lib/Lex/PPMacroExpansion.cpp
@@ -1636,6 +1636,9 @@
               .Case("__array_extent", true)
               .Case("__reference_binds_to_temporary", true)
               .Case("__underlying_type", true)
+              .Case("__add_lvalue_reference", true)
+              .Case("__add_rvalue_reference", true)
+              .Case("__remove_reference", true)
               .Default(false);
         } else {
           return llvm::StringSwitch<bool>(II->getName())
Index: clang/lib/Format/FormatToken.cpp
===================================================================
--- clang/lib/Format/FormatToken.cpp
+++ clang/lib/Format/FormatToken.cpp
@@ -55,6 +55,9 @@
   case tok::kw_wchar_t:
   case tok::kw_bool:
   case tok::kw___underlying_type:
+  case tok::kw___add_lvalue_reference:
+  case tok::kw___add_rvalue_reference:
+  case tok::kw___remove_reference:
   case tok::annot_typename:
   case tok::kw_char8_t:
   case tok::kw_char16_t:
Index: clang/lib/AST/TypePrinter.cpp
===================================================================
--- clang/lib/AST/TypePrinter.cpp
+++ clang/lib/AST/TypePrinter.cpp
@@ -1024,6 +1024,24 @@
       OS << ')';
       spaceBeforePlaceHolder(OS);
       return;
+    case UnaryTransformType::RemoveReferenceType:
+      OS << "__remove_reference";
+      print(T->getBaseType(), OS, StringRef());
+      OS << ')';
+      spaceBeforePlaceHolder(OS);
+      return;
+    case UnaryTransformType::AddRValueRefType:
+      OS << "__add_rvalue_reference(";
+      print(T->getBaseType(), OS, StringRef());
+      OS << ')';
+      spaceBeforePlaceHolder(OS);
+      return;
+    case UnaryTransformType::AddLValueRefType:
+      OS << "__add_lvalue_reference(";
+      print(T->getBaseType(), OS, StringRef());
+      OS << ')';
+      spaceBeforePlaceHolder(OS);
+      return;
   }
 
   printBefore(T->getBaseType(), OS);
@@ -1035,6 +1053,9 @@
 
   switch (T->getUTTKind()) {
     case UnaryTransformType::EnumUnderlyingType:
+    case UnaryTransformType::RemoveReferenceType:
+    case UnaryTransformType::AddLValueRefType:
+    case UnaryTransformType::AddRValueRefType:
       return;
   }
 
Index: clang/lib/AST/TextNodeDumper.cpp
===================================================================
--- clang/lib/AST/TextNodeDumper.cpp
+++ clang/lib/AST/TextNodeDumper.cpp
@@ -1180,6 +1180,15 @@
   case UnaryTransformType::EnumUnderlyingType:
     OS << " underlying_type";
     break;
+  case UnaryTransformType::RemoveReferenceType:
+    OS << " remove_reference";
+    break;
+  case UnaryTransformType::AddRValueRefType:
+    OS << " add_rvalue_reference";
+    break;
+  case UnaryTransformType::AddLValueRefType:
+    OS << " add_lvalue_reference";
+    break;
   }
 }
 
Index: clang/lib/AST/JSONNodeDumper.cpp
===================================================================
--- clang/lib/AST/JSONNodeDumper.cpp
+++ clang/lib/AST/JSONNodeDumper.cpp
@@ -589,6 +589,15 @@
   case UnaryTransformType::EnumUnderlyingType:
     JOS.attribute("transformKind", "underlying_type");
     break;
+  case UnaryTransformType::RemoveReferenceType:
+    JOS.attribute("transformKind", "remove_reference");
+    break;
+  case UnaryTransformType::AddRValueRefType:
+    JOS.attribute("transformKind", "add_rvalue_reference");
+    break;
+  case UnaryTransformType::AddLValueRefType:
+    JOS.attribute("transformKind", "add_lvalue_reference");
+    break;
   }
 }
 
@@ -962,7 +971,7 @@
   case ObjCPropertyDecl::Required: JOS.attribute("control", "required"); break;
   case ObjCPropertyDecl::Optional: JOS.attribute("control", "optional"); break;
   }
-  
+
   ObjCPropertyDecl::PropertyAttributeKind Attrs = D->getPropertyAttributes();
   if (Attrs != ObjCPropertyDecl::OBJC_PR_noattr) {
     if (Attrs & ObjCPropertyDecl::OBJC_PR_getter)
Index: clang/lib/AST/ItaniumMangle.cpp
===================================================================
--- clang/lib/AST/ItaniumMangle.cpp
+++ clang/lib/AST/ItaniumMangle.cpp
@@ -3409,6 +3409,15 @@
       case UnaryTransformType::EnumUnderlyingType:
         Out << "3eut";
         break;
+      case UnaryTransformType::RemoveReferenceType:
+        Out << "3err";
+        break;
+      case UnaryTransformType::AddRValueRefType:
+        Out << "3earvr";
+        break;
+      case UnaryTransformType::AddLValueRefType:
+        Out << "3ealvr";
+        break;
     }
   }
 
Index: clang/include/clang/Sema/DeclSpec.h
===================================================================
--- clang/include/clang/Sema/DeclSpec.h
+++ clang/include/clang/Sema/DeclSpec.h
@@ -300,6 +300,9 @@
   static const TST TST_decltype = clang::TST_decltype;
   static const TST TST_decltype_auto = clang::TST_decltype_auto;
   static const TST TST_underlyingType = clang::TST_underlyingType;
+  static const TST TST_addLValueReferenceType = clang::TST_addLValueReferenceType;
+  static const TST TST_addRValueReferenceType = clang::TST_addRValueReferenceType;
+  static const TST TST_removeReferenceType = clang::TST_removeReferenceType;
   static const TST TST_auto = clang::TST_auto;
   static const TST TST_auto_type = clang::TST_auto_type;
   static const TST TST_unknown_anytype = clang::TST_unknown_anytype;
@@ -408,7 +411,9 @@
 
   static bool isTypeRep(TST T) {
     return (T == TST_typename || T == TST_typeofType ||
-            T == TST_underlyingType || T == TST_atomic);
+            T == TST_underlyingType || T == TST_atomic||
+            T == TST_addLValueReferenceType || T == TST_addRValueReferenceType ||
+            T == TST_removeReferenceType);
   }
   static bool isExprRep(TST T) {
     return (T == TST_typeofExpr || T == TST_decltype);
Index: clang/include/clang/Parse/Parser.h
===================================================================
--- clang/include/clang/Parse/Parser.h
+++ clang/include/clang/Parse/Parser.h
@@ -2602,6 +2602,8 @@
                                          SourceLocation StartLoc,
                                          SourceLocation EndLoc);
   void ParseUnderlyingTypeSpecifier(DeclSpec &DS);
+  DeclSpec::TST ReferenceTransformTokToDeclSpec();
+  void ParseAddReferenceTypeSpecifier(DeclSpec &DS);
   void ParseAtomicSpecifier(DeclSpec &DS);
 
   ExprResult ParseAlignArgument(SourceLocation Start,
Index: clang/include/clang/Basic/TokenKinds.def
===================================================================
--- clang/include/clang/Basic/TokenKinds.def
+++ clang/include/clang/Basic/TokenKinds.def
@@ -486,7 +486,10 @@
 TYPE_TRAIT_1(__is_union, IsUnion, KEYCXX)
 TYPE_TRAIT_1(__has_unique_object_representations,
              HasUniqueObjectRepresentations, KEYCXX)
-KEYWORD(__underlying_type           , KEYCXX)
+KEYWORD(__underlying_type                  , KEYCXX)
+KEYWORD(__add_lvalue_reference             , KEYCXX)
+KEYWORD(__add_rvalue_reference             , KEYCXX)
+KEYWORD(__remove_reference                 , KEYCXX)
 
 // Clang-only C++ Type Traits
 TYPE_TRAIT_2(__reference_binds_to_temporary, ReferenceBindsToTemporary, KEYCXX)
Index: clang/include/clang/Basic/Specifiers.h
===================================================================
--- clang/include/clang/Basic/Specifiers.h
+++ clang/include/clang/Basic/Specifiers.h
@@ -88,6 +88,9 @@
     TST_typeofExpr,
     TST_decltype,         // C++11 decltype
     TST_underlyingType,   // __underlying_type for C++11
+    TST_addLValueReferenceType, // __add_lvalue_reference
+    TST_addRValueReferenceType, // __add_rvalue_reference
+    TST_removeReferenceType, // __remove_reference
     TST_auto,             // C++11 auto
     TST_decltype_auto,    // C++1y decltype(auto)
     TST_auto_type,        // __auto_type extension
Index: clang/include/clang/AST/Type.h
===================================================================
--- clang/include/clang/AST/Type.h
+++ clang/include/clang/AST/Type.h
@@ -4363,7 +4363,10 @@
 class UnaryTransformType : public Type {
 public:
   enum UTTKind {
-    EnumUnderlyingType
+    EnumUnderlyingType,
+    RemoveReferenceType,
+    AddRValueRefType,
+    AddLValueRefType
   };
 
 private:
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to