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 @@ -740,6 +740,8 @@ return Value.getPointer().isNull(); } + bool isReferenceable() const; + /// Determine whether this particular QualType instance has the /// "const" qualifier set, without looking through typedefs that may have /// added "const" at a different level. @@ -4553,7 +4555,24 @@ class UnaryTransformType : public Type { public: enum UTTKind { - EnumUnderlyingType + EnumUnderlyingType, + AddCV, + AddConst, + AddLvalueReference, + AddPointer, + AddRvalueReference, + AddVolatile, + Decay, + MakeSigned, + MakeUnsigned, + RemoveConst, + RemoveCV, + RemoveCVRef, + RemoveAllExtents, + RemoveExtent, + RemovePointer, + RemoveReference, + RemoveVolatile, }; private: @@ -6455,6 +6474,21 @@ return (isNull() ? nullptr : getCommonPtr()->BaseType); } +inline bool QualType::isReferenceable() const { + // C++ [defns.referenceable] + // type that is either an object type, a function type that does not have + // cv-qualifiers or a ref-qualifier, or a reference type + const Type &Self = **this; + if (Self.isObjectType() || Self.isReferenceType()) + return true; + if (!Self.isFunctionType()) + return false; + + const auto *F = Self.getAs(); + return F == nullptr || + (F->getMethodQuals().empty() && F->getRefQualifier() == RQ_None); +} + inline SplitQualType QualType::split() const { if (!hasLocalNonFastQualifiers()) return SplitQualType(getTypePtrUnsafe(), diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -8591,6 +8591,8 @@ "a vector of such types is required">; def err_cast_selector_expr : Error< "cannot type cast @selector expression">; +def err_make_signed_integral_only : Error< + "'%select{make_unsigned|make_signed}0' is only compatible with non-bool integers and enum types, but was given %1">; def ext_typecheck_cond_incompatible_pointers : ExtWarn< "pointer type mismatch%diff{ ($ and $)|}0,1">, InGroup>; 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 @@ -53,41 +53,58 @@ 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_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 trait + TST_add_cv, // __add_cv trait + TST_add_lvalue_reference, // __add_add_lvalue_reference trait + TST_add_pointer, // __add_pointer trait + TST_add_rvalue_reference, // __add_add_rvalue_reference trait + TST_add_volatile, // __add_volatile trait + TST_decay, // __decay trait + TST_make_signed, // __make_signed trait + TST_make_unsigned, // __make_unsigned trait + TST_remove_const, // __remove_const trait + TST_remove_cv, // __remove_cv trait + TST_remove_cvref, // __remove_cvref trait + TST_remove_all_extents, // __remove_all_extents trait + TST_remove_extent, // __remove_extent trait + TST_remove_pointer, // __remove_pointer trait + TST_remove_reference, // __remove_reference trait + TST_remove_volatile, // __remove_volatile trait + 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 @@ -96,8 +113,8 @@ /// Structure that packs information about the type specifiers that /// were written in a particular type specifier sequence. struct WrittenBuiltinSpecs { - static_assert(TST_error < 1 << 6, "Type bitfield not wide enough for TST"); - /*DeclSpec::TST*/ unsigned Type : 6; + static_assert(TST_error < 1 << 7, "Type bitfield not wide enough for TST"); + /*DeclSpec::TST*/ unsigned Type : 7; /*DeclSpec::TSS*/ unsigned Sign : 2; /*TypeSpecifierWidth*/ unsigned Width : 2; unsigned ModeAttr : 1; 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 @@ -508,6 +508,23 @@ TYPE_TRAIT_1(__has_unique_object_representations, HasUniqueObjectRepresentations, KEYCXX) KEYWORD(__underlying_type , KEYCXX) +KEYWORD(__add_const, KEYCXX) +KEYWORD(__add_cv, KEYCXX) +KEYWORD(__add_lvalue_reference, KEYCXX) +KEYWORD(__add_pointer, KEYCXX) +KEYWORD(__add_rvalue_reference, KEYCXX) +KEYWORD(__add_volatile, KEYCXX) +KEYWORD(__decay, KEYCXX) +KEYWORD(__make_signed, KEYCXX) +KEYWORD(__make_unsigned, KEYCXX) +KEYWORD(__remove_const, KEYCXX) +KEYWORD(__remove_cv, KEYCXX) +KEYWORD(__remove_cvref, KEYCXX) +KEYWORD(__remove_all_extents, KEYCXX) +KEYWORD(__remove_extent, KEYCXX) +KEYWORD(__remove_pointer, KEYCXX) +KEYWORD(__remove_reference, KEYCXX) +KEYWORD(__remove_volatile, KEYCXX) // Clang-only C++ Type Traits TYPE_TRAIT_2(__reference_binds_to_temporary, ReferenceBindsToTemporary, KEYCXX) diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h --- a/clang/include/clang/Parse/Parser.h +++ b/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] 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 @@ -32,6 +32,7 @@ #include "clang/Lex/Token.h" #include "clang/Sema/Ownership.h" #include "clang/Sema/ParsedAttr.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" @@ -291,6 +292,23 @@ 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_lvalue_reference = clang::TST_add_lvalue_reference; + static const TST TST_add_pointer = clang::TST_add_pointer; + static const TST TST_add_rvalue_reference = clang::TST_add_rvalue_reference; + static const TST TST_add_volatile = clang::TST_add_volatile; + static const TST TST_decay = clang::TST_decay; + static const TST TST_make_signed = clang::TST_make_signed; + static const TST TST_make_unsigned = clang::TST_make_unsigned; + 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_all_extents = clang::TST_remove_all_extents; + static const TST TST_remove_extent = clang::TST_remove_extent; + static const TST TST_remove_pointer = clang::TST_remove_pointer; + 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; @@ -333,7 +351,7 @@ /*TypeSpecifierWidth*/ unsigned TypeSpecWidth : 2; /*TSC*/unsigned TypeSpecComplex : 2; /*TSS*/unsigned TypeSpecSign : 2; - /*TST*/unsigned TypeSpecType : 6; + /*TST*/ unsigned TypeSpecType : 7; unsigned TypeAltiVecVector : 1; unsigned TypeAltiVecPixel : 1; unsigned TypeAltiVecBool : 1; @@ -400,8 +418,30 @@ ObjCDeclSpec *ObjCQualifiers; static bool isTypeRep(TST T) { - return (T == TST_typename || T == TST_typeofType || - T == TST_underlyingType || T == TST_atomic); + constexpr std::array validTSTs = { + TST_add_const, + TST_add_cv, + TST_add_lvalue_reference, + TST_add_pointer, + TST_add_rvalue_reference, + TST_add_volatile, + TST_atomic, + TST_decay, + TST_make_signed, + TST_make_unsigned, + TST_remove_const, + TST_remove_cv, + TST_remove_cvref, + TST_remove_extent, + TST_remove_all_extents, + TST_remove_pointer, + TST_remove_reference, + TST_remove_volatile, + TST_typename, + TST_typeofType, + TST_underlyingType, + }; + return llvm::any_of(validTSTs, [T](TST X) { return X == T; }); } static bool isExprRep(TST T) { return (T == TST_typeofExpr || T == TST_decltype || T == TST_bitint); diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -5601,6 +5601,7 @@ /// getUnaryTransformationType - We don't unique these, since the memory /// savings are minimal and these are rare. +// Update 2021-12-16: it might be worth revisiting this QualType ASTContext::getUnaryTransformType(QualType BaseType, QualType UnderlyingType, UnaryTransformType::UTTKind Kind) 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 @@ -3925,6 +3925,57 @@ case UnaryTransformType::EnumUnderlyingType: Out << "3eut"; break; + case UnaryTransformType::AddConst: + Out << "2ac"; + break; + case UnaryTransformType::AddCV: + Out << "3acv"; + break; + case UnaryTransformType::AddLvalueReference: + Out << "5alref"; + break; + case UnaryTransformType::AddPointer: + Out << "4aptr"; + break; + case UnaryTransformType::AddRvalueReference: + Out << "5arref"; + break; + case UnaryTransformType::AddVolatile: + Out << "2av"; + break; + case UnaryTransformType::Decay: + Out << "1d"; + break; + case UnaryTransformType::MakeSigned: + Out << "3msi"; + break; + case UnaryTransformType::MakeUnsigned: + Out << "3mui"; + break; + case UnaryTransformType::RemoveConst: + Out << "2rc"; + break; + case UnaryTransformType::RemoveCV: + Out << "3rcv"; + break; + case UnaryTransformType::RemoveCVRef: + Out << "6rcvref"; + break; + case UnaryTransformType::RemoveExtent: + Out << "3rae"; + break; + case UnaryTransformType::RemoveAllExtents: + Out << "4raae"; + break; + case UnaryTransformType::RemovePointer: + Out << "4rptr"; + break; + case UnaryTransformType::RemoveReference: + Out << "2rr"; + break; + case UnaryTransformType::RemoveVolatile: + Out << "2rv"; + 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 @@ -1,4 +1,5 @@ #include "clang/AST/JSONNodeDumper.h" +#include "clang/AST/Type.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/Specifiers.h" #include "clang/Lex/Lexer.h" @@ -665,6 +666,57 @@ 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::AddLvalueReference: + JOS.attribute("transformedKind", "add_lvalue_reference"); + break; + case UnaryTransformType::AddPointer: + JOS.attribute("transformedKind", "add_pointer"); + break; + case UnaryTransformType::AddRvalueReference: + JOS.attribute("transformedKind", "add_rvalue_reference"); + break; + case UnaryTransformType::AddVolatile: + JOS.attribute("transformedKind", "add_volatile"); + break; + case UnaryTransformType::Decay: + JOS.attribute("transformedKind", "decay"); + break; + case UnaryTransformType::MakeSigned: + JOS.attribute("transformedKind", "make_signed"); + break; + case UnaryTransformType::MakeUnsigned: + JOS.attribute("transformedKind", "make_unsigned"); + break; + case UnaryTransformType::RemoveAllExtents: + JOS.attribute("transformedKind", "remove_all_extents"); + 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::RemoveExtent: + JOS.attribute("transformedKind", "remove_extent"); + break; + case UnaryTransformType::RemovePointer: + JOS.attribute("transformedKind", "remove_pointer"); + 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/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -1547,6 +1547,57 @@ case UnaryTransformType::EnumUnderlyingType: OS << " underlying_type"; break; + case UnaryTransformType::AddConst: + OS << " add_const"; + break; + case UnaryTransformType::AddCV: + OS << " add_cv"; + break; + case UnaryTransformType::AddLvalueReference: + OS << " add_lvalue_reference"; + break; + case UnaryTransformType::AddPointer: + OS << " add_pointer"; + break; + case UnaryTransformType::AddRvalueReference: + OS << " add_rvalue_reference"; + break; + case UnaryTransformType::AddVolatile: + OS << " add_volatile"; + break; + case UnaryTransformType::Decay: + OS << " decay"; + break; + case UnaryTransformType::MakeSigned: + OS << " make_signed"; + break; + case UnaryTransformType::MakeUnsigned: + OS << " make_unsigned"; + break; + case UnaryTransformType::RemoveAllExtents: + OS << " remove_all_extents"; + break; + case UnaryTransformType::RemoveConst: + OS << " remove_const"; + break; + case UnaryTransformType::RemoveCV: + OS << " remove_cv"; + break; + case UnaryTransformType::RemoveCVRef: + OS << " remove_cvref"; + break; + case UnaryTransformType::RemoveExtent: + OS << " remove_extent"; + break; + case UnaryTransformType::RemovePointer: + OS << " remove_pointer"; + break; + case UnaryTransformType::RemoveReference: + OS << " remove_reference"; + break; + case UnaryTransformType::RemoveVolatile: + OS << " 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 @@ -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" @@ -32,6 +33,7 @@ #include "clang/Basic/SourceManager.h" #include "clang/Basic/Specifiers.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" @@ -1119,11 +1121,48 @@ switch (T->getUTTKind()) { case UnaryTransformType::EnumUnderlyingType: - OS << "__underlying_type("; + case UnaryTransformType::AddConst: + case UnaryTransformType::AddCV: + case UnaryTransformType::AddLvalueReference: + case UnaryTransformType::AddPointer: + case UnaryTransformType::AddRvalueReference: + case UnaryTransformType::AddVolatile: + case UnaryTransformType::Decay: + case UnaryTransformType::MakeSigned: + case UnaryTransformType::MakeUnsigned: + case UnaryTransformType::RemoveAllExtents: + case UnaryTransformType::RemoveConst: + case UnaryTransformType::RemoveCV: + case UnaryTransformType::RemoveCVRef: + case UnaryTransformType::RemoveExtent: + case UnaryTransformType::RemovePointer: + case UnaryTransformType::RemoveReference: + case UnaryTransformType::RemoveVolatile: { + static llvm::DenseMap Transformation = { + {{UnaryTransformType::EnumUnderlyingType, "__underlying_type"}, + {UnaryTransformType::AddConst, "__add_const"}, + {UnaryTransformType::AddCV, "__add_cv"}, + {UnaryTransformType::AddLvalueReference, "__add_lvalue_reference"}, + {UnaryTransformType::AddPointer, "__add_pointer"}, + {UnaryTransformType::AddRvalueReference, "__add_rvalue_reference"}, + {UnaryTransformType::AddVolatile, "__add_volatile"}, + {UnaryTransformType::Decay, "__decay"}, + {UnaryTransformType::MakeSigned, "__make_signed"}, + {UnaryTransformType::MakeUnsigned, "__make_unsigned"}, + {UnaryTransformType::RemoveAllExtents, "__remove_all_extents"}, + {UnaryTransformType::RemoveConst, "__remove_const"}, + {UnaryTransformType::RemoveCV, "__remove_cv"}, + {UnaryTransformType::RemoveCVRef, "__remove_cvref"}, + {UnaryTransformType::RemoveExtent, "__remove_extent"}, + {UnaryTransformType::RemovePointer, "__remove_pointer"}, + {UnaryTransformType::RemoveReference, "__remove_reference"}, + {UnaryTransformType::RemoveVolatile, "__remove_volatile"}}}; + OS << Transformation[T->getUTTKind()] << '('; print(T->getBaseType(), OS, StringRef()); OS << ')'; spaceBeforePlaceHolder(OS); return; + } } printBefore(T->getBaseType(), OS); @@ -1135,6 +1174,23 @@ switch (T->getUTTKind()) { case UnaryTransformType::EnumUnderlyingType: + case UnaryTransformType::AddConst: + case UnaryTransformType::AddCV: + case UnaryTransformType::AddLvalueReference: + case UnaryTransformType::AddPointer: + case UnaryTransformType::AddRvalueReference: + case UnaryTransformType::AddVolatile: + case UnaryTransformType::Decay: + case UnaryTransformType::MakeSigned: + case UnaryTransformType::MakeUnsigned: + case UnaryTransformType::RemoveAllExtents: + case UnaryTransformType::RemoveConst: + case UnaryTransformType::RemoveCV: + case UnaryTransformType::RemoveCVRef: + case UnaryTransformType::RemoveExtent: + case UnaryTransformType::RemovePointer: + 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 @@ -57,6 +57,23 @@ 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_lvalue_reference: + case tok::kw___add_pointer: + case tok::kw___add_rvalue_reference: + case tok::kw___add_volatile: + case tok::kw___decay: + case tok::kw___make_signed: + case tok::kw___make_unsigned: + case tok::kw___remove_all_extents: + case tok::kw___remove_const: + case tok::kw___remove_cv: + case tok::kw___remove_cvref: + case tok::kw___remove_extent: + case tok::kw___remove_pointer: + case tok::kw___remove_reference: + case tok::kw___remove_volatile: case tok::annot_typename: case tok::kw_char8_t: case tok::kw_char16_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 @@ -1658,6 +1658,23 @@ .Case("__array_extent", true) .Case("__reference_binds_to_temporary", true) .Case("__underlying_type", true) + .Case("__add_const", true) + .Case("__add_cv", true) + .Case("__add_lvalue_reference", true) + .Case("__add_pointer", true) + .Case("__add_rvalue_reference", true) + .Case("__add_volatile", true) + .Case("__decay", true) + .Case("__make_signed", true) + .Case("__make_unsigned", true) + .Case("__remove_all_extents", true) + .Case("__remove_const", true) + .Case("__remove_cv", true) + .Case("__remove_cvref", true) + .Case("__remove_extent", true) + .Case("__remove_pointer", true) + .Case("__remove_reference", true) + .Case("__remove_volatile", true) .Default(false); } else { return llvm::StringSwitch(II->getName()) 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 @@ -4115,6 +4115,26 @@ ParseUnderlyingTypeSpecifier(DS); continue; + case tok::kw___add_const: + case tok::kw___add_cv: + case tok::kw___add_lvalue_reference: + case tok::kw___add_pointer: + case tok::kw___add_rvalue_reference: + case tok::kw___add_volatile: + case tok::kw___decay: + case tok::kw___make_signed: + case tok::kw___make_unsigned: + case tok::kw___remove_all_extents: + case tok::kw___remove_const: + case tok::kw___remove_cv: + case tok::kw___remove_cvref: + case tok::kw___remove_extent: + case tok::kw___remove_pointer: + 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 +4235,59 @@ } } +DeclSpec::TST Parser::TypeTransformTokToDeclSpec() { + switch (Tok.getKind()) { // clang-format off + case tok::kw___add_const: return DeclSpec::TST_add_const; + case tok::kw___add_cv: return DeclSpec::TST_add_cv; + case tok::kw___add_lvalue_reference: return DeclSpec::TST_add_lvalue_reference; + case tok::kw___add_pointer: return DeclSpec::TST_add_pointer; + case tok::kw___add_rvalue_reference: return DeclSpec::TST_add_rvalue_reference; + case tok::kw___add_volatile: return DeclSpec::TST_add_volatile; + case tok::kw___decay: return DeclSpec::TST_decay; + case tok::kw___make_signed: return DeclSpec::TST_make_signed; + case tok::kw___make_unsigned: return DeclSpec::TST_make_unsigned; + case tok::kw___remove_all_extents: return DeclSpec::TST_remove_all_extents; + 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_extent: return DeclSpec::TST_remove_extent; + case tok::kw___remove_pointer: return DeclSpec::TST_remove_pointer; + case tok::kw___remove_reference: return DeclSpec::TST_remove_reference; + case tok::kw___remove_volatile: return DeclSpec::TST_remove_volatile; + default: + llvm_unreachable(__FILE__ + "passed in an unhandled type transformation built-in"); + } // clang-format on +} + +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. /// 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 @@ -1508,61 +1508,77 @@ // 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_lvalue_reference, + tok::kw___add_pointer, + tok::kw___add_rvalue_reference, + tok::kw___add_volatile, + tok::kw___decay, + 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___make_signed, + tok::kw___make_unsigned, + tok::kw___remove_all_extents, + tok::kw___remove_const, + tok::kw___remove_cv, + tok::kw___remove_cvref, + tok::kw___remove_extent, + tok::kw___remove_pointer, + 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 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 @@ -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,23 @@ return false; case TST_underlyingType: + case TST_add_const: + case TST_add_cv: + case TST_add_lvalue_reference: + case TST_add_pointer: + case TST_add_rvalue_reference: + case TST_add_volatile: + case TST_decay: + case TST_make_signed: + case TST_make_unsigned: + case TST_remove_all_extents: + case TST_remove_const: + case TST_remove_cv: + case TST_remove_cvref: + case TST_remove_extent: + case TST_remove_pointer: + case TST_remove_reference: + case TST_remove_volatile: case TST_typename: case TST_typeofType: { QualType QT = DS.getRepAsType().get(); @@ -576,7 +594,25 @@ case DeclSpec::TST_auto_type: return "__auto_type"; case DeclSpec::TST_decltype: return "(decltype)"; case DeclSpec::TST_decltype_auto: return "decltype(auto)"; + // clang-format off 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_lvalue_reference: return "__add_lvalue_reference"; + case DeclSpec::TST_add_pointer: return "__add_pointer"; + case DeclSpec::TST_add_rvalue_reference: return "__add_rvalue_reference"; + case DeclSpec::TST_add_volatile: return "__add_volatile"; + case DeclSpec::TST_decay: return "__decay"; + case DeclSpec::TST_make_signed: return "__make_signed"; + case DeclSpec::TST_make_unsigned: return "__make_unsigned"; + case DeclSpec::TST_remove_all_extents: return "__remove_all_extents"; + 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_extent: return "__remove_extent"; + case DeclSpec::TST_remove_pointer: return "__remove_pointer"; + case DeclSpec::TST_remove_reference: return "__remove_reference"; + case DeclSpec::TST_remove_volatile: return "__remove_volatile"; // clang-format on case DeclSpec::TST_unknown_anytype: return "__unknown_anytype"; case DeclSpec::TST_atomic: return "_Atomic"; case DeclSpec::TST_BFloat16: return "__bf16"; 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 @@ -145,6 +145,19 @@ 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___decay: + case tok::kw___make_signed: + case tok::kw___make_unsigned: + case tok::kw___remove_all_extents: + case tok::kw___remove_const: + case tok::kw___remove_cv: + case tok::kw___remove_cvref: + case tok::kw___remove_extent: + case tok::kw___remove_reference: + case tok::kw___remove_volatile: case tok::kw___auto_type: return true; @@ -5599,6 +5612,19 @@ 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_decay: + case DeclSpec::TST_make_signed: + case DeclSpec::TST_make_unsigned: + case DeclSpec::TST_remove_all_extents: + case DeclSpec::TST_remove_const: + case DeclSpec::TST_remove_cv: + case DeclSpec::TST_remove_cvref: + case DeclSpec::TST_remove_extent: + case DeclSpec::TST_remove_reference: + case DeclSpec::TST_remove_volatile: case DeclSpec::TST_atomic: { // Grab the type from the parser. TypeSourceInfo *TSI = nullptr; 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 @@ -861,6 +861,23 @@ case TST_typename: case TST_typeofType: case TST_underlyingType: + case TST_add_const: + case TST_add_cv: + case TST_add_lvalue_reference: + case TST_add_pointer: + case TST_add_rvalue_reference: + case TST_add_volatile: + case TST_decay: + case TST_make_signed: + case TST_make_unsigned: + case TST_remove_all_extents: + case TST_remove_const: + case TST_remove_cv: + case TST_remove_cvref: + case TST_remove_extent: + case TST_remove_pointer: + case TST_remove_reference: + case TST_remove_volatile: case TST_atomic: { QualType T = DS.getRepAsType().get(); if (!T.isNull() && T->containsUnexpandedParameterPack()) 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 @@ -19,9 +19,11 @@ #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" +#include "clang/AST/Type.h" #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 +1259,31 @@ 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_lvalue_reference: return UnaryTransformType::AddLvalueReference; + case TST_add_pointer: return UnaryTransformType::AddPointer; + case TST_add_rvalue_reference: return UnaryTransformType::AddRvalueReference; + case TST_add_volatile: return UnaryTransformType::AddVolatile; + case TST_decay: return UnaryTransformType::Decay; + case TST_make_signed: return UnaryTransformType::MakeSigned; + case TST_make_unsigned: return UnaryTransformType::MakeUnsigned; + case TST_remove_all_extents: return UnaryTransformType::RemoveAllExtents; + case TST_remove_const: return UnaryTransformType::RemoveConst; + case TST_remove_cv: return UnaryTransformType::RemoveCV; + case TST_remove_cvref: return UnaryTransformType::RemoveCVRef; + case TST_remove_extent: return UnaryTransformType::RemoveExtent; + case TST_remove_pointer: return UnaryTransformType::RemovePointer; + 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,31 @@ break; } case DeclSpec::TST_underlyingType: + case DeclSpec::TST_add_const: + case DeclSpec::TST_add_cv: + case DeclSpec::TST_add_lvalue_reference: + case DeclSpec::TST_add_pointer: + case DeclSpec::TST_add_rvalue_reference: + case DeclSpec::TST_add_volatile: + case DeclSpec::TST_decay: + case DeclSpec::TST_make_signed: + case DeclSpec::TST_make_unsigned: + case DeclSpec::TST_remove_all_extents: + case DeclSpec::TST_remove_const: + case DeclSpec::TST_remove_cv: + case DeclSpec::TST_remove_cvref: + case DeclSpec::TST_remove_extent: + case DeclSpec::TST_remove_pointer: + 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 +6019,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()); @@ -9036,34 +9082,157 @@ QualType Sema::BuildUnaryTransformType(QualType BaseType, UnaryTransformType::UTTKind UKind, SourceLocation Loc) { + if (BaseType->isDependentType()) + return Context.getUnaryTransformType(BaseType, BaseType, UKind); switch (UKind) { - case UnaryTransformType::EnumUnderlyingType: - if (!BaseType->isDependentType() && !BaseType->isEnumeralType()) { + case UnaryTransformType::EnumUnderlyingType: { + if (!BaseType->isEnumeralType()) { Diag(Loc, diag::err_only_enums_have_underlying_types); return QualType(); - } else { - QualType Underlying = BaseType; - if (!BaseType->isDependentType()) { - // The enum could be incomplete if we're parsing its definition or - // recovering from an error. - NamedDecl *FwdDecl = nullptr; - if (BaseType->isIncompleteType(&FwdDecl)) { - Diag(Loc, diag::err_underlying_type_of_incomplete_enum) << BaseType; - Diag(FwdDecl->getLocation(), diag::note_forward_declaration) << FwdDecl; - return QualType(); - } - - EnumDecl *ED = BaseType->castAs()->getDecl(); - assert(ED && "EnumType has no EnumDecl"); + } - DiagnoseUseOfDecl(ED, Loc); + // The enum could be incomplete if we're parsing its definition or + // recovering from an error. + NamedDecl *FwdDecl = nullptr; + if (BaseType->isIncompleteType(&FwdDecl)) { + Diag(Loc, diag::err_underlying_type_of_incomplete_enum) << BaseType; + Diag(FwdDecl->getLocation(), diag::note_forward_declaration) << FwdDecl; + return QualType(); + } - Underlying = ED->getIntegerType(); - assert(!Underlying.isNull()); - } - return Context.getUnaryTransformType(BaseType, Underlying, - UnaryTransformType::EnumUnderlyingType); + EnumDecl *ED = BaseType->castAs()->getDecl(); + assert(ED && "EnumType has no EnumDecl"); + + DiagnoseUseOfDecl(ED, Loc); + + QualType Underlying = ED->getIntegerType(); + assert(!Underlying.isNull()); + return Context.getUnaryTransformType(BaseType, Underlying, + UnaryTransformType::EnumUnderlyingType); + } + case UnaryTransformType::AddPointer: { + DeclarationName EntityName(BaseType.getBaseTypeIdentifier()); + QualType PointerToT = + BaseType.isReferenceable() || BaseType->isVoidType() + ? BuildPointerType(BaseType.getNonReferenceType(), Loc, EntityName) + : BaseType; + return Context.getUnaryTransformType(BaseType, PointerToT, UKind); + } + case UnaryTransformType::RemovePointer: { + if (!BaseType->isPointerType()) + return Context.getUnaryTransformType(BaseType, BaseType, UKind); + return Context.getUnaryTransformType(BaseType, BaseType->getPointeeType(), + UKind); + } + case UnaryTransformType::Decay: { + QualType Underlying = BaseType.getNonReferenceType(); + if (Underlying->isArrayType() || Underlying->isFunctionType()) + return Context.getUnaryTransformType( + BaseType, Context.getDecayedType(Underlying), UKind); + + Qualifiers Quals = Underlying.getQualifiers(); + Quals.removeCVRQualifiers(); + return Context.getUnaryTransformType( + BaseType, + QualType(Underlying.getSplitUnqualifiedType().Ty, + Quals.getAsOpaqueValue()), + UKind); + } + case UnaryTransformType::AddLvalueReference: + case UnaryTransformType::AddRvalueReference: { + DeclarationName EntityName(BaseType.getBaseTypeIdentifier()); + QualType PointerToT = + QualType(BaseType).isReferenceable() + ? BuildReferenceType( + BaseType, UKind == UnaryTransformType::AddLvalueReference, + Loc, EntityName) + : BaseType; + return Context.getUnaryTransformType(BaseType, PointerToT, UKind); + } + case UnaryTransformType::RemoveAllExtents: + case UnaryTransformType::RemoveExtent: { + if (!BaseType->isArrayType()) + return Context.getUnaryTransformType(BaseType, BaseType, UKind); + const ArrayType* ArrayType = BaseType->getAsArrayTypeUnsafe(); + QualType ElementType = UKind == UnaryTransformType::RemoveAllExtents + ? QualType(ArrayType->getBaseElementTypeUnsafe(), {}) + : ArrayType->getElementType(); + QualType Underlying = { + ElementType.getSplitUnqualifiedType().Ty, + BaseType.getCVRQualifiers() + }; + return Context.getUnaryTransformType(BaseType, Underlying, UKind); + } + 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 Context.getUnaryTransformType(BaseType, BaseType, UKind); + + if (UKind == UnaryTransformType::AddConst || + UKind == UnaryTransformType::AddCV) + Quals.addConst(); + if (UKind == UnaryTransformType::AddVolatile || + UKind == UnaryTransformType::AddCV) + Quals.addVolatile(); + + if (UKind == UnaryTransformType::RemoveConst || + UKind == UnaryTransformType::RemoveCV) + Quals.removeConst(); + if (UKind == UnaryTransformType::RemoveVolatile || + UKind == UnaryTransformType::RemoveCV) + Quals.removeVolatile(); + + QualType Underlying(Split.Ty, Quals.getAsOpaqueValue()); + return Context.getUnaryTransformType(BaseType, Underlying, UKind); + } + case UnaryTransformType::MakeSigned: + case UnaryTransformType::MakeUnsigned: { + if (BaseType->isDependentType()) + return Context.getUnaryTransformType(BaseType, BaseType, UKind); + bool IsMakeSigned = UKind == UnaryTransformType::MakeSigned; + if ((!BaseType->isIntegerType() && !BaseType->isEnumeralType()) || + BaseType->isBooleanType()) { + Diag(Loc, diag::err_make_signed_integral_only) + << IsMakeSigned << BaseType; + return QualType(); } + bool IsSigned = BaseType->isSignedIntegerType(); + bool IsNonCharIntegral = + BaseType->isCharType() || BaseType->isEnumeralType(); + + // Clang doesn't seem to have a way to distinguish `char` from `signed char` + // and `unsigned char` + if (IsMakeSigned == IsSigned && !IsNonCharIntegral) + return Context.getUnaryTransformType(BaseType, BaseType, UKind); + + QualType Underlying = Context.getIntTypeForBitwidth( + Context.getIntWidth(BaseType), IsMakeSigned); + Qualifiers Quals = Underlying.getQualifiers(); + Quals.setCVRQualifiers(BaseType.getCVRQualifiers()); + Underlying = QualType(Underlying.getSplitUnqualifiedType().Ty, + Quals.getAsOpaqueValue()); + return Context.getUnaryTransformType(BaseType, Underlying, UKind); + } } llvm_unreachable("unknown unary transform type"); } diff --git a/clang/test/SemaCXX/type-traits.cpp b/clang/test/SemaCXX/type-traits.cpp --- a/clang/test/SemaCXX/type-traits.cpp +++ b/clang/test/SemaCXX/type-traits.cpp @@ -14,6 +14,9 @@ enum Enum { EV }; enum SignedEnum : signed int { }; enum UnsignedEnum : unsigned int { }; +enum class EnumClass { EV }; +enum class SignedEnumClass : signed int { }; +enum class UnsignedEnumClass : unsigned int { }; struct POD { Enum e; int i; float f; NonPOD* p; }; struct Empty {}; struct IncompleteStruct; @@ -2854,3 +2857,1041 @@ #undef T16384 #undef T32768 } // namespace type_trait_expr_numargs_overflow + +template using add_const_t = __add_const(T); + +struct S {}; +void check_add_const() { + { int a[T(__is_same(add_const_t, const void))]; } + { int a[T(__is_same(add_const_t, const int))]; } + { int a[T(__is_same(add_const_t, const int))]; } + { int a[T(__is_same(add_const_t, const volatile int))]; } + { int a[T(__is_same(add_const_t, const volatile int))]; } + { int a[T(__is_same(add_const_t, int* const))]; } + { int a[T(__is_same(add_const_t, int&))]; } + { int a[T(__is_same(add_const_t, int&&))]; } + { int a[T(__is_same(add_const_t, int()))]; } + { int a[T(__is_same(add_const_t, int(* const)()))]; } + { int a[T(__is_same(add_const_t, int(&)()))]; } + + { int a[T(__is_same(add_const_t, const S))]; } + { int a[T(__is_same(add_const_t, const S))]; } + { int a[T(__is_same(add_const_t, const volatile S))]; } + { int a[T(__is_same(add_const_t, const volatile S))]; } + { int a[T(__is_same(add_const_t, int S::* const))]; } + { int a[T(__is_same(add_const_t, int (S::* const)()))]; } + { int a[T(__is_same(add_const_t, int (S::* const)() &))]; } + { int a[T(__is_same(add_const_t, int (S::* const)() &&))]; } + { int a[T(__is_same(add_const_t, int (S::* const)() const))]; } + { int a[T(__is_same(add_const_t, int (S::* const)() const&))]; } + { int a[T(__is_same(add_const_t, int (S::* const)() const&&))]; } + { int a[T(__is_same(add_const_t, int (S::* const)() volatile))]; } + { int a[T(__is_same(add_const_t, int (S::* const)() volatile&))]; } + { int a[T(__is_same(add_const_t, int (S::* const)() volatile&&))]; } + { int a[T(__is_same(add_const_t, int (S::* const)() const volatile))]; } + { int a[T(__is_same(add_const_t, int (S::* const)() const volatile&))]; } + { int a[T(__is_same(add_const_t, int (S::* const)() const volatile&&))]; } +} + +template using remove_const_t = __remove_const(T); + +void check_remove_const() { + { int a[T(__is_same(remove_const_t, void))]; } + { int a[T(__is_same(remove_const_t, void))]; } + { int a[T(__is_same(remove_const_t, int))]; } + { int a[T(__is_same(remove_const_t, int))]; } + { int a[T(__is_same(remove_const_t, volatile int))]; } + { int a[T(__is_same(remove_const_t, volatile int))]; } + { int a[T(__is_same(remove_const_t, int*))]; } + { int a[T(__is_same(remove_const_t, int*))]; } + { int a[T(__is_same(remove_const_t, int const*))]; } + { int a[T(__is_same(remove_const_t, int&))]; } + { int a[T(__is_same(remove_const_t, int const&))]; } + { int a[T(__is_same(remove_const_t, int&&))]; } + { int a[T(__is_same(remove_const_t, int const&&))]; } + { int a[T(__is_same(remove_const_t, int()))]; } + { int a[T(__is_same(remove_const_t, int(*)()))]; } + { int a[T(__is_same(remove_const_t, int(&)()))]; } + + { int a[T(__is_same(remove_const_t, S))]; } + { int a[T(__is_same(remove_const_t, S))]; } + { int a[T(__is_same(remove_const_t, volatile S))]; } + { int a[T(__is_same(remove_const_t, volatile S))]; } + { int a[T(__is_same(remove_const_t, int S::*))]; } + { int a[T(__is_same(remove_const_t, int (S::*)()))]; } + { int a[T(__is_same(remove_const_t, int (S::*)() &))]; } + { int a[T(__is_same(remove_const_t, int (S::*)() &&))]; } + { int a[T(__is_same(remove_const_t, int (S::*)() const))]; } + { int a[T(__is_same(remove_const_t, int (S::*)() const&))]; } + { int a[T(__is_same(remove_const_t, int (S::*)() const&&))]; } + { int a[T(__is_same(remove_const_t, int (S::*)() volatile))]; } + { int a[T(__is_same(remove_const_t, int (S::*)() volatile&))]; } + { int a[T(__is_same(remove_const_t, int (S::*)() volatile&&))]; } + { int a[T(__is_same(remove_const_t, int (S::*)() const volatile))]; } + { int a[T(__is_same(remove_const_t, int (S::*)() const volatile&))]; } + { int a[T(__is_same(remove_const_t, int (S::*)() const volatile&&))]; } +} + +template using add_volatile_t = __add_volatile(T); + +void check_add_volatile() { + { int a[T(__is_same(add_volatile_t, volatile void))]; } + { int a[T(__is_same(add_volatile_t, volatile int))]; } + { int a[T(__is_same(add_volatile_t, const volatile int))]; } + { int a[T(__is_same(add_volatile_t, volatile int))]; } + { int a[T(__is_same(add_volatile_t, const volatile int))]; } + { int a[T(__is_same(add_volatile_t, int* volatile))]; } + { int a[T(__is_same(add_volatile_t, int&))]; } + { int a[T(__is_same(add_volatile_t, int&&))]; } + { int a[T(__is_same(add_volatile_t, int()))]; } + { int a[T(__is_same(add_volatile_t, int(* volatile)()))]; } + { int a[T(__is_same(add_volatile_t, int(&)()))]; } + + { int a[T(__is_same(add_volatile_t, volatile S))]; } + { int a[T(__is_same(add_volatile_t, const volatile S))]; } + { int a[T(__is_same(add_volatile_t, volatile S))]; } + { int a[T(__is_same(add_volatile_t, const volatile S))]; } + { int a[T(__is_same(add_volatile_t, int S::* volatile))]; } + { int a[T(__is_same(add_volatile_t, int (S::* volatile)()))]; } + { int a[T(__is_same(add_volatile_t, int (S::* volatile)() &))]; } + { int a[T(__is_same(add_volatile_t, int (S::* volatile)() &&))]; } + { int a[T(__is_same(add_volatile_t, int (S::* volatile)() const))]; } + { int a[T(__is_same(add_volatile_t, int (S::* volatile)() const&))]; } + { int a[T(__is_same(add_volatile_t, int (S::* volatile)() const&&))]; } + { int a[T(__is_same(add_volatile_t, int (S::* volatile)() volatile))]; } + { int a[T(__is_same(add_volatile_t, int (S::* volatile)() volatile&))]; } + { int a[T(__is_same(add_volatile_t, int (S::* volatile)() volatile&&))]; } + { int a[T(__is_same(add_volatile_t, int (S::* volatile)() const volatile))]; } + { int a[T(__is_same(add_volatile_t, int (S::* volatile)() const volatile&))]; } + { int a[T(__is_same(add_volatile_t, int (S::* volatile)() const volatile&&))]; } +} + +template using remove_volatile_t = __remove_volatile(T); + +void check_remove_volatile() { + { int a[T(__is_same(remove_volatile_t, void))]; } + { int a[T(__is_same(remove_volatile_t, void))]; } + { int a[T(__is_same(remove_volatile_t, int))]; } + { int a[T(__is_same(remove_volatile_t, const int))]; } + { int a[T(__is_same(remove_volatile_t, int))]; } + { int a[T(__is_same(remove_volatile_t, const int))]; } + { int a[T(__is_same(remove_volatile_t, int*))]; } + { int a[T(__is_same(remove_volatile_t, int*))]; } + { int a[T(__is_same(remove_volatile_t, int volatile*))]; } + { int a[T(__is_same(remove_volatile_t, int&))]; } + { int a[T(__is_same(remove_volatile_t, int volatile&))]; } + { int a[T(__is_same(remove_volatile_t, int&&))]; } + { int a[T(__is_same(remove_volatile_t, int volatile&&))]; } + { int a[T(__is_same(remove_volatile_t, int()))]; } + { int a[T(__is_same(remove_volatile_t, int(*)()))]; } + { int a[T(__is_same(remove_volatile_t, int(&)()))]; } + + { int a[T(__is_same(remove_volatile_t, S))]; } + { int a[T(__is_same(remove_volatile_t, const S))]; } + { int a[T(__is_same(remove_volatile_t, S))]; } + { int a[T(__is_same(remove_volatile_t, const S))]; } + { int a[T(__is_same(remove_volatile_t, int S::*))]; } + { int a[T(__is_same(remove_volatile_t, int (S::*)()))]; } + { int a[T(__is_same(remove_volatile_t, int (S::*)() &))]; } + { int a[T(__is_same(remove_volatile_t, int (S::*)() &&))]; } + { int a[T(__is_same(remove_volatile_t, int (S::*)() const))]; } + { int a[T(__is_same(remove_volatile_t, int (S::*)() const&))]; } + { int a[T(__is_same(remove_volatile_t, int (S::*)() const&&))]; } + { int a[T(__is_same(remove_volatile_t, int (S::*)() volatile))]; } + { int a[T(__is_same(remove_volatile_t, int (S::*)() volatile&))]; } + { int a[T(__is_same(remove_volatile_t, int (S::*)() volatile&&))]; } + { int a[T(__is_same(remove_volatile_t, int (S::*)() const volatile))]; } + { int a[T(__is_same(remove_volatile_t, int (S::*)() const volatile&))]; } + { int a[T(__is_same(remove_volatile_t, int (S::*)() const volatile&&))]; } +} + +template using add_cv_t = __add_cv(T); + +void check_add_cv() { + { int a[T(__is_same(add_cv_t, const volatile void))]; } + { int a[T(__is_same(add_cv_t, const volatile int))]; } + { int a[T(__is_same(add_cv_t, const volatile int))]; } + { int a[T(__is_same(add_cv_t, const volatile int))]; } + { int a[T(__is_same(add_cv_t, const volatile int))]; } + { int a[T(__is_same(add_cv_t, int* const volatile))]; } + { int a[T(__is_same(add_cv_t, int&))]; } + { int a[T(__is_same(add_cv_t, int&&))]; } + { int a[T(__is_same(add_cv_t, int()))]; } + { int a[T(__is_same(add_cv_t, int(* const volatile)()))]; } + { int a[T(__is_same(add_cv_t, int(&)()))]; } + + { int a[T(__is_same(add_cv_t, const volatile S))]; } + { int a[T(__is_same(add_cv_t, const volatile S))]; } + { int a[T(__is_same(add_cv_t, const volatile S))]; } + { int a[T(__is_same(add_cv_t, const volatile S))]; } + { int a[T(__is_same(add_cv_t, int S::* const volatile))]; } + { int a[T(__is_same(add_cv_t, int (S::* const volatile)()))]; } + { int a[T(__is_same(add_cv_t, int (S::* const volatile)() &))]; } + { int a[T(__is_same(add_cv_t, int (S::* const volatile)() &&))]; } + { int a[T(__is_same(add_cv_t, int (S::* const volatile)() const))]; } + { int a[T(__is_same(add_cv_t, int (S::* const volatile)() const&))]; } + { int a[T(__is_same(add_cv_t, int (S::* const volatile)() const&&))]; } + { int a[T(__is_same(add_cv_t, int (S::* const volatile)() volatile))]; } + { int a[T(__is_same(add_cv_t, int (S::* const volatile)() volatile&))]; } + { int a[T(__is_same(add_cv_t, int (S::* const volatile)() volatile&&))]; } + { int a[T(__is_same(add_cv_t, int (S::* const volatile)() const volatile))]; } + { int a[T(__is_same(add_cv_t, int (S::* const volatile)() const volatile&))]; } + { int a[T(__is_same(add_cv_t, int (S::* const volatile)() const volatile&&))]; } +} + +template using remove_cv_t = __remove_cv(T); + +void check_remove_cv() { + { int a[T(__is_same(remove_cv_t, void))]; } + { int a[T(__is_same(remove_cv_t, void))]; } + { int a[T(__is_same(remove_cv_t, int))]; } + { int a[T(__is_same(remove_cv_t, int))]; } + { int a[T(__is_same(remove_cv_t, int))]; } + { int a[T(__is_same(remove_cv_t, int))]; } + { int a[T(__is_same(remove_cv_t, int*))]; } + { int a[T(__is_same(remove_cv_t, int*))]; } + { int a[T(__is_same(remove_cv_t, int const*))]; } + { int a[T(__is_same(remove_cv_t, int&))]; } + { int a[T(__is_same(remove_cv_t, int const volatile&))]; } + { int a[T(__is_same(remove_cv_t, int&&))]; } + { int a[T(__is_same(remove_cv_t, int const volatile&&))]; } + { int a[T(__is_same(remove_cv_t, int()))]; } + { int a[T(__is_same(remove_cv_t, int(*)()))]; } + { int a[T(__is_same(remove_cv_t, int(&)()))]; } + + { int a[T(__is_same(remove_cv_t, S))]; } + { int a[T(__is_same(remove_cv_t, S))]; } + { int a[T(__is_same(remove_cv_t, S))]; } + { int a[T(__is_same(remove_cv_t, S))]; } + { int a[T(__is_same(remove_cv_t, int S::*))]; } + { int a[T(__is_same(remove_cv_t, int (S::*)()))]; } + { int a[T(__is_same(remove_cv_t, int (S::*)() &))]; } + { int a[T(__is_same(remove_cv_t, int (S::*)() &&))]; } + { int a[T(__is_same(remove_cv_t, int (S::*)() const))]; } + { int a[T(__is_same(remove_cv_t, int (S::*)() const&))]; } + { int a[T(__is_same(remove_cv_t, int (S::*)() const&&))]; } + { int a[T(__is_same(remove_cv_t, int (S::*)() volatile))]; } + { int a[T(__is_same(remove_cv_t, int (S::*)() volatile&))]; } + { int a[T(__is_same(remove_cv_t, int (S::*)() volatile&&))]; } + { int a[T(__is_same(remove_cv_t, int (S::*)() const volatile))]; } + { int a[T(__is_same(remove_cv_t, int (S::*)() const volatile&))]; } + { int a[T(__is_same(remove_cv_t, int (S::*)() const volatile&&))]; } +} + +template using add_pointer_t = __add_pointer(T); + +void add_pointer() { + { int a[T(__is_same(add_pointer_t, void*))]; } + { int a[T(__is_same(add_pointer_t, const void*))]; } + { int a[T(__is_same(add_pointer_t, volatile void*))]; } + { int a[T(__is_same(add_pointer_t, const volatile void*))]; } + { int a[T(__is_same(add_pointer_t, int*))]; } + { int a[T(__is_same(add_pointer_t, const int*))]; } + { int a[T(__is_same(add_pointer_t, volatile int*))]; } + { int a[T(__is_same(add_pointer_t, const volatile int*))]; } + { int a[T(__is_same(add_pointer_t, int**))]; } + { int a[T(__is_same(add_pointer_t, int*))]; } + { int a[T(__is_same(add_pointer_t, int*))]; } + { int a[T(__is_same(add_pointer_t, int(*)()))]; } + { int a[T(__is_same(add_pointer_t, int(**)()))]; } + { int a[T(__is_same(add_pointer_t, int(*)()))]; } + + { int a[T(__is_same(add_pointer_t, S*))]; } + { int a[T(__is_same(add_pointer_t, const S*))]; } + { int a[T(__is_same(add_pointer_t, volatile S*))]; } + { int a[T(__is_same(add_pointer_t, const volatile S*))]; } + { int a[T(__is_same(add_pointer_t, int S::**))]; } + { int a[T(__is_same(add_pointer_t, int (S::**)()))]; } + { int a[T(__is_same(add_pointer_t, int (S::**)() &))]; } + { int a[T(__is_same(add_pointer_t, int (S::**)() &&))]; } + { int a[T(__is_same(add_pointer_t, int (S::**)() const))]; } + { int a[T(__is_same(add_pointer_t, int (S::**)() const&))]; } + { int a[T(__is_same(add_pointer_t, int (S::**)() const&&))]; } + { int a[T(__is_same(add_pointer_t, int (S::**)() volatile))]; } + { int a[T(__is_same(add_pointer_t, int (S::**)() volatile&))]; } + { int a[T(__is_same(add_pointer_t, int (S::**)() volatile&&))]; } + { int a[T(__is_same(add_pointer_t, int (S::**)() const volatile))]; } + { int a[T(__is_same(add_pointer_t, int (S::**)() const volatile&))]; } + { int a[T(__is_same(add_pointer_t, int (S::**)() const volatile&&))]; } +} + +template using remove_pointer_t = __remove_pointer(T); + +void remove_pointer() { + { int a[T(__is_same(remove_pointer_t, void))]; } + { int a[T(__is_same(remove_pointer_t, const void))]; } + { int a[T(__is_same(remove_pointer_t, volatile void))]; } + { int a[T(__is_same(remove_pointer_t, const volatile void))]; } + { int a[T(__is_same(remove_pointer_t, int))]; } + { int a[T(__is_same(remove_pointer_t, const int))]; } + { int a[T(__is_same(remove_pointer_t, volatile int))]; } + { int a[T(__is_same(remove_pointer_t, const volatile int))]; } + { int a[T(__is_same(remove_pointer_t, int))]; } + { int a[T(__is_same(remove_pointer_t, int&))]; } + { int a[T(__is_same(remove_pointer_t, int&&))]; } + { int a[T(__is_same(remove_pointer_t, int()))]; } + { int a[T(__is_same(remove_pointer_t, int()))]; } + { int a[T(__is_same(remove_pointer_t, int(&)()))]; } + + { int a[T(__is_same(remove_pointer_t, S))]; } + { int a[T(__is_same(remove_pointer_t, const S))]; } + { int a[T(__is_same(remove_pointer_t, volatile S))]; } + { int a[T(__is_same(remove_pointer_t, const volatile S))]; } + { int a[T(__is_same(remove_pointer_t, int S::*))]; } + { int a[T(__is_same(remove_pointer_t, int (S::*)()))]; } + { int a[T(__is_same(remove_pointer_t, int (S::*)() &))]; } + { int a[T(__is_same(remove_pointer_t, int (S::*)() &&))]; } + { int a[T(__is_same(remove_pointer_t, int (S::*)() const))]; } + { int a[T(__is_same(remove_pointer_t, int (S::*)() const&))]; } + { int a[T(__is_same(remove_pointer_t, int (S::*)() const&&))]; } + { int a[T(__is_same(remove_pointer_t, int (S::*)() volatile))]; } + { int a[T(__is_same(remove_pointer_t, int (S::*)() volatile&))]; } + { int a[T(__is_same(remove_pointer_t, int (S::*)() volatile&&))]; } + { int a[T(__is_same(remove_pointer_t, int (S::*)() const volatile))]; } + { int a[T(__is_same(remove_pointer_t, int (S::*)() const volatile&))]; } + { int a[T(__is_same(remove_pointer_t, int (S::*)() const volatile&&))]; } +} + +template using add_lvalue_reference_t = __add_lvalue_reference(T); + +void add_lvalue_reference() { + { int a[T(__is_same(add_lvalue_reference_t, void))]; } + { int a[T(__is_same(add_lvalue_reference_t, const void))]; } + { int a[T(__is_same(add_lvalue_reference_t, volatile void))]; } + { int a[T(__is_same(add_lvalue_reference_t, const volatile void))]; } + { int a[T(__is_same(add_lvalue_reference_t, int&))]; } + { int a[T(__is_same(add_lvalue_reference_t, const int&))]; } + { int a[T(__is_same(add_lvalue_reference_t, volatile int&))]; } + { int a[T(__is_same(add_lvalue_reference_t, const volatile int&))]; } + { int a[T(__is_same(add_lvalue_reference_t, int*&))]; } + { int a[T(__is_same(add_lvalue_reference_t, int&))]; } + { int a[T(__is_same(add_lvalue_reference_t, int&))]; } // reference collapsing + { int a[T(__is_same(add_lvalue_reference_t, int(&)()))]; } + { int a[T(__is_same(add_lvalue_reference_t, int(*&)()))]; } + { int a[T(__is_same(add_lvalue_reference_t, int(&)()))]; } + + { int a[T(__is_same(add_lvalue_reference_t, S&))]; } + { int a[T(__is_same(add_lvalue_reference_t, const S&))]; } + { int a[T(__is_same(add_lvalue_reference_t, volatile S&))]; } + { int a[T(__is_same(add_lvalue_reference_t, const volatile S&))]; } + { int a[T(__is_same(add_lvalue_reference_t, int S::*&))]; } + { int a[T(__is_same(add_lvalue_reference_t, int (S::*&)()))]; } + { int a[T(__is_same(add_lvalue_reference_t, int (S::*&)() &))]; } + { int a[T(__is_same(add_lvalue_reference_t, int (S::*&)() &&))]; } + { int a[T(__is_same(add_lvalue_reference_t, int (S::*&)() const))]; } + { int a[T(__is_same(add_lvalue_reference_t, int (S::*&)() const&))]; } + { int a[T(__is_same(add_lvalue_reference_t, int (S::*&)() const&&))]; } + { int a[T(__is_same(add_lvalue_reference_t, int (S::*&)() volatile))]; } + { int a[T(__is_same(add_lvalue_reference_t, int (S::*&)() volatile&))]; } + { int a[T(__is_same(add_lvalue_reference_t, int (S::*&)() volatile&&))]; } + { int a[T(__is_same(add_lvalue_reference_t, int (S::*&)() const volatile))]; } + { int a[T(__is_same(add_lvalue_reference_t, int (S::*&)() const volatile&))]; } + { int a[T(__is_same(add_lvalue_reference_t, int (S::*&)() const volatile&&))]; } +} + +template using add_rvalue_reference_t = __add_rvalue_reference(T); + +void add_rvalue_reference() { + { int a[T(__is_same(add_rvalue_reference_t, void))]; } + { int a[T(__is_same(add_rvalue_reference_t, const void))]; } + { int a[T(__is_same(add_rvalue_reference_t, volatile void))]; } + { int a[T(__is_same(add_rvalue_reference_t, const volatile void))]; } + { int a[T(__is_same(add_rvalue_reference_t, int&&))]; } + { int a[T(__is_same(add_rvalue_reference_t, const int&&))]; } + { int a[T(__is_same(add_rvalue_reference_t, volatile int&&))]; } + { int a[T(__is_same(add_rvalue_reference_t, const volatile int&&))]; } + { int a[T(__is_same(add_rvalue_reference_t, int*&&))]; } + { int a[T(__is_same(add_rvalue_reference_t, int&))]; } // reference collapsing + { int a[T(__is_same(add_rvalue_reference_t, int&&))]; } + { int a[T(__is_same(add_rvalue_reference_t, int(&&)()))]; } + { int a[T(__is_same(add_rvalue_reference_t, int(*&&)()))]; } + { int a[T(__is_same(add_rvalue_reference_t, int(&)()))]; } // reference collapsing + + { int a[T(__is_same(add_rvalue_reference_t, S&&))]; } + { int a[T(__is_same(add_rvalue_reference_t, const S&&))]; } + { int a[T(__is_same(add_rvalue_reference_t, volatile S&&))]; } + { int a[T(__is_same(add_rvalue_reference_t, const volatile S&&))]; } + { int a[T(__is_same(add_rvalue_reference_t, int S::*&&))]; } + { int a[T(__is_same(add_rvalue_reference_t, int (S::*&&)()))]; } + { int a[T(__is_same(add_rvalue_reference_t, int (S::*&&)() &))]; } + { int a[T(__is_same(add_rvalue_reference_t, int (S::*&&)() &&))]; } + { int a[T(__is_same(add_rvalue_reference_t, int (S::*&&)() const))]; } + { int a[T(__is_same(add_rvalue_reference_t, int (S::*&&)() const&))]; } + { int a[T(__is_same(add_rvalue_reference_t, int (S::*&&)() const&&))]; } + { int a[T(__is_same(add_rvalue_reference_t, int (S::*&&)() volatile))]; } + { int a[T(__is_same(add_rvalue_reference_t, int (S::*&&)() volatile&))]; } + { int a[T(__is_same(add_rvalue_reference_t, int (S::*&&)() volatile&&))]; } + { int a[T(__is_same(add_rvalue_reference_t, int (S::*&&)() const volatile))]; } + { int a[T(__is_same(add_rvalue_reference_t, int (S::*&&)() const volatile&))]; } + { int a[T(__is_same(add_rvalue_reference_t, int (S::*&&)() const volatile&&))]; } +} + +template using remove_reference_t = __remove_reference(T); + +void check_remove_reference() { + { int a[T(__is_same(remove_reference_t, void))]; } + { int a[T(__is_same(remove_reference_t, const volatile void))]; } + { int a[T(__is_same(remove_reference_t, int))]; } + { int a[T(__is_same(remove_reference_t, const int))]; } + { int a[T(__is_same(remove_reference_t, volatile int))]; } + { int a[T(__is_same(remove_reference_t, const volatile int))]; } + { int a[T(__is_same(remove_reference_t, int*))]; } + { int a[T(__is_same(remove_reference_t, int* const volatile))]; } + { int a[T(__is_same(remove_reference_t, int const* const volatile))]; } + { int a[T(__is_same(remove_reference_t, int))]; } + { int a[T(__is_same(remove_reference_t, int const volatile))]; } + { int a[T(__is_same(remove_reference_t, int))]; } + { int a[T(__is_same(remove_reference_t, int const volatile))]; } + { int a[T(__is_same(remove_reference_t, int()))]; } + { int a[T(__is_same(remove_reference_t, int(* const volatile)()))]; } + { int a[T(__is_same(remove_reference_t, int()))]; } + + { int a[T(__is_same(remove_reference_t, S))]; } + { int a[T(__is_same(remove_reference_t, S))]; } + { int a[T(__is_same(remove_reference_t, S))]; } + { int a[T(__is_same(remove_reference_t, const S))]; } + { int a[T(__is_same(remove_reference_t, const S))]; } + { int a[T(__is_same(remove_reference_t, const S))]; } + { int a[T(__is_same(remove_reference_t, volatile S))]; } + { int a[T(__is_same(remove_reference_t, volatile S))]; } + { int a[T(__is_same(remove_reference_t, volatile S))]; } + { int a[T(__is_same(remove_reference_t, const volatile S))]; } + { int a[T(__is_same(remove_reference_t, const volatile S))]; } + { int a[T(__is_same(remove_reference_t, const volatile S))]; } + { int a[T(__is_same(remove_reference_t, int S::* const volatile))]; } + { int a[T(__is_same(remove_reference_t, int (S::* const volatile)()))]; } + { int a[T(__is_same(remove_reference_t, int (S::* const volatile)() &))]; } + { int a[T(__is_same(remove_reference_t, int (S::* const volatile)() &&))]; } + { int a[T(__is_same(remove_reference_t, int (S::* const volatile)() const))]; } + { int a[T(__is_same(remove_reference_t, int (S::* const volatile)() const&))]; } + { int a[T(__is_same(remove_reference_t, int (S::* const volatile)() const&&))]; } + { int a[T(__is_same(remove_reference_t, int (S::* const volatile)() volatile))]; } + { int a[T(__is_same(remove_reference_t, int (S::* const volatile)() volatile&))]; } + { int a[T(__is_same(remove_reference_t, int (S::* const volatile)() volatile&&))]; } + { int a[T(__is_same(remove_reference_t, int (S::* const volatile)() const volatile))]; } + { int a[T(__is_same(remove_reference_t, int (S::* const volatile)() const volatile&))]; } + { int a[T(__is_same(remove_reference_t, int (S::* const volatile)() const volatile&&))]; } + { int a[T(__is_same(remove_reference_t, int (S::* const volatile)()))]; } + { int a[T(__is_same(remove_reference_t, int (S::* const volatile)() &))]; } + { int a[T(__is_same(remove_reference_t, int (S::* const volatile)() &&))]; } + { int a[T(__is_same(remove_reference_t, int (S::* const volatile)() const))]; } + { int a[T(__is_same(remove_reference_t, int (S::* const volatile)() const&))]; } + { int a[T(__is_same(remove_reference_t, int (S::* const volatile)() const&&))]; } + { int a[T(__is_same(remove_reference_t, int (S::* const volatile)() volatile))]; } + { int a[T(__is_same(remove_reference_t, int (S::* const volatile)() volatile&))]; } + { int a[T(__is_same(remove_reference_t, int (S::* const volatile)() volatile&&))]; } + { int a[T(__is_same(remove_reference_t, int (S::* const volatile)() const volatile))]; } + { int a[T(__is_same(remove_reference_t, int (S::* const volatile)() const volatile&))]; } + { int a[T(__is_same(remove_reference_t, int (S::* const volatile)() const volatile&&))]; } +} + +template using remove_cvref_t = __remove_cvref(T); + +void check_remove_cvref() { + { int a[T(__is_same(remove_cvref_t, void))]; } + { int a[T(__is_same(remove_cvref_t, void))]; } + { int a[T(__is_same(remove_cvref_t, int))]; } + { int a[T(__is_same(remove_cvref_t, int))]; } + { int a[T(__is_same(remove_cvref_t, int))]; } + { int a[T(__is_same(remove_cvref_t, int))]; } + { int a[T(__is_same(remove_cvref_t, int*))]; } + { int a[T(__is_same(remove_cvref_t, int*))]; } + { int a[T(__is_same(remove_cvref_t, int const*))]; } + { int a[T(__is_same(remove_cvref_t, int))]; } + { int a[T(__is_same(remove_cvref_t, int))]; } + { int a[T(__is_same(remove_cvref_t, int))]; } + { int a[T(__is_same(remove_cvref_t, int))]; } + { int a[T(__is_same(remove_cvref_t, int()))]; } + { int a[T(__is_same(remove_cvref_t, int(*)()))]; } + { int a[T(__is_same(remove_cvref_t, int()))]; } + + { int a[T(__is_same(remove_cvref_t, S))]; } + { int a[T(__is_same(remove_cvref_t, S))]; } + { int a[T(__is_same(remove_cvref_t, S))]; } + { int a[T(__is_same(remove_cvref_t, S))]; } + { int a[T(__is_same(remove_cvref_t, S))]; } + { int a[T(__is_same(remove_cvref_t, S))]; } + { int a[T(__is_same(remove_cvref_t, S))]; } + { int a[T(__is_same(remove_cvref_t, S))]; } + { int a[T(__is_same(remove_cvref_t, S))]; } + { int a[T(__is_same(remove_cvref_t, S))]; } + { int a[T(__is_same(remove_cvref_t, S))]; } + { int a[T(__is_same(remove_cvref_t, S))]; } + { int a[T(__is_same(remove_cvref_t, int S::*))]; } + { int a[T(__is_same(remove_cvref_t, int (S::*)()))]; } + { int a[T(__is_same(remove_cvref_t, int (S::*)() &))]; } + { int a[T(__is_same(remove_cvref_t, int (S::*)() &&))]; } + { int a[T(__is_same(remove_cvref_t, int (S::*)() const))]; } + { int a[T(__is_same(remove_cvref_t, int (S::*)() const&))]; } + { int a[T(__is_same(remove_cvref_t, int (S::*)() const&&))]; } + { int a[T(__is_same(remove_cvref_t, int (S::*)() volatile))]; } + { int a[T(__is_same(remove_cvref_t, int (S::*)() volatile&))]; } + { int a[T(__is_same(remove_cvref_t, int (S::*)() volatile&&))]; } + { int a[T(__is_same(remove_cvref_t, int (S::*)() const volatile))]; } + { int a[T(__is_same(remove_cvref_t, int (S::*)() const volatile&))]; } + { int a[T(__is_same(remove_cvref_t, int (S::*)() const volatile&&))]; } + { int a[T(__is_same(remove_cvref_t, int S::*))]; } + { int a[T(__is_same(remove_cvref_t, int (S::*)()))]; } + { int a[T(__is_same(remove_cvref_t, int (S::*)() &))]; } + { int a[T(__is_same(remove_cvref_t, int (S::*)() &&))]; } + { int a[T(__is_same(remove_cvref_t, int (S::*)() const))]; } + { int a[T(__is_same(remove_cvref_t, int (S::*)() const&))]; } + { int a[T(__is_same(remove_cvref_t, int (S::*)() const&&))]; } + { int a[T(__is_same(remove_cvref_t, int (S::*)() volatile))]; } + { int a[T(__is_same(remove_cvref_t, int (S::*)() volatile&))]; } + { int a[T(__is_same(remove_cvref_t, int (S::*)() volatile&&))]; } + { int a[T(__is_same(remove_cvref_t, int (S::*)() const volatile))]; } + { int a[T(__is_same(remove_cvref_t, int (S::*)() const volatile&))]; } + { int a[T(__is_same(remove_cvref_t, int (S::*)() const volatile&&))]; } + { int a[T(__is_same(remove_cvref_t, int S::*))]; } + { int a[T(__is_same(remove_cvref_t, int (S::*)()))]; } + { int a[T(__is_same(remove_cvref_t, int (S::*)() &))]; } + { int a[T(__is_same(remove_cvref_t, int (S::*)() &&))]; } + { int a[T(__is_same(remove_cvref_t, int (S::*)() const))]; } + { int a[T(__is_same(remove_cvref_t, int (S::*)() const&))]; } + { int a[T(__is_same(remove_cvref_t, int (S::*)() const&&))]; } + { int a[T(__is_same(remove_cvref_t, int (S::*)() volatile))]; } + { int a[T(__is_same(remove_cvref_t, int (S::*)() volatile&))]; } + { int a[T(__is_same(remove_cvref_t, int (S::*)() volatile&&))]; } + { int a[T(__is_same(remove_cvref_t, int (S::*)() const volatile))]; } + { int a[T(__is_same(remove_cvref_t, int (S::*)() const volatile&))]; } + { int a[T(__is_same(remove_cvref_t, int (S::*)() const volatile&&))]; } +} + +template using decay_t = __decay(T); + +void check_decay() { + { int a[T(__is_same(decay_t, void))]; } + { int a[T(__is_same(decay_t, void))]; } + { int a[T(__is_same(decay_t, int))]; } + { int a[T(__is_same(decay_t, int))]; } + { int a[T(__is_same(decay_t, int))]; } + { int a[T(__is_same(decay_t, int))]; } + { int a[T(__is_same(decay_t, int*))]; } + { int a[T(__is_same(decay_t, int*))]; } + { int a[T(__is_same(decay_t, int const*))]; } + { int a[T(__is_same(decay_t, int))]; } + { int a[T(__is_same(decay_t, int))]; } + { int a[T(__is_same(decay_t, int))]; } + { int a[T(__is_same(decay_t, int))]; } + { int a[T(__is_same(decay_t, int(*)()))]; } + { int a[T(__is_same(decay_t, int(*)()))]; } + { int a[T(__is_same(decay_t, int(*)()))]; } + { int a[T(__is_same(decay_t, int(*)()))]; } + { int a[T(__is_same(decay_t, int(*)()))]; } + { int a[T(__is_same(decay_t, int(*)()))]; } + { int a[T(__is_same(decay_t, int*))]; } + { int a[T(__is_same(decay_t, int*))]; } + + { int a[T(__is_same(decay_t, S))]; } + { int a[T(__is_same(decay_t, S))]; } + { int a[T(__is_same(decay_t, S))]; } + { int a[T(__is_same(decay_t, S))]; } + { int a[T(__is_same(decay_t, S))]; } + { int a[T(__is_same(decay_t, S))]; } + { int a[T(__is_same(decay_t, S))]; } + { int a[T(__is_same(decay_t, S))]; } + { int a[T(__is_same(decay_t, S))]; } + { int a[T(__is_same(decay_t, S))]; } + { int a[T(__is_same(decay_t, S))]; } + { int a[T(__is_same(decay_t, S))]; } + { int a[T(__is_same(decay_t, int S::*))]; } + { int a[T(__is_same(decay_t, int (S::*)()))]; } + { int a[T(__is_same(decay_t, int (S::*)() &))]; } + { int a[T(__is_same(decay_t, int (S::*)() &&))]; } + { int a[T(__is_same(decay_t, int (S::*)() const))]; } + { int a[T(__is_same(decay_t, int (S::*)() const&))]; } + { int a[T(__is_same(decay_t, int (S::*)() const&&))]; } + { int a[T(__is_same(decay_t, int (S::*)() volatile))]; } + { int a[T(__is_same(decay_t, int (S::*)() volatile&))]; } + { int a[T(__is_same(decay_t, int (S::*)() volatile&&))]; } + { int a[T(__is_same(decay_t, int (S::*)() const volatile))]; } + { int a[T(__is_same(decay_t, int (S::*)() const volatile&))]; } + { int a[T(__is_same(decay_t, int (S::*)() const volatile&&))]; } + { int a[T(__is_same(decay_t, int S::*))]; } + { int a[T(__is_same(decay_t, int (S::*)()))]; } + { int a[T(__is_same(decay_t, int (S::*)() &))]; } + { int a[T(__is_same(decay_t, int (S::*)() &&))]; } + { int a[T(__is_same(decay_t, int (S::*)() const))]; } + { int a[T(__is_same(decay_t, int (S::*)() const&))]; } + { int a[T(__is_same(decay_t, int (S::*)() const&&))]; } + { int a[T(__is_same(decay_t, int (S::*)() volatile))]; } + { int a[T(__is_same(decay_t, int (S::*)() volatile&))]; } + { int a[T(__is_same(decay_t, int (S::*)() volatile&&))]; } + { int a[T(__is_same(decay_t, int (S::*)() const volatile))]; } + { int a[T(__is_same(decay_t, int (S::*)() const volatile&))]; } + { int a[T(__is_same(decay_t, int (S::*)() const volatile&&))]; } + { int a[T(__is_same(decay_t, int S::*))]; } + { int a[T(__is_same(decay_t, int (S::*)()))]; } + { int a[T(__is_same(decay_t, int (S::*)() &))]; } + { int a[T(__is_same(decay_t, int (S::*)() &&))]; } + { int a[T(__is_same(decay_t, int (S::*)() const))]; } + { int a[T(__is_same(decay_t, int (S::*)() const&))]; } + { int a[T(__is_same(decay_t, int (S::*)() const&&))]; } + { int a[T(__is_same(decay_t, int (S::*)() volatile))]; } + { int a[T(__is_same(decay_t, int (S::*)() volatile&))]; } + { int a[T(__is_same(decay_t, int (S::*)() volatile&&))]; } + { int a[T(__is_same(decay_t, int (S::*)() const volatile))]; } + { int a[T(__is_same(decay_t, int (S::*)() const volatile&))]; } + { int a[T(__is_same(decay_t, int (S::*)() const volatile&&))]; } +} + +template struct CheckAbominableFunction {}; +template +struct CheckAbominableFunction { + static void checks() + { + { int a[T(__is_same(add_const_t, const M))]; } + { int a[T(__is_same(add_volatile_t, volatile M))]; } + { int a[T(__is_same(add_cv_t, const volatile M))]; } + { int a[T(__is_same(add_lvalue_reference_t, M))]; } + { int a[T(__is_same(add_pointer_t, M))]; } + { int a[T(__is_same(add_rvalue_reference_t, M))]; } + { int a[T(__is_same(remove_const_t, M))]; } + { int a[T(__is_same(remove_volatile_t, M))]; } + { int a[T(__is_same(remove_cv_t, M))]; } + { int a[T(__is_same(remove_cvref_t, M))]; } + { int a[T(__is_same(remove_pointer_t, M))]; } + { int a[T(__is_same(remove_reference_t, M))]; } + } +}; + +void check_abominable_function() +{ + { CheckAbominableFunction x; } + { CheckAbominableFunction x; } + { CheckAbominableFunction x; } + { CheckAbominableFunction x; } + { CheckAbominableFunction x; } + { CheckAbominableFunction x; } + { CheckAbominableFunction x; } + { CheckAbominableFunction x; } + { CheckAbominableFunction x; } + { CheckAbominableFunction x; } + { CheckAbominableFunction x; } +} + +template using make_signed_t = __make_signed(T); + +void make_signed() +{ + { int a[T(__is_same(make_signed_t, signed char))]; } + { int a[T(__is_same(make_signed_t, const signed char))]; } + { int a[T(__is_same(make_signed_t, volatile signed char))]; } + { int a[T(__is_same(make_signed_t, const volatile signed char))]; } + + { int a[T(__is_same(make_signed_t, signed char))]; } + { int a[T(__is_same(make_signed_t, const signed char))]; } + { int a[T(__is_same(make_signed_t, volatile signed char))]; } + { int a[T(__is_same(make_signed_t, const volatile signed char))]; } + + { int a[T(__is_same(make_signed_t, signed char))]; } + { int a[T(__is_same(make_signed_t, const signed char))]; } + { int a[T(__is_same(make_signed_t, volatile signed char))]; } + { int a[T(__is_same(make_signed_t, const volatile signed char))]; } + + { int a[T(__is_same(make_signed_t, short))]; } + { int a[T(__is_same(make_signed_t, const short))]; } + { int a[T(__is_same(make_signed_t, volatile short))]; } + { int a[T(__is_same(make_signed_t, const volatile short))]; } + + { int a[T(__is_same(make_signed_t, short))]; } + { int a[T(__is_same(make_signed_t, const short))]; } + { int a[T(__is_same(make_signed_t, volatile short))]; } + { int a[T(__is_same(make_signed_t, const volatile short))]; } + + { int a[T(__is_same(make_signed_t, int))]; } + { int a[T(__is_same(make_signed_t, const int))]; } + { int a[T(__is_same(make_signed_t, volatile int))]; } + { int a[T(__is_same(make_signed_t, const volatile int))]; } + + { int a[T(__is_same(make_signed_t, int))]; } + { int a[T(__is_same(make_signed_t, const int))]; } + { int a[T(__is_same(make_signed_t, volatile int))]; } + { int a[T(__is_same(make_signed_t, const volatile int))]; } + + { int a[T(__is_same(make_signed_t, long))]; } + { int a[T(__is_same(make_signed_t, const long))]; } + { int a[T(__is_same(make_signed_t, volatile long))]; } + { int a[T(__is_same(make_signed_t, const volatile long))]; } + + { int a[T(__is_same(make_signed_t, long))]; } + { int a[T(__is_same(make_signed_t, const long))]; } + { int a[T(__is_same(make_signed_t, volatile long))]; } + { int a[T(__is_same(make_signed_t, const volatile long))]; } + + { int a[T(__is_same(make_signed_t, long long))]; } // remains unchanged + { int a[T(__is_same(make_signed_t, const long long))]; } // remains unchanged + { int a[T(__is_same(make_signed_t, volatile long long))]; } // remains unchanged + { int a[T(__is_same(make_signed_t, const volatile long long))]; } // remains unchanged + + { int a[T(__is_same(make_signed_t, long))]; } + { int a[T(__is_same(make_signed_t, const long))]; } + { int a[T(__is_same(make_signed_t, volatile long))]; } + { int a[T(__is_same(make_signed_t, const volatile long))]; } + + { int a[T(__is_same(make_signed_t<__int128>, __int128))]; } + { int a[T(__is_same(make_signed_t, const __int128))]; } + { int a[T(__is_same(make_signed_t, volatile __int128))]; } + { int a[T(__is_same(make_signed_t, const volatile __int128))]; } + + { int a[T(__is_same(make_signed_t<__uint128_t>, __int128))]; } + { int a[T(__is_same(make_signed_t, const __int128))]; } + { int a[T(__is_same(make_signed_t, volatile __int128))]; } + { int a[T(__is_same(make_signed_t, const volatile __int128))]; } + + { int a[T(__is_same(make_signed_t, int))]; } + { int a[T(__is_same(make_signed_t, int))]; } + { int a[T(__is_same(make_signed_t, const int))]; } + { int a[T(__is_same(make_signed_t, volatile int))]; } + { int a[T(__is_same(make_signed_t, const volatile int))]; } + { int a[T(__is_same(make_signed_t, int))]; } + { int a[T(__is_same(make_signed_t, const int))]; } + { int a[T(__is_same(make_signed_t, volatile int))]; } + { int a[T(__is_same(make_signed_t, const volatile int))]; } + + { int a[T(__is_same(make_signed_t, int))]; } + { int a[T(__is_same(make_signed_t, int))]; } + { int a[T(__is_same(make_signed_t, const int))]; } + { int a[T(__is_same(make_signed_t, volatile int))]; } + { int a[T(__is_same(make_signed_t, const volatile int))]; } + { int a[T(__is_same(make_signed_t, int))]; } + { int a[T(__is_same(make_signed_t, const int))]; } + { int a[T(__is_same(make_signed_t, volatile int))]; } + { int a[T(__is_same(make_signed_t, const volatile int))]; } + + { using ExpectedError = make_signed_t; } + // expected-error@*:*{{'make_signed' is only compatible with non-bool integers and enum types, but was given 'bool'}} + // expected-note@-2{{in instantiation of template type alias 'make_signed_t' requested here}} + { using ExpectedError = make_signed_t; } + // expected-error@*:*{{'make_signed' is only compatible with non-bool integers and enum types, but was given 'int[]'}} + // expected-note@-2{{in instantiation of template type alias 'make_signed_t' requested here}} + { using ExpectedError = make_signed_t; } + // expected-error@*:*{{'make_signed' is only compatible with non-bool integers and enum types, but was given 'int[5]'}} + // expected-note@-2{{in instantiation of template type alias 'make_signed_t' requested here}} + { using ExpectedError = make_signed_t; } + // expected-error@*:*{{'make_signed' is only compatible with non-bool integers and enum types, but was given 'void'}} + // expected-note@-2{{in instantiation of template type alias 'make_signed_t' requested here}} + { using ExpectedError = make_signed_t; } + // expected-error@*:*{{'make_signed' is only compatible with non-bool integers and enum types, but was given 'int *'}} + // expected-note@-2{{in instantiation of template type alias 'make_signed_t' requested here}} + { using ExpectedError = make_signed_t; } + // expected-error@*:*{{'make_signed' is only compatible with non-bool integers and enum types, but was given 'int &'}} + // expected-note@-2{{in instantiation of template type alias 'make_signed_t' requested here}} + { using ExpectedError = make_signed_t; } + // expected-error@*:*{{'make_signed' is only compatible with non-bool integers and enum types, but was given 'int &&'}} + // expected-note@-2{{in instantiation of template type alias 'make_signed_t' requested here}} + { using ExpectedError = make_signed_t; } + // expected-error@*:*{{'make_signed' is only compatible with non-bool integers and enum types, but was given 'float'}} + // expected-note@-2{{in instantiation of template type alias 'make_signed_t' requested here}} + { using ExpectedError = make_signed_t; } + // expected-error@*:*{{'make_signed' is only compatible with non-bool integers and enum types, but was given 'double'}} + // expected-note@-2{{in instantiation of template type alias 'make_signed_t' requested here}} + { using ExpectedError = make_signed_t; } + // expected-error@*:*{{'make_signed' is only compatible with non-bool integers and enum types, but was given 'long double'}} + // expected-note@-2{{in instantiation of template type alias 'make_signed_t' requested here}} + { using ExpectedError = make_signed_t; } + // expected-error@*:*{{'make_signed' is only compatible with non-bool integers and enum types, but was given 'S'}} + // expected-note@-2{{in instantiation of template type alias 'make_signed_t' requested here}} + { using ExpectedError = make_signed_t; } + // expected-error@*:*{{'make_signed' is only compatible with non-bool integers and enum types, but was given 'S *'}} + // expected-note@-2{{in instantiation of template type alias 'make_signed_t' requested here}} + { using ExpectedError = make_signed_t; } + // expected-error@*:*{{'make_signed' is only compatible with non-bool integers and enum types, but was given 'int S::*'}} + // expected-note@-2{{in instantiation of template type alias 'make_signed_t' requested here}} + { using ExpectedError = make_signed_t; } + // expected-error@*:*{{'make_signed' is only compatible with non-bool integers and enum types, but was given 'int (S::*)()'}} + // expected-note@-2{{in instantiation of template type alias 'make_signed_t' requested here}} + { using ExpectedError = make_signed_t; } + // expected-error@*:*{{'make_signed' is only compatible with non-bool integers and enum types, but was given 'int (S::*)() &'}} + // expected-note@-2{{in instantiation of template type alias 'make_signed_t' requested here}} + { using ExpectedError = make_signed_t; } + // expected-error@*:*{{'make_signed' is only compatible with non-bool integers and enum types, but was given 'int (S::*)() &&'}} + // expected-note@-2{{in instantiation of template type alias 'make_signed_t' requested here}} + { using ExpectedError = make_signed_t; } + // expected-error@*:*{{'make_signed' is only compatible with non-bool integers and enum types, but was given 'int (S::*)() const'}} + // expected-note@-2{{in instantiation of template type alias 'make_signed_t' requested here}} + { using ExpectedError = make_signed_t; } + // expected-error@*:*{{'make_signed' is only compatible with non-bool integers and enum types, but was given 'int (S::*)() const &'}} + // expected-note@-2{{in instantiation of template type alias 'make_signed_t' requested here}} + { using ExpectedError = make_signed_t; } + // expected-error@*:*{{'make_signed' is only compatible with non-bool integers and enum types, but was given 'int (S::*)() const &&'}} + // expected-note@-2{{in instantiation of template type alias 'make_signed_t' requested here}} + { using ExpectedError = make_signed_t; } + // expected-error@*:*{{'make_signed' is only compatible with non-bool integers and enum types, but was given 'int (S::*)() volatile'}} + // expected-note@-2{{in instantiation of template type alias 'make_signed_t' requested here}} + { using ExpectedError = make_signed_t; } + // expected-error@*:*{{'make_signed' is only compatible with non-bool integers and enum types, but was given 'int (S::*)() volatile &'}} + // expected-note@-2{{in instantiation of template type alias 'make_signed_t' requested here}} + { using ExpectedError = make_signed_t; } + // expected-error@*:*{{'make_signed' is only compatible with non-bool integers and enum types, but was given 'int (S::*)() volatile &&'}} + // expected-note@-2{{in instantiation of template type alias 'make_signed_t' requested here}} + { using ExpectedError = make_signed_t; } + // expected-error@*:*{{'make_signed' is only compatible with non-bool integers and enum types, but was given 'int (S::*)() const volatile'}} + // expected-note@-2{{in instantiation of template type alias 'make_signed_t' requested here}} + { using ExpectedError = make_signed_t; } + // expected-error@*:*{{'make_signed' is only compatible with non-bool integers and enum types, but was given 'int (S::*)() const volatile &'}} + // expected-note@-2{{in instantiation of template type alias 'make_signed_t' requested here}} + { using ExpectedError = make_signed_t; } + // expected-error@*:*{{'make_signed' is only compatible with non-bool integers and enum types, but was given 'int (S::*)() const volatile &&'}} + // expected-note@-2{{in instantiation of template type alias 'make_signed_t' requested here}} +} + +template using make_unsigned_t = __make_unsigned(T); + +void make_unsigned() +{ + { int a[T(__is_same(make_unsigned_t, unsigned char))]; } + { int a[T(__is_same(make_unsigned_t, const unsigned char))]; } + { int a[T(__is_same(make_unsigned_t, volatile unsigned char))]; } + { int a[T(__is_same(make_unsigned_t, const volatile unsigned char))]; } + + { int a[T(__is_same(make_unsigned_t, unsigned char))]; } + { int a[T(__is_same(make_unsigned_t, const unsigned char))]; } + { int a[T(__is_same(make_unsigned_t, volatile unsigned char))]; } + { int a[T(__is_same(make_unsigned_t, const volatile unsigned char))]; } + + { int a[T(__is_same(make_unsigned_t, unsigned char))]; } + { int a[T(__is_same(make_unsigned_t, const unsigned char))]; } + { int a[T(__is_same(make_unsigned_t, volatile unsigned char))]; } + { int a[T(__is_same(make_unsigned_t, const volatile unsigned char))]; } + + { int a[T(__is_same(make_unsigned_t, unsigned short))]; } + { int a[T(__is_same(make_unsigned_t, const unsigned short))]; } + { int a[T(__is_same(make_unsigned_t, volatile unsigned short))]; } + { int a[T(__is_same(make_unsigned_t, const volatile unsigned short))]; } + + { int a[T(__is_same(make_unsigned_t, unsigned short))]; } + { int a[T(__is_same(make_unsigned_t, const unsigned short))]; } + { int a[T(__is_same(make_unsigned_t, volatile unsigned short))]; } + { int a[T(__is_same(make_unsigned_t, const volatile unsigned short))]; } + + { int a[T(__is_same(make_unsigned_t, unsigned int))]; } + { int a[T(__is_same(make_unsigned_t, const unsigned int))]; } + { int a[T(__is_same(make_unsigned_t, volatile unsigned int))]; } + { int a[T(__is_same(make_unsigned_t, const volatile unsigned int))]; } + + { int a[T(__is_same(make_unsigned_t, unsigned int))]; } + { int a[T(__is_same(make_unsigned_t, const unsigned int))]; } + { int a[T(__is_same(make_unsigned_t, volatile unsigned int))]; } + { int a[T(__is_same(make_unsigned_t, const volatile unsigned int))]; } + + { int a[T(__is_same(make_unsigned_t, unsigned long))]; } + { int a[T(__is_same(make_unsigned_t, const unsigned long))]; } + { int a[T(__is_same(make_unsigned_t, volatile unsigned long))]; } + { int a[T(__is_same(make_unsigned_t, const volatile unsigned long))]; } + + { int a[T(__is_same(make_unsigned_t, unsigned long))]; } + { int a[T(__is_same(make_unsigned_t, const unsigned long))]; } + { int a[T(__is_same(make_unsigned_t, volatile unsigned long))]; } + { int a[T(__is_same(make_unsigned_t, const volatile unsigned long))]; } + + { int a[T(__is_same(make_unsigned_t, unsigned long))]; } + { int a[T(__is_same(make_unsigned_t, const unsigned long))]; } + { int a[T(__is_same(make_unsigned_t, volatile unsigned long))]; } + { int a[T(__is_same(make_unsigned_t, const volatile unsigned long))]; } + + { int a[T(__is_same(make_unsigned_t, unsigned long long))]; } // remains unchanged + { int a[T(__is_same(make_unsigned_t, const unsigned long long))]; } // remains unchanged + { int a[T(__is_same(make_unsigned_t, volatile unsigned long long))]; } // remains unchanged + { int a[T(__is_same(make_unsigned_t, const volatile unsigned long long))]; } // remains unchanged + + { int a[T(__is_same(make_unsigned_t<__int128>, __uint128_t))]; } + { int a[T(__is_same(make_unsigned_t, const __uint128_t))]; } + { int a[T(__is_same(make_unsigned_t, volatile __uint128_t))]; } + { int a[T(__is_same(make_unsigned_t, const volatile __uint128_t))]; } + + { int a[T(__is_same(make_unsigned_t<__uint128_t>, __uint128_t))]; } + { int a[T(__is_same(make_unsigned_t, const __uint128_t))]; } + { int a[T(__is_same(make_unsigned_t, volatile __uint128_t))]; } + { int a[T(__is_same(make_unsigned_t, const volatile __uint128_t))]; } + + { int a[T(__is_same(make_unsigned_t, unsigned int))]; } + { int a[T(__is_same(make_unsigned_t, unsigned int))]; } + { int a[T(__is_same(make_unsigned_t, const unsigned int))]; } + { int a[T(__is_same(make_unsigned_t, volatile unsigned int))]; } + { int a[T(__is_same(make_unsigned_t, const volatile unsigned int))]; } + { int a[T(__is_same(make_unsigned_t, unsigned int))]; } + { int a[T(__is_same(make_unsigned_t, const unsigned int))]; } + { int a[T(__is_same(make_unsigned_t, volatile unsigned int))]; } + { int a[T(__is_same(make_unsigned_t, const volatile unsigned int))]; } + + { int a[T(__is_same(make_unsigned_t, unsigned int))]; } + { int a[T(__is_same(make_unsigned_t, unsigned int))]; } + { int a[T(__is_same(make_unsigned_t, const unsigned int))]; } + { int a[T(__is_same(make_unsigned_t, volatile unsigned int))]; } + { int a[T(__is_same(make_unsigned_t, const volatile unsigned int))]; } + { int a[T(__is_same(make_unsigned_t, unsigned int))]; } + { int a[T(__is_same(make_unsigned_t, const unsigned int))]; } + { int a[T(__is_same(make_unsigned_t, volatile unsigned int))]; } + { int a[T(__is_same(make_unsigned_t, const volatile unsigned int))]; } + + { using ExpectedError = make_signed_t; } + // expected-error@*:*{{'make_signed' is only compatible with non-bool integers and enum types, but was given 'bool'}} + // expected-note@-2{{in instantiation of template type alias 'make_signed_t' requested here}} + { using ExpectedError = make_unsigned_t; } + // expected-error@*:*{{'make_unsigned' is only compatible with non-bool integers and enum types, but was given 'int[]'}} + // expected-note@-2{{in instantiation of template type alias 'make_unsigned_t' requested here}} + { using ExpectedError = make_unsigned_t; } + // expected-error@*:*{{'make_unsigned' is only compatible with non-bool integers and enum types, but was given 'int[5]'}} + // expected-note@-2{{in instantiation of template type alias 'make_unsigned_t' requested here}} + { using ExpectedError = make_unsigned_t; } + // expected-error@*:*{{'make_unsigned' is only compatible with non-bool integers and enum types, but was given 'void'}} + // expected-note@-2{{in instantiation of template type alias 'make_unsigned_t' requested here}} + { using ExpectedError = make_unsigned_t; } + // expected-error@*:*{{'make_unsigned' is only compatible with non-bool integers and enum types, but was given 'int *'}} + // expected-note@-2{{in instantiation of template type alias 'make_unsigned_t' requested here}} + { using ExpectedError = make_unsigned_t; } + // expected-error@*:*{{'make_unsigned' is only compatible with non-bool integers and enum types, but was given 'int &'}} + // expected-note@-2{{in instantiation of template type alias 'make_unsigned_t' requested here}} + { using ExpectedError = make_unsigned_t; } + // expected-error@*:*{{'make_unsigned' is only compatible with non-bool integers and enum types, but was given 'int &&'}} + // expected-note@-2{{in instantiation of template type alias 'make_unsigned_t' requested here}} + { using ExpectedError = make_unsigned_t; } + // expected-error@*:*{{'make_unsigned' is only compatible with non-bool integers and enum types, but was given 'float'}} + // expected-note@-2{{in instantiation of template type alias 'make_unsigned_t' requested here}} + { using ExpectedError = make_unsigned_t; } + // expected-error@*:*{{'make_unsigned' is only compatible with non-bool integers and enum types, but was given 'double'}} + // expected-note@-2{{in instantiation of template type alias 'make_unsigned_t' requested here}} + { using ExpectedError = make_unsigned_t; } + // expected-error@*:*{{'make_unsigned' is only compatible with non-bool integers and enum types, but was given 'long double'}} + // expected-note@-2{{in instantiation of template type alias 'make_unsigned_t' requested here}} + { using ExpectedError = make_unsigned_t; } + // expected-error@*:*{{'make_unsigned' is only compatible with non-bool integers and enum types, but was given 'S'}} + // expected-note@-2{{in instantiation of template type alias 'make_unsigned_t' requested here}} + { using ExpectedError = make_unsigned_t; } + // expected-error@*:*{{'make_unsigned' is only compatible with non-bool integers and enum types, but was given 'S *'}} + // expected-note@-2{{in instantiation of template type alias 'make_unsigned_t' requested here}} + { using ExpectedError = make_unsigned_t; } + // expected-error@*:*{{'make_unsigned' is only compatible with non-bool integers and enum types, but was given 'int S::*'}} + // expected-note@-2{{in instantiation of template type alias 'make_unsigned_t' requested here}} + { using ExpectedError = make_unsigned_t; } + // expected-error@*:*{{'make_unsigned' is only compatible with non-bool integers and enum types, but was given 'int (S::*)()'}} + // expected-note@-2{{in instantiation of template type alias 'make_unsigned_t' requested here}} + { using ExpectedError = make_unsigned_t; } + // expected-error@*:*{{'make_unsigned' is only compatible with non-bool integers and enum types, but was given 'int (S::*)() &'}} + // expected-note@-2{{in instantiation of template type alias 'make_unsigned_t' requested here}} + { using ExpectedError = make_unsigned_t; } + // expected-error@*:*{{'make_unsigned' is only compatible with non-bool integers and enum types, but was given 'int (S::*)() &&'}} + // expected-note@-2{{in instantiation of template type alias 'make_unsigned_t' requested here}} + { using ExpectedError = make_unsigned_t; } + // expected-error@*:*{{'make_unsigned' is only compatible with non-bool integers and enum types, but was given 'int (S::*)() const'}} + // expected-note@-2{{in instantiation of template type alias 'make_unsigned_t' requested here}} + { using ExpectedError = make_unsigned_t; } + // expected-error@*:*{{'make_unsigned' is only compatible with non-bool integers and enum types, but was given 'int (S::*)() const &'}} + // expected-note@-2{{in instantiation of template type alias 'make_unsigned_t' requested here}} + { using ExpectedError = make_unsigned_t; } + // expected-error@*:*{{'make_unsigned' is only compatible with non-bool integers and enum types, but was given 'int (S::*)() const &&'}} + // expected-note@-2{{in instantiation of template type alias 'make_unsigned_t' requested here}} + { using ExpectedError = make_unsigned_t; } + // expected-error@*:*{{'make_unsigned' is only compatible with non-bool integers and enum types, but was given 'int (S::*)() volatile'}} + // expected-note@-2{{in instantiation of template type alias 'make_unsigned_t' requested here}} + { using ExpectedError = make_unsigned_t; } + // expected-error@*:*{{'make_unsigned' is only compatible with non-bool integers and enum types, but was given 'int (S::*)() volatile &'}} + // expected-note@-2{{in instantiation of template type alias 'make_unsigned_t' requested here}} + { using ExpectedError = make_unsigned_t; } + // expected-error@*:*{{'make_unsigned' is only compatible with non-bool integers and enum types, but was given 'int (S::*)() volatile &&'}} + // expected-note@-2{{in instantiation of template type alias 'make_unsigned_t' requested here}} + { using ExpectedError = make_unsigned_t; } + // expected-error@*:*{{'make_unsigned' is only compatible with non-bool integers and enum types, but was given 'int (S::*)() const volatile'}} + // expected-note@-2{{in instantiation of template type alias 'make_unsigned_t' requested here}} + { using ExpectedError = make_unsigned_t; } + // expected-error@*:*{{'make_unsigned' is only compatible with non-bool integers and enum types, but was given 'int (S::*)() const volatile &'}} + // expected-note@-2{{in instantiation of template type alias 'make_unsigned_t' requested here}} + { using ExpectedError = make_unsigned_t; } + // expected-error@*:*{{'make_unsigned' is only compatible with non-bool integers and enum types, but was given 'int (S::*)() const volatile &&'}} + // expected-note@-2{{in instantiation of template type alias 'make_unsigned_t' requested here}} +} + +template using remove_extent_t = __remove_extent(T); + +void remove_extent() +{ + { int x[T(__is_same(remove_extent_t, void))]; } + { int x[T(__is_same(remove_extent_t, int))]; } + { int x[T(__is_same(remove_extent_t, int))]; } + { int x[T(__is_same(remove_extent_t, int))]; } + { int x[T(__is_same(remove_extent_t, int[2]))]; } + { int x[T(__is_same(remove_extent_t, int[2]))]; } + { int x[T(__is_same(remove_extent_t, const int))]; } + { int x[T(__is_same(remove_extent_t, const int))]; } + { int x[T(__is_same(remove_extent_t, const int[2]))]; } + { int x[T(__is_same(remove_extent_t, const int[2]))]; } + { int x[T(__is_same(remove_extent_t, volatile int))]; } + { int x[T(__is_same(remove_extent_t, volatile int))]; } + { int x[T(__is_same(remove_extent_t, volatile int[2]))]; } + { int x[T(__is_same(remove_extent_t, volatile int[2]))]; } + { int x[T(__is_same(remove_extent_t, const volatile int))]; } + { int x[T(__is_same(remove_extent_t, const volatile int))]; } + { int x[T(__is_same(remove_extent_t, const volatile int[2]))]; } + { int x[T(__is_same(remove_extent_t, const volatile int[2]))]; } + { int x[T(__is_same(remove_extent_t, int*))]; } + { int x[T(__is_same(remove_extent_t, int&))]; } + { int x[T(__is_same(remove_extent_t, int&&))]; } + { int x[T(__is_same(remove_extent_t, int()))]; } + { int x[T(__is_same(remove_extent_t, int(*)()))]; } + { int x[T(__is_same(remove_extent_t, int(&)()))]; } + + { int x[T(__is_same(remove_extent_t, S))]; } + { int x[T(__is_same(remove_extent_t, int S::*))]; } + { int x[T(__is_same(remove_extent_t, int (S::*)()))]; } + { int x[T(__is_same(remove_extent_t, int (S::*)() &))]; } + { int x[T(__is_same(remove_extent_t, int (S::*)() &&))]; } + { int x[T(__is_same(remove_extent_t, int (S::*)() const))]; } + { int x[T(__is_same(remove_extent_t, int (S::*)() const&))]; } + { int x[T(__is_same(remove_extent_t, int (S::*)() const&&))]; } + { int x[T(__is_same(remove_extent_t, int (S::*)() volatile))]; } + { int x[T(__is_same(remove_extent_t, int (S::*)() volatile&))]; } + { int x[T(__is_same(remove_extent_t, int (S::*)() volatile&&))]; } + { int x[T(__is_same(remove_extent_t, int (S::*)() const volatile))]; } + { int x[T(__is_same(remove_extent_t, int (S::*)() const volatile&))]; } + { int x[T(__is_same(remove_extent_t, int (S::*)() const volatile&&))]; } +} + +template using remove_all_extents_t = __remove_all_extents(T); + +void remove_all_extents() +{ + { int x[T(__is_same(remove_all_extents_t, void))]; } + { int x[T(__is_same(remove_all_extents_t, int))]; } + { int x[T(__is_same(remove_all_extents_t, const int))]; } + { int x[T(__is_same(remove_all_extents_t, volatile int))]; } + { int x[T(__is_same(remove_all_extents_t, const volatile int))]; } + { int x[T(__is_same(remove_all_extents_t, int))]; } + { int x[T(__is_same(remove_all_extents_t, int))]; } + { int x[T(__is_same(remove_all_extents_t, int))]; } + { int x[T(__is_same(remove_all_extents_t, int))]; } + { int x[T(__is_same(remove_all_extents_t, const int))]; } + { int x[T(__is_same(remove_all_extents_t, const int))]; } + { int x[T(__is_same(remove_all_extents_t, const int))]; } + { int x[T(__is_same(remove_all_extents_t, const int))]; } + { int x[T(__is_same(remove_all_extents_t, volatile int))]; } + { int x[T(__is_same(remove_all_extents_t, volatile int))]; } + { int x[T(__is_same(remove_all_extents_t, volatile int))]; } + { int x[T(__is_same(remove_all_extents_t, volatile int))]; } + { int x[T(__is_same(remove_all_extents_t, const volatile int))]; } + { int x[T(__is_same(remove_all_extents_t, const volatile int))]; } + { int x[T(__is_same(remove_all_extents_t, const volatile int))]; } + { int x[T(__is_same(remove_all_extents_t, const volatile int))]; } + { int x[T(__is_same(remove_all_extents_t, int*))]; } + { int x[T(__is_same(remove_all_extents_t, int&))]; } + { int x[T(__is_same(remove_all_extents_t, int&&))]; } + { int x[T(__is_same(remove_all_extents_t, int()))]; } + { int x[T(__is_same(remove_all_extents_t, int(*)()))]; } + { int x[T(__is_same(remove_all_extents_t, int(&)()))]; } + + { int x[T(__is_same(remove_all_extents_t, S))]; } + { int x[T(__is_same(remove_all_extents_t, int S::*))]; } + { int x[T(__is_same(remove_all_extents_t, int (S::*)()))]; } + { int x[T(__is_same(remove_all_extents_t, int (S::*)() &))]; } + { int x[T(__is_same(remove_all_extents_t, int (S::*)() &&))]; } + { int x[T(__is_same(remove_all_extents_t, int (S::*)() const))]; } + { int x[T(__is_same(remove_all_extents_t, int (S::*)() const&))]; } + { int x[T(__is_same(remove_all_extents_t, int (S::*)() const&&))]; } + { int x[T(__is_same(remove_all_extents_t, int (S::*)() volatile))]; } + { int x[T(__is_same(remove_all_extents_t, int (S::*)() volatile&))]; } + { int x[T(__is_same(remove_all_extents_t, int (S::*)() volatile&&))]; } + { int x[T(__is_same(remove_all_extents_t, int (S::*)() const volatile))]; } + { int x[T(__is_same(remove_all_extents_t, int (S::*)() const volatile&))]; } + { int x[T(__is_same(remove_all_extents_t, int (S::*)() const volatile&&))]; } +}