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

Remove test code that snuck in.


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
@@ -2048,6 +2048,8 @@
 
   // PR25513
   { int arr[F(__is_constructible(int(int)))]; }
+
+  { int arr[T(__is_constructible(int const&, long))]; }
 }
 
 // Instantiation of __is_trivially_constructible
@@ -2078,6 +2080,46 @@
   { int arr[F((is_trivially_constructible<Abstract>::value))]; } // PR19178
 }
 
+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)))]; }
+
+}
+
 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
@@ -4564,11 +4564,14 @@
   if (Kind <= UTT_Last)
     return EvaluateUnaryTypeTrait(S, Kind, KWLoc, Args[0]->getType());
 
-  if (Kind <= BTT_Last)
+  // Evaluate BTT_ReferenceBindsToTemporary along side 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: {
@@ -4644,6 +4647,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
@@ -847,6 +847,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
@@ -1431,7 +1431,8 @@
                   tok::kw___is_union,
                   tok::kw___is_unsigned,
                   tok::kw___is_void,
-                  tok::kw___is_volatile))
+                  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
@@ -77,7 +77,8 @@
     BTT_IsAssignable,
     BTT_IsNothrowAssignable,
     BTT_IsTriviallyAssignable,
-    BTT_Last = BTT_IsTriviallyAssignable,
+    BTT_ReferenceBindsToTemporary,
+    BTT_Last = BTT_ReferenceBindsToTemporary,
     TT_IsConstructible,
     TT_IsNothrowConstructible,
     TT_IsTriviallyConstructible
Index: include/clang/Basic/TokenKinds.def
===================================================================
--- include/clang/Basic/TokenKinds.def
+++ include/clang/Basic/TokenKinds.def
@@ -452,6 +452,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
@@ -1023,6 +1023,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

Reply via email to