cjdb updated this revision to Diff 396178.
cjdb added a comment.

minor fix


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D116203

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_cv.cpp
  clang/test/SemaCXX/remove_cvref.cpp

Index: clang/test/SemaCXX/remove_cvref.cpp
===================================================================
--- /dev/null
+++ clang/test/SemaCXX/remove_cvref.cpp
@@ -0,0 +1,86 @@
+// RUN: %clang_cc1 -std=c++11 %s
+
+template <class T>
+struct check_remove_reference {
+  constexpr check_remove_reference() {
+    static_assert(__is_same(__remove_reference(T &), T), "");
+    static_assert(__is_same(__remove_reference(const T &), const T), "");
+    static_assert(__is_same(__remove_reference(volatile T &), volatile T), "");
+    static_assert(__is_same(__remove_reference(const volatile T &), const volatile T), "");
+
+    static_assert(__is_same(__remove_reference(T &&), T), "");
+    static_assert(__is_same(__remove_reference(const T &&), const T), "");
+    static_assert(__is_same(__remove_reference(volatile T &&), volatile T), "");
+    static_assert(__is_same(__remove_reference(const volatile T &&), const volatile T), "");
+
+    static_assert(__is_same(__remove_cvref(T &), T), "");
+    static_assert(__is_same(__remove_cvref(const T &), T), "");
+    static_assert(__is_same(__remove_cvref(volatile T &), T), "");
+    static_assert(__is_same(__remove_cvref(const volatile T &), T), "");
+
+    static_assert(__is_same(__remove_cvref(T &&), T), "");
+    static_assert(__is_same(__remove_cvref(const T &&), T), "");
+    static_assert(__is_same(__remove_cvref(volatile T &&), T), "");
+    static_assert(__is_same(__remove_cvref(const volatile T &&), T), "");
+  }
+};
+
+template <> struct check_remove_reference<void> {};
+template <class T> struct check_remove_reference<T &> {};
+template <class T> struct check_remove_reference<T &&> {};
+
+template <class T>
+constexpr bool check_remove_qualifiers() {
+  static_assert(__is_same(__remove_const(const T), T), "");
+  static_assert(__is_same(__remove_const(volatile T), volatile T), "");
+  static_assert(__is_same(__remove_const(const volatile T), volatile T), "");
+
+  static_assert(__is_same(__remove_volatile(const T), const T), "");
+  static_assert(__is_same(__remove_volatile(volatile T), T), "");
+  static_assert(__is_same(__remove_volatile(const volatile T), const T), "");
+
+  static_assert(__is_same(__remove_cv(const T), T), "");
+  static_assert(__is_same(__remove_cv(volatile T), T), "");
+  static_assert(__is_same(__remove_cv(const volatile T), T), "");
+
+  check_remove_reference<T>();
+
+  return true;
+}
+
+static_assert(check_remove_qualifiers<void>(), "");
+static_assert(check_remove_qualifiers<int>(), "");
+static_assert(check_remove_qualifiers<int *>(), "");
+static_assert(check_remove_qualifiers<const int *>(), "");
+static_assert(check_remove_qualifiers<volatile int *>(), "");
+static_assert(check_remove_qualifiers<const volatile int *>(), "");
+static_assert(check_remove_qualifiers<int &>(), "");
+static_assert(check_remove_qualifiers<const int &>(), "");
+static_assert(check_remove_qualifiers<volatile int &>(), "");
+static_assert(check_remove_qualifiers<const volatile int &>(), "");
+static_assert(check_remove_qualifiers<int &&>(), "");
+static_assert(check_remove_qualifiers<const int &&>(), "");
+static_assert(check_remove_qualifiers<volatile int &&>(), "");
+static_assert(check_remove_qualifiers<const volatile int &&>(), "");
+static_assert(check_remove_qualifiers<int()>(), "");
+static_assert(check_remove_qualifiers<int (*)()>(), "");
+static_assert(check_remove_qualifiers<int (&)()>(), "");
+
+struct S {};
+static_assert(check_remove_qualifiers<S>(), "");
+static_assert(check_remove_qualifiers<int S::*>(), "");
+static_assert(check_remove_qualifiers<const int S::*>(), "");
+static_assert(check_remove_qualifiers<volatile int S::*>(), "");
+static_assert(check_remove_qualifiers<const volatile int S::*>(), "");
+static_assert(check_remove_qualifiers<int (S::*)()>(), "");
+static_assert(check_remove_qualifiers<int (S::*)() &>(), "");
+static_assert(check_remove_qualifiers<int (S::*)() &&>(), "");
+static_assert(check_remove_qualifiers<int (S::*)() const>(), "");
+static_assert(check_remove_qualifiers<int (S::*)() const &>(), "");
+static_assert(check_remove_qualifiers<int (S::*)() const &&>(), "");
+static_assert(check_remove_qualifiers<int (S::*)() volatile>(), "");
+static_assert(check_remove_qualifiers<int (S::*)() volatile &>(), "");
+static_assert(check_remove_qualifiers<int (S::*)() volatile &&>(), "");
+static_assert(check_remove_qualifiers<int (S::*)() const volatile>(), "");
+static_assert(check_remove_qualifiers<int (S::*)() const volatile &>(), "");
+static_assert(check_remove_qualifiers<int (S::*)() const volatile &&>(), "");
Index: clang/test/SemaCXX/add_cv.cpp
===================================================================
--- /dev/null
+++ clang/test/SemaCXX/add_cv.cpp
@@ -0,0 +1,41 @@
+// RUN: %clang_cc1 -std=c++11 %s
+
+template <class T>
+using add_const_t = __add_const(T);
+
+template <class T>
+constexpr bool check_add_cv() {
+  static_assert(__is_same(__add_const(T), const T), "");
+  static_assert(__is_same(__add_volatile(T), volatile T), "");
+  static_assert(__is_same(__add_cv(T), const volatile T), "");
+  return true;
+}
+
+static_assert(check_add_cv<void>(), "");
+static_assert(check_add_cv<int>(), "");
+static_assert(check_add_cv<const int>(), "");
+static_assert(check_add_cv<volatile int>(), "");
+static_assert(check_add_cv<const volatile int>(), "");
+static_assert(check_add_cv<int *>(), "");
+static_assert(check_add_cv<int &>(), "");
+static_assert(check_add_cv<int()>(), "");
+static_assert(check_add_cv<int (*)()>(), "");
+static_assert(check_add_cv<int (&)()>(), "");
+
+struct S {};
+static_assert(check_add_cv<S>(), "");
+static_assert(check_add_cv<const S>(), "");
+static_assert(check_add_cv<const volatile S>(), "");
+static_assert(check_add_cv<int S::*>(), "");
+static_assert(check_add_cv<int (S::*)()>(), "");
+static_assert(check_add_cv<int (S::*)() &>(), "");
+static_assert(check_add_cv<int (S::*)() &&>(), "");
+static_assert(check_add_cv<int (S::*)() const>(), "");
+static_assert(check_add_cv<int (S::*)() const &>(), "");
+static_assert(check_add_cv<int (S::*)() const &&>(), "");
+static_assert(check_add_cv<int (S::*)() volatile>(), "");
+static_assert(check_add_cv<int (S::*)() volatile &>(), "");
+static_assert(check_add_cv<int (S::*)() volatile &&>(), "");
+static_assert(check_add_cv<int (S::*)() const volatile>(), "");
+static_assert(check_add_cv<int (S::*)() const volatile &>(), "");
+static_assert(check_add_cv<int (S::*)() const volatile &&>(), "");
Index: clang/lib/Sema/SemaType.cpp
===================================================================
--- clang/lib/Sema/SemaType.cpp
+++ clang/lib/Sema/SemaType.cpp
@@ -22,6 +22,7 @@
 #include "clang/AST/TypeLoc.h"
 #include "clang/AST/TypeLocVisitor.h"
 #include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/Specifiers.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Sema/DeclSpec.h"
@@ -1257,6 +1258,32 @@
   return OpenCLAccessAttr::Keyword_read_only;
 }
 
+static UnaryTransformType::UTTKind
+TSTToUnaryTransformType(DeclSpec::TST SwitchTST) {
+  switch (SwitchTST) {
+  case TST_add_const:
+    return UnaryTransformType::AddConst;
+  case TST_add_cv:
+    return UnaryTransformType::AddCV;
+  case TST_add_volatile:
+    return UnaryTransformType::AddVolatile;
+  case TST_remove_const:
+    return UnaryTransformType::RemoveConst;
+  case TST_remove_cv:
+    return UnaryTransformType::RemoveCV;
+  case TST_remove_cvref:
+    return UnaryTransformType::RemoveCVRef;
+  case TST_remove_reference:
+    return UnaryTransformType::RemoveReference;
+  case TST_remove_volatile:
+    return UnaryTransformType::RemoveVolatile;
+  case TST_underlyingType:
+    return UnaryTransformType::EnumUnderlyingType;
+  default:
+    llvm_unreachable("attempted to parse a non-unary transform builtin");
+  }
+}
+
 /// Convert the specified declspec to the appropriate type
 /// object.
 /// \param state Specifies the declarator containing the declaration specifier
@@ -1640,13 +1667,22 @@
     break;
   }
   case DeclSpec::TST_underlyingType:
+  case DeclSpec::TST_add_const:
+  case DeclSpec::TST_add_cv:
+  case DeclSpec::TST_add_volatile:
+  case DeclSpec::TST_remove_const:
+  case DeclSpec::TST_remove_cv:
+  case DeclSpec::TST_remove_cvref:
+  case DeclSpec::TST_remove_reference:
+  case DeclSpec::TST_remove_volatile:
     Result = S.GetTypeFromParser(DS.getRepAsType());
-    assert(!Result.isNull() && "Didn't get a type for __underlying_type?");
-    Result = S.BuildUnaryTransformType(Result,
-                                       UnaryTransformType::EnumUnderlyingType,
-                                       DS.getTypeSpecTypeLoc());
+    assert(!Result.isNull() && "Didn't get a type for the transformation?");
+    Result = S.BuildUnaryTransformType(
+        Result, TSTToUnaryTransformType(DS.getTypeSpecType()),
+        DS.getTypeSpecTypeLoc());
     if (Result.isNull()) {
-      Result = Context.IntTy;
+      if (DS.getTypeSpecType() == DeclSpec::TST_underlyingType)
+        Result = Context.IntTy;
       declarator.setInvalidType(true);
     }
     break;
@@ -5974,8 +6010,9 @@
       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() <= DeclSpec::TST_remove_volatile);
       TL.setKWLoc(DS.getTypeSpecTypeLoc());
       TL.setParensRange(DS.getTypeofParensRange());
       assert(DS.getRepAsType());
@@ -9065,6 +9102,53 @@
       return Context.getUnaryTransformType(BaseType, Underlying,
                                         UnaryTransformType::EnumUnderlyingType);
     }
+  case UnaryTransformType::RemoveCVRef:
+  case UnaryTransformType::RemoveReference: {
+    QualType Underlying = BaseType.getNonReferenceType();
+    Qualifiers Quals = Underlying.getQualifiers();
+    if (UKind == UnaryTransformType::RemoveCVRef) {
+      Quals.removeConst();
+      Quals.removeVolatile();
+    }
+    return Context.getUnaryTransformType(
+        BaseType,
+        QualType(Underlying.getSplitUnqualifiedType().Ty,
+                 Quals.getAsOpaqueValue()),
+        UKind);
+  }
+  case UnaryTransformType::AddConst:
+  case UnaryTransformType::AddCV:
+  case UnaryTransformType::AddVolatile:
+  case UnaryTransformType::RemoveConst:
+  case UnaryTransformType::RemoveCV:
+  case UnaryTransformType::RemoveVolatile: {
+    SplitQualType Split = BaseType.getSplitUnqualifiedType();
+    Qualifiers Quals = BaseType.getQualifiers();
+    if (BaseType->isReferenceType() || BaseType->isFunctionType())
+      return BaseType;
+    switch (UKind) {
+    case UnaryTransformType::AddConst:
+      Quals.addConst();
+      break;
+    case UnaryTransformType::AddCV:
+      Quals.addConst();
+      [[fallthrough]];
+    case UnaryTransformType::AddVolatile:
+      Quals.addVolatile();
+      break;
+    case UnaryTransformType::RemoveConst:
+      Quals.removeConst();
+      break;
+    case UnaryTransformType::RemoveCV:
+      Quals.removeConst();
+      [[fallthrough]];
+    case UnaryTransformType::RemoveVolatile:
+      Quals.removeVolatile();
+      break;
+    }
+    QualType Underlying(Split.Ty, Quals.getAsOpaqueValue());
+    return Context.getUnaryTransformType(BaseType, Underlying, UKind);
+  }
   }
   llvm_unreachable("unknown unary transform type");
 }
Index: clang/lib/Sema/SemaTemplateVariadic.cpp
===================================================================
--- clang/lib/Sema/SemaTemplateVariadic.cpp
+++ clang/lib/Sema/SemaTemplateVariadic.cpp
@@ -861,6 +861,14 @@
   case TST_typename:
   case TST_typeofType:
   case TST_underlyingType:
+  case TST_add_const:
+  case TST_add_cv:
+  case TST_add_volatile:
+  case TST_remove_const:
+  case TST_remove_cv:
+  case TST_remove_cvref:
+  case TST_remove_reference:
+  case TST_remove_volatile:
   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
@@ -145,6 +145,14 @@
   case tok::kw_wchar_t:
   case tok::kw_bool:
   case tok::kw___underlying_type:
+  case tok::kw___add_const:
+  case tok::kw___add_cv:
+  case tok::kw___add_volatile:
+  case tok::kw___remove_const:
+  case tok::kw___remove_cv:
+  case tok::kw___remove_cvref:
+  case tok::kw___remove_reference:
+  case tok::kw___remove_volatile:
   case tok::kw___auto_type:
     return true;
 
@@ -5599,6 +5607,14 @@
   case DeclSpec::TST_typename:
   case DeclSpec::TST_typeofType:
   case DeclSpec::TST_underlyingType:
+  case DeclSpec::TST_add_const:
+  case DeclSpec::TST_add_cv:
+  case DeclSpec::TST_add_volatile:
+  case DeclSpec::TST_remove_const:
+  case DeclSpec::TST_remove_cv:
+  case DeclSpec::TST_remove_cvref:
+  case DeclSpec::TST_remove_reference:
+  case DeclSpec::TST_remove_volatile:
   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
@@ -18,6 +18,7 @@
 #include "clang/AST/TypeLoc.h"
 #include "clang/Basic/LangOptions.h"
 #include "clang/Basic/SourceManager.h"
+#include "clang/Basic/Specifiers.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Sema/ParsedTemplate.h"
 #include "clang/Sema/Sema.h"
@@ -390,6 +391,14 @@
       return false;
 
     case TST_underlyingType:
+    case TST_add_const:
+    case TST_add_cv:
+    case TST_add_volatile:
+    case TST_remove_const:
+    case TST_remove_cv:
+    case TST_remove_cvref:
+    case TST_remove_reference:
+    case TST_remove_volatile:
     case TST_typename:
     case TST_typeofType: {
       QualType QT = DS.getRepAsType().get();
@@ -577,6 +586,14 @@
   case DeclSpec::TST_decltype:    return "(decltype)";
   case DeclSpec::TST_decltype_auto: return "decltype(auto)";
   case DeclSpec::TST_underlyingType: return "__underlying_type";
+  case DeclSpec::TST_add_const:        return "__add_const";
+  case DeclSpec::TST_add_cv:           return "__add_cv";
+  case DeclSpec::TST_add_volatile:     return "__add_volatile";
+  case DeclSpec::TST_remove_const:     return "__remove_const";
+  case DeclSpec::TST_remove_cv:        return "__remove_cv";
+  case DeclSpec::TST_remove_cvref:     return "__remove_cvref";
+  case DeclSpec::TST_remove_reference: return "__remove_reference";
+  case DeclSpec::TST_remove_volatile:  return "__remove_volatile";
   case DeclSpec::TST_unknown_anytype: return "__unknown_anytype";
   case DeclSpec::TST_atomic: return "_Atomic";
   case DeclSpec::TST_BFloat16: return "__bf16";
Index: clang/lib/Parse/ParseDeclCXX.cpp
===================================================================
--- clang/lib/Parse/ParseDeclCXX.cpp
+++ clang/lib/Parse/ParseDeclCXX.cpp
@@ -1508,61 +1508,68 @@
   // C++11 attributes
   SourceLocation AttrFixitLoc = Tok.getLocation();
 
-  if (TagType == DeclSpec::TST_struct &&
-      Tok.isNot(tok::identifier) &&
-      !Tok.isAnnotation() &&
-      Tok.getIdentifierInfo() &&
-      Tok.isOneOf(tok::kw___is_abstract,
-                  tok::kw___is_aggregate,
-                  tok::kw___is_arithmetic,
-                  tok::kw___is_array,
-                  tok::kw___is_assignable,
-                  tok::kw___is_base_of,
-                  tok::kw___is_class,
-                  tok::kw___is_complete_type,
-                  tok::kw___is_compound,
-                  tok::kw___is_const,
-                  tok::kw___is_constructible,
-                  tok::kw___is_convertible,
-                  tok::kw___is_convertible_to,
-                  tok::kw___is_destructible,
-                  tok::kw___is_empty,
-                  tok::kw___is_enum,
-                  tok::kw___is_floating_point,
-                  tok::kw___is_final,
-                  tok::kw___is_function,
-                  tok::kw___is_fundamental,
-                  tok::kw___is_integral,
-                  tok::kw___is_interface_class,
-                  tok::kw___is_literal,
-                  tok::kw___is_lvalue_expr,
-                  tok::kw___is_lvalue_reference,
-                  tok::kw___is_member_function_pointer,
-                  tok::kw___is_member_object_pointer,
-                  tok::kw___is_member_pointer,
-                  tok::kw___is_nothrow_assignable,
-                  tok::kw___is_nothrow_constructible,
-                  tok::kw___is_nothrow_destructible,
-                  tok::kw___is_object,
-                  tok::kw___is_pod,
-                  tok::kw___is_pointer,
-                  tok::kw___is_polymorphic,
-                  tok::kw___is_reference,
-                  tok::kw___is_rvalue_expr,
-                  tok::kw___is_rvalue_reference,
-                  tok::kw___is_same,
-                  tok::kw___is_scalar,
-                  tok::kw___is_sealed,
-                  tok::kw___is_signed,
-                  tok::kw___is_standard_layout,
-                  tok::kw___is_trivial,
-                  tok::kw___is_trivially_assignable,
-                  tok::kw___is_trivially_constructible,
-                  tok::kw___is_trivially_copyable,
-                  tok::kw___is_union,
-                  tok::kw___is_unsigned,
-                  tok::kw___is_void,
-                  tok::kw___is_volatile))
+  if (TagType == DeclSpec::TST_struct && Tok.isNot(tok::identifier) &&
+      !Tok.isAnnotation() && Tok.getIdentifierInfo() &&
+      Tok.isOneOf( // clang-format off
+          tok::kw___add_const,
+          tok::kw___add_cv,
+          tok::kw___add_volatile,
+          tok::kw___is_abstract,
+          tok::kw___is_aggregate,
+          tok::kw___is_arithmetic,
+          tok::kw___is_array,
+          tok::kw___is_assignable,
+          tok::kw___is_base_of,
+          tok::kw___is_class,
+          tok::kw___is_complete_type,
+          tok::kw___is_compound,
+          tok::kw___is_const,
+          tok::kw___is_constructible,
+          tok::kw___is_convertible,
+          tok::kw___is_convertible_to,
+          tok::kw___is_destructible,
+          tok::kw___is_empty,
+          tok::kw___is_enum,
+          tok::kw___is_floating_point,
+          tok::kw___is_final,
+          tok::kw___is_function,
+          tok::kw___is_fundamental,
+          tok::kw___is_integral,
+          tok::kw___is_interface_class,
+          tok::kw___is_literal,
+          tok::kw___is_lvalue_expr,
+          tok::kw___is_lvalue_reference,
+          tok::kw___is_member_function_pointer,
+          tok::kw___is_member_object_pointer,
+          tok::kw___is_member_pointer,
+          tok::kw___is_nothrow_assignable,
+          tok::kw___is_nothrow_constructible,
+          tok::kw___is_nothrow_destructible,
+          tok::kw___is_object,
+          tok::kw___is_pod,
+          tok::kw___is_pointer,
+          tok::kw___is_polymorphic,
+          tok::kw___is_reference,
+          tok::kw___is_rvalue_expr,
+          tok::kw___is_rvalue_reference,
+          tok::kw___is_same,
+          tok::kw___is_scalar,
+          tok::kw___is_sealed,
+          tok::kw___is_signed,
+          tok::kw___is_standard_layout,
+          tok::kw___is_trivial,
+          tok::kw___is_trivially_assignable,
+          tok::kw___is_trivially_constructible,
+          tok::kw___is_trivially_copyable,
+          tok::kw___is_union,
+          tok::kw___is_unsigned,
+          tok::kw___is_void,
+          tok::kw___is_volatile,
+          tok::kw___remove_const,
+          tok::kw___remove_cv,
+          tok::kw___remove_cvref,
+          tok::kw___remove_reference,
+          tok::kw___remove_volatile)) // clang-format on
     // GNU libstdc++ 4.2 and libc++ use certain intrinsic names as the
     // name of struct templates, but some are keywords in GCC >= 4.3
     // and Clang. Therefore, when we see the token sequence "struct
Index: clang/lib/Parse/ParseDecl.cpp
===================================================================
--- clang/lib/Parse/ParseDecl.cpp
+++ clang/lib/Parse/ParseDecl.cpp
@@ -4115,6 +4115,17 @@
       ParseUnderlyingTypeSpecifier(DS);
       continue;
 
+    case tok::kw___add_const:
+    case tok::kw___add_cv:
+    case tok::kw___add_volatile:
+    case tok::kw___remove_const:
+    case tok::kw___remove_cv:
+    case tok::kw___remove_cvref:
+    case tok::kw___remove_reference:
+    case tok::kw___remove_volatile:
+      ParseTypeTransformTypeSpecifier(DS);
+      continue;
+
     case tok::kw__Atomic:
       // C11 6.7.2.4/4:
       //   If the _Atomic keyword is immediately followed by a left parenthesis,
@@ -4215,6 +4226,57 @@
   }
 }
 
+DeclSpec::TST Parser::TypeTransformTokToDeclSpec() {
+  switch (Tok.getKind()) {
+  case tok::kw___add_const:
+    return DeclSpec::TST_add_const;
+  case tok::kw___add_cv:
+    return DeclSpec::TST_add_cv;
+  case tok::kw___add_volatile:
+    return DeclSpec::TST_add_volatile;
+  case tok::kw___remove_const:
+    return DeclSpec::TST_remove_const;
+  case tok::kw___remove_cv:
+    return DeclSpec::TST_remove_cv;
+  case tok::kw___remove_cvref:
+    return DeclSpec::TST_remove_cvref;
+  case tok::kw___remove_reference:
+    return DeclSpec::TST_remove_reference;
+  case tok::kw___remove_volatile:
+    return DeclSpec::TST_remove_volatile;
+  }
+
+  __builtin_unreachable();
+}
+
+void Parser::ParseTypeTransformTypeSpecifier(DeclSpec &DS) {
+  DeclSpec::TST TypeTransformTST = TypeTransformTokToDeclSpec();
+  SourceLocation StartLoc = ConsumeToken();
+  BalancedDelimiterTracker T(*this, tok::l_paren);
+  if (T.expectAndConsume(diag::err_expected_lparen_after,
+                         "type transformation 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(TypeTransformTST, StartLoc, PrevSpec, DiagID,
+                         BaseTyResult.get(),
+                         Actions.getASTContext().getPrintingPolicy())) {
+    Diag(StartLoc, DiagID) << PrevSpec;
+  }
+  DS.setTypeofParensRange(T.getRange());
+}
+
 /// ParseStructDeclaration - Parse a struct declaration without the terminating
 /// semicolon.
 ///
Index: clang/lib/Lex/PPMacroExpansion.cpp
===================================================================
--- clang/lib/Lex/PPMacroExpansion.cpp
+++ clang/lib/Lex/PPMacroExpansion.cpp
@@ -1658,6 +1658,14 @@
               .Case("__array_extent", true)
               .Case("__reference_binds_to_temporary", true)
               .Case("__underlying_type", true)
+              .Case("__add_const", true)
+              .Case("__add_cv", true)
+              .Case("__add_volatile", true)
+              .Case("__remove_const", true)
+              .Case("__remove_cv", true)
+              .Case("__remove_cvref", true)
+              .Case("__remove_reference", true)
+              .Case("__remove_volatile", 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
@@ -57,6 +57,14 @@
   case tok::kw_wchar_t:
   case tok::kw_bool:
   case tok::kw___underlying_type:
+  case tok::kw___add_const:
+  case tok::kw___add_cv:
+  case tok::kw___add_volatile:
+  case tok::kw___remove_const:
+  case tok::kw___remove_cv:
+  case tok::kw___remove_cvref:
+  case tok::kw___remove_reference:
+  case tok::kw___remove_volatile:
   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
@@ -22,6 +22,7 @@
 #include "clang/AST/PrettyPrinter.h"
 #include "clang/AST/TemplateBase.h"
 #include "clang/AST/TemplateName.h"
+#include "clang/AST/TextNodeDumper.h"
 #include "clang/AST/Type.h"
 #include "clang/Basic/AddressSpaces.h"
 #include "clang/Basic/ExceptionSpecificationType.h"
@@ -1119,11 +1120,24 @@
 
   switch (T->getUTTKind()) {
     case UnaryTransformType::EnumUnderlyingType:
-      OS << "__underlying_type(";
+    case UnaryTransformType::AddConst:
+    case UnaryTransformType::AddCV:
+    case UnaryTransformType::AddVolatile:
+    case UnaryTransformType::RemoveConst:
+    case UnaryTransformType::RemoveCV:
+    case UnaryTransformType::RemoveCVRef:
+    case UnaryTransformType::RemoveReference:
+    case UnaryTransformType::RemoveVolatile: {
+      constexpr std::array<const char *, 9> Transformation = {
+          "__underlying_type", "__add_const",        "__add_cv",
+          "__add_volatile",    "__remove_const",     "__remove_cv",
+          "__remove_cvref",    "__remove_reference", "__remove_volatile"};
+      OS << Transformation[T->getUTTKind()] << '(';
       print(T->getBaseType(), OS, StringRef());
       OS << ')';
       spaceBeforePlaceHolder(OS);
       return;
+    }
   }
 
   printBefore(T->getBaseType(), OS);
@@ -1135,6 +1149,14 @@
 
   switch (T->getUTTKind()) {
     case UnaryTransformType::EnumUnderlyingType:
+    case UnaryTransformType::AddConst:
+    case UnaryTransformType::AddCV:
+    case UnaryTransformType::AddVolatile:
+    case UnaryTransformType::RemoveConst:
+    case UnaryTransformType::RemoveCV:
+    case UnaryTransformType::RemoveCVRef:
+    case UnaryTransformType::RemoveReference:
+    case UnaryTransformType::RemoveVolatile:
       return;
   }
 
Index: clang/lib/AST/TextNodeDumper.cpp
===================================================================
--- clang/lib/AST/TextNodeDumper.cpp
+++ clang/lib/AST/TextNodeDumper.cpp
@@ -1547,6 +1547,30 @@
   case UnaryTransformType::EnumUnderlyingType:
     OS << " underlying_type";
     break;
+  case UnaryTransformType::AddConst:
+    OS << " add_const";
+    break;
+  case UnaryTransformType::AddCV:
+    OS << " add_cv";
+    break;
+  case UnaryTransformType::AddVolatile:
+    OS << " add_volatile";
+    break;
+  case UnaryTransformType::RemoveConst:
+    OS << " remove_const";
+    break;
+  case UnaryTransformType::RemoveCV:
+    OS << " remove_cv";
+    break;
+  case UnaryTransformType::RemoveCVRef:
+    OS << " remove_cvref";
+    break;
+  case UnaryTransformType::RemoveReference:
+    OS << " remove_reference";
+    break;
+  case UnaryTransformType::RemoveVolatile:
+    OS << " remove_volatile";
+    break;
   }
 }
 
Index: clang/lib/AST/JSONNodeDumper.cpp
===================================================================
--- clang/lib/AST/JSONNodeDumper.cpp
+++ clang/lib/AST/JSONNodeDumper.cpp
@@ -665,6 +665,30 @@
   case UnaryTransformType::EnumUnderlyingType:
     JOS.attribute("transformKind", "underlying_type");
     break;
+  case UnaryTransformType::AddConst:
+    JOS.attribute("transformedKind", "add_const");
+    break;
+  case UnaryTransformType::AddCV:
+    JOS.attribute("transformedKind", "add_cv");
+    break;
+  case UnaryTransformType::AddVolatile:
+    JOS.attribute("transformedKind", "add_volatile");
+    break;
+  case UnaryTransformType::RemoveConst:
+    JOS.attribute("transformedKind", "remove_const");
+    break;
+  case UnaryTransformType::RemoveCV:
+    JOS.attribute("transformedKind", "remove_cv");
+    break;
+  case UnaryTransformType::RemoveCVRef:
+    JOS.attribute("transformedKind", "remove_cvref");
+    break;
+  case UnaryTransformType::RemoveReference:
+    JOS.attribute("transformedKind", "remove_reference");
+    break;
+  case UnaryTransformType::RemoveVolatile:
+    JOS.attribute("transformedKind", "remove_volatile");
+    break;
   }
 }
 
Index: clang/lib/AST/ItaniumMangle.cpp
===================================================================
--- clang/lib/AST/ItaniumMangle.cpp
+++ clang/lib/AST/ItaniumMangle.cpp
@@ -3925,6 +3925,30 @@
       case UnaryTransformType::EnumUnderlyingType:
         Out << "3eut";
         break;
+      case UnaryTransformType::AddConst:
+        Out << "3ac";
+        break;
+      case UnaryTransformType::AddCV:
+        Out << "3acv";
+        break;
+      case UnaryTransformType::AddVolatile:
+        Out << "3av";
+        break;
+      case UnaryTransformType::RemoveConst:
+        Out << "3rc";
+        break;
+      case UnaryTransformType::RemoveCV:
+        Out << "3rcv";
+        break;
+      case UnaryTransformType::RemoveCVRef:
+        Out << "3rcvr";
+        break;
+      case UnaryTransformType::RemoveReference:
+        Out << "3rr";
+        break;
+      case UnaryTransformType::RemoveVolatile:
+        Out << "3rv";
+        break;
     }
   }
 
Index: clang/include/clang/Sema/DeclSpec.h
===================================================================
--- clang/include/clang/Sema/DeclSpec.h
+++ clang/include/clang/Sema/DeclSpec.h
@@ -291,6 +291,14 @@
   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_add_const = clang::TST_add_const;
+  static const TST TST_add_cv = clang::TST_add_cv;
+  static const TST TST_add_volatile = clang::TST_add_volatile;
+  static const TST TST_remove_const = clang::TST_remove_const;
+  static const TST TST_remove_cv = clang::TST_remove_cv;
+  static const TST TST_remove_cvref = clang::TST_remove_cvref;
+  static const TST TST_remove_reference = clang::TST_remove_reference;
+  static const TST TST_remove_volatile = clang::TST_remove_volatile;
   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;
Index: clang/include/clang/Parse/Parser.h
===================================================================
--- clang/include/clang/Parse/Parser.h
+++ clang/include/clang/Parse/Parser.h
@@ -3034,6 +3034,8 @@
          SourceLocation &EllipsisLoc);
   void ParseBracketDeclarator(Declarator &D);
   void ParseMisplacedBracketDeclarator(Declarator &D);
+  void ParseTypeTransformTypeSpecifier(DeclSpec &DS);
+  DeclSpec::TST TypeTransformTokToDeclSpec();
 
   //===--------------------------------------------------------------------===//
   // C++ 7: Declarations [dcl.dcl]
Index: clang/include/clang/Basic/TokenKinds.def
===================================================================
--- clang/include/clang/Basic/TokenKinds.def
+++ clang/include/clang/Basic/TokenKinds.def
@@ -508,6 +508,14 @@
 TYPE_TRAIT_1(__has_unique_object_representations,
              HasUniqueObjectRepresentations, KEYCXX)
 KEYWORD(__underlying_type           , KEYCXX)
+KEYWORD(__add_const, KEYCXX)
+KEYWORD(__add_cv, KEYCXX)
+KEYWORD(__add_volatile, KEYCXX)
+KEYWORD(__remove_const, KEYCXX)
+KEYWORD(__remove_cv, KEYCXX)
+KEYWORD(__remove_cvref, KEYCXX)
+KEYWORD(__remove_reference, KEYCXX)
+KEYWORD(__remove_volatile, 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
@@ -53,41 +53,49 @@
     TST_unspecified,
     TST_void,
     TST_char,
-    TST_wchar,        // C++ wchar_t
-    TST_char8,        // C++20 char8_t (proposed)
-    TST_char16,       // C++11 char16_t
-    TST_char32,       // C++11 char32_t
+    TST_wchar,  // C++ wchar_t
+    TST_char8,  // C++20 char8_t (proposed)
+    TST_char16, // C++11 char16_t
+    TST_char32, // C++11 char32_t
     TST_int,
     TST_int128,
-    TST_bitint,       // Bit-precise integer types.
-    TST_half,         // OpenCL half, ARM NEON __fp16
-    TST_Float16,      // C11 extension ISO/IEC TS 18661-3
-    TST_Accum,        // ISO/IEC JTC1 SC22 WG14 N1169 Extension
+    TST_bitint,  // Bit-precise integer types.
+    TST_half,    // OpenCL half, ARM NEON __fp16
+    TST_Float16, // C11 extension ISO/IEC TS 18661-3
+    TST_Accum,   // ISO/IEC JTC1 SC22 WG14 N1169 Extension
     TST_Fract,
     TST_BFloat16,
     TST_float,
     TST_double,
     TST_float128,
     TST_ibm128,
-    TST_bool,         // _Bool
-    TST_decimal32,    // _Decimal32
-    TST_decimal64,    // _Decimal64
-    TST_decimal128,   // _Decimal128
+    TST_bool,       // _Bool
+    TST_decimal32,  // _Decimal32
+    TST_decimal64,  // _Decimal64
+    TST_decimal128, // _Decimal128
     TST_enum,
     TST_union,
     TST_struct,
-    TST_class,        // C++ class type
-    TST_interface,    // C++ (Microsoft-specific) __interface type
-    TST_typename,     // Typedef, C++ class-name or enum name, etc.
+    TST_class,     // C++ class type
+    TST_interface, // C++ (Microsoft-specific) __interface type
+    TST_typename,  // Typedef, C++ class-name or enum name, etc.
     TST_typeofType,
     TST_typeofExpr,
     TST_decltype,         // C++11 decltype
     TST_underlyingType,   // __underlying_type for C++11
+    TST_add_const,        // __add_const extension
+    TST_add_cv,           // __add_cv extension
+    TST_add_volatile,     // __add_volatile extension
+    TST_remove_const,     // __remove_const extension
+    TST_remove_cv,        // __remove_cv extension
+    TST_remove_cvref,     // __remove_cvref extension
+    TST_remove_reference, // __remove_reference extension
+    TST_remove_volatile,  // __remove_volatile extension
     TST_auto,             // C++11 auto
     TST_decltype_auto,    // C++1y decltype(auto)
     TST_auto_type,        // __auto_type extension
     TST_unknown_anytype,  // __unknown_anytype extension
-    TST_atomic,           // C11 _Atomic
+    TST_atomic,           // C11 _Atomic,
 #define GENERIC_IMAGE_TYPE(ImgType, Id) TST_##ImgType##_t, // OpenCL image types
 #include "clang/Basic/OpenCLImageTypes.def"
     TST_error // erroneous type
Index: clang/include/clang/AST/Type.h
===================================================================
--- clang/include/clang/AST/Type.h
+++ clang/include/clang/AST/Type.h
@@ -4553,7 +4553,15 @@
 class UnaryTransformType : public Type {
 public:
   enum UTTKind {
-    EnumUnderlyingType
+    EnumUnderlyingType,
+    AddCV,
+    AddConst,
+    AddVolatile,
+    RemoveConst,
+    RemoveCV,
+    RemoveCVRef,
+    RemoveReference,
+    RemoveVolatile,
   };
 
 private:
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to