zoecarver updated this revision to Diff 221014. zoecarver added a comment. Herald added a subscriber: erik.pilkington.
- address review comments - fix warnings in build 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/add_reference.cpp libcxx/test/libcxx/utilities/meta/stress_tests/stress_test_add_lvalue_reference.sh.cpp libcxx/test/libcxx/utilities/meta/stress_tests/stress_test_add_rvalue_reference.sh.cpp libcxx/test/libcxx/utilities/meta/stress_tests/stress_test_remove_reference.sh.cpp
Index: libcxx/test/libcxx/utilities/meta/stress_tests/stress_test_remove_reference.sh.cpp =================================================================== --- /dev/null +++ libcxx/test/libcxx/utilities/meta/stress_tests/stress_test_remove_reference.sh.cpp @@ -0,0 +1,63 @@ +//===----------------------------------------------------------------------===// +// +// 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 is a dummy feature that prevents this test from running by default. + +// The table below compares the compile time and object size for each of the +// variants listed in the RUN script. +// +// Impl Compile Time Object Size +// ---------------------------------------------------------- +// new_remove_reference: 22.849 s 121 K +// std::remove_reference: 25.643 s 121 K +// +// RUN: %cxx %flags %compile_flags -c %s -o %S/orig.o -ggdb -ggnu-pubnames -ftemplate-depth=5000 -ftime-trace -std=c++17 +// RUN: %cxx %flags %compile_flags -c %s -o %S/new.o -ggdb -ggnu-pubnames -ftemplate-depth=5000 -ftime-trace -std=c++17 -DTEST_NEW + +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "template_cost_testing.h" + +template <int N> struct Arg { enum { value = 1 }; }; + +#ifdef TEST_NEW + +template <class T> +struct new_remove_reference +{ + typedef __remove_reference(T) type; +}; + +#define TEST_CASE_NOP() new_remove_reference< Arg< __COUNTER__ > >{}, +#define TEST_CASE_TYPE() typename new_remove_reference< Arg< __COUNTER__ > >::type, + +#else + +#define TEST_CASE_NOP() std::remove_reference< Arg< __COUNTER__ > >{}, +#define TEST_CASE_TYPE() typename std::remove_reference< Arg< __COUNTER__ > >::type, + +#endif + +int sink(...); + +int x = sink( + REPEAT_10000(TEST_CASE_NOP) + REPEAT_10000(TEST_CASE_NOP) 42 +); + +void Foo( REPEAT_10000(TEST_CASE_TYPE) int) { } + +void escape() { + +sink(&x); +sink(&Foo); +} + + Index: libcxx/test/libcxx/utilities/meta/stress_tests/stress_test_add_rvalue_reference.sh.cpp =================================================================== --- /dev/null +++ libcxx/test/libcxx/utilities/meta/stress_tests/stress_test_add_rvalue_reference.sh.cpp @@ -0,0 +1,63 @@ +//===----------------------------------------------------------------------===// +// +// 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 is a dummy feature that prevents this test from running by default. + +// The table below compares the compile time and object size for each of the +// variants listed in the RUN script. +// +// Impl Compile Time Object Size +// ---------------------------------------------------------- +// new_add_rvalue_reference: 56.398 s 171 K +// std::add_rvalue_reference: 114.59 s 271 K +// +// RUN: %cxx %flags %compile_flags -c %s -o %S/orig.o -ggdb -ggnu-pubnames -ftemplate-depth=5000 -ftime-trace -std=c++17 +// RUN: %cxx %flags %compile_flags -c %s -o %S/new.o -ggdb -ggnu-pubnames -ftemplate-depth=5000 -ftime-trace -std=c++17 -DTEST_NEW + +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "template_cost_testing.h" + +template <int N> struct Arg { enum { value = 1 }; }; + +#ifdef TEST_NEW + +template <class T> +struct new_add_rvalue_reference +{ + typedef __add_rvalue_reference(T) type; +}; + +#define TEST_CASE_NOP() new_add_rvalue_reference< Arg< __COUNTER__ > >{}, +#define TEST_CASE_TYPE() typename new_add_rvalue_reference< Arg< __COUNTER__ > >::type, + +#else + +#define TEST_CASE_NOP() std::add_rvalue_reference< Arg< __COUNTER__ > >{}, +#define TEST_CASE_TYPE() typename std::add_rvalue_reference< Arg< __COUNTER__ > >::type, + +#endif + +int sink(...); + +int x = sink( + REPEAT_10000(TEST_CASE_NOP) + REPEAT_10000(TEST_CASE_NOP) 42 +); + +void Foo( REPEAT_10000(TEST_CASE_TYPE) int) { } + +void escape() { + +sink(&x); +sink(&Foo); +} + + Index: libcxx/test/libcxx/utilities/meta/stress_tests/stress_test_add_lvalue_reference.sh.cpp =================================================================== --- /dev/null +++ libcxx/test/libcxx/utilities/meta/stress_tests/stress_test_add_lvalue_reference.sh.cpp @@ -0,0 +1,63 @@ +//===----------------------------------------------------------------------===// +// +// 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 is a dummy feature that prevents this test from running by default. + +// The table below compares the compile time and object size for each of the +// variants listed in the RUN script. +// +// Impl Compile Time Object Size +// ---------------------------------------------------------- +// new_add_lvalue_reference: 23,359.202 ms 171 K +// std::add_lvalue_reference: 73,160.138 ms 201 K +// +// RUN: %cxx %flags %compile_flags -c %s -o %S/orig.o -ggdb -ggnu-pubnames -ftemplate-depth=5000 -ftime-trace -std=c++17 +// RUN: %cxx %flags %compile_flags -c %s -o %S/new.o -ggdb -ggnu-pubnames -ftemplate-depth=5000 -ftime-trace -std=c++17 -DTEST_NEW + +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "template_cost_testing.h" + +template <int N> struct Arg { enum { value = 1 }; }; + +#ifdef TEST_NEW + +template <class T> +struct new_add_lvalue_reference +{ + typedef __add_lvalue_reference(T) type; +}; + +#define TEST_CASE_NOP() new_add_lvalue_reference< Arg< __COUNTER__ > >{}, +#define TEST_CASE_TYPE() typename new_add_lvalue_reference< Arg< __COUNTER__ > >::type, + +#else + +#define TEST_CASE_NOP() std::add_lvalue_reference< Arg< __COUNTER__ > >{}, +#define TEST_CASE_TYPE() typename std::add_lvalue_reference< Arg< __COUNTER__ > >::type, + +#endif + +int sink(...); + +int x = sink( + REPEAT_10000(TEST_CASE_NOP) + REPEAT_10000(TEST_CASE_NOP) 42 +); + +void Foo( REPEAT_10000(TEST_CASE_TYPE) int) { } + +void escape() { + +sink(&x); +sink(&Foo); +} + + Index: clang/test/SemaCXX/add_reference.cpp =================================================================== --- /dev/null +++ clang/test/SemaCXX/add_reference.cpp @@ -0,0 +1,69 @@ +// RUN: %clang_cc1 -std=c++11 %s + +template<class T> +struct test_lval_trait +{ + typedef __add_lvalue_reference(T) type; +}; + +template<class T> +struct test_lval +{ + static const bool value = __is_same(typename test_lval_trait<T>::type, T&) && + __is_same(typename test_lval_trait<T&>::type, T&) && + __is_same(typename test_lval_trait<T&&>::type, T&); +}; + +template<class T> +struct test_rval_trait +{ + typedef __add_rvalue_reference(T) type; +}; + +template<class T> +struct test_rval +{ + static const bool value = __is_same(typename test_rval_trait<T>::type, T&&) && + __is_same(typename test_rval_trait<T&>::type, T&&) && + __is_same(typename test_rval_trait<T&&>::type, T&&); +}; + +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/lib/Sema/SemaType.cpp =================================================================== --- clang/lib/Sema/SemaType.cpp +++ clang/lib/Sema/SemaType.cpp @@ -1251,6 +1251,22 @@ return OpenCLAccessAttr::Keyword_read_only; } +static UnaryTransformType::UTTKind +TSTToUnaryTransformType(DeclSpec::TST SwitchTST) { + switch (SwitchTST) { + case TST_addLValueReferenceType: + return UnaryTransformType::AddLValueRefType; + case TST_addRValueReferenceType: + return UnaryTransformType::AddRValueRefType; + case TST_removeReferenceType: + return UnaryTransformType::RemoveReferenceType; + case TST_underlyingType: + return UnaryTransformType::EnumUnderlyingType; + default: + llvm_unreachable("Cannot map TST to unary transform type"); + } +} + /// Convert the specified declspec to the appropriate type /// object. /// \param state Specifies the declarator containing the declaration specifier @@ -1593,6 +1609,20 @@ declarator.setInvalidType(true); } break; + case DeclSpec::TST_addLValueReferenceType: + case DeclSpec::TST_addRValueReferenceType: + case DeclSpec::TST_removeReferenceType: + 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_auto: Result = Context.getAutoType(QualType(), AutoTypeKeyword::Auto, false); @@ -5462,8 +5492,11 @@ 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); + + // assert(DS.getTypeSpecType() == DeclSpec::TST_underlyingType); TL.setKWLoc(DS.getTypeSpecTypeLoc()); TL.setParensRange(DS.getTypeofParensRange()); assert(DS.getRepAsType()); @@ -7927,7 +7960,7 @@ break; } - SourceRange Loc = + SourceRange Loc = S.ImplicitMSInheritanceAttrLoc.isValid() ? S.ImplicitMSInheritanceAttrLoc : RD->getSourceRange(); @@ -8380,6 +8413,21 @@ return Context.getUnaryTransformType(BaseType, Underlying, UnaryTransformType::EnumUnderlyingType); } + case UnaryTransformType::AddLValueRefType: { + QualType Underlying = Context.getLValueReferenceType(BaseType.getCanonicalType()); + return Context.getUnaryTransformType(BaseType, Underlying, + UnaryTransformType::AddLValueRefType); + } + case UnaryTransformType::AddRValueRefType: { + QualType Underlying = Context.getRValueReferenceType(BaseType.getCanonicalType()); + return Context.getUnaryTransformType(BaseType, Underlying, + UnaryTransformType::AddRValueRefType); + } + case UnaryTransformType::RemoveReferenceType: { + QualType Underlying = BaseType.getNonReferenceType(); + return Context.getUnaryTransformType(BaseType, Underlying, + UnaryTransformType::RemoveReferenceType); + } } 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,9 @@ case TST_typename: case TST_typeofType: case TST_underlyingType: + case TST_addLValueReferenceType: + case TST_addRValueReferenceType: + case TST_removeReferenceType: 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,9 @@ case tok::kw_wchar_t: case tok::kw_bool: case tok::kw___underlying_type: + case tok::kw___add_lvalue_reference: + case tok::kw___add_rvalue_reference: + case tok::kw___remove_reference: case tok::kw___auto_type: return true; @@ -5287,6 +5290,9 @@ case DeclSpec::TST_typename: case DeclSpec::TST_typeofType: case DeclSpec::TST_underlyingType: + case DeclSpec::TST_addLValueReferenceType: + case DeclSpec::TST_addRValueReferenceType: + case DeclSpec::TST_removeReferenceType: 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 @@ -374,6 +374,9 @@ return false; case TST_underlyingType: + case TST_addLValueReferenceType: + case TST_addRValueReferenceType: + case TST_removeReferenceType: case TST_typename: case TST_typeofType: { QualType QT = DS.getRepAsType().get(); @@ -553,6 +556,9 @@ case DeclSpec::TST_decltype: return "(decltype)"; case DeclSpec::TST_decltype_auto: return "decltype(auto)"; case DeclSpec::TST_underlyingType: return "__underlying_type"; + case DeclSpec::TST_addLValueReferenceType: return "__add_lvalue_reference"; + case DeclSpec::TST_addRValueReferenceType: return "__add_rvalue_reference"; + case DeclSpec::TST_removeReferenceType: return "__remove_reference"; 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 @@ -1083,6 +1083,48 @@ DS.setTypeofParensRange(T.getRange()); } +DeclSpec::TST Parser::ReferenceTransformTokToDeclSpec() { + switch (Tok.getKind()) { + case tok::kw___add_lvalue_reference: + return DeclSpec::TST_addLValueReferenceType; + case tok::kw___add_rvalue_reference: + return DeclSpec::TST_addRValueReferenceType; + case tok::kw___remove_reference: + return DeclSpec::TST_removeReferenceType; + default: + llvm_unreachable("Not a reference type specifier"); + } +} + +void Parser::ParseAddReferenceTypeSpecifier(DeclSpec &DS) { + DeclSpec::TST ReferenceTransformTST = ReferenceTransformTokToDeclSpec(); + + 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(ReferenceTransformTST, + 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 @@ -3919,6 +3919,12 @@ ParseUnderlyingTypeSpecifier(DS); continue; + case tok::kw___remove_reference: + case tok::kw___add_rvalue_reference: + case tok::kw___add_lvalue_reference: + ParseAddReferenceTypeSpecifier(DS); + continue; + case tok::kw__Atomic: // C11 6.7.2.4/4: // If the _Atomic keyword is immediately followed by a left parenthesis, Index: clang/lib/Lex/PPMacroExpansion.cpp =================================================================== --- clang/lib/Lex/PPMacroExpansion.cpp +++ clang/lib/Lex/PPMacroExpansion.cpp @@ -1636,6 +1636,9 @@ .Case("__array_extent", true) .Case("__reference_binds_to_temporary", true) .Case("__underlying_type", true) + .Case("__add_lvalue_reference", true) + .Case("__add_rvalue_reference", true) + .Case("__remove_reference", 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,9 @@ case tok::kw_wchar_t: case tok::kw_bool: case tok::kw___underlying_type: + case tok::kw___add_lvalue_reference: + case tok::kw___add_rvalue_reference: + case tok::kw___remove_reference: 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,24 @@ OS << ')'; spaceBeforePlaceHolder(OS); return; + case UnaryTransformType::RemoveReferenceType: + OS << "__remove_reference"; + print(T->getBaseType(), OS, StringRef()); + OS << ')'; + spaceBeforePlaceHolder(OS); + return; + case UnaryTransformType::AddRValueRefType: + OS << "__add_rvalue_reference("; + print(T->getBaseType(), OS, StringRef()); + OS << ')'; + spaceBeforePlaceHolder(OS); + return; + case UnaryTransformType::AddLValueRefType: + OS << "__add_lvalue_reference("; + print(T->getBaseType(), OS, StringRef()); + OS << ')'; + spaceBeforePlaceHolder(OS); + return; } printBefore(T->getBaseType(), OS); @@ -1035,6 +1053,9 @@ switch (T->getUTTKind()) { case UnaryTransformType::EnumUnderlyingType: + case UnaryTransformType::RemoveReferenceType: + case UnaryTransformType::AddLValueRefType: + case UnaryTransformType::AddRValueRefType: return; } Index: clang/lib/AST/TextNodeDumper.cpp =================================================================== --- clang/lib/AST/TextNodeDumper.cpp +++ clang/lib/AST/TextNodeDumper.cpp @@ -1180,6 +1180,15 @@ case UnaryTransformType::EnumUnderlyingType: OS << " underlying_type"; break; + case UnaryTransformType::RemoveReferenceType: + OS << " remove_reference"; + break; + case UnaryTransformType::AddRValueRefType: + OS << " add_rvalue_reference"; + break; + case UnaryTransformType::AddLValueRefType: + OS << " add_lvalue_reference"; + break; } } Index: clang/lib/AST/JSONNodeDumper.cpp =================================================================== --- clang/lib/AST/JSONNodeDumper.cpp +++ clang/lib/AST/JSONNodeDumper.cpp @@ -589,6 +589,15 @@ case UnaryTransformType::EnumUnderlyingType: JOS.attribute("transformKind", "underlying_type"); break; + case UnaryTransformType::RemoveReferenceType: + JOS.attribute("transformKind", "remove_reference"); + break; + case UnaryTransformType::AddRValueRefType: + JOS.attribute("transformKind", "add_rvalue_reference"); + break; + case UnaryTransformType::AddLValueRefType: + JOS.attribute("transformKind", "add_lvalue_reference"); + break; } } @@ -962,7 +971,7 @@ case ObjCPropertyDecl::Required: JOS.attribute("control", "required"); break; case ObjCPropertyDecl::Optional: JOS.attribute("control", "optional"); break; } - + ObjCPropertyDecl::PropertyAttributeKind Attrs = D->getPropertyAttributes(); if (Attrs != ObjCPropertyDecl::OBJC_PR_noattr) { if (Attrs & ObjCPropertyDecl::OBJC_PR_getter) Index: clang/lib/AST/ItaniumMangle.cpp =================================================================== --- clang/lib/AST/ItaniumMangle.cpp +++ clang/lib/AST/ItaniumMangle.cpp @@ -3409,6 +3409,15 @@ case UnaryTransformType::EnumUnderlyingType: Out << "3eut"; break; + case UnaryTransformType::RemoveReferenceType: + Out << "3err"; + break; + case UnaryTransformType::AddRValueRefType: + Out << "3earvr"; + break; + case UnaryTransformType::AddLValueRefType: + Out << "3ealvr"; + break; } } Index: clang/include/clang/Sema/DeclSpec.h =================================================================== --- clang/include/clang/Sema/DeclSpec.h +++ clang/include/clang/Sema/DeclSpec.h @@ -300,6 +300,9 @@ static const TST TST_decltype = clang::TST_decltype; static const TST TST_decltype_auto = clang::TST_decltype_auto; static const TST TST_underlyingType = clang::TST_underlyingType; + static const TST TST_addLValueReferenceType = clang::TST_addLValueReferenceType; + static const TST TST_addRValueReferenceType = clang::TST_addRValueReferenceType; + static const TST TST_removeReferenceType = clang::TST_removeReferenceType; 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; @@ -408,7 +411,9 @@ static bool isTypeRep(TST T) { return (T == TST_typename || T == TST_typeofType || - T == TST_underlyingType || T == TST_atomic); + T == TST_underlyingType || T == TST_atomic|| + T == TST_addLValueReferenceType || T == TST_addRValueReferenceType || + T == TST_removeReferenceType); } 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 @@ -2602,6 +2602,8 @@ SourceLocation StartLoc, SourceLocation EndLoc); void ParseUnderlyingTypeSpecifier(DeclSpec &DS); + DeclSpec::TST ReferenceTransformTokToDeclSpec(); + void ParseAddReferenceTypeSpecifier(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 @@ -486,7 +486,10 @@ TYPE_TRAIT_1(__is_union, IsUnion, KEYCXX) TYPE_TRAIT_1(__has_unique_object_representations, HasUniqueObjectRepresentations, KEYCXX) -KEYWORD(__underlying_type , KEYCXX) +KEYWORD(__underlying_type , KEYCXX) +KEYWORD(__add_lvalue_reference , KEYCXX) +KEYWORD(__add_rvalue_reference , KEYCXX) +KEYWORD(__remove_reference , 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,9 @@ TST_typeofExpr, TST_decltype, // C++11 decltype TST_underlyingType, // __underlying_type for C++11 + TST_addLValueReferenceType, // __add_lvalue_reference + TST_addRValueReferenceType, // __add_rvalue_reference + TST_removeReferenceType, // __remove_reference 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 @@ -4363,7 +4363,10 @@ class UnaryTransformType : public Type { public: enum UTTKind { - EnumUnderlyingType + EnumUnderlyingType, + RemoveReferenceType, + AddRValueRefType, + AddLValueRefType }; private:
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits