forked from OSchip/llvm-project
[clang] adds unary type transformations as compiler built-ins
Adds * `__add_lvalue_reference` * `__add_pointer` * `__add_rvalue_reference` * `__decay` * `__make_signed` * `__make_unsigned` * `__remove_all_extents` * `__remove_extent` * `__remove_const` * `__remove_volatile` * `__remove_cv` * `__remove_pointer` * `__remove_reference` * `__remove_cvref` These are all compiler built-in equivalents of the unary type traits found in [[meta.trans]][1]. The compiler already has all of the information it needs to answer these transformations, so we can skip needing to make partial specialisations in standard library implementations (we already do this for a lot of the query traits). This will hopefully improve compile times, as we won't need use as much memory in such a base part of the standard library. [1]: http://wg21.link/meta.trans Co-authored-by: zoecarver Reviewed By: aaron.ballman, rsmith Differential Revision: https://reviews.llvm.org/D116203
This commit is contained in:
parent
d2d77e050b
commit
e9ef45635b
|
@ -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(),
|
||||
|
|
|
@ -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">>;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
|
@ -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]
|
||||
|
|
|
@ -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 ||
|
||||
|
|
|
@ -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);
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
|
|
@ -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 * }
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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'.
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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");
|
||||
|
||||
SourceLocation StartLoc = ConsumeToken();
|
||||
BalancedDelimiterTracker T(*this, tok::l_paren);
|
||||
if (T.expectAndConsume(diag::err_expected_lparen_after, "__underlying_type",
|
||||
tok::r_paren)) {
|
||||
return;
|
||||
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, 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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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: {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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);
|
||||
static QualType GetEnumUnderlyingType(Sema &S, QualType BaseType,
|
||||
SourceLocation Loc) {
|
||||
assert(BaseType->isEnumeralType());
|
||||
EnumDecl *ED = BaseType->castAs<EnumType>()->getDecl();
|
||||
assert(ED && "EnumType has no EnumDecl");
|
||||
|
||||
S.DiagnoseUseOfDecl(ED, Loc);
|
||||
|
||||
QualType Underlying = ED->getIntegerType();
|
||||
assert(!Underlying.isNull());
|
||||
|
||||
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();
|
||||
} else {
|
||||
QualType Underlying = BaseType;
|
||||
if (!BaseType->isDependentType()) {
|
||||
// The enum could be incomplete if we're parsing its definition or
|
||||
// recovering from an error.
|
||||
NamedDecl *FwdDecl = nullptr;
|
||||
if (BaseType->isIncompleteType(&FwdDecl)) {
|
||||
Diag(Loc, diag::err_underlying_type_of_incomplete_enum) << BaseType;
|
||||
Diag(FwdDecl->getLocation(), diag::note_forward_declaration) << FwdDecl;
|
||||
return QualType();
|
||||
}
|
||||
|
||||
EnumDecl *ED = BaseType->castAs<EnumType>()->getDecl();
|
||||
assert(ED && "EnumType has no EnumDecl");
|
||||
|
||||
DiagnoseUseOfDecl(ED, Loc);
|
||||
|
||||
Underlying = ED->getIntegerType();
|
||||
assert(!Underlying.isNull());
|
||||
}
|
||||
return Context.getUnaryTransformType(BaseType, Underlying,
|
||||
UnaryTransformType::EnumUnderlyingType);
|
||||
}
|
||||
}
|
||||
llvm_unreachable("unknown unary transform type");
|
||||
|
||||
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;
|
||||
}
|
||||
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) {
|
||||
|
|
|
@ -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)) {}
|
||||
void f1(T, __underlying_type(T)) {}
|
||||
template void f1<E>(E, __underlying_type(E));
|
||||
// CHECK-LABEL: @_ZN6test552f1INS_1EEEEvT_u17__underlying_typeIS2_E
|
||||
|
||||
template void fn<E>(E, __underlying_type(E));
|
||||
// CHECK-LABEL: @_ZN6test552fnINS_1EEEEvT_U3eutS2_
|
||||
}
|
||||
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;
|
||||
|
|
|
@ -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>>;
|
|
@ -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), "");
|
|
@ -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), "");
|
||||
}
|
||||
|
|
|
@ -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&~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 & PtrMask) == StoredCXXConstructorName">C++ Constructor {{{(clang::detail::CXXSpecialNameExtra *)(Ptr & ~PtrMask),view(cpp)na}}}</DisplayString>
|
||||
<DisplayString Condition="(Ptr & PtrMask) == StoredCXXDestructorName">C++ Destructor {{*(clang::detail::CXXSpecialNameExtra *)(Ptr & ~PtrMask)}}</DisplayString>
|
||||
<DisplayString Condition="(Ptr & PtrMask) == StoredCXXConversionFunctionName">C++ Conversion function {{*(clang::detail::CXXSpecialNameExtra *)(Ptr & ~PtrMask)}}</DisplayString>
|
||||
<DisplayString Condition="(Ptr & PtrMask) == StoredCXXOperatorName">C++ Operator {{*(clang::detail::CXXOperatorIdName *)(Ptr & ~PtrMask)}}</DisplayString>
|
||||
<DisplayString Condition="(Ptr & PtrMask) == StoredCXXOperatorName">C++ Operator {{*(clang::detail::CXXOperatorIdName *)(Ptr & ~PtrMask)}}</DisplayString>
|
||||
<DisplayString Condition="(Ptr & PtrMask) == StoredDeclarationNameExtra"
|
||||
IncludeView="cpp">{*(clang::detail::DeclarationNameExtra *)(Ptr & ~PtrMask),view(cpp)}</DisplayString>
|
||||
<DisplayString Condition="(Ptr & PtrMask) == StoredDeclarationNameExtra">{{Extra ({*(clang::detail::DeclarationNameExtra *)(Ptr & ~PtrMask)})}}</DisplayString>
|
||||
|
@ -706,7 +706,7 @@ For later versions of Visual Studio, no setup is required-->
|
|||
<Item Condition="(Ptr & PtrMask) == StoredCXXConstructorName" Name="[C++ Constructor]">*(clang::detail::CXXSpecialNameExtra *)(Ptr & ~PtrMask),na</Item>
|
||||
<Item Condition="(Ptr & PtrMask) == StoredCXXDestructorName" Name="[C++ Destructor]">*(clang::detail::CXXSpecialNameExtra *)(Ptr & ~PtrMask),na</Item>
|
||||
<Item Condition="(Ptr & PtrMask) == StoredCXXConversionFunctionName" Name="[C++ Conversion function]">*(clang::detail::CXXSpecialNameExtra *)(Ptr & ~PtrMask),na</Item>
|
||||
<Item Condition="(Ptr & PtrMask) == StoredCXXOperatorName" Name="[C++ Operator]">*(clang::detail::CXXOperatorIdName *)(Ptr & ~PtrMask),na</Item>
|
||||
<Item Condition="(Ptr & PtrMask) == StoredCXXOperatorName" Name="[C++ Operator]">*(clang::detail::CXXOperatorIdName *)(Ptr & ~PtrMask),na</Item>
|
||||
<Item Condition="(Ptr & PtrMask) == StoredDeclarationNameExtra" Name="[Extra]">(clang::detail::DeclarationNameExtra *)(Ptr & ~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">
|
||||
|
|
Loading…
Reference in New Issue