zoecarver updated this revision to Diff 243834.
zoecarver added a comment.
- Combine D67052 <https://reviews.llvm.org/D67052> and D67588
<https://reviews.llvm.org/D67588>.
- Remove `__add*` type traits.
- Update mangling/dumping/encoding of all traits.
- Remove stress tests.
- Address comments in D67588 <https://reviews.llvm.org/D67588>.
I'll work on some failing tests and add those when they're ready.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D67052/new/
https://reviews.llvm.org/D67052
Files:
clang/include/clang/AST/Type.h
clang/include/clang/Basic/Specifiers.h
clang/include/clang/Basic/TokenKinds.def
clang/include/clang/Parse/Parser.h
clang/include/clang/Sema/DeclSpec.h
clang/lib/AST/ItaniumMangle.cpp
clang/lib/AST/JSONNodeDumper.cpp
clang/lib/AST/TextNodeDumper.cpp
clang/lib/AST/TypePrinter.cpp
clang/lib/Format/FormatToken.cpp
clang/lib/Lex/PPMacroExpansion.cpp
clang/lib/Parse/ParseDecl.cpp
clang/lib/Parse/ParseDeclCXX.cpp
clang/lib/Sema/DeclSpec.cpp
clang/lib/Sema/SemaDecl.cpp
clang/lib/Sema/SemaTemplateVariadic.cpp
clang/lib/Sema/SemaType.cpp
clang/test/SemaCXX/remove_cv.cpp
clang/test/SemaCXX/remove_reference.cpp
Index: clang/test/SemaCXX/remove_reference.cpp
===================================================================
--- /dev/null
+++ clang/test/SemaCXX/remove_reference.cpp
@@ -0,0 +1,41 @@
+// RUN: %clang_cc1 -std=c++11 %s
+
+template<class T>
+struct test_remove_ref_trait
+{
+ typedef __remove_reference(T) type;
+};
+
+template<class T>
+struct test_remove_ref
+{
+ static const bool value = __is_same(typename test_remove_ref_trait<T>::type, T) &&
+ __is_same(typename test_remove_ref_trait<T&>::type, T) &&
+ __is_same(typename test_remove_ref_trait<T&&>::type, T);
+};
+
+template<class T>
+struct test
+{
+ static const bool value = test_remove_ref<T>::value &&
+ test_rval<T>::value &&
+ test_lval<T>::value;
+};
+
+struct Foo { };
+
+template<class T>
+struct Bar { };
+
+template<class T>
+class Baz { };
+
+static_assert(test<int>::value, "");
+static_assert(test<int[]>::value, "");
+static_assert(test<int[8]>::value, "");
+static_assert(test<Foo>::value, "");
+static_assert(test<Bar<int>>::value, "");
+static_assert(test<Baz<int>>::value, "");
+static_assert(test<int*>::value, "");
+static_assert(test<int const>::value, "");
+static_assert(test<int(int)>::value, "");
Index: clang/test/SemaCXX/remove_cv.cpp
===================================================================
--- /dev/null
+++ clang/test/SemaCXX/remove_cv.cpp
@@ -0,0 +1,52 @@
+// RUN: %clang_cc1 -std=c++11 %s
+
+template<class T>
+struct remove_const
+{
+ typedef __remove_const(T) type;
+};
+
+template<class T>
+struct remove_volatile
+{
+ typedef __remove_volatile(T) type;
+};
+
+template<class T>
+struct remove_cv
+{
+ typedef __remove_cv(T) type;
+};
+
+template<class T>
+struct test
+{
+ static const bool value =
+ __is_same(typename remove_const<T>::type, T) &&
+ __is_same(typename remove_const<const volatile T>::type, volatile T) &&
+ __is_same(typename remove_const<const T>::type, T) &&
+
+ __is_same(typename remove_volatile<T>::type, T) &&
+ __is_same(typename remove_volatile<const volatile T>::type, const T) &&
+ __is_same(typename remove_volatile<volatile T>::type, T) &&
+
+ __is_same(typename remove_cv<const volatile T>::type, T) &&
+ __is_same(typename remove_cv<T>::type, T) &&
+ __is_same(typename remove_cv<const T>::type, T) &&
+ __is_same(typename remove_cv<volatile T>::type, T);
+};
+
+struct Foo { };
+
+template<class T>
+struct Bar { };
+
+template<class T>
+class Baz { };
+
+static_assert(test<int>::value, "");
+static_assert(test<int[]>::value, "");
+static_assert(test<int[8]>::value, "");
+static_assert(test<Foo>::value, "");
+static_assert(test<Bar<int>>::value, "");
+static_assert(test<Baz<int>>::value, "");
Index: clang/lib/Sema/SemaType.cpp
===================================================================
--- clang/lib/Sema/SemaType.cpp
+++ clang/lib/Sema/SemaType.cpp
@@ -1252,6 +1252,24 @@
return OpenCLAccessAttr::Keyword_read_only;
}
+static UnaryTransformType::UTTKind
+TSTToUnaryTransformType(DeclSpec::TST SwitchTST) {
+ switch (SwitchTST) {
+ case TST_removeCV:
+ return UnaryTransformType::RemoveCV;
+ case TST_removeConst:
+ return UnaryTransformType::RemoveConst;
+ case TST_removeVolatile:
+ return UnaryTransformType::RemoveVolatile;
+ case TST_removeReferenceType:
+ return UnaryTransformType::RemoveReferenceType;
+ case TST_underlyingType:
+ return UnaryTransformType::EnumUnderlyingType;
+ default:
+ llvm_unreachable("Cannot map TST to unary transform type");
+ }
+}
+
static QualType ConvertConstrainedAutoDeclSpecToType(Sema &S, DeclSpec &DS,
AutoTypeKeyword AutoKW) {
assert(DS.isConstrainedAuto());
@@ -1603,6 +1621,21 @@
}
break;
}
+ case DeclSpec::TST_removeReferenceType:
+ case DeclSpec::TST_removeCV:
+ case DeclSpec::TST_removeConst:
+ case DeclSpec::TST_removeVolatile: {
+ Result = S.GetTypeFromParser(DS.getRepAsType());
+ assert(!Result.isNull() &&
+ "Reference manipulation type transform may not have received a type.");
+ Result = S.BuildUnaryTransformType(Result,
+ TSTToUnaryTransformType(DS.getTypeSpecType()),
+ DS.getTypeSpecTypeLoc());
+ if (Result.isNull()) {
+ declarator.setInvalidType(true);
+ }
+ break;
+ }
case DeclSpec::TST_underlyingType:
Result = S.GetTypeFromParser(DS.getRepAsType());
assert(!Result.isNull() && "Didn't get a type for __underlying_type?");
@@ -5643,8 +5676,9 @@
TL.setUnderlyingTInfo(TInfo);
}
void VisitUnaryTransformTypeLoc(UnaryTransformTypeLoc TL) {
- // FIXME: This holds only because we only have one unary transform.
- assert(DS.getTypeSpecType() == DeclSpec::TST_underlyingType);
+ // Make sure it is a unary transform type
+ assert(DS.getTypeSpecType() >= DeclSpec::TST_underlyingType &&
+ DS.getTypeSpecType() <= TST_removeReferenceType);
TL.setKWLoc(DS.getTypeSpecTypeLoc());
TL.setParensRange(DS.getTypeofParensRange());
assert(DS.getRepAsType());
@@ -8534,6 +8568,36 @@
return Context.getUnaryTransformType(BaseType, Underlying,
UnaryTransformType::EnumUnderlyingType);
}
+ case UnaryTransformType::RemoveReferenceType: {
+ QualType Underlying = BaseType.getNonReferenceType();
+ return Context.getUnaryTransformType(BaseType, Underlying,
+ UnaryTransformType::RemoveReferenceType);
+ }
+ case UnaryTransformType::RemoveCV: {
+ SplitQualType Split = BaseType.getSplitUnqualifiedType();
+ Qualifiers Quals = BaseType.getQualifiers();
+ Quals.removeConst();
+ Quals.removeVolatile();
+ QualType Underlying(Split.Ty, Quals.getAsOpaqueValue());
+ return Context.getUnaryTransformType(BaseType, Underlying,
+ UnaryTransformType::RemoveCV);
+ }
+ case UnaryTransformType::RemoveConst: {
+ SplitQualType Split = BaseType.getSplitUnqualifiedType();
+ Qualifiers Quals = BaseType.getQualifiers();
+ Quals.removeConst();
+ QualType Underlying(Split.Ty, Quals.getAsOpaqueValue());
+ return Context.getUnaryTransformType(BaseType, Underlying,
+ UnaryTransformType::RemoveConst);
+ }
+ case UnaryTransformType::RemoveVolatile: {
+ SplitQualType Split = BaseType.getSplitUnqualifiedType();
+ Qualifiers Quals = BaseType.getQualifiers();
+ Quals.removeVolatile();
+ QualType Underlying(Split.Ty, Quals.getAsOpaqueValue());
+ return Context.getUnaryTransformType(BaseType, Underlying,
+ UnaryTransformType::RemoveVolatile);
+ }
}
llvm_unreachable("unknown unary transform type");
}
Index: clang/lib/Sema/SemaTemplateVariadic.cpp
===================================================================
--- clang/lib/Sema/SemaTemplateVariadic.cpp
+++ clang/lib/Sema/SemaTemplateVariadic.cpp
@@ -838,6 +838,10 @@
case TST_typename:
case TST_typeofType:
case TST_underlyingType:
+ case TST_removeReferenceType:
+ case TST_removeCV:
+ case TST_removeConst:
+ case TST_removeVolatile:
case TST_atomic: {
QualType T = DS.getRepAsType().get();
if (!T.isNull() && T->containsUnexpandedParameterPack())
Index: clang/lib/Sema/SemaDecl.cpp
===================================================================
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -141,6 +141,10 @@
case tok::kw_wchar_t:
case tok::kw_bool:
case tok::kw___underlying_type:
+ case tok::kw___remove_reference:
+ case tok::kw___remove_cv:
+ case tok::kw___remove_const:
+ case tok::kw___remove_volatile:
case tok::kw___auto_type:
return true;
@@ -5451,6 +5455,10 @@
case DeclSpec::TST_typename:
case DeclSpec::TST_typeofType:
case DeclSpec::TST_underlyingType:
+ case DeclSpec::TST_removeReferenceType:
+ case DeclSpec::TST_removeCV:
+ case DeclSpec::TST_removeConst:
+ case DeclSpec::TST_removeVolatile:
case DeclSpec::TST_atomic: {
// Grab the type from the parser.
TypeSourceInfo *TSI = nullptr;
Index: clang/lib/Sema/DeclSpec.cpp
===================================================================
--- clang/lib/Sema/DeclSpec.cpp
+++ clang/lib/Sema/DeclSpec.cpp
@@ -376,6 +376,10 @@
return false;
case TST_underlyingType:
+ case TST_removeReferenceType:
+ case TST_removeCV:
+ case TST_removeConst:
+ case TST_removeVolatile:
case TST_typename:
case TST_typeofType: {
QualType QT = DS.getRepAsType().get();
@@ -555,6 +559,10 @@
case DeclSpec::TST_decltype: return "(decltype)";
case DeclSpec::TST_decltype_auto: return "decltype(auto)";
case DeclSpec::TST_underlyingType: return "__underlying_type";
+ case DeclSpec::TST_removeReferenceType: return "__remove_reference";
+ case DeclSpec::TST_removeCV: return "__remove_cv";
+ case DeclSpec::TST_removeConst: return "__remove_const";
+ case DeclSpec::TST_removeVolatile: return "__remove_volatile";
case DeclSpec::TST_unknown_anytype: return "__unknown_anytype";
case DeclSpec::TST_atomic: return "_Atomic";
#define GENERIC_IMAGE_TYPE(ImgType, Id) \
Index: clang/lib/Parse/ParseDeclCXX.cpp
===================================================================
--- clang/lib/Parse/ParseDeclCXX.cpp
+++ clang/lib/Parse/ParseDeclCXX.cpp
@@ -1086,6 +1086,51 @@
DS.setTypeofParensRange(T.getRange());
}
+DeclSpec::TST Parser::TypeTransformTokToDeclSpec() {
+ switch (Tok.getKind()) {
+ case tok::kw___remove_reference:
+ return DeclSpec::TST_removeReferenceType;
+ case tok::kw___remove_cv:
+ return DeclSpec::TST_removeCV;
+ case tok::kw___remove_const:
+ return DeclSpec::TST_removeConst;
+ case tok::kw___remove_volatile:
+ return DeclSpec::TST_removeVolatile;
+ default:
+ assert(false && "Not a reference type specifier");
+ }
+}
+
+void Parser::ParseTypeTransformTypeSpecifier(DeclSpec &DS) {
+ DeclSpec::TST TypeTransformTST = TypeTransformTokToDeclSpec();
+
+ SourceLocation StartLoc = ConsumeToken();
+ BalancedDelimiterTracker T(*this, tok::l_paren);
+ if (T.expectAndConsume(diag::err_expected_lparen_after,
+ "reference manipulation builtin",
+ tok::r_paren)) return;
+
+ TypeResult BaseTyResult = ParseTypeName();
+ if (BaseTyResult.isInvalid()) {
+ SkipUntil(tok::r_paren, StopAtSemi);
+ return;
+ }
+
+ T.consumeClose();
+ if (T.getCloseLocation().isInvalid()) return;
+
+ const char *PrevSpec;
+ unsigned DiagID;
+ if (DS.SetTypeSpecType(TypeTransformTST,
+ StartLoc, PrevSpec,
+ DiagID, BaseTyResult.get(),
+ Actions.getASTContext().getPrintingPolicy())) {
+ Diag(StartLoc, DiagID) << PrevSpec;
+ }
+ DS.setTypeofParensRange(T.getRange());
+}
+
+
/// ParseBaseTypeSpecifier - Parse a C++ base-type-specifier which is either a
/// class name or decltype-specifier. Note that we only check that the result
/// names a type; semantic analysis will need to verify that the type names a
Index: clang/lib/Parse/ParseDecl.cpp
===================================================================
--- clang/lib/Parse/ParseDecl.cpp
+++ clang/lib/Parse/ParseDecl.cpp
@@ -4001,6 +4001,13 @@
case tok::kw___underlying_type:
ParseUnderlyingTypeSpecifier(DS);
continue;
+
+ case tok::kw___remove_reference:
+ case tok::kw___remove_cv:
+ case tok::kw___remove_const:
+ case tok::kw___remove_volatile:
+ ParseTypeTransformTypeSpecifier(DS);
+ continue;
case tok::kw__Atomic:
// C11 6.7.2.4/4:
Index: clang/lib/Lex/PPMacroExpansion.cpp
===================================================================
--- clang/lib/Lex/PPMacroExpansion.cpp
+++ clang/lib/Lex/PPMacroExpansion.cpp
@@ -1662,6 +1662,10 @@
.Case("__array_extent", true)
.Case("__reference_binds_to_temporary", true)
.Case("__underlying_type", true)
+ .Case("__remove_reference", true)
+ .Case("__remove_cv", true)
+ .Case("__remove_const", true)
+ .Case("__remove_volatile", true)
.Default(false);
} else {
return llvm::StringSwitch<bool>(II->getName())
Index: clang/lib/Format/FormatToken.cpp
===================================================================
--- clang/lib/Format/FormatToken.cpp
+++ clang/lib/Format/FormatToken.cpp
@@ -55,6 +55,10 @@
case tok::kw_wchar_t:
case tok::kw_bool:
case tok::kw___underlying_type:
+ case tok::kw___remove_reference:
+ case tok::kw___remove_cv:
+ case tok::kw___remove_const:
+ case tok::kw___remove_volatile:
case tok::annot_typename:
case tok::kw_char8_t:
case tok::kw_char16_t:
Index: clang/lib/AST/TypePrinter.cpp
===================================================================
--- clang/lib/AST/TypePrinter.cpp
+++ clang/lib/AST/TypePrinter.cpp
@@ -1024,6 +1024,30 @@
OS << ')';
spaceBeforePlaceHolder(OS);
return;
+ case UnaryTransformType::RemoveReferenceType:
+ OS << "__remove_reference";
+ print(T->getBaseType(), OS, StringRef());
+ OS << ')';
+ spaceBeforePlaceHolder(OS);
+ return;
+ case UnaryTransformType::RemoveCV:
+ OS << "__remove_cv";
+ print(T->getBaseType(), OS, StringRef());
+ OS << ')';
+ spaceBeforePlaceHolder(OS);
+ return;
+ case UnaryTransformType::RemoveConst:
+ OS << "__remove_const";
+ print(T->getBaseType(), OS, StringRef());
+ OS << ')';
+ spaceBeforePlaceHolder(OS);
+ return;
+ case UnaryTransformType::RemoveVolatile:
+ OS << "__remove_volatile";
+ print(T->getBaseType(), OS, StringRef());
+ OS << ')';
+ spaceBeforePlaceHolder(OS);
+ return;
}
printBefore(T->getBaseType(), OS);
@@ -1035,6 +1059,9 @@
switch (T->getUTTKind()) {
case UnaryTransformType::EnumUnderlyingType:
+ case UnaryTransformType::RemoveCV:
+ case UnaryTransformType::RemoveConst:
+ case UnaryTransformType::RemoveVolatile:
return;
}
Index: clang/lib/AST/TextNodeDumper.cpp
===================================================================
--- clang/lib/AST/TextNodeDumper.cpp
+++ clang/lib/AST/TextNodeDumper.cpp
@@ -1182,6 +1182,18 @@
case UnaryTransformType::EnumUnderlyingType:
OS << " underlying_type";
break;
+ case UnaryTransformType::RemoveReferenceType:
+ OS << " remove_reference";
+ break;
+ case UnaryTransformType::RemoveCV:
+ OS << " remove_cv";
+ break;
+ case UnaryTransformType::RemoveConst:
+ OS << " remove_const";
+ break;
+ case UnaryTransformType::RemoveVolatile:
+ OS << " remove_volatile";
+ break;
}
}
Index: clang/lib/AST/JSONNodeDumper.cpp
===================================================================
--- clang/lib/AST/JSONNodeDumper.cpp
+++ clang/lib/AST/JSONNodeDumper.cpp
@@ -620,6 +620,18 @@
case UnaryTransformType::EnumUnderlyingType:
JOS.attribute("transformKind", "underlying_type");
break;
+ case UnaryTransformType::RemoveReferenceType:
+ JOS.attribute("transformKind", "remove_reference");
+ break;
+ case UnaryTransformType::RemoveCV:
+ JOS.attribute("transformKind", "remove_cv");
+ break;
+ case UnaryTransformType::RemoveConst:
+ JOS.attribute("transformKind", "remove_const");
+ break;
+ case UnaryTransformType::RemoveVolatile:
+ JOS.attribute("transformKind", "remove_volatile");
+ break;
}
}
Index: clang/lib/AST/ItaniumMangle.cpp
===================================================================
--- clang/lib/AST/ItaniumMangle.cpp
+++ clang/lib/AST/ItaniumMangle.cpp
@@ -3420,6 +3420,20 @@
case UnaryTransformType::EnumUnderlyingType:
Out << "3eut";
break;
+ case UnaryTransformType::RemoveReferenceType:
+ Out << "3rrt";
+ break;
+ case UnaryTransformType::RemoveCV:
+ Out << "3rcvt";
+ break;
+ break;
+ case UnaryTransformType::RemoveConst:
+ Out << "3rct";
+ break;
+ break;
+ case UnaryTransformType::RemoveVolatile:
+ Out << "3rvt";
+ break;
}
}
Index: clang/include/clang/Sema/DeclSpec.h
===================================================================
--- clang/include/clang/Sema/DeclSpec.h
+++ clang/include/clang/Sema/DeclSpec.h
@@ -294,16 +294,20 @@
static const TST TST_struct = clang::TST_struct;
static const TST TST_interface = clang::TST_interface;
static const TST TST_class = clang::TST_class;
- static const TST TST_typename = clang::TST_typename;
- static const TST TST_typeofType = clang::TST_typeofType;
- 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_typeofExpr = clang::TST_typeofExpr;
+ static const TST TST_typename = clang::TST_typename;
+ static const TST TST_typeofType = clang::TST_typeofType;
static const TST TST_underlyingType = clang::TST_underlyingType;
+ static const TST TST_removeReferenceType = clang::TST_removeReferenceType;
+ static const TST TST_removeCV = clang::TST_removeCV;
+ static const TST TST_removeConst = clang::TST_removeConst;
+ static const TST TST_removeVolatile = clang::TST_removeVolatile;
+ static const TST TST_atomic = clang::TST_atomic;
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;
- static const TST TST_atomic = clang::TST_atomic;
#define GENERIC_IMAGE_TYPE(ImgType, Id) \
static const TST TST_##ImgType##_t = clang::TST_##ImgType##_t;
#include "clang/Basic/OpenCLImageTypes.def"
@@ -409,8 +413,7 @@
ObjCDeclSpec *ObjCQualifiers;
static bool isTypeRep(TST T) {
- return (T == TST_typename || T == TST_typeofType ||
- T == TST_underlyingType || T == TST_atomic);
+ return (TST_typename <= T <= TST_atomic);
}
static bool isExprRep(TST T) {
return (T == TST_typeofExpr || T == TST_decltype);
Index: clang/include/clang/Parse/Parser.h
===================================================================
--- clang/include/clang/Parse/Parser.h
+++ clang/include/clang/Parse/Parser.h
@@ -2684,6 +2684,8 @@
SourceLocation StartLoc,
SourceLocation EndLoc);
void ParseUnderlyingTypeSpecifier(DeclSpec &DS);
+ DeclSpec::TST TypeTransformTokToDeclSpec();
+ void ParseTypeTransformTypeSpecifier(DeclSpec &DS);
void ParseAtomicSpecifier(DeclSpec &DS);
ExprResult ParseAlignArgument(SourceLocation Start,
Index: clang/include/clang/Basic/TokenKinds.def
===================================================================
--- clang/include/clang/Basic/TokenKinds.def
+++ clang/include/clang/Basic/TokenKinds.def
@@ -487,6 +487,10 @@
TYPE_TRAIT_1(__has_unique_object_representations,
HasUniqueObjectRepresentations, KEYCXX)
KEYWORD(__underlying_type , KEYCXX)
+KEYWORD(__remove_reference , KEYCXX)
+KEYWORD(__remove_cv , KEYCXX)
+KEYWORD(__remove_const , KEYCXX)
+KEYWORD(__remove_volatile , KEYCXX)
// Clang-only C++ Type Traits
TYPE_TRAIT_2(__reference_binds_to_temporary, ReferenceBindsToTemporary, KEYCXX)
Index: clang/include/clang/Basic/Specifiers.h
===================================================================
--- clang/include/clang/Basic/Specifiers.h
+++ clang/include/clang/Basic/Specifiers.h
@@ -88,6 +88,10 @@
TST_typeofExpr,
TST_decltype, // C++11 decltype
TST_underlyingType, // __underlying_type for C++11
+ TST_removeReferenceType, // __remove_reference
+ TST_removeCV, // __remove_cv
+ TST_removeConst, // __remove_const
+ TST_removeVolatile, // __remove_volatile
TST_auto, // C++11 auto
TST_decltype_auto, // C++1y decltype(auto)
TST_auto_type, // __auto_type extension
Index: clang/include/clang/AST/Type.h
===================================================================
--- clang/include/clang/AST/Type.h
+++ clang/include/clang/AST/Type.h
@@ -4413,7 +4413,11 @@
class UnaryTransformType : public Type {
public:
enum UTTKind {
- EnumUnderlyingType
+ EnumUnderlyingType,
+ RemoveReferenceType,
+ RemoveCV,
+ RemoveConst,
+ RemoveVolatile,
};
private:
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits