7 changes: 5 additions & 2 deletions clang/lib/AST/JSONNodeDumper.cpp
Original file line number Diff line number Diff line change
@@ -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"
Expand Down Expand Up @@ -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"
}
}

Expand Down
6 changes: 4 additions & 2 deletions clang/lib/AST/TextNodeDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
}

Expand Down
32 changes: 12 additions & 20 deletions clang/lib/AST/TypePrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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"
Expand Down Expand Up @@ -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'.
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Format/FormatToken.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Format/FormatToken.h
Original file line number Diff line number Diff line change
Expand Up @@ -681,7 +681,8 @@ struct FormatToken {
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:
Expand Down
6 changes: 4 additions & 2 deletions clang/lib/Format/TokenAnnotator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -317,8 +317,10 @@ class AnnotatingParser {
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))
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Lex/PPMacroExpansion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down
18 changes: 12 additions & 6 deletions clang/lib/Parse/ParseDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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'.
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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;
Expand Down
116 changes: 80 additions & 36 deletions clang/lib/Parse/ParseDeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -1142,35 +1143,48 @@ void Parser::AnnotateExistingDecltypeSpecifier(const DeclSpec &DS,
PP.AnnotateCachedTokens(Tok);
}

void Parser::ParseUnderlyingTypeSpecifier(DeclSpec &DS) {
assert(Tok.is(tok::kw___underlying_type) &&
"Not an underlying type specifier");
DeclSpec::TST Parser::TypeTransformTokToDeclSpec() {
switch (Tok.getKind()) {
#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) \
case tok::kw___##Trait: \
return DeclSpec::TST_##Trait;
#include "clang/Basic/TransformTypeTraits.def"
default:
llvm_unreachable("passed in an unhandled type transformation built-in");
}
}

bool Parser::MaybeParseTypeTransformTypeSpecifier(DeclSpec &DS) {
if (!NextToken().is(tok::l_paren)) {
Tok.setKind(tok::identifier);
return false;
}
DeclSpec::TST TypeTransformTST = TypeTransformTokToDeclSpec();
SourceLocation StartLoc = ConsumeToken();

BalancedDelimiterTracker T(*this, tok::l_paren);
if (T.expectAndConsume(diag::err_expected_lparen_after, "__underlying_type",
tok::r_paren)) {
return;
}
if (T.expectAndConsume(diag::err_expected_lparen_after, Tok.getName(),
tok::r_paren))
return true;

TypeResult Result = ParseTypeName();
if (Result.isInvalid()) {
SkipUntil(tok::r_paren, StopAtSemi);
return;
return true;
}

// Match the ')'
T.consumeClose();
if (T.getCloseLocation().isInvalid())
return;
return true;

const char *PrevSpec = nullptr;
unsigned DiagID;
if (DS.SetTypeSpecType(DeclSpec::TST_underlyingType, StartLoc, PrevSpec,
DiagID, Result.get(),
if (DS.SetTypeSpecType(TypeTransformTST, StartLoc, PrevSpec, DiagID,
Result.get(),
Actions.getASTContext().getPrintingPolicy()))
Diag(StartLoc, DiagID) << PrevSpec;
DS.setTypeofParensRange(T.getRange());
DS.setTypeArgumentRange(T.getRange());
return true;
}

/// ParseBaseTypeSpecifier - Parse a C++ base-type-specifier which is either a
Expand Down Expand Up @@ -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
Expand Down
22 changes: 19 additions & 3 deletions clang/lib/Parse/ParseExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -1766,6 +1781,7 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,
}
[[fallthrough]];
default:
ExpectedExpression:
NotCastExpr = true;
return ExprError();
}
Expand Down
20 changes: 17 additions & 3 deletions clang/lib/Parse/ParseExprCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@
#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"
#include "clang/Parse/RAIIObjectsForParser.h"
#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>

Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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
Expand Down
18 changes: 16 additions & 2 deletions clang/lib/Parse/ParseStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -188,7 +189,8 @@ StmtResult Parser::ParseStatementOrDeclarationAfterAttributes(
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
Expand Down Expand Up @@ -261,7 +263,19 @@ StmtResult Parser::ParseStatementOrDeclarationAfterAttributes(
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: {
Expand Down
11 changes: 7 additions & 4 deletions clang/lib/Parse/ParseTentative.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
9 changes: 7 additions & 2 deletions clang/lib/Sema/DeclSpec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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";
Expand Down
6 changes: 4 additions & 2 deletions clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Sema/SemaTemplateVariadic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down
305 changes: 270 additions & 35 deletions clang/lib/Sema/SemaType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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"
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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());
Expand Down Expand Up @@ -9205,39 +9220,259 @@ QualType Sema::BuildDecltypeType(Expr *E, bool AsUnevaluated) {
return Context.getDecltypeType(E, getDecltypeForExpr(E));
}

QualType Sema::BuildUnaryTransformType(QualType BaseType,
UnaryTransformType::UTTKind UKind,
SourceLocation Loc) {
switch (UKind) {
case UnaryTransformType::EnumUnderlyingType:
if (!BaseType->isDependentType() && !BaseType->isEnumeralType()) {
Diag(Loc, diag::err_only_enums_have_underlying_types);
return QualType();
} else {
QualType Underlying = BaseType;
if (!BaseType->isDependentType()) {
// The enum could be incomplete if we're parsing its definition or
// recovering from an error.
NamedDecl *FwdDecl = nullptr;
if (BaseType->isIncompleteType(&FwdDecl)) {
Diag(Loc, diag::err_underlying_type_of_incomplete_enum) << BaseType;
Diag(FwdDecl->getLocation(), diag::note_forward_declaration) << FwdDecl;
return QualType();
}
static QualType GetEnumUnderlyingType(Sema &S, QualType BaseType,
SourceLocation Loc) {
assert(BaseType->isEnumeralType());
EnumDecl *ED = BaseType->castAs<EnumType>()->getDecl();
assert(ED && "EnumType has no EnumDecl");

EnumDecl *ED = BaseType->castAs<EnumType>()->getDecl();
assert(ED && "EnumType has no EnumDecl");
S.DiagnoseUseOfDecl(ED, Loc);

DiagnoseUseOfDecl(ED, Loc);
QualType Underlying = ED->getIntegerType();
assert(!Underlying.isNull());

Underlying = ED->getIntegerType();
assert(!Underlying.isNull());
}
return Context.getUnaryTransformType(BaseType, Underlying,
UnaryTransformType::EnumUnderlyingType);
return Underlying;
}

QualType Sema::BuiltinEnumUnderlyingType(QualType BaseType,
SourceLocation Loc) {
if (!BaseType->isEnumeralType()) {
Diag(Loc, diag::err_only_enums_have_underlying_types);
return QualType();
}

// The enum could be incomplete if we're parsing its definition or
// recovering from an error.
NamedDecl *FwdDecl = nullptr;
if (BaseType->isIncompleteType(&FwdDecl)) {
Diag(Loc, diag::err_underlying_type_of_incomplete_enum) << BaseType;
Diag(FwdDecl->getLocation(), diag::note_forward_declaration) << FwdDecl;
return QualType();
}

return GetEnumUnderlyingType(*this, BaseType, Loc);
}

QualType Sema::BuiltinAddPointer(QualType BaseType, SourceLocation Loc) {
QualType Pointer = BaseType.isReferenceable() || BaseType->isVoidType()
? BuildPointerType(BaseType.getNonReferenceType(), Loc,
DeclarationName())
: BaseType;

return Pointer.isNull() ? QualType() : Pointer;
}

QualType Sema::BuiltinRemovePointer(QualType BaseType, SourceLocation Loc) {
// We don't want block pointers or ObjectiveC's id type.
if (!BaseType->isAnyPointerType() || BaseType->isObjCIdType())
return BaseType;

return BaseType->getPointeeType();
}

QualType Sema::BuiltinDecay(QualType BaseType, SourceLocation Loc) {
QualType Underlying = BaseType.getNonReferenceType();
if (Underlying->isArrayType())
return Context.getDecayedType(Underlying);

if (Underlying->isFunctionType())
return BuiltinAddPointer(BaseType, Loc);

SplitQualType Split = Underlying.getSplitUnqualifiedType();
// std::decay is supposed to produce 'std::remove_cv', but since 'restrict' is
// in the same group of qualifiers as 'const' and 'volatile', we're extending
// '__decay(T)' so that it removes all qualifiers.
Split.Quals.removeCVRQualifiers();
return Context.getQualifiedType(Split);
}

QualType Sema::BuiltinAddReference(QualType BaseType, UTTKind UKind,
SourceLocation Loc) {
assert(LangOpts.CPlusPlus);
QualType Reference =
BaseType.isReferenceable()
? BuildReferenceType(BaseType,
UKind == UnaryTransformType::AddLvalueReference,
Loc, DeclarationName())
: BaseType;
return Reference.isNull() ? QualType() : Reference;
}

QualType Sema::BuiltinRemoveExtent(QualType BaseType, UTTKind UKind,
SourceLocation Loc) {
if (UKind == UnaryTransformType::RemoveAllExtents)
return Context.getBaseElementType(BaseType);

if (const auto *AT = Context.getAsArrayType(BaseType))
return AT->getElementType();

return BaseType;
}

QualType Sema::BuiltinRemoveReference(QualType BaseType, UTTKind UKind,
SourceLocation Loc) {
assert(LangOpts.CPlusPlus);
QualType T = BaseType.getNonReferenceType();
if (UKind == UTTKind::RemoveCVRef &&
(T.isConstQualified() || T.isVolatileQualified())) {
Qualifiers Quals;
QualType Unqual = Context.getUnqualifiedArrayType(T, Quals);
Quals.removeConst();
Quals.removeVolatile();
T = Context.getQualifiedType(Unqual, Quals);
}
return T;
}

QualType Sema::BuiltinChangeCVRQualifiers(QualType BaseType, UTTKind UKind,
SourceLocation Loc) {
if ((BaseType->isReferenceType() && UKind != UTTKind::RemoveRestrict) ||
BaseType->isFunctionType())
return BaseType;

Qualifiers Quals;
QualType Unqual = Context.getUnqualifiedArrayType(BaseType, Quals);

if (UKind == UTTKind::RemoveConst || UKind == UTTKind::RemoveCV)
Quals.removeConst();
if (UKind == UTTKind::RemoveVolatile || UKind == UTTKind::RemoveCV)
Quals.removeVolatile();
if (UKind == UTTKind::RemoveRestrict)
Quals.removeRestrict();

return Context.getQualifiedType(Unqual, Quals);
}

static QualType ChangeIntegralSignedness(Sema &S, QualType BaseType,
bool IsMakeSigned,
SourceLocation Loc) {
if (BaseType->isEnumeralType()) {
QualType Underlying = GetEnumUnderlyingType(S, BaseType, Loc);
if (auto *BitInt = dyn_cast<BitIntType>(Underlying)) {
unsigned int Bits = BitInt->getNumBits();
if (Bits > 1)
return S.Context.getBitIntType(!IsMakeSigned, Bits);

S.Diag(Loc, diag::err_make_signed_integral_only)
<< IsMakeSigned << /*_BitInt(1)*/ true << BaseType << 1 << Underlying;
return QualType();
}
if (Underlying->isBooleanType()) {
S.Diag(Loc, diag::err_make_signed_integral_only)
<< IsMakeSigned << /*_BitInt(1)*/ false << BaseType << 1
<< Underlying;
return QualType();
}
}

bool Int128Unsupported = !S.Context.getTargetInfo().hasInt128Type();
std::array<CanQualType *, 6> AllSignedIntegers = {
&S.Context.SignedCharTy, &S.Context.ShortTy, &S.Context.IntTy,
&S.Context.LongTy, &S.Context.LongLongTy, &S.Context.Int128Ty};
ArrayRef<CanQualType *> AvailableSignedIntegers(
AllSignedIntegers.data(), AllSignedIntegers.size() - Int128Unsupported);
std::array<CanQualType *, 6> AllUnsignedIntegers = {
&S.Context.UnsignedCharTy, &S.Context.UnsignedShortTy,
&S.Context.UnsignedIntTy, &S.Context.UnsignedLongTy,
&S.Context.UnsignedLongLongTy, &S.Context.UnsignedInt128Ty};
ArrayRef<CanQualType *> AvailableUnsignedIntegers(AllUnsignedIntegers.data(),
AllUnsignedIntegers.size() -
Int128Unsupported);
ArrayRef<CanQualType *> *Consider =
IsMakeSigned ? &AvailableSignedIntegers : &AvailableUnsignedIntegers;

uint64_t BaseSize = S.Context.getTypeSize(BaseType);
auto *Result =
llvm::find_if(*Consider, [&S, BaseSize](const CanQual<Type> *T) {
return BaseSize == S.Context.getTypeSize(T->getTypePtr());
});

assert(Result != Consider->end());
return QualType((*Result)->getTypePtr(), 0);
}

QualType Sema::BuiltinChangeSignedness(QualType BaseType, UTTKind UKind,
SourceLocation Loc) {
bool IsMakeSigned = UKind == UnaryTransformType::MakeSigned;
if ((!BaseType->isIntegerType() && !BaseType->isEnumeralType()) ||
BaseType->isBooleanType() ||
(BaseType->isBitIntType() &&
BaseType->getAs<BitIntType>()->getNumBits() < 2)) {
Diag(Loc, diag::err_make_signed_integral_only)
<< IsMakeSigned << BaseType->isBitIntType() << BaseType << 0;
return QualType();
}

bool IsNonIntIntegral =
BaseType->isChar16Type() || BaseType->isChar32Type() ||
BaseType->isWideCharType() || BaseType->isEnumeralType();

QualType Underlying =
IsNonIntIntegral
? ChangeIntegralSignedness(*this, BaseType, IsMakeSigned, Loc)
: IsMakeSigned ? Context.getCorrespondingSignedType(BaseType)
: Context.getCorrespondingUnsignedType(BaseType);
if (Underlying.isNull())
return Underlying;
return Context.getQualifiedType(Underlying, BaseType.getQualifiers());
}

QualType Sema::BuildUnaryTransformType(QualType BaseType, UTTKind UKind,
SourceLocation Loc) {
if (BaseType->isDependentType())
return Context.getUnaryTransformType(BaseType, BaseType, UKind);
QualType Result;
switch (UKind) {
case UnaryTransformType::EnumUnderlyingType: {
Result = BuiltinEnumUnderlyingType(BaseType, Loc);
break;
}
case UnaryTransformType::AddPointer: {
Result = BuiltinAddPointer(BaseType, Loc);
break;
}
case UnaryTransformType::RemovePointer: {
Result = BuiltinRemovePointer(BaseType, Loc);
break;
}
case UnaryTransformType::Decay: {
Result = BuiltinDecay(BaseType, Loc);
break;
}
case UnaryTransformType::AddLvalueReference:
case UnaryTransformType::AddRvalueReference: {
Result = BuiltinAddReference(BaseType, UKind, Loc);
break;
}
llvm_unreachable("unknown unary transform type");
case UnaryTransformType::RemoveAllExtents:
case UnaryTransformType::RemoveExtent: {
Result = BuiltinRemoveExtent(BaseType, UKind, Loc);
break;
}
case UnaryTransformType::RemoveCVRef:
case UnaryTransformType::RemoveReference: {
Result = BuiltinRemoveReference(BaseType, UKind, Loc);
break;
}
case UnaryTransformType::RemoveConst:
case UnaryTransformType::RemoveCV:
case UnaryTransformType::RemoveRestrict:
case UnaryTransformType::RemoveVolatile: {
Result = BuiltinChangeCVRQualifiers(BaseType, UKind, Loc);
break;
}
case UnaryTransformType::MakeSigned:
case UnaryTransformType::MakeUnsigned: {
Result = BuiltinChangeSignedness(BaseType, UKind, Loc);
break;
}
default:
llvm_unreachable("unknown unary transform type");
}

return !Result.isNull()
? Context.getUnaryTransformType(BaseType, Result, UKind)
: Result;
}

QualType Sema::BuildAtomicType(QualType T, SourceLocation Loc) {
Expand Down
97 changes: 80 additions & 17 deletions clang/test/CodeGenCXX/mangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {};

Expand Down Expand Up @@ -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);
}
Expand All @@ -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
Expand Down Expand Up @@ -208,7 +208,7 @@ void extern_f(void) { }

struct S7 {
S7();

struct S { S(); };
struct {
S s;
Expand Down Expand Up @@ -276,7 +276,7 @@ struct Ops {
Ops& operator-(const Ops&);
Ops& operator&(const Ops&);
Ops& operator*(const Ops&);

void *v;
};

Expand Down Expand Up @@ -493,7 +493,7 @@ namespace test11 {
struct A {
void f(...);
};

// CHECK: @_ZN6test111A1fEz
void A::f(...) { }
}
Expand Down Expand Up @@ -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>))) {}
Expand Down Expand Up @@ -1107,11 +1107,74 @@ namespace test55 {
enum E { R };

template <typename T>
void fn(T, __underlying_type(T)) {}

template void fn<E>(E, __underlying_type(E));
// CHECK-LABEL: @_ZN6test552fnINS_1EEEEvT_U3eutS2_
}
void f1(T, __underlying_type(T)) {}
template void f1<E>(E, __underlying_type(E));
// CHECK-LABEL: @_ZN6test552f1INS_1EEEEvT_u17__underlying_typeIS2_E

template <typename T> void f2(T, __add_lvalue_reference(T)) {}
template void f2<int>(int, __add_lvalue_reference(int));
// CHECK-LABEL: @_ZN6test552f2IiEEvT_u22__add_lvalue_referenceIS1_E

template <typename T> void f3(T, __add_pointer(T)) {}
template void f3<int>(int, __add_pointer(int));
// CHECK-LABEL: @_ZN6test552f3IiEEvT_u13__add_pointerIS1_E

template <typename T> void f4(T, __add_rvalue_reference(T)) {}
template void f4<int>(int, __add_rvalue_reference(int));
// CHECK-LABEL: @_ZN6test552f4IiEEvT_u22__add_rvalue_referenceIS1_E

template <typename T> void f5(T, __decay(T)) {}
template void f5<int>(int, __decay(int));
// CHECK-LABEL: @_ZN6test552f5IiEEvT_u7__decayIS1_E

template <typename T> void f6(T, __make_signed(T)) {}
template void f6<int>(int, __make_signed(int));
// CHECK-LABEL: @_ZN6test552f6IiEEvT_u13__make_signedIS1_E

template <typename T> void f7(T, __make_unsigned(T)) {}
template void f7<int>(int, __make_unsigned(int));
// CHECK-LABEL: @_ZN6test552f7IiEEvT_u15__make_unsignedIS1_E

template <typename T> void f8(T, __remove_const(T)) {}
template void f8<int>(int, __remove_const(int));
// CHECK-LABEL: @_ZN6test552f8IiEEvT_u14__remove_constIS1_E

template <typename T> void f9(T, __remove_cv(T)) {}
template void f9<int>(int, __remove_cv(int));
// CHECK-LABEL: @_ZN6test552f9IiEEvT_u11__remove_cvIS1_E

template <typename T> void f10(T, __remove_cvref(T)) {}
template void f10<int>(int, __remove_cvref(int));
// CHECK-LABEL: @_ZN6test553f10IiEEvT_u14__remove_cvrefIS1_E

template <typename T> void f11(T, __remove_volatile(T)) {}
template void f11<int>(int, __remove_volatile(int));
// CHECK-LABEL: @_ZN6test553f11IiEEvT_u17__remove_volatileIS1_E

template <typename T> void f12(T, __remove_extent(T)) {}
template void f12<int>(int, __remove_extent(int));
// CHECK-LABEL: @_ZN6test553f12IiEEvT_u15__remove_extentIS1_E

template <typename T> void f13(T, __remove_all_extents(T)) {}
template void f13<int>(int, __remove_all_extents(int));
// CHECK-LABEL: @_ZN6test553f13IiEEvT_u20__remove_all_extentsIS1_E

template <typename T> void f14(T, __remove_pointer(T)) {}
template void f14<int>(int, __remove_pointer(int));
// CHECK-LABEL: @_ZN6test553f14IiEEvT_u16__remove_pointerIS1_E

template <typename T> void f15(T, __remove_reference(T)) {}
template void f15<int>(int, __remove_reference(int));
// CHECK-LABEL: @_ZN6test553f15IiEEvT_u18__remove_referenceIS1_E

template <typename T> void f16(T, __remove_volatile(T)) {}
template void f16<int>(int, __remove_volatile(int));
// CHECK-LABEL: @_ZN6test553f16IiEEvT_u17__remove_volatileIS1_E

template <typename T> void f17(T, __remove_restrict(T)) {}
template void f17<int>(int, __remove_restrict(int));
// CHECK-LABEL: @_ZN6test553f17IiEEvT_u17__remove_restrictIS1_E
} // namespace test55

namespace test56 {
struct A { A *operator->(); int n; } a;
Expand Down
84 changes: 84 additions & 0 deletions clang/test/SemaCXX/libstdcxx_transform_type_traits_hack.cpp
Original file line number Diff line number Diff line change
@@ -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>>;
8 changes: 8 additions & 0 deletions clang/test/SemaCXX/remove_pointer.mm
Original file line number Diff line number Diff line change
@@ -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), "");
700 changes: 697 additions & 3 deletions clang/test/SemaCXX/type-traits.cpp

Large diffs are not rendered by default.

20 changes: 10 additions & 10 deletions clang/utils/ClangVisualizers/clang.natvis
Original file line number Diff line number Diff line change
Expand Up @@ -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-->
Expand All @@ -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
Expand Down Expand Up @@ -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>
Expand Down Expand Up @@ -201,7 +201,7 @@ For later versions of Visual Studio, no setup is required-->
<DisplayString IncludeView="DefaultArg">{{InheritedInitializer}}</DisplayString>
<DisplayString IncludeView="Initializer" Condition="DefaultArgument.ValueOrInherited.Val.Value&amp;~3LL">= {this,view(DefaultArg)na}</DisplayString>
<DisplayString IncludeView="Initializer"></DisplayString>
<DisplayString>{*this,view(TorC)} {*this,view(MaybeEllipses)}{Name,view(cpp)} {this,view(Initializer)na}</DisplayString>
<DisplayString>{*this,view(TorC)} {*this,view(MaybeEllipses)}{Name,view(cpp)} {this,view(Initializer)na}</DisplayString>
</Type>
<Type Name="clang::TemplateDecl">
<DisplayString IncludeView="cpp">{*TemplatedDecl,view(cpp)}</DisplayString>
Expand Down Expand Up @@ -694,7 +694,7 @@ For later versions of Visual Studio, no setup is required-->
<DisplayString Condition="(Ptr &amp; PtrMask) == StoredCXXConstructorName">C++ Constructor {{{(clang::detail::CXXSpecialNameExtra *)(Ptr &amp; ~PtrMask),view(cpp)na}}}</DisplayString>
<DisplayString Condition="(Ptr &amp; PtrMask) == StoredCXXDestructorName">C++ Destructor {{*(clang::detail::CXXSpecialNameExtra *)(Ptr &amp; ~PtrMask)}}</DisplayString>
<DisplayString Condition="(Ptr &amp; PtrMask) == StoredCXXConversionFunctionName">C++ Conversion function {{*(clang::detail::CXXSpecialNameExtra *)(Ptr &amp; ~PtrMask)}}</DisplayString>
<DisplayString Condition="(Ptr &amp; PtrMask) == StoredCXXOperatorName">C++ Operator {{*(clang::detail::CXXOperatorIdName *)(Ptr &amp; ~PtrMask)}}</DisplayString>
<DisplayString Condition="(Ptr &amp; PtrMask) == StoredCXXOperatorName">C++ Operator {{*(clang::detail::CXXOperatorIdName *)(Ptr &amp; ~PtrMask)}}</DisplayString>
<DisplayString Condition="(Ptr &amp; PtrMask) == StoredDeclarationNameExtra"
IncludeView="cpp">{*(clang::detail::DeclarationNameExtra *)(Ptr &amp; ~PtrMask),view(cpp)}</DisplayString>
<DisplayString Condition="(Ptr &amp; PtrMask) == StoredDeclarationNameExtra">{{Extra ({*(clang::detail::DeclarationNameExtra *)(Ptr &amp; ~PtrMask)})}}</DisplayString>
Expand All @@ -706,7 +706,7 @@ For later versions of Visual Studio, no setup is required-->
<Item Condition="(Ptr &amp; PtrMask) == StoredCXXConstructorName" Name="[C++ Constructor]">*(clang::detail::CXXSpecialNameExtra *)(Ptr &amp; ~PtrMask),na</Item>
<Item Condition="(Ptr &amp; PtrMask) == StoredCXXDestructorName" Name="[C++ Destructor]">*(clang::detail::CXXSpecialNameExtra *)(Ptr &amp; ~PtrMask),na</Item>
<Item Condition="(Ptr &amp; PtrMask) == StoredCXXConversionFunctionName" Name="[C++ Conversion function]">*(clang::detail::CXXSpecialNameExtra *)(Ptr &amp; ~PtrMask),na</Item>
<Item Condition="(Ptr &amp; PtrMask) == StoredCXXOperatorName" Name="[C++ Operator]">*(clang::detail::CXXOperatorIdName *)(Ptr &amp; ~PtrMask),na</Item>
<Item Condition="(Ptr &amp; PtrMask) == StoredCXXOperatorName" Name="[C++ Operator]">*(clang::detail::CXXOperatorIdName *)(Ptr &amp; ~PtrMask),na</Item>
<Item Condition="(Ptr &amp; PtrMask) == StoredDeclarationNameExtra" Name="[Extra]">(clang::detail::DeclarationNameExtra *)(Ptr &amp; ~PtrMask),na</Item>
</Expand>
</Type>
Expand All @@ -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>
Expand Down Expand Up @@ -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">
Expand All @@ -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">
Expand Down
12 changes: 11 additions & 1 deletion libcxx/include/__type_traits/add_lvalue_reference.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,21 @@

_LIBCPP_BEGIN_NAMESPACE_STD

template <class _Tp, bool = __is_referenceable<_Tp>::value> struct __add_lvalue_reference_impl { typedef _LIBCPP_NODEBUG _Tp type; };
#if __has_builtin(__add_lvalue_reference)
template <class _Tp>
struct add_lvalue_reference {
using type _LIBCPP_NODEBUG = __add_lvalue_reference(_Tp);
};
#else
template <class _Tp, bool = __libcpp_is_referenceable<_Tp>::value>
struct __add_lvalue_reference_impl {
typedef _LIBCPP_NODEBUG _Tp type;
};
template <class _Tp > struct __add_lvalue_reference_impl<_Tp, true> { typedef _LIBCPP_NODEBUG _Tp& type; };

template <class _Tp> struct _LIBCPP_TEMPLATE_VIS add_lvalue_reference
{typedef _LIBCPP_NODEBUG typename __add_lvalue_reference_impl<_Tp>::type type;};
#endif // __has_builtin(__add_lvalue_reference)

#if _LIBCPP_STD_VER > 11
template <class _Tp> using add_lvalue_reference_t = typename add_lvalue_reference<_Tp>::type;
Expand Down
15 changes: 11 additions & 4 deletions libcxx/include/__type_traits/add_pointer.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,23 @@

_LIBCPP_BEGIN_NAMESPACE_STD

#if __has_builtin(__add_pointer)
template <class _Tp>
struct add_pointer {
using type _LIBCPP_NODEBUG = __add_pointer(_Tp);
};
#else
template <class _Tp,
bool = __is_referenceable<_Tp>::value ||
_IsSame<typename remove_cv<_Tp>::type, void>::value>
struct __add_pointer_impl
{typedef _LIBCPP_NODEBUG typename remove_reference<_Tp>::type* type;};
bool = __libcpp_is_referenceable<_Tp>::value || _IsSame<typename remove_cv<_Tp>::type, void>::value>
struct __add_pointer_impl {
typedef _LIBCPP_NODEBUG typename remove_reference<_Tp>::type* type;
};
template <class _Tp> struct __add_pointer_impl<_Tp, false>
{typedef _LIBCPP_NODEBUG _Tp type;};

template <class _Tp> struct _LIBCPP_TEMPLATE_VIS add_pointer
{typedef _LIBCPP_NODEBUG typename __add_pointer_impl<_Tp>::type type;};
#endif // __has_builtin(__add_pointer)

#if _LIBCPP_STD_VER > 11
template <class _Tp> using add_pointer_t = typename add_pointer<_Tp>::type;
Expand Down
12 changes: 11 additions & 1 deletion libcxx/include/__type_traits/add_rvalue_reference.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,21 @@

_LIBCPP_BEGIN_NAMESPACE_STD

template <class _Tp, bool = __is_referenceable<_Tp>::value> struct __add_rvalue_reference_impl { typedef _LIBCPP_NODEBUG _Tp type; };
#if __has_builtin(__add_rvalue_reference)
template <class _Tp>
struct add_rvalue_reference {
using type _LIBCPP_NODEBUG = __add_rvalue_reference(_Tp);
};
#else
template <class _Tp, bool = __libcpp_is_referenceable<_Tp>::value>
struct __add_rvalue_reference_impl {
typedef _LIBCPP_NODEBUG _Tp type;
};
template <class _Tp > struct __add_rvalue_reference_impl<_Tp, true> { typedef _LIBCPP_NODEBUG _Tp&& type; };

template <class _Tp> struct _LIBCPP_TEMPLATE_VIS add_rvalue_reference
{typedef _LIBCPP_NODEBUG typename __add_rvalue_reference_impl<_Tp>::type type;};
#endif // __has_builtin(__add_rvalue_reference)

#if _LIBCPP_STD_VER > 11
template <class _Tp> using add_rvalue_reference_t = typename add_rvalue_reference<_Tp>::type;
Expand Down
9 changes: 8 additions & 1 deletion libcxx/include/__type_traits/decay.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@

_LIBCPP_BEGIN_NAMESPACE_STD

#if __has_builtin(__decay)
template <class _Tp>
struct decay {
using type _LIBCPP_NODEBUG = __decay(_Tp);
};
#else
template <class _Up, bool>
struct __decay {
typedef _LIBCPP_NODEBUG typename remove_cv<_Up>::type type;
Expand Down Expand Up @@ -53,8 +59,9 @@ struct _LIBCPP_TEMPLATE_VIS decay
private:
typedef _LIBCPP_NODEBUG typename remove_reference<_Tp>::type _Up;
public:
typedef _LIBCPP_NODEBUG typename __decay<_Up, __is_referenceable<_Up>::value>::type type;
typedef _LIBCPP_NODEBUG typename __decay<_Up, __libcpp_is_referenceable<_Up>::value>::type type;
};
#endif // __has_builtin(__decay)

#if _LIBCPP_STD_VER > 11
template <class _Tp> using decay_t = typename decay<_Tp>::type;
Expand Down
18 changes: 13 additions & 5 deletions libcxx/include/__type_traits/is_referenceable.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,22 @@

_LIBCPP_BEGIN_NAMESPACE_STD

struct __is_referenceable_impl {
template <class _Tp> static _Tp& __test(int);
template <class _Tp> static false_type __test(...);
#if __has_builtin(__is_referenceable)
template <class _Tp>
struct __libcpp_is_referenceable : integral_constant<bool, __is_referenceable(_Tp)> {};
#else
struct __libcpp_is_referenceable_impl {
template <class _Tp>
static _Tp& __test(int);
template <class _Tp>
static false_type __test(...);
};

template <class _Tp>
struct __is_referenceable : integral_constant<bool,
_IsNotSame<decltype(__is_referenceable_impl::__test<_Tp>(0)), false_type>::value> {};
struct __libcpp_is_referenceable
: integral_constant<bool, _IsNotSame<decltype(__libcpp_is_referenceable_impl::__test<_Tp>(0)), false_type>::value> {
};
#endif // __has_builtin(__is_referenceable)

_LIBCPP_END_NAMESPACE_STD

Expand Down
4 changes: 2 additions & 2 deletions libcxx/include/__type_traits/is_swappable.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ struct _LIBCPP_TEMPLATE_VIS is_swappable_with
template <class _Tp>
struct _LIBCPP_TEMPLATE_VIS is_swappable
: public conditional<
__is_referenceable<_Tp>::value,
__libcpp_is_referenceable<_Tp>::value,
is_swappable_with<
typename add_lvalue_reference<_Tp>::type,
typename add_lvalue_reference<_Tp>::type>,
Expand All @@ -137,7 +137,7 @@ struct _LIBCPP_TEMPLATE_VIS is_nothrow_swappable_with
template <class _Tp>
struct _LIBCPP_TEMPLATE_VIS is_nothrow_swappable
: public conditional<
__is_referenceable<_Tp>::value,
__libcpp_is_referenceable<_Tp>::value,
is_nothrow_swappable_with<
typename add_lvalue_reference<_Tp>::type,
typename add_lvalue_reference<_Tp>::type>,
Expand Down
19 changes: 13 additions & 6 deletions libcxx/include/__type_traits/make_signed.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,25 @@

_LIBCPP_BEGIN_NAMESPACE_STD

#if __has_builtin(__make_signed)
template <class _Tp>
struct make_signed {
using type _LIBCPP_NODEBUG = __make_signed(_Tp);
};
#else
typedef
__type_list<signed char,
__type_list<signed short,
__type_list<signed int,
__type_list<signed long,
__type_list<signed long long,
#ifndef _LIBCPP_HAS_NO_INT128
# ifndef _LIBCPP_HAS_NO_INT128
__type_list<__int128_t,
#endif
# endif
__nat
#ifndef _LIBCPP_HAS_NO_INT128
# ifndef _LIBCPP_HAS_NO_INT128
>
#endif
# endif
> > > > > __signed_types;

template <class _Tp, bool = is_integral<_Tp>::value || is_enum<_Tp>::value>
Expand All @@ -56,16 +62,17 @@ template <> struct __make_signed< signed long, true> {typedef long ty
template <> struct __make_signed<unsigned long, true> {typedef long type;};
template <> struct __make_signed< signed long long, true> {typedef long long type;};
template <> struct __make_signed<unsigned long long, true> {typedef long long type;};
#ifndef _LIBCPP_HAS_NO_INT128
# ifndef _LIBCPP_HAS_NO_INT128
template <> struct __make_signed<__int128_t, true> {typedef __int128_t type;};
template <> struct __make_signed<__uint128_t, true> {typedef __int128_t type;};
#endif
# endif

template <class _Tp>
struct _LIBCPP_TEMPLATE_VIS make_signed
{
typedef typename __apply_cv<_Tp, typename __make_signed<typename remove_cv<_Tp>::type>::type>::type type;
};
#endif // __has_builtin(__make_signed)

#if _LIBCPP_STD_VER > 11
template <class _Tp> using make_signed_t = typename make_signed<_Tp>::type;
Expand Down
19 changes: 13 additions & 6 deletions libcxx/include/__type_traits/make_unsigned.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,25 @@

_LIBCPP_BEGIN_NAMESPACE_STD

#if __has_builtin(__make_unsigned)
template <class _Tp>
struct make_unsigned {
using type _LIBCPP_NODEBUG = __make_unsigned(_Tp);
};
#else
typedef
__type_list<unsigned char,
__type_list<unsigned short,
__type_list<unsigned int,
__type_list<unsigned long,
__type_list<unsigned long long,
#ifndef _LIBCPP_HAS_NO_INT128
# ifndef _LIBCPP_HAS_NO_INT128
__type_list<__uint128_t,
#endif
# endif
__nat
#ifndef _LIBCPP_HAS_NO_INT128
# ifndef _LIBCPP_HAS_NO_INT128
>
#endif
# endif
> > > > > __unsigned_types;

template <class _Tp, bool = is_integral<_Tp>::value || is_enum<_Tp>::value>
Expand All @@ -58,16 +64,17 @@ template <> struct __make_unsigned< signed long, true> {typedef unsigned l
template <> struct __make_unsigned<unsigned long, true> {typedef unsigned long type;};
template <> struct __make_unsigned< signed long long, true> {typedef unsigned long long type;};
template <> struct __make_unsigned<unsigned long long, true> {typedef unsigned long long type;};
#ifndef _LIBCPP_HAS_NO_INT128
# ifndef _LIBCPP_HAS_NO_INT128
template <> struct __make_unsigned<__int128_t, true> {typedef __uint128_t type;};
template <> struct __make_unsigned<__uint128_t, true> {typedef __uint128_t type;};
#endif
# endif

template <class _Tp>
struct _LIBCPP_TEMPLATE_VIS make_unsigned
{
typedef typename __apply_cv<_Tp, typename __make_unsigned<typename remove_cv<_Tp>::type>::type>::type type;
};
#endif // __has_builtin(__make_unsigned)

#if _LIBCPP_STD_VER > 11
template <class _Tp> using make_unsigned_t = typename make_unsigned<_Tp>::type;
Expand Down
7 changes: 7 additions & 0 deletions libcxx/include/__type_traits/remove_all_extents.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,19 @@

_LIBCPP_BEGIN_NAMESPACE_STD

#if __has_builtin(__remove_all_extents)
template <class _Tp>
struct remove_all_extents {
using type _LIBCPP_NODEBUG = __remove_all_extents(_Tp);
};
#else
template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_all_extents
{typedef _Tp type;};
template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_all_extents<_Tp[]>
{typedef typename remove_all_extents<_Tp>::type type;};
template <class _Tp, size_t _Np> struct _LIBCPP_TEMPLATE_VIS remove_all_extents<_Tp[_Np]>
{typedef typename remove_all_extents<_Tp>::type type;};
#endif // __has_builtin(__remove_all_extents)

#if _LIBCPP_STD_VER > 11
template <class _Tp> using remove_all_extents_t = typename remove_all_extents<_Tp>::type;
Expand Down
8 changes: 8 additions & 0 deletions libcxx/include/__type_traits/remove_const.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,16 @@

_LIBCPP_BEGIN_NAMESPACE_STD

#if __has_builtin(__remove_const)
template <class _Tp>
struct remove_const {
using type _LIBCPP_NODEBUG = __remove_const(_Tp);
};
#else
template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_const {typedef _Tp type;};
template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_const<const _Tp> {typedef _Tp type;};
#endif // __has_builtin(__remove_const)

#if _LIBCPP_STD_VER > 11
template <class _Tp> using remove_const_t = typename remove_const<_Tp>::type;
#endif
Expand Down
8 changes: 8 additions & 0 deletions libcxx/include/__type_traits/remove_cv.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,16 @@

_LIBCPP_BEGIN_NAMESPACE_STD

#if __has_builtin(__remove_cv)
template <class _Tp>
struct remove_cv {
using type _LIBCPP_NODEBUG = __remove_cv(_Tp);
};
#else
template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_cv
{typedef typename remove_volatile<typename remove_const<_Tp>::type>::type type;};
#endif // __has_builtin(__remove_cv)

#if _LIBCPP_STD_VER > 11
template <class _Tp> using remove_cv_t = typename remove_cv<_Tp>::type;
#endif
Expand Down
5 changes: 5 additions & 0 deletions libcxx/include/__type_traits/remove_cvref.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,13 @@

_LIBCPP_BEGIN_NAMESPACE_STD

#if __has_builtin(__remove_cvref)
template <class _Tp>
using __uncvref_t _LIBCPP_NODEBUG = __remove_cvref(_Tp);
#else
template <class _Tp>
using __uncvref_t _LIBCPP_NODEBUG = typename remove_cv<typename remove_reference<_Tp>::type>::type;
#endif // __has_builtin(__remove_cvref)

template <class _Tp, class _Up>
struct __is_same_uncvref : _IsSame<__uncvref_t<_Tp>, __uncvref_t<_Up> > {};
Expand Down
7 changes: 7 additions & 0 deletions libcxx/include/__type_traits/remove_extent.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,19 @@

_LIBCPP_BEGIN_NAMESPACE_STD

#if __has_builtin(__remove_extent)
template <class _Tp>
struct remove_extent {
using type _LIBCPP_NODEBUG = __remove_extent(_Tp);
};
#else
template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_extent
{typedef _Tp type;};
template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_extent<_Tp[]>
{typedef _Tp type;};
template <class _Tp, size_t _Np> struct _LIBCPP_TEMPLATE_VIS remove_extent<_Tp[_Np]>
{typedef _Tp type;};
#endif // __has_builtin(__remove_extent)

#if _LIBCPP_STD_VER > 11
template <class _Tp> using remove_extent_t = typename remove_extent<_Tp>::type;
Expand Down
7 changes: 7 additions & 0 deletions libcxx/include/__type_traits/remove_pointer.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,18 @@

_LIBCPP_BEGIN_NAMESPACE_STD

#if __has_builtin(__remove_pointer)
template <class _Tp>
struct remove_pointer {
using type _LIBCPP_NODEBUG = __remove_pointer(_Tp);
};
#else
template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_pointer {typedef _LIBCPP_NODEBUG _Tp type;};
template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_pointer<_Tp*> {typedef _LIBCPP_NODEBUG _Tp type;};
template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_pointer<_Tp* const> {typedef _LIBCPP_NODEBUG _Tp type;};
template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_pointer<_Tp* volatile> {typedef _LIBCPP_NODEBUG _Tp type;};
template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_pointer<_Tp* const volatile> {typedef _LIBCPP_NODEBUG _Tp type;};
#endif // __has_builtin(__remove_pointer)

#if _LIBCPP_STD_VER > 11
template <class _Tp> using remove_pointer_t = typename remove_pointer<_Tp>::type;
Expand Down
7 changes: 7 additions & 0 deletions libcxx/include/__type_traits/remove_reference.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,16 @@

_LIBCPP_BEGIN_NAMESPACE_STD

#if __has_builtin(__remove_reference)
template <class _Tp>
struct remove_reference {
using type _LIBCPP_NODEBUG = __remove_reference(_Tp);
};
#else
template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_reference {typedef _LIBCPP_NODEBUG _Tp type;};
template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_reference<_Tp&> {typedef _LIBCPP_NODEBUG _Tp type;};
template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_reference<_Tp&&> {typedef _LIBCPP_NODEBUG _Tp type;};
#endif // __has_builtin(__remove_reference)

#if _LIBCPP_STD_VER > 11
template <class _Tp> using remove_reference_t = typename remove_reference<_Tp>::type;
Expand Down
8 changes: 8 additions & 0 deletions libcxx/include/__type_traits/remove_volatile.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,16 @@

_LIBCPP_BEGIN_NAMESPACE_STD

#if __has_builtin(__remove_volatile)
template <class _Tp>
struct remove_volatile {
using type _LIBCPP_NODEBUG = __remove_volatile(_Tp);
};
#else
template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_volatile {typedef _Tp type;};
template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_volatile<volatile _Tp> {typedef _Tp type;};
#endif // __has_builtin(__remove_volatile)

#if _LIBCPP_STD_VER > 11
template <class _Tp> using remove_volatile_t = typename remove_volatile<_Tp>::type;
#endif
Expand Down
230 changes: 115 additions & 115 deletions libcxx/test/libcxx/utilities/meta/is_referenceable.pass.cpp

Large diffs are not rendered by default.