EricWF updated this revision to Diff 123741.
EricWF added a comment.

- Address spelling errors pointed out during review.


https://reviews.llvm.org/D29930

Files:
  docs/LanguageExtensions.rst
  include/clang/Basic/TokenKinds.def
  include/clang/Basic/TypeTraits.h
  lib/Parse/ParseDeclCXX.cpp
  lib/Parse/ParseExpr.cpp
  lib/Sema/SemaExprCXX.cpp
  test/SemaCXX/type-traits.cpp

Index: test/SemaCXX/type-traits.cpp
===================================================================
--- test/SemaCXX/type-traits.cpp
+++ test/SemaCXX/type-traits.cpp
@@ -2225,6 +2225,7 @@
 
   // PR25513
   { int arr[F(__is_constructible(int(int)))]; }
+  { int arr[T(__is_constructible(int const &, long))]; }
 
   { int arr[T(__is_constructible(ACompleteType))]; }
   { int arr[T(__is_nothrow_constructible(ACompleteType))]; }
@@ -2275,6 +2276,47 @@
   { int arr[F(__is_trivially_constructible(const volatile void))]; }
 }
 
+template <class T, class RefType = T &>
+struct ConvertsToRef {
+  operator RefType() const { return static_cast<RefType>(obj); }
+  mutable T obj = 42;
+};
+
+void reference_binds_to_temporary_checks() {
+  { int arr[F((__reference_binds_to_temporary(int &, int &)))]; }
+  { int arr[F((__reference_binds_to_temporary(int &, int &&)))]; }
+
+  { int arr[F((__reference_binds_to_temporary(int const &, int &)))]; }
+  { int arr[F((__reference_binds_to_temporary(int const &, int const &)))]; }
+  { int arr[F((__reference_binds_to_temporary(int const &, int &&)))]; }
+
+  { int arr[F((__reference_binds_to_temporary(int &, long &)))]; } // doesn't construct
+  { int arr[T((__reference_binds_to_temporary(int const &, long &)))]; }
+  { int arr[T((__reference_binds_to_temporary(int const &, long &&)))]; }
+  { int arr[T((__reference_binds_to_temporary(int &&, long &)))]; }
+
+  using LRef = ConvertsToRef<int, int &>;
+  using RRef = ConvertsToRef<int, int &&>;
+  using CLRef = ConvertsToRef<int, const int &>;
+  using LongRef = ConvertsToRef<long, long &>;
+  { int arr[T((__is_constructible(int &, LRef)))]; }
+  { int arr[F((__reference_binds_to_temporary(int &, LRef)))]; }
+
+  { int arr[T((__is_constructible(int &&, RRef)))]; }
+  { int arr[F((__reference_binds_to_temporary(int &&, RRef)))]; }
+
+  { int arr[T((__is_constructible(int const &, CLRef)))]; }
+  { int arr[F((__reference_binds_to_temporary(int &&, CLRef)))]; }
+
+  { int arr[T((__is_constructible(int const &, LongRef)))]; }
+  { int arr[T((__reference_binds_to_temporary(int const &, LongRef)))]; }
+
+  // Test that it doesn't accept non-reference types as input.
+  { int arr[F((__reference_binds_to_temporary(int, long)))]; }
+
+  { int arr[T((__reference_binds_to_temporary(const int &, long)))]; }
+}
+
 void array_rank() {
   int t01[T(__array_rank(IntAr) == 1)];
   int t02[T(__array_rank(ConstIntArAr) == 2)];
Index: lib/Sema/SemaExprCXX.cpp
===================================================================
--- lib/Sema/SemaExprCXX.cpp
+++ lib/Sema/SemaExprCXX.cpp
@@ -4629,11 +4629,14 @@
   if (Kind <= UTT_Last)
     return EvaluateUnaryTypeTrait(S, Kind, KWLoc, Args[0]->getType());
 
-  if (Kind <= BTT_Last)
+  // Evaluate BTT_ReferenceBindsToTemporary alongside the IsConstructible
+  // traits to avoid duplication.
+  if (Kind <= BTT_Last && Kind != BTT_ReferenceBindsToTemporary)
     return EvaluateBinaryTypeTrait(S, Kind, Args[0]->getType(),
                                    Args[1]->getType(), RParenLoc);
 
   switch (Kind) {
+  case clang::BTT_ReferenceBindsToTemporary:
   case clang::TT_IsConstructible:
   case clang::TT_IsNothrowConstructible:
   case clang::TT_IsTriviallyConstructible: {
@@ -4710,6 +4713,13 @@
     if (Kind == clang::TT_IsConstructible)
       return true;
 
+    if (Kind == clang::BTT_ReferenceBindsToTemporary) {
+      if (!T->isReferenceType())
+        return false;
+
+      return !Init.isDirectReferenceBinding();
+    }
+
     if (Kind == clang::TT_IsNothrowConstructible)
       return S.canThrow(Result.get()) == CT_Cannot;
 
Index: lib/Parse/ParseExpr.cpp
===================================================================
--- lib/Parse/ParseExpr.cpp
+++ lib/Parse/ParseExpr.cpp
@@ -900,6 +900,7 @@
           REVERTIBLE_TYPE_TRAIT(__is_unsigned);
           REVERTIBLE_TYPE_TRAIT(__is_void);
           REVERTIBLE_TYPE_TRAIT(__is_volatile);
+          REVERTIBLE_TYPE_TRAIT(__reference_binds_to_temporary);
 #undef REVERTIBLE_TYPE_TRAIT
 #undef RTT_JOIN
         }
Index: lib/Parse/ParseDeclCXX.cpp
===================================================================
--- lib/Parse/ParseDeclCXX.cpp
+++ lib/Parse/ParseDeclCXX.cpp
@@ -1404,61 +1404,32 @@
   // C++11 attributes
   SourceLocation AttrFixitLoc = Tok.getLocation();
 
-  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,
-                  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_volatile))
+  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,
+          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_volatile, tok::kw___reference_binds_to_temporary))
     // GNU libstdc++ 4.2 and libc++ use certain intrinsic names as the
     // name of struct templates, but some are keywords in GCC >= 4.3
     // and Clang. Therefore, when we see the token sequence "struct
Index: include/clang/Basic/TypeTraits.h
===================================================================
--- include/clang/Basic/TypeTraits.h
+++ include/clang/Basic/TypeTraits.h
@@ -18,87 +18,85 @@
 namespace clang {
 
   /// \brief Names for traits that operate specifically on types.
-  enum TypeTrait {
-    UTT_HasNothrowAssign,
-    UTT_HasNothrowMoveAssign,
-    UTT_HasNothrowCopy,
-    UTT_HasNothrowConstructor,
-    UTT_HasTrivialAssign,
-    UTT_HasTrivialMoveAssign,
-    UTT_HasTrivialCopy,
-    UTT_HasTrivialDefaultConstructor,
-    UTT_HasTrivialMoveConstructor,
-    UTT_HasTrivialDestructor,
-    UTT_HasVirtualDestructor,
-    UTT_IsAbstract,
-    UTT_IsAggregate,
-    UTT_IsArithmetic,
-    UTT_IsArray,
-    UTT_IsClass,
-    UTT_IsCompleteType,
-    UTT_IsCompound,
-    UTT_IsConst,
-    UTT_IsDestructible,
-    UTT_IsEmpty,
-    UTT_IsEnum,
-    UTT_IsFinal,
-    UTT_IsFloatingPoint,
-    UTT_IsFunction,
-    UTT_IsFundamental,
-    UTT_IsIntegral,
-    UTT_IsInterfaceClass,
-    UTT_IsLiteral,
-    UTT_IsLvalueReference,
-    UTT_IsMemberFunctionPointer,
-    UTT_IsMemberObjectPointer,
-    UTT_IsMemberPointer,
-    UTT_IsNothrowDestructible,
-    UTT_IsObject,
-    UTT_IsPOD,
-    UTT_IsPointer,
-    UTT_IsPolymorphic,
-    UTT_IsReference,
-    UTT_IsRvalueReference,
-    UTT_IsScalar,
-    UTT_IsSealed,
-    UTT_IsSigned,
-    UTT_IsStandardLayout,
-    UTT_IsTrivial,
-    UTT_IsTriviallyCopyable,
-    UTT_IsTriviallyDestructible,
-    UTT_IsUnion,
-    UTT_IsUnsigned,
-    UTT_IsVoid,
-    UTT_IsVolatile,
-    UTT_HasUniqueObjectRepresentations,
-    UTT_Last = UTT_HasUniqueObjectRepresentations,
-    BTT_IsBaseOf,
-    BTT_IsConvertible,
-    BTT_IsConvertibleTo,
-    BTT_IsSame,
-    BTT_TypeCompatible,
-    BTT_IsAssignable,
-    BTT_IsNothrowAssignable,
-    BTT_IsTriviallyAssignable,
-    BTT_Last = BTT_IsTriviallyAssignable,
-    TT_IsConstructible,
-    TT_IsNothrowConstructible,
-    TT_IsTriviallyConstructible
-  };
+enum TypeTrait {
+  UTT_HasNothrowAssign,
+  UTT_HasNothrowMoveAssign,
+  UTT_HasNothrowCopy,
+  UTT_HasNothrowConstructor,
+  UTT_HasTrivialAssign,
+  UTT_HasTrivialMoveAssign,
+  UTT_HasTrivialCopy,
+  UTT_HasTrivialDefaultConstructor,
+  UTT_HasTrivialMoveConstructor,
+  UTT_HasTrivialDestructor,
+  UTT_HasVirtualDestructor,
+  UTT_IsAbstract,
+  UTT_IsAggregate,
+  UTT_IsArithmetic,
+  UTT_IsArray,
+  UTT_IsClass,
+  UTT_IsCompleteType,
+  UTT_IsCompound,
+  UTT_IsConst,
+  UTT_IsDestructible,
+  UTT_IsEmpty,
+  UTT_IsEnum,
+  UTT_IsFinal,
+  UTT_IsFloatingPoint,
+  UTT_IsFunction,
+  UTT_IsFundamental,
+  UTT_IsIntegral,
+  UTT_IsInterfaceClass,
+  UTT_IsLiteral,
+  UTT_IsLvalueReference,
+  UTT_IsMemberFunctionPointer,
+  UTT_IsMemberObjectPointer,
+  UTT_IsMemberPointer,
+  UTT_IsNothrowDestructible,
+  UTT_IsObject,
+  UTT_IsPOD,
+  UTT_IsPointer,
+  UTT_IsPolymorphic,
+  UTT_IsReference,
+  UTT_IsRvalueReference,
+  UTT_IsScalar,
+  UTT_IsSealed,
+  UTT_IsSigned,
+  UTT_IsStandardLayout,
+  UTT_IsTrivial,
+  UTT_IsTriviallyCopyable,
+  UTT_IsTriviallyDestructible,
+  UTT_IsUnion,
+  UTT_IsUnsigned,
+  UTT_IsVoid,
+  UTT_IsVolatile,
+  UTT_HasUniqueObjectRepresentations,
+  UTT_Last = UTT_HasUniqueObjectRepresentations,
+  BTT_IsBaseOf,
+  BTT_IsConvertible,
+  BTT_IsConvertibleTo,
+  BTT_IsSame,
+  BTT_TypeCompatible,
+  BTT_IsAssignable,
+  BTT_IsNothrowAssignable,
+  BTT_IsTriviallyAssignable,
+  BTT_ReferenceBindsToTemporary,
+  BTT_Last = BTT_ReferenceBindsToTemporary,
+  TT_IsConstructible,
+  TT_IsNothrowConstructible,
+  TT_IsTriviallyConstructible
+};
 
-  /// \brief Names for the array type traits.
-  enum ArrayTypeTrait {
-    ATT_ArrayRank,
-    ATT_ArrayExtent
-  };
+/// \brief Names for the array type traits.
+enum ArrayTypeTrait { ATT_ArrayRank, ATT_ArrayExtent };
 
-  /// \brief Names for the "expression or type" traits.
-  enum UnaryExprOrTypeTrait {
-    UETT_SizeOf,
-    UETT_AlignOf,
-    UETT_VecStep,
-    UETT_OpenMPRequiredSimdAlign,
-  };
+/// \brief Names for the "expression or type" traits.
+enum UnaryExprOrTypeTrait {
+  UETT_SizeOf,
+  UETT_AlignOf,
+  UETT_VecStep,
+  UETT_OpenMPRequiredSimdAlign,
+};
 }
 
 #endif
Index: include/clang/Basic/TokenKinds.def
===================================================================
--- include/clang/Basic/TokenKinds.def
+++ include/clang/Basic/TokenKinds.def
@@ -462,6 +462,7 @@
 TYPE_TRAIT_N(__is_trivially_constructible, IsTriviallyConstructible, KEYCXX)
 TYPE_TRAIT_1(__is_trivially_copyable, IsTriviallyCopyable, KEYCXX)
 TYPE_TRAIT_2(__is_trivially_assignable, IsTriviallyAssignable, KEYCXX)
+TYPE_TRAIT_2(__reference_binds_to_temporary, ReferenceBindsToTemporary, KEYCXX)
 KEYWORD(__underlying_type           , KEYCXX)
 
 // Embarcadero Expression Traits
Index: docs/LanguageExtensions.rst
===================================================================
--- docs/LanguageExtensions.rst
+++ docs/LanguageExtensions.rst
@@ -1067,6 +1067,11 @@
 * ``__is_constructible`` (MSVC 2013, clang)
 * ``__is_nothrow_constructible`` (MSVC 2013, clang)
 * ``__is_assignable`` (MSVC 2015, clang)
+* ``__reference_binds_to_temporary(T, U)`` (Clang):  Determines whether a
+  reference of type ``T`` bound to an expression of type ``U`` would bind to a
+  materialized temporary object. If ``T`` is not a reference type the result
+  is false. Note this trait will also return false when the initialization of
+  ``T`` from ``U`` is ill-formed.
 
 Blocks
 ======
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D29930: A... Eric Fiselier via Phabricator via cfe-commits
    • [PATCH] D299... Richard Smith - zygoloid via Phabricator via cfe-commits
    • [PATCH] D299... Eric Fiselier via Phabricator via cfe-commits
    • [PATCH] D299... Eric Fiselier via Phabricator via cfe-commits

Reply via email to