diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -4558,6 +4558,7 @@ AddConst, AddVolatile, RemoveConst, + RemoveCV, RemoveVolatile, }; diff --git a/clang/include/clang/Basic/Specifiers.h b/clang/include/clang/Basic/Specifiers.h --- a/clang/include/clang/Basic/Specifiers.h +++ b/clang/include/clang/Basic/Specifiers.h @@ -87,6 +87,7 @@ 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_volatile, // __remove_volatile extension TST_auto, // C++11 auto TST_decltype_auto, // C++1y decltype(auto) diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/include/clang/Basic/TokenKinds.def @@ -512,6 +512,7 @@ KEYWORD(__add_cv, KEYCXX) KEYWORD(__add_volatile, KEYCXX) KEYWORD(__remove_const, KEYCXX) +KEYWORD(__remove_cv, KEYCXX) KEYWORD(__remove_volatile, KEYCXX) // Clang-only C++ Type Traits diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h --- a/clang/include/clang/Sema/DeclSpec.h +++ b/clang/include/clang/Sema/DeclSpec.h @@ -295,6 +295,7 @@ 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_volatile = clang::TST_remove_volatile; static const TST TST_auto = clang::TST_auto; static const TST TST_auto_type = clang::TST_auto_type; diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -3937,6 +3937,9 @@ case UnaryTransformType::RemoveConst: Out << "3rc"; break; + case UnaryTransformType::RemoveCV: + Out << "3rcv"; + break; case UnaryTransformType::RemoveVolatile: Out << "3rv"; break; diff --git a/clang/lib/AST/JSONNodeDumper.cpp b/clang/lib/AST/JSONNodeDumper.cpp --- a/clang/lib/AST/JSONNodeDumper.cpp +++ b/clang/lib/AST/JSONNodeDumper.cpp @@ -677,6 +677,9 @@ case UnaryTransformType::RemoveConst: JOS.attribute("transformedKind", "remove_const"); break; + case UnaryTransformType::RemoveCV: + JOS.attribute("transformedKind", "remove_cv"); + break; case UnaryTransformType::RemoveVolatile: JOS.attribute("transformedKind", "remove_volatile"); break; diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -1125,9 +1125,10 @@ case UnaryTransformType::AddVolatile: case UnaryTransformType::RemoveConst: case UnaryTransformType::RemoveVolatile: { - constexpr std::array Transformation = { + constexpr std::array Transformation = { "__underlying_type", "__add_const", "__add_cv", - "__add_volatile", "__remove_const", "__remove_volatile"}; + "__add_volatile", "__remove_const", "__remove_cv", + "__remove_volatile"}; OS << Transformation[T->getUTTKind()] << '('; print(T->getBaseType(), OS, StringRef()); OS << ')'; @@ -1149,6 +1150,7 @@ case UnaryTransformType::AddCV: case UnaryTransformType::AddVolatile: case UnaryTransformType::RemoveConst: + case UnaryTransformType::RemoveCV: case UnaryTransformType::RemoveVolatile: return; } diff --git a/clang/lib/Format/FormatToken.cpp b/clang/lib/Format/FormatToken.cpp --- a/clang/lib/Format/FormatToken.cpp +++ b/clang/lib/Format/FormatToken.cpp @@ -61,6 +61,7 @@ case tok::kw___add_cv: case tok::kw___add_volatile: case tok::kw___remove_const: + case tok::kw___remove_cv: case tok::kw___remove_volatile: case tok::annot_typename: case tok::kw_char8_t: diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp --- a/clang/lib/Lex/PPMacroExpansion.cpp +++ b/clang/lib/Lex/PPMacroExpansion.cpp @@ -1662,6 +1662,7 @@ .Case("__add_cv", true) .Case("__add_volatile", true) .Case("__remove_const", true) + .Case("__remove_cv", true) .Case("__remove_volatile", true) .Default(false); } else { diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -4119,6 +4119,7 @@ case tok::kw___add_cv: case tok::kw___add_volatile: case tok::kw___remove_const: + case tok::kw___remove_cv: case tok::kw___remove_volatile: ParseTypeTransformTypeSpecifier(DS); continue; @@ -4233,6 +4234,8 @@ 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_volatile: return DeclSpec::TST_remove_volatile; } diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -1534,7 +1534,7 @@ 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___is_volatile, tok::kw___remove_const, tok::kw___remove_cv, tok::kw___remove_volatile)) // GNU libstdc++ 4.2 and libc++ use certain intrinsic names as the // name of struct templates, but some are keywords in GCC >= 4.3 diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp --- a/clang/lib/Sema/DeclSpec.cpp +++ b/clang/lib/Sema/DeclSpec.cpp @@ -395,6 +395,7 @@ case TST_add_cv: case TST_add_volatile: case TST_remove_const: + case TST_remove_cv: case TST_remove_volatile: case TST_typename: case TST_typeofType: { @@ -591,6 +592,8 @@ return "__add_volatile"; case DeclSpec::TST_remove_const: return "__remove_const"; + case DeclSpec::TST_remove_cv: + return "__remove_cv"; case DeclSpec::TST_remove_volatile: return "__remove_volatile"; case DeclSpec::TST_unknown_anytype: return "__unknown_anytype"; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -149,6 +149,7 @@ case tok::kw___add_cv: case tok::kw___add_volatile: case tok::kw___remove_const: + case tok::kw___remove_cv: case tok::kw___remove_volatile: case tok::kw___auto_type: return true; @@ -5608,6 +5609,7 @@ case DeclSpec::TST_add_cv: case DeclSpec::TST_add_volatile: case DeclSpec::TST_remove_const: + case DeclSpec::TST_remove_cv: case DeclSpec::TST_remove_volatile: case DeclSpec::TST_atomic: { // Grab the type from the parser. diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp --- a/clang/lib/Sema/SemaTemplateVariadic.cpp +++ b/clang/lib/Sema/SemaTemplateVariadic.cpp @@ -865,6 +865,7 @@ case TST_add_cv: case TST_add_volatile: case TST_remove_const: + case TST_remove_cv: case TST_remove_volatile: case TST_atomic: { QualType T = DS.getRepAsType().get(); diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -1269,6 +1269,8 @@ return UnaryTransformType::AddVolatile; case TST_remove_const: return UnaryTransformType::RemoveConst; + case TST_remove_cv: + return UnaryTransformType::RemoveCV; case TST_remove_volatile: return UnaryTransformType::RemoveVolatile; case TST_underlyingType: @@ -1665,6 +1667,7 @@ case DeclSpec::TST_add_cv: case DeclSpec::TST_add_volatile: case DeclSpec::TST_remove_const: + case DeclSpec::TST_remove_cv: case DeclSpec::TST_remove_volatile: Result = S.GetTypeFromParser(DS.getRepAsType()); assert(!Result.isNull() && "Didn't get a type for the transformation?"); @@ -9097,6 +9100,7 @@ case UnaryTransformType::AddCV: case UnaryTransformType::AddVolatile: case UnaryTransformType::RemoveConst: + case UnaryTransformType::RemoveCV: case UnaryTransformType::RemoveVolatile: { SplitQualType Split = BaseType.getSplitUnqualifiedType(); Qualifiers Quals = BaseType.getQualifiers(); @@ -9115,6 +9119,9 @@ case UnaryTransformType::RemoveConst: Quals.removeConst(); break; + case UnaryTransformType::RemoveCV: + Quals.removeConst(); + [[fallthrough]]; case UnaryTransformType::RemoveVolatile: Quals.removeVolatile(); break; diff --git a/clang/test/SemaCXX/remove_cvref.cpp b/clang/test/SemaCXX/remove_cvref.cpp --- a/clang/test/SemaCXX/remove_cvref.cpp +++ b/clang/test/SemaCXX/remove_cvref.cpp @@ -9,6 +9,10 @@ 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), ""); return true; }