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, + 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 @@ -81,19 +81,20 @@ 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_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_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_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, #define GENERIC_IMAGE_TYPE(ImgType, Id) TST_##ImgType##_t, // OpenCL image types #include "clang/Basic/OpenCLImageTypes.def" TST_error // erroneous type 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_reference, 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 @@ -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_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; 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::RemoveReference: + Out << "3rr"; + 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 @@ -680,6 +680,9 @@ case UnaryTransformType::RemoveCV: JOS.attribute("transformedKind", "remove_cv"); break; + case UnaryTransformType::RemoveReference: + JOS.attribute("transformedKind", "remove_reference"); + 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,11 +1125,12 @@ case UnaryTransformType::AddVolatile: case UnaryTransformType::RemoveConst: case UnaryTransformType::RemoveCV: + case UnaryTransformType::RemoveReference: case UnaryTransformType::RemoveVolatile: { - constexpr std::array Transformation = { - "__underlying_type", "__add_const", "__add_cv", - "__add_volatile", "__remove_const", "__remove_cv", - "__remove_volatile"}; + constexpr std::array Transformation = { + "__underlying_type", "__add_const", "__add_cv", + "__add_volatile", "__remove_const", "__remove_cv", + "__remove_reference", "__remove_volatile"}; OS << Transformation[T->getUTTKind()] << '('; print(T->getBaseType(), OS, StringRef()); OS << ')'; @@ -1152,6 +1153,7 @@ case UnaryTransformType::AddVolatile: case UnaryTransformType::RemoveConst: case UnaryTransformType::RemoveCV: + 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_reference: 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 @@ -1663,6 +1663,7 @@ .Case("__add_volatile", true) .Case("__remove_const", true) .Case("__remove_cv", true) + .Case("__remove_reference", 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 @@ -4120,6 +4120,7 @@ case tok::kw___add_volatile: case tok::kw___remove_const: case tok::kw___remove_cv: + case tok::kw___remove_reference: case tok::kw___remove_volatile: ParseTypeTransformTypeSpecifier(DS); continue; @@ -4236,6 +4237,8 @@ return DeclSpec::TST_remove_const; case tok::kw___remove_cv: return DeclSpec::TST_remove_cv; + case tok::kw___remove_reference: + return DeclSpec::TST_remove_reference; 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 @@ -1535,7 +1535,7 @@ 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_volatile)) + 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_reference: case TST_remove_volatile: case TST_typename: case TST_typeofType: { @@ -594,6 +595,8 @@ return "__remove_const"; case DeclSpec::TST_remove_cv: return "__remove_cv"; + case DeclSpec::TST_remove_reference: + return "__remove_reference"; 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 @@ -150,6 +150,7 @@ case tok::kw___add_volatile: case tok::kw___remove_const: case tok::kw___remove_cv: + case tok::kw___remove_reference: case tok::kw___remove_volatile: case tok::kw___auto_type: return true; @@ -5610,6 +5611,7 @@ case DeclSpec::TST_add_volatile: case DeclSpec::TST_remove_const: case DeclSpec::TST_remove_cv: + case DeclSpec::TST_remove_reference: 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 @@ -866,6 +866,7 @@ case TST_add_volatile: case TST_remove_const: case TST_remove_cv: + case TST_remove_reference: 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 @@ -1271,6 +1271,8 @@ return UnaryTransformType::RemoveConst; case TST_remove_cv: return UnaryTransformType::RemoveCV; + case TST_remove_reference: + return UnaryTransformType::RemoveReference; case TST_remove_volatile: return UnaryTransformType::RemoveVolatile; case TST_underlyingType: @@ -1668,6 +1670,7 @@ case DeclSpec::TST_add_volatile: case DeclSpec::TST_remove_const: case DeclSpec::TST_remove_cv: + case DeclSpec::TST_remove_reference: case DeclSpec::TST_remove_volatile: Result = S.GetTypeFromParser(DS.getRepAsType()); assert(!Result.isNull() && "Didn't get a type for the transformation?"); @@ -9096,6 +9099,11 @@ return Context.getUnaryTransformType(BaseType, Underlying, UnaryTransformType::EnumUnderlyingType); } + case UnaryTransformType::RemoveReference: { + QualType Underlying = BaseType.getNonReferenceType(); + return Context.getUnaryTransformType(BaseType, Underlying, + UnaryTransformType::RemoveReference); + } case UnaryTransformType::AddConst: case UnaryTransformType::AddCV: case UnaryTransformType::AddVolatile: 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 @@ -1,5 +1,24 @@ // RUN: %clang_cc1 -std=c++11 %s +template +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), ""); + } +}; + +template<> struct check_remove_reference {}; +template struct check_remove_reference {}; +template struct check_remove_reference {}; + template constexpr bool check_remove_qualifiers() { static_assert(__is_same(__remove_const(const T), T), ""); @@ -13,6 +32,9 @@ 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(); + return true; } @@ -26,6 +48,10 @@ static_assert(check_remove_qualifiers(), ""); static_assert(check_remove_qualifiers(), ""); static_assert(check_remove_qualifiers(), ""); +static_assert(check_remove_qualifiers(), ""); +static_assert(check_remove_qualifiers(), ""); +static_assert(check_remove_qualifiers(), ""); +static_assert(check_remove_qualifiers(), ""); static_assert(check_remove_qualifiers(), ""); static_assert(check_remove_qualifiers(), ""); static_assert(check_remove_qualifiers(), "");