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 @@ -4559,6 +4559,7 @@ AddVolatile, RemoveConst, RemoveCV, + RemoveCVRef, RemoveReference, 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 @@ -88,6 +88,7 @@ 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 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 @@ -513,6 +513,7 @@ KEYWORD(__add_volatile, KEYCXX) KEYWORD(__remove_const, KEYCXX) KEYWORD(__remove_cv, KEYCXX) +KEYWORD(__remove_cvref, KEYCXX) KEYWORD(__remove_reference, KEYCXX) KEYWORD(__remove_volatile, KEYCXX) 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 @@ -296,6 +296,7 @@ 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; 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 @@ -3940,6 +3940,9 @@ case UnaryTransformType::RemoveCV: Out << "3rcv"; break; + case UnaryTransformType::RemoveCVRef: + Out << "3rcvr"; + break; case UnaryTransformType::RemoveReference: Out << "3rr"; 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 @@ -680,6 +680,9 @@ 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; 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,12 +1125,13 @@ case UnaryTransformType::AddVolatile: case UnaryTransformType::RemoveConst: case UnaryTransformType::RemoveCV: + case UnaryTransformType::RemoveCVRef: case UnaryTransformType::RemoveReference: case UnaryTransformType::RemoveVolatile: { - constexpr std::array Transformation = { - "__underlying_type", "__add_const", "__add_cv", - "__add_volatile", "__remove_const", "__remove_cv", - "__remove_reference", "__remove_volatile"}; + constexpr std::array 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 << ')'; @@ -1153,6 +1154,7 @@ case UnaryTransformType::AddVolatile: case UnaryTransformType::RemoveConst: case UnaryTransformType::RemoveCV: + case UnaryTransformType::RemoveCVRef: case UnaryTransformType::RemoveReference: 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 @@ -62,6 +62,7 @@ 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: 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 @@ -1663,6 +1663,7 @@ .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); 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 @@ -4120,6 +4120,7 @@ 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); @@ -4237,6 +4238,8 @@ 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: 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 @@ -1535,7 +1535,8 @@ 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_reference, tok::kw___remove_volatile)) + tok::kw___remove_cvref, tok::kw___remove_reference, + 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 // and Clang. Therefore, when we see the token sequence "struct 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 @@ -396,6 +396,7 @@ 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: @@ -595,6 +596,8 @@ 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: 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 @@ -150,6 +150,7 @@ 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: @@ -5611,6 +5612,7 @@ 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: { 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 @@ -866,6 +866,7 @@ 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: { 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 @@ -1271,6 +1271,8 @@ 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: @@ -1670,6 +1672,7 @@ 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()); @@ -9099,10 +9102,19 @@ return Context.getUnaryTransformType(BaseType, Underlying, UnaryTransformType::EnumUnderlyingType); } + case UnaryTransformType::RemoveCVRef: case UnaryTransformType::RemoveReference: { QualType Underlying = BaseType.getNonReferenceType(); - return Context.getUnaryTransformType(BaseType, Underlying, - UnaryTransformType::RemoveReference); + 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: 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 @@ -12,6 +12,16 @@ 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), ""); } };