aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/AST/Type.h19
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td4
-rw-r--r--clang/include/clang/Basic/Specifiers.h49
-rw-r--r--clang/include/clang/Basic/TokenKinds.def4
-rw-r--r--clang/include/clang/Basic/TransformTypeTraits.def29
-rw-r--r--clang/include/clang/Parse/Parser.h3
-rw-r--r--clang/include/clang/Sema/DeclSpec.h21
-rw-r--r--clang/include/clang/Sema/Sema.h19
-rw-r--r--clang/include/clang/module.modulemap1
-rw-r--r--clang/lib/AST/ASTContext.cpp27
-rw-r--r--clang/lib/AST/ItaniumMangle.cpp14
-rw-r--r--clang/lib/AST/JSONNodeDumper.cpp7
-rw-r--r--clang/lib/AST/TextNodeDumper.cpp6
-rw-r--r--clang/lib/AST/TypePrinter.cpp32
-rw-r--r--clang/lib/Format/FormatToken.cpp3
-rw-r--r--clang/lib/Format/FormatToken.h3
-rw-r--r--clang/lib/Format/TokenAnnotator.cpp6
-rw-r--r--clang/lib/Lex/PPMacroExpansion.cpp3
-rw-r--r--clang/lib/Parse/ParseDecl.cpp18
-rw-r--r--clang/lib/Parse/ParseDeclCXX.cpp116
-rw-r--r--clang/lib/Parse/ParseExpr.cpp22
-rw-r--r--clang/lib/Parse/ParseExprCXX.cpp20
-rw-r--r--clang/lib/Parse/ParseStmt.cpp18
-rw-r--r--clang/lib/Parse/ParseTentative.cpp11
-rw-r--r--clang/lib/Sema/DeclSpec.cpp9
-rw-r--r--clang/lib/Sema/SemaDecl.cpp6
-rw-r--r--clang/lib/Sema/SemaTemplateVariadic.cpp3
-rw-r--r--clang/lib/Sema/SemaType.cpp305
-rw-r--r--clang/test/CodeGenCXX/mangle.cpp97
-rw-r--r--clang/test/SemaCXX/libstdcxx_transform_type_traits_hack.cpp84
-rw-r--r--clang/test/SemaCXX/remove_pointer.mm8
-rw-r--r--clang/test/SemaCXX/type-traits.cpp700
-rw-r--r--clang/utils/ClangVisualizers/clang.natvis20
33 files changed, 1489 insertions, 198 deletions
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index ad9835e..f46224f 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -797,6 +797,9 @@ public:
return Value.getPointer().isNull();
}
+ // Determines if a type can form `T&`.
+ 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.
@@ -4637,7 +4640,8 @@ public:
class UnaryTransformType : public Type {
public:
enum UTTKind {
- EnumUnderlyingType
+#define TRANSFORM_TYPE_TRAIT_DEF(Enum, _) Enum,
+#include "clang/Basic/TransformTypeTraits.def"
};
private:
@@ -6584,6 +6588,19 @@ inline const Type *QualType::getTypePtrOrNull() const {
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 (const auto *F = Self.getAs<FunctionProtoType>())
+ return F->getMethodQuals().empty() && F->getRefQualifier() == RQ_None;
+
+ return false;
+}
+
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
index 791ef9d..f544bd3 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -8674,6 +8674,10 @@ def err_typecheck_expect_flt_or_vector : Error<
"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-%select{bool|_BitInt(1)}1 integers and enum types, but was given "
+ "%2%select{| whose underlying type is %4}3">;
def ext_typecheck_cond_incompatible_pointers : ExtWarn<
"pointer type mismatch%diff{ ($ and $)|}0,1">,
InGroup<DiagGroup<"pointer-type-mismatch">>;
diff --git a/clang/include/clang/Basic/Specifiers.h b/clang/include/clang/Basic/Specifiers.h
index 7657ae3..8a08a43 100644
--- a/clang/include/clang/Basic/Specifiers.h
+++ b/clang/include/clang/Basic/Specifiers.h
@@ -53,41 +53,42 @@ namespace clang {
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
+#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) TST_##Trait,
+#include "clang/Basic/TransformTypeTraits.def"
+ 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 +97,8 @@ namespace clang {
/// 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
index 565e5a3..7f421ad 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -501,7 +501,9 @@ TYPE_TRAIT_1(__is_trivially_copyable, IsTriviallyCopyable, KEYCXX)
TYPE_TRAIT_1(__is_union, IsUnion, KEYCXX)
TYPE_TRAIT_1(__has_unique_object_representations,
HasUniqueObjectRepresentations, KEYCXX)
-KEYWORD(__underlying_type , KEYCXX)
+
+#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) KEYWORD(__##Trait, KEYCXX)
+#include "clang/Basic/TransformTypeTraits.def"
// Clang-only C++ Type Traits
TYPE_TRAIT_1(__is_trivially_relocatable, IsTriviallyRelocatable, KEYCXX)
diff --git a/clang/include/clang/Basic/TransformTypeTraits.def b/clang/include/clang/Basic/TransformTypeTraits.def
new file mode 100644
index 0000000..9389eff
--- /dev/null
+++ b/clang/include/clang/Basic/TransformTypeTraits.def
@@ -0,0 +1,29 @@
+//==--- TransformTypeTraits.def - type trait transformations --------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines transform type traits' names.
+//
+//===----------------------------------------------------------------------===//
+
+TRANSFORM_TYPE_TRAIT_DEF(AddLvalueReference, add_lvalue_reference)
+TRANSFORM_TYPE_TRAIT_DEF(AddPointer, add_pointer)
+TRANSFORM_TYPE_TRAIT_DEF(AddRvalueReference, add_rvalue_reference)
+TRANSFORM_TYPE_TRAIT_DEF(Decay, decay)
+TRANSFORM_TYPE_TRAIT_DEF(MakeSigned, make_signed)
+TRANSFORM_TYPE_TRAIT_DEF(MakeUnsigned, make_unsigned)
+TRANSFORM_TYPE_TRAIT_DEF(RemoveAllExtents, remove_all_extents)
+TRANSFORM_TYPE_TRAIT_DEF(RemoveConst, remove_const)
+TRANSFORM_TYPE_TRAIT_DEF(RemoveCV, remove_cv)
+TRANSFORM_TYPE_TRAIT_DEF(RemoveCVRef, remove_cvref)
+TRANSFORM_TYPE_TRAIT_DEF(RemoveExtent, remove_extent)
+TRANSFORM_TYPE_TRAIT_DEF(RemovePointer, remove_pointer)
+TRANSFORM_TYPE_TRAIT_DEF(RemoveReference, remove_reference)
+TRANSFORM_TYPE_TRAIT_DEF(RemoveRestrict, remove_restrict)
+TRANSFORM_TYPE_TRAIT_DEF(RemoveVolatile, remove_volatile)
+TRANSFORM_TYPE_TRAIT_DEF(EnumUnderlyingType, underlying_type)
+#undef TRANSFORM_TYPE_TRAIT_DEF
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index 567433f..3dd92f0 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -2906,7 +2906,6 @@ private:
void AnnotateExistingDecltypeSpecifier(const DeclSpec &DS,
SourceLocation StartLoc,
SourceLocation EndLoc);
- void ParseUnderlyingTypeSpecifier(DeclSpec &DS);
void ParseAtomicSpecifier(DeclSpec &DS);
ExprResult ParseAlignArgument(SourceLocation Start,
@@ -3004,6 +3003,8 @@ private:
SourceLocation &EllipsisLoc);
void ParseBracketDeclarator(Declarator &D);
void ParseMisplacedBracketDeclarator(Declarator &D);
+ bool MaybeParseTypeTransformTypeSpecifier(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
index be94dab..bb49151 100644
--- 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"
@@ -290,7 +291,9 @@ public:
static const TST TST_typeofExpr = clang::TST_typeofExpr;
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;
+#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) \
+ static const TST TST_##Trait = clang::TST_##Trait;
+#include "clang/Basic/TransformTypeTraits.def"
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 +336,7 @@ private:
/*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 +403,8 @@ private:
ObjCDeclSpec *ObjCQualifiers;
static bool isTypeRep(TST T) {
- return (T == TST_typename || T == TST_typeofType ||
- T == TST_underlyingType || T == TST_atomic);
+ return T == TST_atomic || T == TST_typename || T == TST_typeofType ||
+ isTransformTypeTrait(T);
}
static bool isExprRep(TST T) {
return (T == TST_typeofExpr || T == TST_decltype || T == TST_bitint);
@@ -418,6 +421,14 @@ public:
T == TST_interface || T == TST_union ||
T == TST_class);
}
+ static bool isTransformTypeTrait(TST T) {
+ constexpr std::array<TST, 16> Traits = {
+#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) TST_##Trait,
+#include "clang/Basic/TransformTypeTraits.def"
+ };
+
+ return T >= Traits.front() && T <= Traits.back();
+ }
DeclSpec(AttributeFactory &attrFactory)
: StorageClassSpec(SCS_unspecified),
@@ -522,7 +533,7 @@ public:
}
SourceRange getTypeofParensRange() const { return TypeofParensRange; }
- void setTypeofParensRange(SourceRange range) { TypeofParensRange = range; }
+ void setTypeArgumentRange(SourceRange range) { TypeofParensRange = range; }
bool hasAutoTypeSpec() const {
return (TypeSpecType == TST_auto || TypeSpecType == TST_auto_type ||
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 14bb2b1..c6c298e 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -2511,8 +2511,23 @@ public:
/// If AsUnevaluated is false, E is treated as though it were an evaluated
/// context, such as when building a type for decltype(auto).
QualType BuildDecltypeType(Expr *E, bool AsUnevaluated = true);
- QualType BuildUnaryTransformType(QualType BaseType,
- UnaryTransformType::UTTKind UKind,
+
+ using UTTKind = UnaryTransformType::UTTKind;
+ QualType BuildUnaryTransformType(QualType BaseType, UTTKind UKind,
+ SourceLocation Loc);
+ QualType BuiltinEnumUnderlyingType(QualType BaseType, SourceLocation Loc);
+ QualType BuiltinAddPointer(QualType BaseType, SourceLocation Loc);
+ QualType BuiltinRemovePointer(QualType BaseType, SourceLocation Loc);
+ QualType BuiltinDecay(QualType BaseType, SourceLocation Loc);
+ QualType BuiltinAddReference(QualType BaseType, UTTKind UKind,
+ SourceLocation Loc);
+ QualType BuiltinRemoveExtent(QualType BaseType, UTTKind UKind,
+ SourceLocation Loc);
+ QualType BuiltinRemoveReference(QualType BaseType, UTTKind UKind,
+ SourceLocation Loc);
+ QualType BuiltinChangeCVRQualifiers(QualType BaseType, UTTKind UKind,
+ SourceLocation Loc);
+ QualType BuiltinChangeSignedness(QualType BaseType, UTTKind UKind,
SourceLocation Loc);
//===--------------------------------------------------------------------===//
diff --git a/clang/include/clang/module.modulemap b/clang/include/clang/module.modulemap
index 01bce77..ef055b5 100644
--- a/clang/include/clang/module.modulemap
+++ b/clang/include/clang/module.modulemap
@@ -71,6 +71,7 @@ module Clang_Basic {
textual header "Basic/RISCVVTypes.def"
textual header "Basic/Sanitizers.def"
textual header "Basic/TargetCXXABI.def"
+ textual header "Basic/TransformTypeTraits.def"
module * { export * }
}
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 0786c1e..a4c6a69 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -10781,7 +10781,8 @@ unsigned ASTContext::getIntWidth(QualType T) const {
}
QualType ASTContext::getCorrespondingUnsignedType(QualType T) const {
- assert((T->hasSignedIntegerRepresentation() || T->isSignedFixedPointType()) &&
+ assert((T->hasIntegerRepresentation() || T->isEnumeralType() ||
+ T->isFixedPointType()) &&
"Unexpected type");
// Turn <4 x signed int> -> <4 x unsigned int>
@@ -10799,8 +10800,11 @@ QualType ASTContext::getCorrespondingUnsignedType(QualType T) const {
T = ETy->getDecl()->getIntegerType();
switch (T->castAs<BuiltinType>()->getKind()) {
+ case BuiltinType::Char_U:
+ // Plain `char` is mapped to `unsigned char` even if it's already unsigned
case BuiltinType::Char_S:
case BuiltinType::SChar:
+ case BuiltinType::Char8:
return UnsignedCharTy;
case BuiltinType::Short:
return UnsignedShortTy;
@@ -10814,7 +10818,7 @@ QualType ASTContext::getCorrespondingUnsignedType(QualType T) const {
return UnsignedInt128Ty;
// wchar_t is special. It is either signed or not, but when it's signed,
// there's no matching "unsigned wchar_t". Therefore we return the unsigned
- // version of it's underlying type instead.
+ // version of its underlying type instead.
case BuiltinType::WChar_S:
return getUnsignedWCharType();
@@ -10843,13 +10847,16 @@ QualType ASTContext::getCorrespondingUnsignedType(QualType T) const {
case BuiltinType::SatLongFract:
return SatUnsignedLongFractTy;
default:
- llvm_unreachable("Unexpected signed integer or fixed point type");
+ assert((T->hasUnsignedIntegerRepresentation() ||
+ T->isUnsignedFixedPointType()) &&
+ "Unexpected signed integer or fixed point type");
+ return T;
}
}
QualType ASTContext::getCorrespondingSignedType(QualType T) const {
- assert((T->hasUnsignedIntegerRepresentation() ||
- T->isUnsignedFixedPointType()) &&
+ assert((T->hasIntegerRepresentation() || T->isEnumeralType() ||
+ T->isFixedPointType()) &&
"Unexpected type");
// Turn <4 x unsigned int> -> <4 x signed int>
@@ -10867,8 +10874,11 @@ QualType ASTContext::getCorrespondingSignedType(QualType T) const {
T = ETy->getDecl()->getIntegerType();
switch (T->castAs<BuiltinType>()->getKind()) {
+ case BuiltinType::Char_S:
+ // Plain `char` is mapped to `signed char` even if it's already signed
case BuiltinType::Char_U:
case BuiltinType::UChar:
+ case BuiltinType::Char8:
return SignedCharTy;
case BuiltinType::UShort:
return ShortTy;
@@ -10882,7 +10892,7 @@ QualType ASTContext::getCorrespondingSignedType(QualType T) const {
return Int128Ty;
// wchar_t is special. It is either unsigned or not, but when it's unsigned,
// there's no matching "signed wchar_t". Therefore we return the signed
- // version of it's underlying type instead.
+ // version of its underlying type instead.
case BuiltinType::WChar_U:
return getSignedWCharType();
@@ -10911,7 +10921,10 @@ QualType ASTContext::getCorrespondingSignedType(QualType T) const {
case BuiltinType::SatULongFract:
return SatLongFractTy;
default:
- llvm_unreachable("Unexpected unsigned integer or fixed point type");
+ assert(
+ (T->hasSignedIntegerRepresentation() || T->isSignedFixedPointType()) &&
+ "Unexpected signed integer or fixed point type");
+ return T;
}
}
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index fc5a590..46229a0 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -3980,16 +3980,22 @@ void CXXNameMangler::mangleType(const UnaryTransformType *T) {
// If this is dependent, we need to record that. If not, we simply
// mangle it as the underlying type since they are equivalent.
if (T->isDependentType()) {
- Out << 'U';
+ Out << "u";
+ StringRef BuiltinName;
switch (T->getUTTKind()) {
- case UnaryTransformType::EnumUnderlyingType:
- Out << "3eut";
- break;
+#define TRANSFORM_TYPE_TRAIT_DEF(Enum, Trait) \
+ case UnaryTransformType::Enum: \
+ BuiltinName = "__" #Trait; \
+ break;
+#include "clang/Basic/TransformTypeTraits.def"
}
+ Out << BuiltinName.size() << BuiltinName;
}
+ Out << "I";
mangleType(T->getBaseType());
+ Out << "E";
}
void CXXNameMangler::mangleType(const AutoType *T) {
diff --git a/clang/lib/AST/JSONNodeDumper.cpp b/clang/lib/AST/JSONNodeDumper.cpp
index 74ef4c3..ae9c85e 100644
--- 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"
@@ -662,9 +663,11 @@ void JSONNodeDumper::VisitUnresolvedUsingType(const UnresolvedUsingType *UUT) {
void JSONNodeDumper::VisitUnaryTransformType(const UnaryTransformType *UTT) {
switch (UTT->getUTTKind()) {
- case UnaryTransformType::EnumUnderlyingType:
- JOS.attribute("transformKind", "underlying_type");
+#define TRANSFORM_TYPE_TRAIT_DEF(Enum, Trait) \
+ case UnaryTransformType::Enum: \
+ JOS.attribute("transformKind", #Trait); \
break;
+#include "clang/Basic/TransformTypeTraits.def"
}
}
diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp
index c3da5a4..f9f149b 100644
--- a/clang/lib/AST/TextNodeDumper.cpp
+++ b/clang/lib/AST/TextNodeDumper.cpp
@@ -1551,9 +1551,11 @@ void TextNodeDumper::VisitTypedefType(const TypedefType *T) {
void TextNodeDumper::VisitUnaryTransformType(const UnaryTransformType *T) {
switch (T->getUTTKind()) {
- case UnaryTransformType::EnumUnderlyingType:
- OS << " underlying_type";
+#define TRANSFORM_TYPE_TRAIT_DEF(Enum, Trait) \
+ case UnaryTransformType::Enum: \
+ OS << " " #Trait; \
break;
+#include "clang/Basic/TransformTypeTraits.def"
}
}
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index 3cb2001..a7da9fd 100644
--- 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"
@@ -1140,29 +1142,19 @@ void TypePrinter::printUnaryTransformBefore(const UnaryTransformType *T,
raw_ostream &OS) {
IncludeStrongLifetimeRAII Strong(Policy);
- switch (T->getUTTKind()) {
- case UnaryTransformType::EnumUnderlyingType:
- OS << "__underlying_type(";
- print(T->getBaseType(), OS, StringRef());
- OS << ')';
- spaceBeforePlaceHolder(OS);
- return;
- }
-
- printBefore(T->getBaseType(), OS);
+ static llvm::DenseMap<int, const char *> Transformation = {{
+#define TRANSFORM_TYPE_TRAIT_DEF(Enum, Trait) \
+ {UnaryTransformType::Enum, "__" #Trait},
+#include "clang/Basic/TransformTypeTraits.def"
+ }};
+ OS << Transformation[T->getUTTKind()] << '(';
+ print(T->getBaseType(), OS, StringRef());
+ OS << ')';
+ spaceBeforePlaceHolder(OS);
}
void TypePrinter::printUnaryTransformAfter(const UnaryTransformType *T,
- raw_ostream &OS) {
- IncludeStrongLifetimeRAII Strong(Policy);
-
- switch (T->getUTTKind()) {
- case UnaryTransformType::EnumUnderlyingType:
- return;
- }
-
- printAfter(T->getBaseType(), OS);
-}
+ raw_ostream &OS) {}
void TypePrinter::printAutoBefore(const AutoType *T, raw_ostream &OS) {
// If the type has been deduced, do not print 'auto'.
diff --git a/clang/lib/Format/FormatToken.cpp b/clang/lib/Format/FormatToken.cpp
index 832af46..f9f0d71 100644
--- a/clang/lib/Format/FormatToken.cpp
+++ b/clang/lib/Format/FormatToken.cpp
@@ -56,7 +56,8 @@ bool FormatToken::isSimpleTypeSpecifier() const {
case tok::kw___ibm128:
case tok::kw_wchar_t:
case tok::kw_bool:
- case tok::kw___underlying_type:
+#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait:
+#include "clang/Basic/TransformTypeTraits.def"
case tok::annot_typename:
case tok::kw_char8_t:
case tok::kw_char16_t:
diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h
index 21ed9bb..8751537 100644
--- a/clang/lib/Format/FormatToken.h
+++ b/clang/lib/Format/FormatToken.h
@@ -681,7 +681,8 @@ public:
case tok::kw_static_assert:
case tok::kw__Atomic:
case tok::kw___attribute:
- case tok::kw___underlying_type:
+#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait:
+#include "clang/Basic/TransformTypeTraits.def"
case tok::kw_requires:
return true;
default:
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index 668f8b3..94b897a 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -317,8 +317,10 @@ private:
if (PrevNonComment->is(tok::kw___attribute)) {
OpeningParen.setType(TT_AttributeParen);
} else if (PrevNonComment->isOneOf(TT_TypenameMacro, tok::kw_decltype,
- tok::kw_typeof, tok::kw__Atomic,
- tok::kw___underlying_type)) {
+ tok::kw_typeof,
+#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) tok::kw___##Trait,
+#include "clang/Basic/TransformTypeTraits.def"
+ tok::kw__Atomic)) {
OpeningParen.setType(TT_TypeDeclarationParen);
// decltype() and typeof() usually contain expressions.
if (PrevNonComment->isOneOf(tok::kw_decltype, tok::kw_typeof))
diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp
index f3be210..78ab8ba 100644
--- a/clang/lib/Lex/PPMacroExpansion.cpp
+++ b/clang/lib/Lex/PPMacroExpansion.cpp
@@ -1663,7 +1663,8 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
.Case("__array_rank", true)
.Case("__array_extent", true)
.Case("__reference_binds_to_temporary", true)
- .Case("__underlying_type", true)
+#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) .Case("__" #Trait, true)
+#include "clang/Basic/TransformTypeTraits.def"
.Default(false);
} else {
return llvm::StringSwitch<bool>(II->getName())
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 769809c..97a856a 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -3472,7 +3472,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// typedef-name
case tok::kw___super:
case tok::kw_decltype:
- case tok::identifier: {
+ case tok::identifier:
+ ParseIdentifier: {
// This identifier can only be a typedef name if we haven't already seen
// a type-specifier. Without this check we misparse:
// typedef int X; struct Y { short X; }; as 'short int'.
@@ -3665,7 +3666,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
}
}
ConsumedEnd = Tok.getLocation();
- DS.setTypeofParensRange(Tracker.getRange());
+ DS.setTypeArgumentRange(Tracker.getRange());
// Even if something went wrong above, continue as if we've seen
// `decltype(auto)`.
isInvalid = DS.SetTypeSpecType(TST_decltype_auto, Loc, PrevSpec,
@@ -4207,8 +4208,13 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
HandlePragmaMSPointersToMembers();
continue;
- case tok::kw___underlying_type:
- ParseUnderlyingTypeSpecifier(DS);
+#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait:
+#include "clang/Basic/TransformTypeTraits.def"
+ // HACK: libstdc++ already uses '__remove_cv' as an alias template so we
+ // work around this by expecting all transform type traits to be suffixed
+ // with '('. They're an identifier otherwise.
+ if (!MaybeParseTypeTransformTypeSpecifier(DS))
+ goto ParseIdentifier;
continue;
case tok::kw__Atomic:
@@ -7446,7 +7452,7 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) {
ExprResult Operand = Actions.CorrectDelayedTyposInExpr(
ParseExprAfterUnaryExprOrTypeTrait(OpTok, isCastExpr, CastTy, CastRange));
if (hasParens)
- DS.setTypeofParensRange(CastRange);
+ DS.setTypeArgumentRange(CastRange);
if (CastRange.getEnd().isInvalid())
// FIXME: Not accurate, the range gets one token more than it should.
@@ -7516,7 +7522,7 @@ void Parser::ParseAtomicSpecifier(DeclSpec &DS) {
if (T.getCloseLocation().isInvalid())
return;
- DS.setTypeofParensRange(T.getRange());
+ DS.setTypeArgumentRange(T.getRange());
DS.SetRangeEnd(T.getCloseLocation());
const char *PrevSpec = nullptr;
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 8dfa91e..4510ff8 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -18,6 +18,7 @@
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TokenKinds.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/Parser.h"
#include "clang/Parse/RAIIObjectsForParser.h"
@@ -1021,7 +1022,7 @@ SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) {
EndLoc = Tok.getAnnotationEndLoc();
// Unfortunately, we don't know the LParen source location as the annotated
// token doesn't have it.
- DS.setTypeofParensRange(SourceRange(SourceLocation(), EndLoc));
+ DS.setTypeArgumentRange(SourceRange(SourceLocation(), EndLoc));
ConsumeAnnotationToken();
if (Result.isInvalid()) {
DS.SetTypeSpecError();
@@ -1085,7 +1086,7 @@ SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) {
// Match the ')'
T.consumeClose();
- DS.setTypeofParensRange(T.getRange());
+ DS.setTypeArgumentRange(T.getRange());
if (T.getCloseLocation().isInvalid()) {
DS.SetTypeSpecError();
// FIXME: this should return the location of the last token
@@ -1142,35 +1143,48 @@ void Parser::AnnotateExistingDecltypeSpecifier(const DeclSpec &DS,
PP.AnnotateCachedTokens(Tok);
}
-void Parser::ParseUnderlyingTypeSpecifier(DeclSpec &DS) {
- assert(Tok.is(tok::kw___underlying_type) &&
- "Not an underlying type specifier");
+DeclSpec::TST Parser::TypeTransformTokToDeclSpec() {
+ switch (Tok.getKind()) {
+#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) \
+ case tok::kw___##Trait: \
+ return DeclSpec::TST_##Trait;
+#include "clang/Basic/TransformTypeTraits.def"
+ default:
+ llvm_unreachable("passed in an unhandled type transformation built-in");
+ }
+}
+bool Parser::MaybeParseTypeTransformTypeSpecifier(DeclSpec &DS) {
+ if (!NextToken().is(tok::l_paren)) {
+ Tok.setKind(tok::identifier);
+ return false;
+ }
+ DeclSpec::TST TypeTransformTST = TypeTransformTokToDeclSpec();
SourceLocation StartLoc = ConsumeToken();
+
BalancedDelimiterTracker T(*this, tok::l_paren);
- if (T.expectAndConsume(diag::err_expected_lparen_after, "__underlying_type",
- tok::r_paren)) {
- return;
- }
+ if (T.expectAndConsume(diag::err_expected_lparen_after, Tok.getName(),
+ tok::r_paren))
+ return true;
TypeResult Result = ParseTypeName();
if (Result.isInvalid()) {
SkipUntil(tok::r_paren, StopAtSemi);
- return;
+ return true;
}
- // Match the ')'
T.consumeClose();
if (T.getCloseLocation().isInvalid())
- return;
+ return true;
const char *PrevSpec = nullptr;
unsigned DiagID;
- if (DS.SetTypeSpecType(DeclSpec::TST_underlyingType, StartLoc, PrevSpec,
- DiagID, Result.get(),
+ if (DS.SetTypeSpecType(TypeTransformTST, StartLoc, PrevSpec, DiagID,
+ Result.get(),
Actions.getASTContext().getPrintingPolicy()))
Diag(StartLoc, DiagID) << PrevSpec;
- DS.setTypeofParensRange(T.getRange());
+ DS.setTypeArgumentRange(T.getRange());
+ return true;
}
/// ParseBaseTypeSpecifier - Parse a C++ base-type-specifier which is either a
@@ -1525,28 +1539,58 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
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,
+#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) tok::kw___##Trait,
+#include "clang/Basic/TransformTypeTraits.def"
+ 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_trivially_constructible,
+ tok::kw___is_trivially_copyable,
+ tok::kw___is_union,
+ tok::kw___is_unsigned,
+ tok::kw___is_void,
tok::kw___is_volatile))
// GNU libstdc++ 4.2 and libc++ use certain intrinsic names as the
// name of struct templates, but some are keywords in GCC >= 4.3
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 354908a..588f4cf 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -1038,9 +1038,10 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,
return ParseCastExpression(ParseKind, isAddressOfOperand, isTypeCast,
isVectorLiteral, NotPrimaryExpression);
- case tok::identifier: { // primary-expression: identifier
- // unqualified-id: identifier
- // constant: enumeration-constant
+ case tok::identifier:
+ ParseIdentifier: { // primary-expression: identifier
+ // unqualified-id: identifier
+ // constant: enumeration-constant
// Turn a potentially qualified name into a annot_typename or
// annot_cxxscope if it would be valid. This handles things like x::y, etc.
if (getLangOpts().CPlusPlus) {
@@ -1113,6 +1114,9 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,
REVERTIBLE_TYPE_TRAIT(__is_unsigned);
REVERTIBLE_TYPE_TRAIT(__is_void);
REVERTIBLE_TYPE_TRAIT(__is_volatile);
+#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) \
+ REVERTIBLE_TYPE_TRAIT(RTT_JOIN(__, Trait));
+#include "clang/Basic/TransformTypeTraits.def"
#undef REVERTIBLE_TYPE_TRAIT
#undef RTT_JOIN
}
@@ -1739,6 +1743,17 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,
PreferredType.get(Tok.getLocation()));
return ExprError();
}
+#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait:
+#include "clang/Basic/TransformTypeTraits.def"
+ // HACK: libstdc++ uses some of the transform-type-traits as alias
+ // templates, so we need to work around this.
+ if (!NextToken().is(tok::l_paren)) {
+ Tok.setKind(tok::identifier);
+ Diag(Tok, diag::ext_keyword_as_ident)
+ << Tok.getIdentifierInfo()->getName() << 0;
+ goto ParseIdentifier;
+ }
+ goto ExpectedExpression;
case tok::l_square:
if (getLangOpts().CPlusPlus11) {
if (getLangOpts().ObjC) {
@@ -1766,6 +1781,7 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,
}
[[fallthrough]];
default:
+ ExpectedExpression:
NotCastExpr = true;
return ExprError();
}
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index 2f30075..b2e9aa1 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -14,6 +14,7 @@
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/ExprCXX.h"
#include "clang/Basic/PrettyStackTrace.h"
+#include "clang/Basic/TokenKinds.h"
#include "clang/Lex/LiteralSupport.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/Parser.h"
@@ -21,6 +22,7 @@
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/Scope.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include <numeric>
@@ -2819,6 +2821,7 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, ParsedType ObjectType,
// identifier
// template-id (when it hasn't already been annotated)
if (Tok.is(tok::identifier)) {
+ ParseIdentifier:
// Consume the identifier.
IdentifierInfo *Id = Tok.getIdentifierInfo();
SourceLocation IdLoc = ConsumeToken();
@@ -3053,9 +3056,20 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, ParsedType ObjectType,
return false;
}
- Diag(Tok, diag::err_expected_unqualified_id)
- << getLangOpts().CPlusPlus;
- return true;
+ switch (Tok.getKind()) {
+#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait:
+#include "clang/Basic/TransformTypeTraits.def"
+ if (!NextToken().is(tok::l_paren)) {
+ Tok.setKind(tok::identifier);
+ Diag(Tok, diag::ext_keyword_as_ident)
+ << Tok.getIdentifierInfo()->getName() << 0;
+ goto ParseIdentifier;
+ }
+ LLVM_FALLTHROUGH;
+ default:
+ Diag(Tok, diag::err_expected_unqualified_id) << getLangOpts().CPlusPlus;
+ return true;
+ }
}
/// ParseCXXNewExpression - Parse a C++ new-expression. New is used to allocate
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index 530e0de..fc515f1 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -14,6 +14,7 @@
#include "clang/AST/PrettyDeclStackTrace.h"
#include "clang/Basic/Attributes.h"
#include "clang/Basic/PrettyStackTrace.h"
+#include "clang/Basic/TokenKinds.h"
#include "clang/Parse/LoopHint.h"
#include "clang/Parse/Parser.h"
#include "clang/Parse/RAIIObjectsForParser.h"
@@ -188,7 +189,8 @@ Retry:
Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Statement);
return StmtError();
- case tok::identifier: {
+ case tok::identifier:
+ ParseIdentifier: {
Token Next = NextToken();
if (Next.is(tok::colon)) { // C99 6.8.1: labeled-statement
// Both C++11 and GNU attributes preceding the label appertain to the
@@ -261,7 +263,19 @@ Retry:
return StmtError();
}
- return ParseExprStatement(StmtCtx);
+ switch (Tok.getKind()) {
+#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait:
+#include "clang/Basic/TransformTypeTraits.def"
+ if (NextToken().is(tok::less)) {
+ Tok.setKind(tok::identifier);
+ Diag(Tok, diag::ext_keyword_as_ident)
+ << Tok.getIdentifierInfo()->getName() << 0;
+ goto ParseIdentifier;
+ }
+ LLVM_FALLTHROUGH;
+ default:
+ return ParseExprStatement(StmtCtx);
+ }
}
case tok::kw___attribute: {
diff --git a/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp
index 8f45584..9cd405a 100644
--- a/clang/lib/Parse/ParseTentative.cpp
+++ b/clang/lib/Parse/ParseTentative.cpp
@@ -161,7 +161,9 @@ Parser::TPResult Parser::TryConsumeDeclarationSpecifier() {
[[fallthrough]];
case tok::kw_typeof:
case tok::kw___attribute:
- case tok::kw___underlying_type: {
+#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait:
+#include "clang/Basic/TransformTypeTraits.def"
+ {
ConsumeToken();
if (Tok.isNot(tok::l_paren))
return TPResult::Error;
@@ -1682,8 +1684,8 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
return TPResult::True;
}
- // C++0x type traits support
- case tok::kw___underlying_type:
+#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait:
+#include "clang/Basic/TransformTypeTraits.def"
return TPResult::True;
// C11 _Atomic
@@ -1721,7 +1723,8 @@ bool Parser::isCXXDeclarationSpecifierAType() {
case tok::annot_template_id:
case tok::annot_typename:
case tok::kw_typeof:
- case tok::kw___underlying_type:
+#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait:
+#include "clang/Basic/TransformTypeTraits.def"
return true;
// elaborated-type-specifier
diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp
index d4dc790..af31105 100644
--- 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"
@@ -389,7 +390,8 @@ bool Declarator::isDeclarationOfFunction() const {
return E->getType()->isFunctionType();
return false;
- case TST_underlyingType:
+#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case TST_##Trait:
+#include "clang/Basic/TransformTypeTraits.def"
case TST_typename:
case TST_typeofType: {
QualType QT = DS.getRepAsType().get();
@@ -576,7 +578,10 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T,
case DeclSpec::TST_auto_type: return "__auto_type";
case DeclSpec::TST_decltype: return "(decltype)";
case DeclSpec::TST_decltype_auto: return "decltype(auto)";
- case DeclSpec::TST_underlyingType: return "__underlying_type";
+#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) \
+ case DeclSpec::TST_##Trait: \
+ return "__" #Trait;
+#include "clang/Basic/TransformTypeTraits.def"
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
index 004c1ff..463551c 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -145,7 +145,8 @@ bool Sema::isSimpleTypeSpecifier(tok::TokenKind Kind) const {
case tok::kw___ibm128:
case tok::kw_wchar_t:
case tok::kw_bool:
- case tok::kw___underlying_type:
+#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait:
+#include "clang/Basic/TransformTypeTraits.def"
case tok::kw___auto_type:
return true;
@@ -5923,7 +5924,8 @@ static bool RebuildDeclaratorInCurrentInstantiation(Sema &S, Declarator &D,
switch (DS.getTypeSpecType()) {
case DeclSpec::TST_typename:
case DeclSpec::TST_typeofType:
- case DeclSpec::TST_underlyingType:
+#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case DeclSpec::TST_##Trait:
+#include "clang/Basic/TransformTypeTraits.def"
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
index 790792f..285bf67 100644
--- a/clang/lib/Sema/SemaTemplateVariadic.cpp
+++ b/clang/lib/Sema/SemaTemplateVariadic.cpp
@@ -858,7 +858,8 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) {
switch (DS.getTypeSpecType()) {
case TST_typename:
case TST_typeofType:
- case TST_underlyingType:
+#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case TST_##Trait:
+#include "clang/Basic/TransformTypeTraits.def"
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
index 14b2d2e..9ea9d80 100644
--- 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/SourceLocation.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/Preprocessor.h"
@@ -33,6 +35,7 @@
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Template.h"
#include "clang/Sema/TemplateInstCallback.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringSwitch.h"
@@ -1247,6 +1250,18 @@ getImageAccess(const ParsedAttributesView &Attrs) {
return OpenCLAccessAttr::Keyword_read_only;
}
+static UnaryTransformType::UTTKind
+TSTToUnaryTransformType(DeclSpec::TST SwitchTST) {
+ switch (SwitchTST) {
+#define TRANSFORM_TYPE_TRAIT_DEF(Enum, Trait) \
+ case TST_##Trait: \
+ return UnaryTransformType::Enum;
+#include "clang/Basic/TransformTypeTraits.def"
+ 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
@@ -1628,12 +1643,13 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
}
break;
}
- case DeclSpec::TST_underlyingType:
+#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case DeclSpec::TST_##Trait:
+#include "clang/Basic/TransformTypeTraits.def"
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;
declarator.setInvalidType(true);
@@ -6067,8 +6083,7 @@ namespace {
TL.setRParenLoc(DS.getTypeofParensRange().getEnd());
}
void VisitUnaryTransformTypeLoc(UnaryTransformTypeLoc TL) {
- // FIXME: This holds only because we only have one unary transform.
- assert(DS.getTypeSpecType() == DeclSpec::TST_underlyingType);
+ assert(DS.isTransformTypeTrait(DS.getTypeSpecType()));
TL.setKWLoc(DS.getTypeSpecTypeLoc());
TL.setParensRange(DS.getTypeofParensRange());
assert(DS.getRepAsType());
@@ -9205,39 +9220,259 @@ QualType Sema::BuildDecltypeType(Expr *E, bool AsUnevaluated) {
return Context.getDecltypeType(E, getDecltypeForExpr(E));
}
-QualType Sema::BuildUnaryTransformType(QualType BaseType,
- UnaryTransformType::UTTKind UKind,
- SourceLocation Loc) {
- switch (UKind) {
- case UnaryTransformType::EnumUnderlyingType:
- if (!BaseType->isDependentType() && !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();
- }
+static QualType GetEnumUnderlyingType(Sema &S, QualType BaseType,
+ SourceLocation Loc) {
+ assert(BaseType->isEnumeralType());
+ EnumDecl *ED = BaseType->castAs<EnumType>()->getDecl();
+ assert(ED && "EnumType has no EnumDecl");
- EnumDecl *ED = BaseType->castAs<EnumType>()->getDecl();
- assert(ED && "EnumType has no EnumDecl");
+ S.DiagnoseUseOfDecl(ED, Loc);
- DiagnoseUseOfDecl(ED, Loc);
+ QualType Underlying = ED->getIntegerType();
+ assert(!Underlying.isNull());
- Underlying = ED->getIntegerType();
- assert(!Underlying.isNull());
- }
- return Context.getUnaryTransformType(BaseType, Underlying,
- UnaryTransformType::EnumUnderlyingType);
+ return Underlying;
+}
+
+QualType Sema::BuiltinEnumUnderlyingType(QualType BaseType,
+ SourceLocation Loc) {
+ if (!BaseType->isEnumeralType()) {
+ Diag(Loc, diag::err_only_enums_have_underlying_types);
+ return QualType();
+ }
+
+ // 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();
+ }
+
+ return GetEnumUnderlyingType(*this, BaseType, Loc);
+}
+
+QualType Sema::BuiltinAddPointer(QualType BaseType, SourceLocation Loc) {
+ QualType Pointer = BaseType.isReferenceable() || BaseType->isVoidType()
+ ? BuildPointerType(BaseType.getNonReferenceType(), Loc,
+ DeclarationName())
+ : BaseType;
+
+ return Pointer.isNull() ? QualType() : Pointer;
+}
+
+QualType Sema::BuiltinRemovePointer(QualType BaseType, SourceLocation Loc) {
+ // We don't want block pointers or ObjectiveC's id type.
+ if (!BaseType->isAnyPointerType() || BaseType->isObjCIdType())
+ return BaseType;
+
+ return BaseType->getPointeeType();
+}
+
+QualType Sema::BuiltinDecay(QualType BaseType, SourceLocation Loc) {
+ QualType Underlying = BaseType.getNonReferenceType();
+ if (Underlying->isArrayType())
+ return Context.getDecayedType(Underlying);
+
+ if (Underlying->isFunctionType())
+ return BuiltinAddPointer(BaseType, Loc);
+
+ SplitQualType Split = Underlying.getSplitUnqualifiedType();
+ // std::decay is supposed to produce 'std::remove_cv', but since 'restrict' is
+ // in the same group of qualifiers as 'const' and 'volatile', we're extending
+ // '__decay(T)' so that it removes all qualifiers.
+ Split.Quals.removeCVRQualifiers();
+ return Context.getQualifiedType(Split);
+}
+
+QualType Sema::BuiltinAddReference(QualType BaseType, UTTKind UKind,
+ SourceLocation Loc) {
+ assert(LangOpts.CPlusPlus);
+ QualType Reference =
+ BaseType.isReferenceable()
+ ? BuildReferenceType(BaseType,
+ UKind == UnaryTransformType::AddLvalueReference,
+ Loc, DeclarationName())
+ : BaseType;
+ return Reference.isNull() ? QualType() : Reference;
+}
+
+QualType Sema::BuiltinRemoveExtent(QualType BaseType, UTTKind UKind,
+ SourceLocation Loc) {
+ if (UKind == UnaryTransformType::RemoveAllExtents)
+ return Context.getBaseElementType(BaseType);
+
+ if (const auto *AT = Context.getAsArrayType(BaseType))
+ return AT->getElementType();
+
+ return BaseType;
+}
+
+QualType Sema::BuiltinRemoveReference(QualType BaseType, UTTKind UKind,
+ SourceLocation Loc) {
+ assert(LangOpts.CPlusPlus);
+ QualType T = BaseType.getNonReferenceType();
+ if (UKind == UTTKind::RemoveCVRef &&
+ (T.isConstQualified() || T.isVolatileQualified())) {
+ Qualifiers Quals;
+ QualType Unqual = Context.getUnqualifiedArrayType(T, Quals);
+ Quals.removeConst();
+ Quals.removeVolatile();
+ T = Context.getQualifiedType(Unqual, Quals);
+ }
+ return T;
+}
+
+QualType Sema::BuiltinChangeCVRQualifiers(QualType BaseType, UTTKind UKind,
+ SourceLocation Loc) {
+ if ((BaseType->isReferenceType() && UKind != UTTKind::RemoveRestrict) ||
+ BaseType->isFunctionType())
+ return BaseType;
+
+ Qualifiers Quals;
+ QualType Unqual = Context.getUnqualifiedArrayType(BaseType, Quals);
+
+ if (UKind == UTTKind::RemoveConst || UKind == UTTKind::RemoveCV)
+ Quals.removeConst();
+ if (UKind == UTTKind::RemoveVolatile || UKind == UTTKind::RemoveCV)
+ Quals.removeVolatile();
+ if (UKind == UTTKind::RemoveRestrict)
+ Quals.removeRestrict();
+
+ return Context.getQualifiedType(Unqual, Quals);
+}
+
+static QualType ChangeIntegralSignedness(Sema &S, QualType BaseType,
+ bool IsMakeSigned,
+ SourceLocation Loc) {
+ if (BaseType->isEnumeralType()) {
+ QualType Underlying = GetEnumUnderlyingType(S, BaseType, Loc);
+ if (auto *BitInt = dyn_cast<BitIntType>(Underlying)) {
+ unsigned int Bits = BitInt->getNumBits();
+ if (Bits > 1)
+ return S.Context.getBitIntType(!IsMakeSigned, Bits);
+
+ S.Diag(Loc, diag::err_make_signed_integral_only)
+ << IsMakeSigned << /*_BitInt(1)*/ true << BaseType << 1 << Underlying;
+ return QualType();
}
+ if (Underlying->isBooleanType()) {
+ S.Diag(Loc, diag::err_make_signed_integral_only)
+ << IsMakeSigned << /*_BitInt(1)*/ false << BaseType << 1
+ << Underlying;
+ return QualType();
+ }
+ }
+
+ bool Int128Unsupported = !S.Context.getTargetInfo().hasInt128Type();
+ std::array<CanQualType *, 6> AllSignedIntegers = {
+ &S.Context.SignedCharTy, &S.Context.ShortTy, &S.Context.IntTy,
+ &S.Context.LongTy, &S.Context.LongLongTy, &S.Context.Int128Ty};
+ ArrayRef<CanQualType *> AvailableSignedIntegers(
+ AllSignedIntegers.data(), AllSignedIntegers.size() - Int128Unsupported);
+ std::array<CanQualType *, 6> AllUnsignedIntegers = {
+ &S.Context.UnsignedCharTy, &S.Context.UnsignedShortTy,
+ &S.Context.UnsignedIntTy, &S.Context.UnsignedLongTy,
+ &S.Context.UnsignedLongLongTy, &S.Context.UnsignedInt128Ty};
+ ArrayRef<CanQualType *> AvailableUnsignedIntegers(AllUnsignedIntegers.data(),
+ AllUnsignedIntegers.size() -
+ Int128Unsupported);
+ ArrayRef<CanQualType *> *Consider =
+ IsMakeSigned ? &AvailableSignedIntegers : &AvailableUnsignedIntegers;
+
+ uint64_t BaseSize = S.Context.getTypeSize(BaseType);
+ auto *Result =
+ llvm::find_if(*Consider, [&S, BaseSize](const CanQual<Type> *T) {
+ return BaseSize == S.Context.getTypeSize(T->getTypePtr());
+ });
+
+ assert(Result != Consider->end());
+ return QualType((*Result)->getTypePtr(), 0);
+}
+
+QualType Sema::BuiltinChangeSignedness(QualType BaseType, UTTKind UKind,
+ SourceLocation Loc) {
+ bool IsMakeSigned = UKind == UnaryTransformType::MakeSigned;
+ if ((!BaseType->isIntegerType() && !BaseType->isEnumeralType()) ||
+ BaseType->isBooleanType() ||
+ (BaseType->isBitIntType() &&
+ BaseType->getAs<BitIntType>()->getNumBits() < 2)) {
+ Diag(Loc, diag::err_make_signed_integral_only)
+ << IsMakeSigned << BaseType->isBitIntType() << BaseType << 0;
+ return QualType();
+ }
+
+ bool IsNonIntIntegral =
+ BaseType->isChar16Type() || BaseType->isChar32Type() ||
+ BaseType->isWideCharType() || BaseType->isEnumeralType();
+
+ QualType Underlying =
+ IsNonIntIntegral
+ ? ChangeIntegralSignedness(*this, BaseType, IsMakeSigned, Loc)
+ : IsMakeSigned ? Context.getCorrespondingSignedType(BaseType)
+ : Context.getCorrespondingUnsignedType(BaseType);
+ if (Underlying.isNull())
+ return Underlying;
+ return Context.getQualifiedType(Underlying, BaseType.getQualifiers());
+}
+
+QualType Sema::BuildUnaryTransformType(QualType BaseType, UTTKind UKind,
+ SourceLocation Loc) {
+ if (BaseType->isDependentType())
+ return Context.getUnaryTransformType(BaseType, BaseType, UKind);
+ QualType Result;
+ switch (UKind) {
+ case UnaryTransformType::EnumUnderlyingType: {
+ Result = BuiltinEnumUnderlyingType(BaseType, Loc);
+ break;
+ }
+ case UnaryTransformType::AddPointer: {
+ Result = BuiltinAddPointer(BaseType, Loc);
+ break;
+ }
+ case UnaryTransformType::RemovePointer: {
+ Result = BuiltinRemovePointer(BaseType, Loc);
+ break;
+ }
+ case UnaryTransformType::Decay: {
+ Result = BuiltinDecay(BaseType, Loc);
+ break;
+ }
+ case UnaryTransformType::AddLvalueReference:
+ case UnaryTransformType::AddRvalueReference: {
+ Result = BuiltinAddReference(BaseType, UKind, Loc);
+ break;
}
- llvm_unreachable("unknown unary transform type");
+ case UnaryTransformType::RemoveAllExtents:
+ case UnaryTransformType::RemoveExtent: {
+ Result = BuiltinRemoveExtent(BaseType, UKind, Loc);
+ break;
+ }
+ case UnaryTransformType::RemoveCVRef:
+ case UnaryTransformType::RemoveReference: {
+ Result = BuiltinRemoveReference(BaseType, UKind, Loc);
+ break;
+ }
+ case UnaryTransformType::RemoveConst:
+ case UnaryTransformType::RemoveCV:
+ case UnaryTransformType::RemoveRestrict:
+ case UnaryTransformType::RemoveVolatile: {
+ Result = BuiltinChangeCVRQualifiers(BaseType, UKind, Loc);
+ break;
+ }
+ case UnaryTransformType::MakeSigned:
+ case UnaryTransformType::MakeUnsigned: {
+ Result = BuiltinChangeSignedness(BaseType, UKind, Loc);
+ break;
+ }
+ default:
+ llvm_unreachable("unknown unary transform type");
+ }
+
+ return !Result.isNull()
+ ? Context.getUnaryTransformType(BaseType, Result, UKind)
+ : Result;
}
QualType Sema::BuildAtomicType(QualType T, SourceLocation Loc) {
diff --git a/clang/test/CodeGenCXX/mangle.cpp b/clang/test/CodeGenCXX/mangle.cpp
index eb87118..708b492 100644
--- a/clang/test/CodeGenCXX/mangle.cpp
+++ b/clang/test/CodeGenCXX/mangle.cpp
@@ -51,7 +51,7 @@ namespace N { int f(int, int) { static int b; return b; } }
namespace N { int h(); void g() { static int a = h(); } }
// CHECK-LABEL: define{{.*}} void @_Z1fno
-void f(__int128_t, __uint128_t) { }
+void f(__int128_t, __uint128_t) {}
template <typename T> struct S1 {};
@@ -101,13 +101,13 @@ namespace NS {
void g1() {
// CHECK: @_Z3ft1IidEvT0_T_
ft1<int, double>(1, 0);
-
+
// CHECK: @_Z3ft2IcEvT_PFvS0_ES2_
ft2<char>(1, 0, 0);
-
+
// CHECK: @_Z3ft3IiEvP2S4IT_2S1IS1_EE
ft3<int>(0);
-
+
// CHECK: @_ZN2NS3ft1IiEEvT_
NS::ft1<int>(1);
}
@@ -119,14 +119,14 @@ template<int I> void ft4(S5<I>) { }
void g2() {
// CHECK: @_Z3ft4ILi10EEv2S5IXT_EE
ft4(S5<10>());
-
+
// CHECK: @_Z3ft4ILi20EEv2S5IXT_EE
ft4(S5<20>());
}
extern "C++" {
// CHECK: @_Z1hv
- void h() { }
+void h() {}
}
// PR5019
@@ -208,7 +208,7 @@ void extern_f(void) { }
struct S7 {
S7();
-
+
struct S { S(); };
struct {
S s;
@@ -276,7 +276,7 @@ struct Ops {
Ops& operator-(const Ops&);
Ops& operator&(const Ops&);
Ops& operator*(const Ops&);
-
+
void *v;
};
@@ -493,7 +493,7 @@ namespace test11 {
struct A {
void f(...);
};
-
+
// CHECK: @_ZN6test111A1fEz
void A::f(...) { }
}
@@ -832,9 +832,9 @@ namespace test34 {
namespace test35 {
// Dependent operator names of unknown arity.
- struct A {
- template<typename U> A operator+(U) const;
- };
+struct A {
+ template <typename U> A operator+(U) const;
+};
template<typename T>
void f1(decltype(sizeof(&T::template operator+<int>))) {}
@@ -1107,11 +1107,74 @@ namespace test55 {
enum E { R };
template <typename T>
-void fn(T, __underlying_type(T)) {}
-
-template void fn<E>(E, __underlying_type(E));
-// CHECK-LABEL: @_ZN6test552fnINS_1EEEEvT_U3eutS2_
-}
+void f1(T, __underlying_type(T)) {}
+template void f1<E>(E, __underlying_type(E));
+// CHECK-LABEL: @_ZN6test552f1INS_1EEEEvT_u17__underlying_typeIS2_E
+
+template <typename T> void f2(T, __add_lvalue_reference(T)) {}
+template void f2<int>(int, __add_lvalue_reference(int));
+// CHECK-LABEL: @_ZN6test552f2IiEEvT_u22__add_lvalue_referenceIS1_E
+
+template <typename T> void f3(T, __add_pointer(T)) {}
+template void f3<int>(int, __add_pointer(int));
+// CHECK-LABEL: @_ZN6test552f3IiEEvT_u13__add_pointerIS1_E
+
+template <typename T> void f4(T, __add_rvalue_reference(T)) {}
+template void f4<int>(int, __add_rvalue_reference(int));
+// CHECK-LABEL: @_ZN6test552f4IiEEvT_u22__add_rvalue_referenceIS1_E
+
+template <typename T> void f5(T, __decay(T)) {}
+template void f5<int>(int, __decay(int));
+// CHECK-LABEL: @_ZN6test552f5IiEEvT_u7__decayIS1_E
+
+template <typename T> void f6(T, __make_signed(T)) {}
+template void f6<int>(int, __make_signed(int));
+// CHECK-LABEL: @_ZN6test552f6IiEEvT_u13__make_signedIS1_E
+
+template <typename T> void f7(T, __make_unsigned(T)) {}
+template void f7<int>(int, __make_unsigned(int));
+// CHECK-LABEL: @_ZN6test552f7IiEEvT_u15__make_unsignedIS1_E
+
+template <typename T> void f8(T, __remove_const(T)) {}
+template void f8<int>(int, __remove_const(int));
+// CHECK-LABEL: @_ZN6test552f8IiEEvT_u14__remove_constIS1_E
+
+template <typename T> void f9(T, __remove_cv(T)) {}
+template void f9<int>(int, __remove_cv(int));
+// CHECK-LABEL: @_ZN6test552f9IiEEvT_u11__remove_cvIS1_E
+
+template <typename T> void f10(T, __remove_cvref(T)) {}
+template void f10<int>(int, __remove_cvref(int));
+// CHECK-LABEL: @_ZN6test553f10IiEEvT_u14__remove_cvrefIS1_E
+
+template <typename T> void f11(T, __remove_volatile(T)) {}
+template void f11<int>(int, __remove_volatile(int));
+// CHECK-LABEL: @_ZN6test553f11IiEEvT_u17__remove_volatileIS1_E
+
+template <typename T> void f12(T, __remove_extent(T)) {}
+template void f12<int>(int, __remove_extent(int));
+// CHECK-LABEL: @_ZN6test553f12IiEEvT_u15__remove_extentIS1_E
+
+template <typename T> void f13(T, __remove_all_extents(T)) {}
+template void f13<int>(int, __remove_all_extents(int));
+// CHECK-LABEL: @_ZN6test553f13IiEEvT_u20__remove_all_extentsIS1_E
+
+template <typename T> void f14(T, __remove_pointer(T)) {}
+template void f14<int>(int, __remove_pointer(int));
+// CHECK-LABEL: @_ZN6test553f14IiEEvT_u16__remove_pointerIS1_E
+
+template <typename T> void f15(T, __remove_reference(T)) {}
+template void f15<int>(int, __remove_reference(int));
+// CHECK-LABEL: @_ZN6test553f15IiEEvT_u18__remove_referenceIS1_E
+
+template <typename T> void f16(T, __remove_volatile(T)) {}
+template void f16<int>(int, __remove_volatile(int));
+// CHECK-LABEL: @_ZN6test553f16IiEEvT_u17__remove_volatileIS1_E
+
+template <typename T> void f17(T, __remove_restrict(T)) {}
+template void f17<int>(int, __remove_restrict(int));
+// CHECK-LABEL: @_ZN6test553f17IiEEvT_u17__remove_restrictIS1_E
+} // namespace test55
namespace test56 {
struct A { A *operator->(); int n; } a;
diff --git a/clang/test/SemaCXX/libstdcxx_transform_type_traits_hack.cpp b/clang/test/SemaCXX/libstdcxx_transform_type_traits_hack.cpp
new file mode 100644
index 0000000..5032c3a
--- /dev/null
+++ b/clang/test/SemaCXX/libstdcxx_transform_type_traits_hack.cpp
@@ -0,0 +1,84 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify -std=gnu++11 -fms-extensions -Wno-microsoft %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify -std=gnu++14 -fms-extensions -Wno-microsoft %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify -std=gnu++1z -fms-extensions -Wno-microsoft %s
+
+// libstdc++ uses __remove_cv as an alias, so we make our transform type traits alias-revertible
+template <class T, class U>
+struct Same {
+ static constexpr auto value = __is_same(T, U);
+};
+
+template <class T>
+using __remove_const = int; // expected-warning{{keyword '__remove_const' will be made available as an identifier here}}
+template <class T>
+using A = Same<__remove_const<T>, __remove_const<T>>;
+
+template <class T>
+using __remove_restrict = int; // expected-warning{{keyword '__remove_restrict' will be made available as an identifier here}}
+template <class T>
+using B = Same<__remove_restrict<T>, __remove_restrict<T>>;
+
+template <class T>
+using __remove_volatile = int; // expected-warning{{keyword '__remove_volatile' will be made available as an identifier here}}
+template <class T>
+using C = Same<__remove_volatile<T>, __remove_volatile<T>>;
+
+template <class T>
+using __remove_cv = int; // expected-warning{{keyword '__remove_cv' will be made available as an identifier here}}
+template <class T>
+using D = Same<__remove_cv<T>, __remove_cv<T>>;
+
+template <class T>
+using __add_pointer = int; // expected-warning{{keyword '__add_pointer' will be made available as an identifier here}}
+template <class T>
+using E = Same<__add_pointer<T>, __add_pointer<T>>;
+
+template <class T>
+using __remove_pointer = int; // expected-warning{{keyword '__remove_pointer' will be made available as an identifier here}}
+template <class T>
+using F = Same<__remove_pointer<T>, __remove_pointer<T>>;
+
+template <class T>
+using __add_lvalue_reference = int; // expected-warning{{keyword '__add_lvalue_reference' will be made available as an identifier here}}
+template <class T>
+using G = Same<__add_lvalue_reference<T>, __add_lvalue_reference<T>>;
+
+template <class T>
+using __add_rvalue_reference = int; // expected-warning{{keyword '__add_rvalue_reference' will be made available as an identifier here}}
+template <class T>
+using H = Same<__add_rvalue_reference<T>, __add_rvalue_reference<T>>;
+
+template <class T>
+using __remove_reference = int; // expected-warning{{keyword '__remove_reference' will be made available as an identifier here}}
+template <class T>
+using I = Same<__remove_reference<T>, __remove_reference<T>>;
+
+template <class T>
+using __remove_cvref = int; // expected-warning{{keyword '__remove_cvref' will be made available as an identifier here}}
+template <class T>
+using J = Same<__remove_cvref<T>, __remove_cvref<T>>;
+
+template <class T>
+using __decay = int; // expected-warning{{keyword '__decay' will be made available as an identifier here}}
+template <class T>
+using K = Same<__decay<T>, __decay<T>>;
+
+template <class T>
+using __make_signed = int; // expected-warning{{keyword '__make_signed' will be made available as an identifier here}}
+template <class T>
+using L = Same<__make_signed<T>, __make_signed<T>>;
+
+template <class T>
+using __make_unsigned = int; // expected-warning{{keyword '__make_unsigned' will be made available as an identifier here}}
+template <class T>
+using M = Same<__make_unsigned<T>, __make_unsigned<T>>;
+
+template <class T>
+using __remove_extent = int; // expected-warning{{keyword '__remove_extent' will be made available as an identifier here}}
+template <class T>
+using N = Same<__remove_extent<T>, __remove_extent<T>>;
+
+template <class T>
+using __remove_all_extents = int; // expected-warning{{keyword '__remove_all_extents' will be made available as an identifier here}}
+template <class T>
+using O = Same<__remove_all_extents<T>, __remove_all_extents<T>>;
diff --git a/clang/test/SemaCXX/remove_pointer.mm b/clang/test/SemaCXX/remove_pointer.mm
new file mode 100644
index 0000000..d1cf1fa
--- /dev/null
+++ b/clang/test/SemaCXX/remove_pointer.mm
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// expected-no-diagnostics
+
+@class X;
+
+static_assert(__is_same(__remove_pointer(X *), X), "");
+static_assert(__is_same(__remove_pointer(id), id), "");
diff --git a/clang/test/SemaCXX/type-traits.cpp b/clang/test/SemaCXX/type-traits.cpp
index 0ef1205..f54ae0e 100644
--- a/clang/test/SemaCXX/type-traits.cpp
+++ b/clang/test/SemaCXX/type-traits.cpp
@@ -1,6 +1,6 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify -std=gnu++11 -Wno-deprecated-builtins -fms-extensions -Wno-microsoft %s
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify -std=gnu++14 -Wno-deprecated-builtins -fms-extensions -Wno-microsoft %s
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify -std=gnu++1z -Wno-deprecated-builtins -fms-extensions -Wno-microsoft %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify -std=gnu++11 -fblocks -Wno-deprecated-builtins -fms-extensions -Wno-microsoft %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify -std=gnu++14 -fblocks -Wno-deprecated-builtins -fms-extensions -Wno-microsoft %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify -std=gnu++1z -fblocks -Wno-deprecated-builtins -fms-extensions -Wno-microsoft %s
#define T(b) (b) ? 1 : -1
#define F(b) (b) ? -1 : 1
@@ -14,6 +14,9 @@ typedef NonPOD NonPODArMB[10][2];
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;
@@ -2915,3 +2918,694 @@ static_assert(__is_trivially_relocatable(TrivialAbiNontrivialMoveCtor), "");
static_assert(__is_trivially_relocatable(TrivialAbiNontrivialMoveCtor[]), "");
} // namespace is_trivially_relocatable
+
+struct S {};
+template <class T> using remove_const_t = __remove_const(T);
+
+void check_remove_const() {
+ static_assert(__is_same(remove_const_t<void>, void), "");
+ static_assert(__is_same(remove_const_t<const void>, void), "");
+ static_assert(__is_same(remove_const_t<int>, int), "");
+ static_assert(__is_same(remove_const_t<const int>, int), "");
+ static_assert(__is_same(remove_const_t<volatile int>, volatile int), "");
+ static_assert(__is_same(remove_const_t<const volatile int>, volatile int), "");
+ static_assert(__is_same(remove_const_t<int *>, int *), "");
+ static_assert(__is_same(remove_const_t<int *const>, int *), "");
+ static_assert(__is_same(remove_const_t<int const *const>, int const *), "");
+ static_assert(__is_same(remove_const_t<int const *const __restrict>, int const *__restrict), "");
+ static_assert(__is_same(remove_const_t<int &>, int &), "");
+ static_assert(__is_same(remove_const_t<int const &>, int const &), "");
+ static_assert(__is_same(remove_const_t<int &&>, int &&), "");
+ static_assert(__is_same(remove_const_t<int const &&>, int const &&), "");
+ static_assert(__is_same(remove_const_t<int()>, int()), "");
+ static_assert(__is_same(remove_const_t<int (*const)()>, int (*)()), "");
+ static_assert(__is_same(remove_const_t<int (&)()>, int (&)()), "");
+
+ static_assert(__is_same(remove_const_t<S>, S), "");
+ static_assert(__is_same(remove_const_t<const S>, S), "");
+ static_assert(__is_same(remove_const_t<volatile S>, volatile S), "");
+ static_assert(__is_same(remove_const_t<S *__restrict>, S *__restrict), "");
+ static_assert(__is_same(remove_const_t<const volatile S>, volatile S), "");
+ static_assert(__is_same(remove_const_t<S *const volatile __restrict>, S *volatile __restrict), "");
+ static_assert(__is_same(remove_const_t<int S::*const>, int S::*), "");
+ static_assert(__is_same(remove_const_t<int (S::*const)()>, int(S::*)()), "");
+}
+
+template <class T> using remove_restrict_t = __remove_restrict(T);
+
+void check_remove_restrict() {
+ static_assert(__is_same(remove_restrict_t<void>, void), "");
+ static_assert(__is_same(remove_restrict_t<int>, int), "");
+ static_assert(__is_same(remove_restrict_t<const int>, const int), "");
+ static_assert(__is_same(remove_restrict_t<volatile int>, volatile int), "");
+ static_assert(__is_same(remove_restrict_t<int *__restrict>, int *), "");
+ static_assert(__is_same(remove_restrict_t<int *const volatile __restrict>, int *const volatile), "");
+ static_assert(__is_same(remove_restrict_t<int *>, int *), "");
+ static_assert(__is_same(remove_restrict_t<int *__restrict>, int *), "");
+ static_assert(__is_same(remove_restrict_t<int &>, int &), "");
+ static_assert(__is_same(remove_restrict_t<int &__restrict>, int &), "");
+ static_assert(__is_same(remove_restrict_t<int &&>, int &&), "");
+ static_assert(__is_same(remove_restrict_t<int &&__restrict>, int &&), "");
+ static_assert(__is_same(remove_restrict_t<int()>, int()), "");
+ static_assert(__is_same(remove_restrict_t<int (*const volatile)()>, int (*const volatile)()), "");
+ static_assert(__is_same(remove_restrict_t<int (&)()>, int (&)()), "");
+
+ static_assert(__is_same(remove_restrict_t<S>, S), "");
+ static_assert(__is_same(remove_restrict_t<const S>, const S), "");
+ static_assert(__is_same(remove_restrict_t<volatile S>, volatile S), "");
+ static_assert(__is_same(remove_restrict_t<S *__restrict>, S *), "");
+ static_assert(__is_same(remove_restrict_t<S *const volatile __restrict>, S *const volatile), "");
+ static_assert(__is_same(remove_restrict_t<int S::*__restrict>, int S::*), "");
+ static_assert(__is_same(remove_restrict_t<int (S::*const volatile)()>, int(S::*const volatile)()), "");
+}
+
+template <class T> using remove_volatile_t = __remove_volatile(T);
+
+void check_remove_volatile() {
+ static_assert(__is_same(remove_volatile_t<void>, void), "");
+ static_assert(__is_same(remove_volatile_t<volatile void>, void), "");
+ static_assert(__is_same(remove_volatile_t<int>, int), "");
+ static_assert(__is_same(remove_volatile_t<const int>, const int), "");
+ static_assert(__is_same(remove_volatile_t<volatile int>, int), "");
+ static_assert(__is_same(remove_volatile_t<int *__restrict>, int *__restrict), "");
+ static_assert(__is_same(remove_volatile_t<const volatile int>, const int), "");
+ static_assert(__is_same(remove_volatile_t<int *const volatile __restrict>, int *const __restrict), "");
+ static_assert(__is_same(remove_volatile_t<int *>, int *), "");
+ static_assert(__is_same(remove_volatile_t<int *volatile>, int *), "");
+ static_assert(__is_same(remove_volatile_t<int volatile *volatile>, int volatile *), "");
+ static_assert(__is_same(remove_volatile_t<int &>, int &), "");
+ static_assert(__is_same(remove_volatile_t<int volatile &>, int volatile &), "");
+ static_assert(__is_same(remove_volatile_t<int &&>, int &&), "");
+ static_assert(__is_same(remove_volatile_t<int volatile &&>, int volatile &&), "");
+ static_assert(__is_same(remove_volatile_t<int()>, int()), "");
+ static_assert(__is_same(remove_volatile_t<int (*volatile)()>, int (*)()), "");
+ static_assert(__is_same(remove_volatile_t<int (&)()>, int (&)()), "");
+
+ static_assert(__is_same(remove_volatile_t<S>, S), "");
+ static_assert(__is_same(remove_volatile_t<const S>, const S), "");
+ static_assert(__is_same(remove_volatile_t<volatile S>, S), "");
+ static_assert(__is_same(remove_volatile_t<const volatile S>, const S), "");
+ static_assert(__is_same(remove_volatile_t<int S::*volatile>, int S::*), "");
+ static_assert(__is_same(remove_volatile_t<int (S::*volatile)()>, int(S::*)()), "");
+}
+
+template <class T> using remove_cv_t = __remove_cv(T);
+
+void check_remove_cv() {
+ static_assert(__is_same(remove_cv_t<void>, void), "");
+ static_assert(__is_same(remove_cv_t<const volatile void>, void), "");
+ static_assert(__is_same(remove_cv_t<int>, int), "");
+ static_assert(__is_same(remove_cv_t<const int>, int), "");
+ static_assert(__is_same(remove_cv_t<volatile int>, int), "");
+ static_assert(__is_same(remove_cv_t<const volatile int>, int), "");
+ static_assert(__is_same(remove_cv_t<int *>, int *), "");
+ static_assert(__is_same(remove_cv_t<int *const volatile>, int *), "");
+ static_assert(__is_same(remove_cv_t<int const *const volatile>, int const *), "");
+ static_assert(__is_same(remove_cv_t<int const *const volatile __restrict>, int const *__restrict), "");
+ static_assert(__is_same(remove_cv_t<int const *const volatile _Nonnull>, int const *_Nonnull), "");
+ static_assert(__is_same(remove_cv_t<int &>, int &), "");
+ static_assert(__is_same(remove_cv_t<int const volatile &>, int const volatile &), "");
+ static_assert(__is_same(remove_cv_t<int &&>, int &&), "");
+ static_assert(__is_same(remove_cv_t<int const volatile &&>, int const volatile &&), "");
+ static_assert(__is_same(remove_cv_t<int()>, int()), "");
+ static_assert(__is_same(remove_cv_t<int (*const volatile)()>, int (*)()), "");
+ static_assert(__is_same(remove_cv_t<int (&)()>, int (&)()), "");
+
+ static_assert(__is_same(remove_cv_t<S>, S), "");
+ static_assert(__is_same(remove_cv_t<const S>, S), "");
+ static_assert(__is_same(remove_cv_t<volatile S>, S), "");
+ static_assert(__is_same(remove_cv_t<const volatile S>, S), "");
+ static_assert(__is_same(remove_cv_t<int S::*const volatile>, int S::*), "");
+ static_assert(__is_same(remove_cv_t<int (S::*const volatile)()>, int(S::*)()), "");
+}
+
+template <class T> using add_pointer_t = __add_pointer(T);
+
+void add_pointer() {
+ static_assert(__is_same(add_pointer_t<void>, void *), "");
+ static_assert(__is_same(add_pointer_t<const void>, const void *), "");
+ static_assert(__is_same(add_pointer_t<volatile void>, volatile void *), "");
+ static_assert(__is_same(add_pointer_t<const volatile void>, const volatile void *), "");
+ static_assert(__is_same(add_pointer_t<int>, int *), "");
+ static_assert(__is_same(add_pointer_t<const int>, const int *), "");
+ static_assert(__is_same(add_pointer_t<volatile int>, volatile int *), "");
+ static_assert(__is_same(add_pointer_t<const volatile int>, const volatile int *), "");
+ static_assert(__is_same(add_pointer_t<int *>, int **), "");
+ static_assert(__is_same(add_pointer_t<int &>, int *), "");
+ static_assert(__is_same(add_pointer_t<int &&>, int *), "");
+ static_assert(__is_same(add_pointer_t<int()>, int (*)()), "");
+ static_assert(__is_same(add_pointer_t<int (*)()>, int (**)()), "");
+ static_assert(__is_same(add_pointer_t<int (&)()>, int (*)()), "");
+
+ static_assert(__is_same(add_pointer_t<S>, S *), "");
+ static_assert(__is_same(add_pointer_t<const S>, const S *), "");
+ static_assert(__is_same(add_pointer_t<volatile S>, volatile S *), "");
+ static_assert(__is_same(add_pointer_t<const volatile S>, const volatile S *), "");
+ static_assert(__is_same(add_pointer_t<int S::*>, int S::**), "");
+ static_assert(__is_same(add_pointer_t<int (S::*)()>, int(S::**)()), "");
+
+ static_assert(__is_same(add_pointer_t<int __attribute__((address_space(1)))>, int __attribute__((address_space(1))) *), "");
+ static_assert(__is_same(add_pointer_t<S __attribute__((address_space(2)))>, S __attribute__((address_space(2))) *), "");
+}
+
+template <class T> using remove_pointer_t = __remove_pointer(T);
+
+void remove_pointer() {
+ static_assert(__is_same(remove_pointer_t<void>, void), "");
+ static_assert(__is_same(remove_pointer_t<const void>, const void), "");
+ static_assert(__is_same(remove_pointer_t<volatile void>, volatile void), "");
+ static_assert(__is_same(remove_pointer_t<const volatile void>, const volatile void), "");
+ static_assert(__is_same(remove_pointer_t<int>, int), "");
+ static_assert(__is_same(remove_pointer_t<const int>, const int), "");
+ static_assert(__is_same(remove_pointer_t<volatile int>, volatile int), "");
+ static_assert(__is_same(remove_pointer_t<const volatile int>, const volatile int), "");
+ static_assert(__is_same(remove_pointer_t<int *>, int), "");
+ static_assert(__is_same(remove_pointer_t<const int *>, const int), "");
+ static_assert(__is_same(remove_pointer_t<volatile int *>, volatile int), "");
+ static_assert(__is_same(remove_pointer_t<const volatile int *>, const volatile int), "");
+ static_assert(__is_same(remove_pointer_t<int *const>, int), "");
+ static_assert(__is_same(remove_pointer_t<int *volatile>, int), "");
+ static_assert(__is_same(remove_pointer_t<int *const volatile>, int), "");
+ static_assert(__is_same(remove_pointer_t<int &>, int &), "");
+ static_assert(__is_same(remove_pointer_t<int &&>, int &&), "");
+ static_assert(__is_same(remove_pointer_t<int()>, int()), "");
+ static_assert(__is_same(remove_pointer_t<int (*)()>, int()), "");
+ static_assert(__is_same(remove_pointer_t<int (&)()>, int (&)()), "");
+
+ static_assert(__is_same(remove_pointer_t<S>, S), "");
+ static_assert(__is_same(remove_pointer_t<const S>, const S), "");
+ static_assert(__is_same(remove_pointer_t<volatile S>, volatile S), "");
+ static_assert(__is_same(remove_pointer_t<const volatile S>, const volatile S), "");
+ static_assert(__is_same(remove_pointer_t<int S::*>, int S::*), "");
+ static_assert(__is_same(remove_pointer_t<int (S::*)()>, int(S::*)()), "");
+
+ static_assert(__is_same(remove_pointer_t<int __attribute__((address_space(1))) *>, int __attribute__((address_space(1)))), "");
+ static_assert(__is_same(remove_pointer_t<S __attribute__((address_space(2))) *>, S __attribute__((address_space(2)))), "");
+
+ static_assert(__is_same(remove_pointer_t<int (^)(char)>, int (^)(char)), "");
+}
+
+template <class T> using add_lvalue_reference_t = __add_lvalue_reference(T);
+
+void add_lvalue_reference() {
+ static_assert(__is_same(add_lvalue_reference_t<void>, void), "");
+ static_assert(__is_same(add_lvalue_reference_t<const void>, const void), "");
+ static_assert(__is_same(add_lvalue_reference_t<volatile void>, volatile void), "");
+ static_assert(__is_same(add_lvalue_reference_t<const volatile void>, const volatile void), "");
+ static_assert(__is_same(add_lvalue_reference_t<int>, int &), "");
+ static_assert(__is_same(add_lvalue_reference_t<const int>, const int &), "");
+ static_assert(__is_same(add_lvalue_reference_t<volatile int>, volatile int &), "");
+ static_assert(__is_same(add_lvalue_reference_t<const volatile int>, const volatile int &), "");
+ static_assert(__is_same(add_lvalue_reference_t<int *>, int *&), "");
+ static_assert(__is_same(add_lvalue_reference_t<int &>, int &), "");
+ static_assert(__is_same(add_lvalue_reference_t<int &&>, int &), ""); // reference collapsing
+ static_assert(__is_same(add_lvalue_reference_t<int()>, int (&)()), "");
+ static_assert(__is_same(add_lvalue_reference_t<int (*)()>, int (*&)()), "");
+ static_assert(__is_same(add_lvalue_reference_t<int (&)()>, int (&)()), "");
+
+ static_assert(__is_same(add_lvalue_reference_t<S>, S &), "");
+ static_assert(__is_same(add_lvalue_reference_t<const S>, const S &), "");
+ static_assert(__is_same(add_lvalue_reference_t<volatile S>, volatile S &), "");
+ static_assert(__is_same(add_lvalue_reference_t<const volatile S>, const volatile S &), "");
+ static_assert(__is_same(add_lvalue_reference_t<int S::*>, int S::*&), "");
+ static_assert(__is_same(add_lvalue_reference_t<int (S::*)()>, int(S::*&)()), "");
+}
+
+template <class T> using add_rvalue_reference_t = __add_rvalue_reference(T);
+
+void add_rvalue_reference() {
+ static_assert(__is_same(add_rvalue_reference_t<void>, void), "");
+ static_assert(__is_same(add_rvalue_reference_t<const void>, const void), "");
+ static_assert(__is_same(add_rvalue_reference_t<volatile void>, volatile void), "");
+ static_assert(__is_same(add_rvalue_reference_t<const volatile void>, const volatile void), "");
+ static_assert(__is_same(add_rvalue_reference_t<int>, int &&), "");
+ static_assert(__is_same(add_rvalue_reference_t<const int>, const int &&), "");
+ static_assert(__is_same(add_rvalue_reference_t<volatile int>, volatile int &&), "");
+ static_assert(__is_same(add_rvalue_reference_t<const volatile int>, const volatile int &&), "");
+ static_assert(__is_same(add_rvalue_reference_t<int *>, int *&&), "");
+ static_assert(__is_same(add_rvalue_reference_t<int &>, int &), ""); // reference collapsing
+ static_assert(__is_same(add_rvalue_reference_t<int &&>, int &&), "");
+ static_assert(__is_same(add_rvalue_reference_t<int()>, int(&&)()), "");
+ static_assert(__is_same(add_rvalue_reference_t<int (*)()>, int (*&&)()), "");
+ static_assert(__is_same(add_rvalue_reference_t<int (&)()>, int (&)()), ""); // reference collapsing
+
+ static_assert(__is_same(add_rvalue_reference_t<S>, S &&), "");
+ static_assert(__is_same(add_rvalue_reference_t<const S>, const S &&), "");
+ static_assert(__is_same(add_rvalue_reference_t<volatile S>, volatile S &&), "");
+ static_assert(__is_same(add_rvalue_reference_t<const volatile S>, const volatile S &&), "");
+ static_assert(__is_same(add_rvalue_reference_t<int S::*>, int S::*&&), "");
+ static_assert(__is_same(add_rvalue_reference_t<int (S::*)()>, int(S::* &&)()), "");
+}
+
+template <class T> using remove_reference_t = __remove_reference(T);
+
+void check_remove_reference() {
+ static_assert(__is_same(remove_reference_t<void>, void), "");
+ static_assert(__is_same(remove_reference_t<const volatile void>, const volatile void), "");
+ static_assert(__is_same(remove_reference_t<int>, int), "");
+ static_assert(__is_same(remove_reference_t<const int>, const int), "");
+ static_assert(__is_same(remove_reference_t<volatile int>, volatile int), "");
+ static_assert(__is_same(remove_reference_t<const volatile int>, const volatile int), "");
+ static_assert(__is_same(remove_reference_t<int *>, int *), "");
+ static_assert(__is_same(remove_reference_t<int *const volatile>, int *const volatile), "");
+ static_assert(__is_same(remove_reference_t<int const *const volatile>, int const *const volatile), "");
+ static_assert(__is_same(remove_reference_t<int &>, int), "");
+ static_assert(__is_same(remove_reference_t<int const volatile &>, int const volatile), "");
+ static_assert(__is_same(remove_reference_t<int &&>, int), "");
+ static_assert(__is_same(remove_reference_t<int const volatile &&>, int const volatile), "");
+ static_assert(__is_same(remove_reference_t<int()>, int()), "");
+ static_assert(__is_same(remove_reference_t<int (*const volatile)()>, int (*const volatile)()), "");
+ static_assert(__is_same(remove_reference_t<int (&)()>, int()), "");
+
+ static_assert(__is_same(remove_reference_t<S>, S), "");
+ static_assert(__is_same(remove_reference_t<S &>, S), "");
+ static_assert(__is_same(remove_reference_t<S &&>, S), "");
+ static_assert(__is_same(remove_reference_t<const S>, const S), "");
+ static_assert(__is_same(remove_reference_t<const S &>, const S), "");
+ static_assert(__is_same(remove_reference_t<const S &&>, const S), "");
+ static_assert(__is_same(remove_reference_t<volatile S>, volatile S), "");
+ static_assert(__is_same(remove_reference_t<volatile S &>, volatile S), "");
+ static_assert(__is_same(remove_reference_t<volatile S &&>, volatile S), "");
+ static_assert(__is_same(remove_reference_t<const volatile S>, const volatile S), "");
+ static_assert(__is_same(remove_reference_t<const volatile S &>, const volatile S), "");
+ static_assert(__is_same(remove_reference_t<const volatile S &&>, const volatile S), "");
+ static_assert(__is_same(remove_reference_t<int S::*const volatile &>, int S::*const volatile), "");
+ static_assert(__is_same(remove_reference_t<int (S::*const volatile &)()>, int(S::*const volatile)()), "");
+ static_assert(__is_same(remove_reference_t<int (S::*const volatile &&)() &>, int(S::*const volatile)() &), "");
+}
+
+template <class T> using remove_cvref_t = __remove_cvref(T);
+
+void check_remove_cvref() {
+ static_assert(__is_same(remove_cvref_t<void>, void), "");
+ static_assert(__is_same(remove_cvref_t<const volatile void>, void), "");
+ static_assert(__is_same(remove_cvref_t<int>, int), "");
+ static_assert(__is_same(remove_cvref_t<const int>, int), "");
+ static_assert(__is_same(remove_cvref_t<volatile int>, int), "");
+ static_assert(__is_same(remove_cvref_t<const volatile int>, int), "");
+ static_assert(__is_same(remove_cvref_t<int *>, int *), "");
+ static_assert(__is_same(remove_cvref_t<int *const volatile>, int *), "");
+ static_assert(__is_same(remove_cvref_t<int const *const volatile>, int const *), "");
+ static_assert(__is_same(remove_cvref_t<int const *const volatile __restrict>, int const *__restrict), "");
+ static_assert(__is_same(remove_cvref_t<int const *const volatile _Nonnull>, int const *_Nonnull), "");
+ static_assert(__is_same(remove_cvref_t<int &>, int), "");
+ static_assert(__is_same(remove_cvref_t<int const volatile &>, int), "");
+ static_assert(__is_same(remove_cvref_t<int &&>, int), "");
+ static_assert(__is_same(remove_cvref_t<int const volatile &&>, int), "");
+ static_assert(__is_same(remove_cvref_t<int()>, int()), "");
+ static_assert(__is_same(remove_cvref_t<int (*const volatile)()>, int (*)()), "");
+ static_assert(__is_same(remove_cvref_t<int (&)()>, int()), "");
+
+ static_assert(__is_same(remove_cvref_t<S>, S), "");
+ static_assert(__is_same(remove_cvref_t<S &>, S), "");
+ static_assert(__is_same(remove_cvref_t<S &&>, S), "");
+ static_assert(__is_same(remove_cvref_t<const S>, S), "");
+ static_assert(__is_same(remove_cvref_t<const S &>, S), "");
+ static_assert(__is_same(remove_cvref_t<const S &&>, S), "");
+ static_assert(__is_same(remove_cvref_t<volatile S>, S), "");
+ static_assert(__is_same(remove_cvref_t<volatile S &>, S), "");
+ static_assert(__is_same(remove_cvref_t<volatile S &&>, S), "");
+ static_assert(__is_same(remove_cvref_t<const volatile S>, S), "");
+ static_assert(__is_same(remove_cvref_t<const volatile S &>, S), "");
+ static_assert(__is_same(remove_cvref_t<const volatile S &&>, S), "");
+ static_assert(__is_same(remove_cvref_t<int S::*const volatile>, int S::*), "");
+ static_assert(__is_same(remove_cvref_t<int (S::*const volatile)()>, int(S::*)()), "");
+ static_assert(__is_same(remove_cvref_t<int (S::*const volatile)() &>, int(S::*)() &), "");
+ static_assert(__is_same(remove_cvref_t<int (S::*const volatile)() &&>, int(S::*)() &&), "");
+}
+
+template <class T> using decay_t = __decay(T);
+template <class T> struct dne;
+
+void check_decay() {
+ static_assert(__is_same(decay_t<void>, void), "");
+ static_assert(__is_same(decay_t<const volatile void>, void), "");
+ static_assert(__is_same(decay_t<int>, int), "");
+ static_assert(__is_same(decay_t<const int>, int), "");
+ static_assert(__is_same(decay_t<volatile int>, int), "");
+ static_assert(__is_same(decay_t<const volatile int>, int), "");
+ static_assert(__is_same(decay_t<int *>, int *), "");
+ static_assert(__is_same(decay_t<int *const volatile>, int *), "");
+ static_assert(__is_same(decay_t<int *const volatile __restrict>, int *), "");
+ static_assert(__is_same(decay_t<int const *const volatile>, int const *), "");
+ static_assert(__is_same(decay_t<int const *const volatile _Nonnull>, int const *), "");
+ static_assert(__is_same(decay_t<int &>, int), "");
+ static_assert(__is_same(decay_t<int const volatile &>, int), "");
+ static_assert(__is_same(decay_t<int &&>, int), "");
+ static_assert(__is_same(decay_t<int const volatile &&>, int), "");
+ static_assert(__is_same(decay_t<int()>, int (*)()), "");
+ static_assert(__is_same(decay_t<int (*)()>, int (*)()), "");
+ static_assert(__is_same(decay_t<int (*const)()>, int (*)()), "");
+ static_assert(__is_same(decay_t<int (*volatile)()>, int (*)()), "");
+ static_assert(__is_same(decay_t<int (*const volatile)()>, int (*)()), "");
+ static_assert(__is_same(decay_t<int (&)()>, int (*)()), "");
+ static_assert(__is_same(decay_t<IntAr>, int *), "");
+ static_assert(__is_same(decay_t<IntArNB>, int *), "");
+
+ static_assert(__is_same(decay_t<S>, S), "");
+ static_assert(__is_same(decay_t<S &>, S), "");
+ static_assert(__is_same(decay_t<S &&>, S), "");
+ static_assert(__is_same(decay_t<const S>, S), "");
+ static_assert(__is_same(decay_t<const S &>, S), "");
+ static_assert(__is_same(decay_t<const S &&>, S), "");
+ static_assert(__is_same(decay_t<volatile S>, S), "");
+ static_assert(__is_same(decay_t<volatile S &>, S), "");
+ static_assert(__is_same(decay_t<volatile S &&>, S), "");
+ static_assert(__is_same(decay_t<const volatile S>, S), "");
+ static_assert(__is_same(decay_t<const volatile S &>, S), "");
+ static_assert(__is_same(decay_t<const volatile S &&>, S), "");
+ static_assert(__is_same(decay_t<int S::*const volatile>, int S::*), "");
+ static_assert(__is_same(decay_t<int (S::*const volatile)()>, int(S::*)()), "");
+ static_assert(__is_same(decay_t<int S::*const volatile &>, int S::*), "");
+ static_assert(__is_same(decay_t<int (S::*const volatile &)()>, int(S::*)()), "");
+ static_assert(__is_same(decay_t<int S::*const volatile &&>, int S::*), "");
+}
+
+template <class T> struct CheckAbominableFunction {};
+template <class M>
+struct CheckAbominableFunction<M S::*> {
+ static void checks() {
+ static_assert(__is_same(add_lvalue_reference_t<M>, M), "");
+ static_assert(__is_same(add_pointer_t<M>, M), "");
+ static_assert(__is_same(add_rvalue_reference_t<M>, M), "");
+ static_assert(__is_same(decay_t<M>, M), "");
+ static_assert(__is_same(remove_const_t<M>, M), "");
+ static_assert(__is_same(remove_volatile_t<M>, M), "");
+ static_assert(__is_same(remove_cv_t<M>, M), "");
+ static_assert(__is_same(remove_cvref_t<M>, M), "");
+ static_assert(__is_same(remove_pointer_t<M>, M), "");
+ static_assert(__is_same(remove_reference_t<M>, M), "");
+ }
+};
+
+void check_abominable_function() {
+ { CheckAbominableFunction<int (S::*)() &> x; }
+ { CheckAbominableFunction<int (S::*)() &&> x; }
+ { CheckAbominableFunction<int (S::*)() const> x; }
+ { CheckAbominableFunction<int (S::*)() const &> x; }
+ { CheckAbominableFunction<int (S::*)() const &&> x; }
+ { CheckAbominableFunction<int (S::*)() volatile> x; }
+ { CheckAbominableFunction<int (S::*)() volatile &> x; }
+ { CheckAbominableFunction<int (S::*)() volatile &&> x; }
+ { CheckAbominableFunction<int (S::*)() const volatile> x; }
+ { CheckAbominableFunction<int (S::*)() const volatile &> x; }
+ { CheckAbominableFunction<int (S::*)() const volatile &&> x; }
+}
+
+template <class T> using make_signed_t = __make_signed(T);
+template <class T, class Expected>
+void check_make_signed() {
+ static_assert(__is_same(make_signed_t<T>, Expected), "");
+ static_assert(__is_same(make_signed_t<const T>, const Expected), "");
+ static_assert(__is_same(make_signed_t<volatile T>, volatile Expected), "");
+ static_assert(__is_same(make_signed_t<const volatile T>, const volatile Expected), "");
+}
+
+#if defined(__ILP32__) || defined(__LLP64__)
+ using Int64 = long long;
+ using UInt64 = unsigned long long;
+#elif defined(__LP64__) || defined(__ILP64__) || defined(__SILP64__)
+ using Int64 = long;
+ using UInt64 = unsigned long;
+#else
+#error Programming model currently unsupported; please add a new entry.
+#endif
+
+enum UnscopedBool : bool {}; // deliberately char
+enum class ScopedBool : bool {}; // deliberately char
+enum UnscopedChar : char {}; // deliberately char
+enum class ScopedChar : char {}; // deliberately char
+enum UnscopedUChar : unsigned char {};
+enum class ScopedUChar : unsigned char {};
+enum UnscopedLongLong : long long {};
+enum UnscopedULongLong : unsigned long long {};
+enum class ScopedLongLong : long long {};
+enum class ScopedULongLong : unsigned long long {};
+enum class UnscopedInt128 : __int128 {};
+enum class ScopedInt128 : __int128 {};
+enum class UnscopedUInt128 : unsigned __int128 {};
+enum class ScopedUInt128 : unsigned __int128 {};
+enum UnscopedBit : unsigned _BitInt(1) {};
+enum ScopedBit : unsigned _BitInt(1) {};
+enum UnscopedIrregular : _BitInt(21) {};
+enum UnscopedUIrregular : unsigned _BitInt(21) {};
+enum class ScopedIrregular : _BitInt(21) {};
+enum class ScopedUIrregular : unsigned _BitInt(21) {};
+
+void make_signed() {
+ check_make_signed<char, signed char>();
+ check_make_signed<signed char, signed char>();
+ check_make_signed<unsigned char, signed char>();
+ check_make_signed<short, short>();
+ check_make_signed<unsigned short, short>();
+ check_make_signed<int, int>();
+ check_make_signed<unsigned int, int>();
+ check_make_signed<long, long>();
+ check_make_signed<unsigned long, long>();
+ check_make_signed<long long, long long>();
+ check_make_signed<unsigned long long, long long>();
+ check_make_signed<__int128, __int128>();
+ check_make_signed<__uint128_t, __int128>();
+ check_make_signed<_BitInt(65), _BitInt(65)>();
+ check_make_signed<unsigned _BitInt(65), _BitInt(65)>();
+
+ check_make_signed<wchar_t, int>();
+#if __cplusplus >= 202002L
+ check_make_signed<char8_t, signed char>();
+#endif
+#if __cplusplus >= 201103L
+ check_make_signed<char16_t, short>();
+ check_make_signed<char32_t, int>();
+#endif
+
+ check_make_signed<UnscopedChar, signed char>();
+ check_make_signed<ScopedChar, signed char>();
+ check_make_signed<UnscopedUChar, signed char>();
+ check_make_signed<ScopedUChar, signed char>();
+
+ check_make_signed<UnscopedLongLong, Int64>();
+ check_make_signed<UnscopedULongLong, Int64>();
+ check_make_signed<ScopedLongLong, Int64>();
+ check_make_signed<ScopedULongLong, Int64>();
+
+ check_make_signed<UnscopedInt128, __int128>();
+ check_make_signed<ScopedInt128, __int128>();
+ check_make_signed<UnscopedUInt128, __int128>();
+ check_make_signed<ScopedUInt128, __int128>();
+
+ check_make_signed<UnscopedIrregular, _BitInt(21)>();
+ check_make_signed<UnscopedUIrregular, _BitInt(21)>();
+ check_make_signed<ScopedIrregular, _BitInt(21)>();
+ check_make_signed<ScopedUIrregular, _BitInt(21)>();
+
+ { using ExpectedError = __make_signed(bool); }
+ // expected-error@*:*{{'make_signed' is only compatible with non-bool integers and enum types, but was given 'bool'}}
+ { using ExpectedError = __make_signed(UnscopedBool); }
+ // expected-error@*:*{{'make_signed' is only compatible with non-bool integers and enum types, but was given 'UnscopedBool' whose underlying type is 'bool'}}
+ { using ExpectedError = __make_signed(ScopedBool); }
+ // expected-error@*:*{{'make_signed' is only compatible with non-bool integers and enum types, but was given 'ScopedBool' whose underlying type is 'bool'}}
+ { using ExpectedError = __make_signed(unsigned _BitInt(1)); }
+ // expected-error@*:*{{'make_signed' is only compatible with non-_BitInt(1) integers and enum types, but was given 'unsigned _BitInt(1)'}}
+ { using ExpectedError = __make_signed(UnscopedBit); }
+ // expected-error@*:*{{'make_signed' is only compatible with non-_BitInt(1) integers and enum types, but was given 'UnscopedBit' whose underlying type is 'unsigned _BitInt(1)'}}
+ { using ExpectedError = __make_signed(ScopedBit); }
+ // expected-error@*:*{{'make_signed' is only compatible with non-_BitInt(1) integers and enum types, but was given 'ScopedBit' whose underlying type is 'unsigned _BitInt(1)'}}
+ { using ExpectedError = __make_signed(int[]); }
+ // expected-error@*:*{{'make_signed' is only compatible with non-bool integers and enum types, but was given 'int[]'}}
+ { using ExpectedError = __make_signed(int[5]); }
+ // expected-error@*:*{{'make_signed' is only compatible with non-bool integers and enum types, but was given 'int[5]'}}
+ { using ExpectedError = __make_signed(void); }
+ // expected-error@*:*{{'make_signed' is only compatible with non-bool integers and enum types, but was given 'void'}}
+ { using ExpectedError = __make_signed(int *); }
+ // expected-error@*:*{{'make_signed' is only compatible with non-bool integers and enum types, but was given 'int *'}}
+ { using ExpectedError = __make_signed(int &); }
+ // expected-error@*:*{{'make_signed' is only compatible with non-bool integers and enum types, but was given 'int &'}}
+ { using ExpectedError = __make_signed(int &&); }
+ // expected-error@*:*{{'make_signed' is only compatible with non-bool integers and enum types, but was given 'int &&'}}
+ { using ExpectedError = __make_signed(float); }
+ // expected-error@*:*{{'make_signed' is only compatible with non-bool integers and enum types, but was given 'float'}}
+ { using ExpectedError = __make_signed(double); }
+ // expected-error@*:*{{'make_signed' is only compatible with non-bool integers and enum types, but was given 'double'}}
+ { using ExpectedError = __make_signed(long double); }
+ // expected-error@*:*{{'make_signed' is only compatible with non-bool integers and enum types, but was given 'long double'}}
+ { using ExpectedError = __make_signed(S); }
+ // expected-error@*:*{{'make_signed' is only compatible with non-bool integers and enum types, but was given 'S'}}
+ { using ExpectedError = __make_signed(S *); }
+ // expected-error@*:*{{'make_signed' is only compatible with non-bool integers and enum types, but was given 'S *'}}
+ { using ExpectedError = __make_signed(int S::*); }
+ // expected-error@*:*{{'make_signed' is only compatible with non-bool integers and enum types, but was given 'int S::*'}}
+ { using ExpectedError = __make_signed(int(S::*)()); }
+ // expected-error@*:*{{'make_signed' is only compatible with non-bool integers and enum types, but was given 'int (S::*)()'}}
+}
+
+template <class T>
+using make_unsigned_t = __make_unsigned(T);
+
+template <class T, class Expected>
+void check_make_unsigned() {
+ static_assert(__is_same(make_unsigned_t<T>, Expected), "");
+ static_assert(__is_same(make_unsigned_t<const T>, const Expected), "");
+ static_assert(__is_same(make_unsigned_t<volatile T>, volatile Expected), "");
+ static_assert(__is_same(make_unsigned_t<const volatile T>, const volatile Expected), "");
+}
+
+void make_unsigned() {
+ check_make_unsigned<char, unsigned char>();
+ check_make_unsigned<signed char, unsigned char>();
+ check_make_unsigned<unsigned char, unsigned char>();
+ check_make_unsigned<short, unsigned short>();
+ check_make_unsigned<unsigned short, unsigned short>();
+ check_make_unsigned<int, unsigned int>();
+ check_make_unsigned<unsigned int, unsigned int>();
+ check_make_unsigned<long, unsigned long>();
+ check_make_unsigned<unsigned long, unsigned long>();
+ check_make_unsigned<long long, unsigned long long>();
+ check_make_unsigned<unsigned long long, unsigned long long>();
+ check_make_unsigned<__int128, __uint128_t>();
+ check_make_unsigned<__uint128_t, __uint128_t>();
+ check_make_unsigned<_BitInt(65), unsigned _BitInt(65)>();
+ check_make_unsigned<unsigned _BitInt(65), unsigned _BitInt(65)>();
+
+ check_make_unsigned<wchar_t, unsigned int>();
+#if __cplusplus >= 202002L
+ check_make_unsigned<char8_t, unsigned char>();
+#endif
+#if __cplusplus >= 201103L
+ check_make_unsigned<char16_t, unsigned short>();
+ check_make_unsigned<char32_t, unsigned int>();
+#endif
+
+ check_make_unsigned<UnscopedChar, unsigned char>();
+ check_make_unsigned<ScopedChar, unsigned char>();
+ check_make_unsigned<UnscopedUChar, unsigned char>();
+ check_make_unsigned<ScopedUChar, unsigned char>();
+
+ check_make_unsigned<UnscopedLongLong, UInt64>();
+ check_make_unsigned<UnscopedULongLong, UInt64>();
+ check_make_unsigned<ScopedLongLong, UInt64>();
+ check_make_unsigned<ScopedULongLong, UInt64>();
+
+ check_make_unsigned<UnscopedInt128, unsigned __int128>();
+ check_make_unsigned<ScopedInt128, unsigned __int128>();
+ check_make_unsigned<UnscopedUInt128, unsigned __int128>();
+ check_make_unsigned<ScopedUInt128, unsigned __int128>();
+
+ check_make_unsigned<UnscopedIrregular, unsigned _BitInt(21)>();
+ check_make_unsigned<UnscopedUIrregular, unsigned _BitInt(21)>();
+ check_make_unsigned<ScopedIrregular, unsigned _BitInt(21)>();
+ check_make_unsigned<ScopedUIrregular, unsigned _BitInt(21)>();
+
+ { using ExpectedError = __make_unsigned(bool); }
+ // expected-error@*:*{{'make_unsigned' is only compatible with non-bool integers and enum types, but was given 'bool'}}
+ { using ExpectedError = __make_unsigned(UnscopedBool); }
+ // expected-error@*:*{{'make_unsigned' is only compatible with non-bool integers and enum types, but was given 'UnscopedBool' whose underlying type is 'bool'}}
+ { using ExpectedError = __make_unsigned(ScopedBool); }
+ // expected-error@*:*{{'make_unsigned' is only compatible with non-bool integers and enum types, but was given 'ScopedBool' whose underlying type is 'bool'}}
+ { using ExpectedError = __make_unsigned(unsigned _BitInt(1)); }
+ // expected-error@*:*{{'make_unsigned' is only compatible with non-_BitInt(1) integers and enum types, but was given 'unsigned _BitInt(1)'}}
+ { using ExpectedError = __make_unsigned(UnscopedBit); }
+ // expected-error@*:*{{'make_unsigned' is only compatible with non-_BitInt(1) integers and enum types, but was given 'UnscopedBit'}}
+ { using ExpectedError = __make_unsigned(ScopedBit); }
+ // expected-error@*:*{{'make_unsigned' is only compatible with non-_BitInt(1) integers and enum types, but was given 'ScopedBit'}}
+ { using ExpectedError = __make_unsigned(int[]); }
+ // expected-error@*:*{{'make_unsigned' is only compatible with non-bool integers and enum types, but was given 'int[]'}}
+ { using ExpectedError = __make_unsigned(int[5]); }
+ // expected-error@*:*{{'make_unsigned' is only compatible with non-bool integers and enum types, but was given 'int[5]'}}
+ { using ExpectedError = __make_unsigned(void); }
+ // expected-error@*:*{{'make_unsigned' is only compatible with non-bool integers and enum types, but was given 'void'}}
+ { using ExpectedError = __make_unsigned(int *); }
+ // expected-error@*:*{{'make_unsigned' is only compatible with non-bool integers and enum types, but was given 'int *'}}
+ { using ExpectedError = __make_unsigned(int &); }
+ // expected-error@*:*{{'make_unsigned' is only compatible with non-bool integers and enum types, but was given 'int &'}}
+ { using ExpectedError = __make_unsigned(int &&); }
+ // expected-error@*:*{{'make_unsigned' is only compatible with non-bool integers and enum types, but was given 'int &&'}}
+ { using ExpectedError = __make_unsigned(float); }
+ // expected-error@*:*{{'make_unsigned' is only compatible with non-bool integers and enum types, but was given 'float'}}
+ { using ExpectedError = __make_unsigned(double); }
+ // expected-error@*:*{{'make_unsigned' is only compatible with non-bool integers and enum types, but was given 'double'}}
+ { using ExpectedError = __make_unsigned(long double); }
+ // expected-error@*:*{{'make_unsigned' is only compatible with non-bool integers and enum types, but was given 'long double'}}
+ { using ExpectedError = __make_unsigned(S); }
+ // expected-error@*:*{{'make_unsigned' is only compatible with non-bool integers and enum types, but was given 'S'}}
+ { using ExpectedError = __make_unsigned(S *); }
+ // expected-error@*:*{{'make_unsigned' is only compatible with non-bool integers and enum types, but was given 'S *'}}
+ { using ExpectedError = __make_unsigned(int S::*); }
+ // expected-error@*:*{{'make_unsigned' is only compatible with non-bool integers and enum types, but was given 'int S::*'}}
+ { using ExpectedError = __make_unsigned(int(S::*)()); }
+ // expected-error@*:*{{'make_unsigned' is only compatible with non-bool integers and enum types, but was given 'int (S::*)()'}}
+}
+
+template <class T> using remove_extent_t = __remove_extent(T);
+
+void remove_extent() {
+ static_assert(__is_same(remove_extent_t<void>, void), "");
+ static_assert(__is_same(remove_extent_t<int>, int), "");
+ static_assert(__is_same(remove_extent_t<int[]>, int), "");
+ static_assert(__is_same(remove_extent_t<int[1]>, int), "");
+ static_assert(__is_same(remove_extent_t<int[1][2]>, int[2]), "");
+ static_assert(__is_same(remove_extent_t<int[][2]>, int[2]), "");
+ static_assert(__is_same(remove_extent_t<const int[]>, const int), "");
+ static_assert(__is_same(remove_extent_t<const int[1]>, const int), "");
+ static_assert(__is_same(remove_extent_t<const int[1][2]>, const int[2]), "");
+ static_assert(__is_same(remove_extent_t<const int[][2]>, const int[2]), "");
+ static_assert(__is_same(remove_extent_t<volatile int[]>, volatile int), "");
+ static_assert(__is_same(remove_extent_t<volatile int[1]>, volatile int), "");
+ static_assert(__is_same(remove_extent_t<volatile int[1][2]>, volatile int[2]), "");
+ static_assert(__is_same(remove_extent_t<volatile int[][2]>, volatile int[2]), "");
+ static_assert(__is_same(remove_extent_t<const volatile int[]>, const volatile int), "");
+ static_assert(__is_same(remove_extent_t<const volatile int[1]>, const volatile int), "");
+ static_assert(__is_same(remove_extent_t<const volatile int[1][2]>, const volatile int[2]), "");
+ static_assert(__is_same(remove_extent_t<const volatile int[][2]>, const volatile int[2]), "");
+ static_assert(__is_same(remove_extent_t<int *>, int *), "");
+ static_assert(__is_same(remove_extent_t<int &>, int &), "");
+ static_assert(__is_same(remove_extent_t<int &&>, int &&), "");
+ static_assert(__is_same(remove_extent_t<int()>, int()), "");
+ static_assert(__is_same(remove_extent_t<int (*)()>, int (*)()), "");
+ static_assert(__is_same(remove_extent_t<int (&)()>, int (&)()), "");
+
+ static_assert(__is_same(remove_extent_t<S>, S), "");
+ static_assert(__is_same(remove_extent_t<int S::*>, int S::*), "");
+ static_assert(__is_same(remove_extent_t<int (S::*)()>, int(S::*)()), "");
+
+ using SomeArray = int[1][2];
+ static_assert(__is_same(remove_extent_t<const SomeArray>, const int[2]), "");
+}
+
+template <class T> using remove_all_extents_t = __remove_all_extents(T);
+
+void remove_all_extents() {
+ static_assert(__is_same(remove_all_extents_t<void>, void), "");
+ static_assert(__is_same(remove_all_extents_t<int>, int), "");
+ static_assert(__is_same(remove_all_extents_t<const int>, const int), "");
+ static_assert(__is_same(remove_all_extents_t<volatile int>, volatile int), "");
+ static_assert(__is_same(remove_all_extents_t<const volatile int>, const volatile int), "");
+ static_assert(__is_same(remove_all_extents_t<int[]>, int), "");
+ static_assert(__is_same(remove_all_extents_t<int[1]>, int), "");
+ static_assert(__is_same(remove_all_extents_t<int[1][2]>, int), "");
+ static_assert(__is_same(remove_all_extents_t<int[][2]>, int), "");
+ static_assert(__is_same(remove_all_extents_t<const int[]>, const int), "");
+ static_assert(__is_same(remove_all_extents_t<const int[1]>, const int), "");
+ static_assert(__is_same(remove_all_extents_t<const int[1][2]>, const int), "");
+ static_assert(__is_same(remove_all_extents_t<const int[][2]>, const int), "");
+ static_assert(__is_same(remove_all_extents_t<volatile int[]>, volatile int), "");
+ static_assert(__is_same(remove_all_extents_t<volatile int[1]>, volatile int), "");
+ static_assert(__is_same(remove_all_extents_t<volatile int[1][2]>, volatile int), "");
+ static_assert(__is_same(remove_all_extents_t<volatile int[][2]>, volatile int), "");
+ static_assert(__is_same(remove_all_extents_t<const volatile int[]>, const volatile int), "");
+ static_assert(__is_same(remove_all_extents_t<const volatile int[1]>, const volatile int), "");
+ static_assert(__is_same(remove_all_extents_t<const volatile int[1][2]>, const volatile int), "");
+ static_assert(__is_same(remove_all_extents_t<const volatile int[][2]>, const volatile int), "");
+ static_assert(__is_same(remove_all_extents_t<int *>, int *), "");
+ static_assert(__is_same(remove_all_extents_t<int &>, int &), "");
+ static_assert(__is_same(remove_all_extents_t<int &&>, int &&), "");
+ static_assert(__is_same(remove_all_extents_t<int()>, int()), "");
+ static_assert(__is_same(remove_all_extents_t<int (*)()>, int (*)()), "");
+ static_assert(__is_same(remove_all_extents_t<int (&)()>, int (&)()), "");
+
+ static_assert(__is_same(remove_all_extents_t<S>, S), "");
+ static_assert(__is_same(remove_all_extents_t<int S::*>, int S::*), "");
+ static_assert(__is_same(remove_all_extents_t<int (S::*)()>, int(S::*)()), "");
+
+ using SomeArray = int[1][2];
+ static_assert(__is_same(remove_all_extents_t<const SomeArray>, const int), "");
+}
diff --git a/clang/utils/ClangVisualizers/clang.natvis b/clang/utils/ClangVisualizers/clang.natvis
index 36dea11..3e6148c 100644
--- a/clang/utils/ClangVisualizers/clang.natvis
+++ b/clang/utils/ClangVisualizers/clang.natvis
@@ -2,7 +2,7 @@
<!--
Visual Studio Native Debugging Visualizers for LLVM
-For Visual Studio 2013 only, put this file into
+For Visual Studio 2013 only, put this file into
"%USERPROFILE%\Documents\Visual Studio 2013\Visualizers" or create a symbolic link so it updates automatically.
For later versions of Visual Studio, no setup is required-->
@@ -11,8 +11,8 @@ For later versions of Visual Studio, no setup is required-->
<Type Name="clang::Type">
<!-- To visualize clang::Types, we need to look at TypeBits.TC to determine the actual
type subclass and manually dispatch accordingly (Visual Studio can't identify the real type
- because clang::Type has no virtual members hence no RTTI).
-
+ because clang::Type has no virtual members hence no RTTI).
+
Views:
"cmn": Visualization that is common to all clang::Type subclasses
"poly": Visualization that is specific to the actual clang::Type subclass. The subtype-specific
@@ -160,7 +160,7 @@ For later versions of Visual Studio, no setup is required-->
<Type Name="clang::AttributedType">
<DisplayString>{ModifiedType} Attribute={(clang::AttributedType::Kind)AttributedTypeBits.AttrKind}</DisplayString>
</Type>
-
+
<!-- Unfortunately, Visual Studio has trouble seeing the PointerBitMask member PointerIntUnion, so I hardwire it to 2 bits-->
<Type Name="clang::DeclContext">
<DisplayString>{(clang::Decl::Kind)DeclContextBits.DeclKind,en}Decl</DisplayString>
@@ -201,7 +201,7 @@ For later versions of Visual Studio, no setup is required-->
<DisplayString IncludeView="DefaultArg">{{InheritedInitializer}}</DisplayString>
<DisplayString IncludeView="Initializer" Condition="DefaultArgument.ValueOrInherited.Val.Value&amp;~3LL">= {this,view(DefaultArg)na}</DisplayString>
<DisplayString IncludeView="Initializer"></DisplayString>
- <DisplayString>{*this,view(TorC)} {*this,view(MaybeEllipses)}{Name,view(cpp)} {this,view(Initializer)na}</DisplayString>
+ <DisplayString>{*this,view(TorC)} {*this,view(MaybeEllipses)}{Name,view(cpp)} {this,view(Initializer)na}</DisplayString>
</Type>
<Type Name="clang::TemplateDecl">
<DisplayString IncludeView="cpp">{*TemplatedDecl,view(cpp)}</DisplayString>
@@ -694,7 +694,7 @@ For later versions of Visual Studio, no setup is required-->
<DisplayString Condition="(Ptr &amp; PtrMask) == StoredCXXConstructorName">C++ Constructor {{{(clang::detail::CXXSpecialNameExtra *)(Ptr &amp; ~PtrMask),view(cpp)na}}}</DisplayString>
<DisplayString Condition="(Ptr &amp; PtrMask) == StoredCXXDestructorName">C++ Destructor {{*(clang::detail::CXXSpecialNameExtra *)(Ptr &amp; ~PtrMask)}}</DisplayString>
<DisplayString Condition="(Ptr &amp; PtrMask) == StoredCXXConversionFunctionName">C++ Conversion function {{*(clang::detail::CXXSpecialNameExtra *)(Ptr &amp; ~PtrMask)}}</DisplayString>
- <DisplayString Condition="(Ptr &amp; PtrMask) == StoredCXXOperatorName">C++ Operator {{*(clang::detail::CXXOperatorIdName *)(Ptr &amp; ~PtrMask)}}</DisplayString>
+ <DisplayString Condition="(Ptr &amp; PtrMask) == StoredCXXOperatorName">C++ Operator {{*(clang::detail::CXXOperatorIdName *)(Ptr &amp; ~PtrMask)}}</DisplayString>
<DisplayString Condition="(Ptr &amp; PtrMask) == StoredDeclarationNameExtra"
IncludeView="cpp">{*(clang::detail::DeclarationNameExtra *)(Ptr &amp; ~PtrMask),view(cpp)}</DisplayString>
<DisplayString Condition="(Ptr &amp; PtrMask) == StoredDeclarationNameExtra">{{Extra ({*(clang::detail::DeclarationNameExtra *)(Ptr &amp; ~PtrMask)})}}</DisplayString>
@@ -706,7 +706,7 @@ For later versions of Visual Studio, no setup is required-->
<Item Condition="(Ptr &amp; PtrMask) == StoredCXXConstructorName" Name="[C++ Constructor]">*(clang::detail::CXXSpecialNameExtra *)(Ptr &amp; ~PtrMask),na</Item>
<Item Condition="(Ptr &amp; PtrMask) == StoredCXXDestructorName" Name="[C++ Destructor]">*(clang::detail::CXXSpecialNameExtra *)(Ptr &amp; ~PtrMask),na</Item>
<Item Condition="(Ptr &amp; PtrMask) == StoredCXXConversionFunctionName" Name="[C++ Conversion function]">*(clang::detail::CXXSpecialNameExtra *)(Ptr &amp; ~PtrMask),na</Item>
- <Item Condition="(Ptr &amp; PtrMask) == StoredCXXOperatorName" Name="[C++ Operator]">*(clang::detail::CXXOperatorIdName *)(Ptr &amp; ~PtrMask),na</Item>
+ <Item Condition="(Ptr &amp; PtrMask) == StoredCXXOperatorName" Name="[C++ Operator]">*(clang::detail::CXXOperatorIdName *)(Ptr &amp; ~PtrMask),na</Item>
<Item Condition="(Ptr &amp; PtrMask) == StoredDeclarationNameExtra" Name="[Extra]">(clang::detail::DeclarationNameExtra *)(Ptr &amp; ~PtrMask),na</Item>
</Expand>
</Type>
@@ -718,7 +718,7 @@ For later versions of Visual Studio, no setup is required-->
{(CXXDeductionGuideNameExtra *)this,nand}
</DisplayString>
<DisplayString Condition="ExtraKindOrNumArgs == CXXLiteralOperatorName">C++ Literal operator</DisplayString>
- <DisplayString Condition="ExtraKindOrNumArgs == CXXUsingDirective">C++ Using directive</DisplayString>
+ <DisplayString Condition="ExtraKindOrNumArgs == CXXUsingDirective">C++ Using directive</DisplayString>
<DisplayString>{(clang::detail::DeclarationNameExtra::ExtraKind)ExtraKindOrNumArgs,en}{" ",sb}{*this,view(cpp)}</DisplayString>
<Expand>
<ExpandedItem Condition="ExtraKindOrNumArgs == CXXDeductionGuideName">(CXXDeductionGuideNameExtra *)this</ExpandedItem>
@@ -809,7 +809,7 @@ For later versions of Visual Studio, no setup is required-->
<DisplayString>[{this,view(default)na}{this,view(capture0)na}]</DisplayString>
</Type>
<Type Name="clang::DeclSpec">
- <DisplayString IncludeView="extra" Condition="TypeSpecType == TST_typename || TypeSpecType == TST_typeofType || TypeSpecType == TST_underlyingType || TypeSpecType == TST_atomic">
+ <DisplayString IncludeView="extra" Condition="TypeSpecType == TST_typename || TypeSpecType == TST_typeofType || TypeSpecType == TST_underlying_type || TypeSpecType == TST_atomic">
, [{TypeRep}]
</DisplayString>
<DisplayString IncludeView="extra" Condition="TypeSpecType == TST_typeofExpr || TypeSpecType == TST_decltype">
@@ -823,7 +823,7 @@ For later versions of Visual Studio, no setup is required-->
<Expand>
<Item Name="StorageClassSpec">(clang::DeclSpec::SCS)StorageClassSpec</Item>
<Item Name="TypeSpecType">(clang::TypeSpecifierType)TypeSpecType</Item>
- <Item Name="TypeRep" Condition="TypeSpecType == TST_typename || TypeSpecType == TST_typeofType || TypeSpecType == TST_underlyingType || TypeSpecType == TST_atomic">
+ <Item Name="TypeRep" Condition="TypeSpecType == TST_typename || TypeSpecType == TST_typeofType || TypeSpecType == TST_underlying_type || TypeSpecType == TST_atomic">
TypeRep
</Item>
<Item Name="ExprRep" Condition="TypeSpecType == TST_typeofExpr || TypeSpecType == TST_decltype">