[cfe-commits] r124425 - in /cfe/trunk: include/clang/Basic/TokenKinds.def include/clang/Basic/TypeTraits.h lib/AST/StmtPrinter.cpp lib/Parse/ParseExpr.cpp lib/Parse/ParseExprCXX.cpp lib/Parse/ParseTentative.cpp lib/Sema/SemaExprCXX.cpp test/SemaCXX/type-traits.cpp

Douglas Gregor dgregor at apple.com
Thu Jan 27 12:28:01 PST 2011


Author: dgregor
Date: Thu Jan 27 14:28:01 2011
New Revision: 124425

URL: http://llvm.org/viewvc/llvm-project?rev=124425&view=rev
Log:
Implement the Microsoft __is_convertible_to type trait, modeling the
semantics after the C++0x is_convertible type trait. This
implementation is not 100% complete, because it allows access errors
to be hard errors (rather than just evaluating false).

Original patch by Steven Watanabe!

Modified:
    cfe/trunk/include/clang/Basic/TokenKinds.def
    cfe/trunk/include/clang/Basic/TypeTraits.h
    cfe/trunk/lib/AST/StmtPrinter.cpp
    cfe/trunk/lib/Parse/ParseExpr.cpp
    cfe/trunk/lib/Parse/ParseExprCXX.cpp
    cfe/trunk/lib/Parse/ParseTentative.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/test/SemaCXX/type-traits.cpp

Modified: cfe/trunk/include/clang/Basic/TokenKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TokenKinds.def?rev=124425&r1=124424&r2=124425&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/TokenKinds.def (original)
+++ cfe/trunk/include/clang/Basic/TokenKinds.def Thu Jan 27 14:28:01 2011
@@ -319,6 +319,7 @@
 KEYWORD(__is_abstract               , KEYCXX)
 KEYWORD(__is_base_of                , KEYCXX)
 KEYWORD(__is_class                  , KEYCXX)
+KEYWORD(__is_convertible_to         , KEYCXX)
 KEYWORD(__is_empty                  , KEYCXX)
 KEYWORD(__is_enum                   , KEYCXX)
 KEYWORD(__is_pod                    , KEYCXX)
@@ -326,7 +327,6 @@
 KEYWORD(__is_union                  , KEYCXX)
 // Tentative name - there's no implementation of std::is_literal_type yet.
 KEYWORD(__is_literal                , KEYCXX)
-// FIXME: Add MS's traits, too.
 
 // Apple Extension.
 KEYWORD(__private_extern__          , KEYALL)

Modified: cfe/trunk/include/clang/Basic/TypeTraits.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TypeTraits.h?rev=124425&r1=124424&r2=124425&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/TypeTraits.h (original)
+++ cfe/trunk/include/clang/Basic/TypeTraits.h Thu Jan 27 14:28:01 2011
@@ -39,7 +39,8 @@
   /// BinaryTypeTrait - Names for the binary type traits.
   enum BinaryTypeTrait {
     BTT_IsBaseOf,
-    BTT_TypeCompatible
+    BTT_TypeCompatible,
+    BTT_IsConvertibleTo
   };
 }
 

Modified: cfe/trunk/lib/AST/StmtPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=124425&r1=124424&r2=124425&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtPrinter.cpp (original)
+++ cfe/trunk/lib/AST/StmtPrinter.cpp Thu Jan 27 14:28:01 2011
@@ -1225,9 +1225,9 @@
 
 static const char *getTypeTraitName(BinaryTypeTrait BTT) {
   switch (BTT) {
-  default: llvm_unreachable("Unknown binary type trait");
   case BTT_IsBaseOf:         return "__is_base_of";
   case BTT_TypeCompatible:   return "__builtin_types_compatible_p";
+  case BTT_IsConvertibleTo:  return "__is_convertible_to";
   }
   return "";
 }

Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=124425&r1=124424&r2=124425&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Thu Jan 27 14:28:01 2011
@@ -537,8 +537,9 @@
 ///                   '__is_polymorphic'
 ///                   '__is_union'
 ///
-/// [GNU] binary-type-trait:
-///                   '__is_base_of'                          [TODO]
+///       binary-type-trait:
+/// [GNU]             '__is_base_of'       
+/// [MS]              '__is_convertible_to'
 ///
 ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
                                        bool isAddressOfOperand,
@@ -988,6 +989,7 @@
 
   case tok::kw___builtin_types_compatible_p:
   case tok::kw___is_base_of:
+  case tok::kw___is_convertible_to:
     return ParseBinaryTypeTrait();
 
   case tok::at: {

Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=124425&r1=124424&r2=124425&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Thu Jan 27 14:28:01 2011
@@ -1828,6 +1828,7 @@
   default: llvm_unreachable("Not a known binary type trait");
   case tok::kw___is_base_of:                 return BTT_IsBaseOf;
   case tok::kw___builtin_types_compatible_p: return BTT_TypeCompatible;
+  case tok::kw___is_convertible_to:          return BTT_IsConvertibleTo;
   }
 }
 

Modified: cfe/trunk/lib/Parse/ParseTentative.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTentative.cpp?rev=124425&r1=124424&r2=124425&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseTentative.cpp (original)
+++ cfe/trunk/lib/Parse/ParseTentative.cpp Thu Jan 27 14:28:01 2011
@@ -655,6 +655,7 @@
   case tok::kw___is_abstract:
   case tok::kw___is_base_of:
   case tok::kw___is_class:
+  case tok::kw___is_convertible_to:
   case tok::kw___is_empty:
   case tok::kw___is_enum:
   case tok::kw___is_pod:

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=124425&r1=124424&r2=124425&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Thu Jan 27 14:28:01 2011
@@ -2499,6 +2499,52 @@
   case BTT_TypeCompatible:
     return Self.Context.typesAreCompatible(LhsT.getUnqualifiedType(),
                                            RhsT.getUnqualifiedType());
+      
+  case BTT_IsConvertibleTo: {
+    // C++0x [meta.rel]p4:
+    //   Given the following function prototype:
+    //
+    //     template <class T> 
+    //       typename add_rvalue_reference<T>::type create();
+    //
+    //   the predicate condition for a template specialization 
+    //   is_convertible<From, To> shall be satisfied if and only if 
+    //   the return expression in the following code would be 
+    //   well-formed, including any implicit conversions to the return
+    //   type of the function:
+    //
+    //     To test() { 
+    //       return create<From>();
+    //     }
+    //
+    //   Access checking is performed as if in a context unrelated to To and 
+    //   From. Only the validity of the immediate context of the expression 
+    //   of the return-statement (including conversions to the return type)
+    //   is considered.
+    //
+    // We model the initialization as a copy-initialization of a temporary
+    // of the appropriate type, which for this expression is identical to the
+    // return statement (since NRVO doesn't apply).
+    if (LhsT->isObjectType() || LhsT->isFunctionType())
+      LhsT = Self.Context.getRValueReferenceType(LhsT);
+    
+    InitializedEntity To(InitializedEntity::InitializeTemporary(RhsT));
+    OpaqueValueExpr From(LhsT.getNonLValueExprType(Self.Context),
+                         Expr::getValueKindForType(LhsT));
+    Expr *FromPtr = &From;
+    InitializationKind Kind(InitializationKind::CreateCopy(KeyLoc, 
+                                                           SourceLocation()));
+    
+    // Perform the initialization within a SFINAE trap.
+    // FIXME: We don't implement the access-checking bits yet, because we don't
+    // handle access control as part of SFINAE.
+    Sema::SFINAETrap SFINAE(Self);
+    InitializationSequence Init(Self, To, Kind, &FromPtr, 1);
+    if (Init.getKind() == InitializationSequence::FailedSequence)
+      return false;
+    ExprResult Result = Init.Perform(Self, To, Kind, MultiExprArg(&FromPtr, 1));
+    return !Result.isInvalid() && !SFINAE.hasErrorOccurred();
+  }
   }
   llvm_unreachable("Unknown type trait or not implemented");
 }
@@ -2538,9 +2584,9 @@
   // Select trait result type.
   QualType ResultType;
   switch (BTT) {
-  default: llvm_unreachable("Unknown type trait or not implemented");
   case BTT_IsBaseOf:       ResultType = Context.BoolTy; break;
   case BTT_TypeCompatible: ResultType = Context.IntTy; break;
+  case BTT_IsConvertibleTo: ResultType = Context.BoolTy; break;
   }
 
   return Owned(new (Context) BinaryTypeTraitExpr(KWLoc, BTT, LhsTSInfo,

Modified: cfe/trunk/test/SemaCXX/type-traits.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/type-traits.cpp?rev=124425&r1=124424&r2=124425&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/type-traits.cpp (original)
+++ cfe/trunk/test/SemaCXX/type-traits.cpp Thu Jan 27 14:28:01 2011
@@ -497,3 +497,31 @@
   isBaseOfT<BaseA<int>, DerivedB<int> >();
   isBaseOfF<DerivedB<int>, BaseA<int> >();
 }
+
+struct FromInt { FromInt(int); };
+struct ToInt { operator int(); };
+typedef void Function();
+
+void is_convertible_to() {
+  int t01[T(__is_convertible_to(Int, Int))];
+  int t02[F(__is_convertible_to(Int, IntAr))];
+  int t03[F(__is_convertible_to(IntAr, IntAr))];
+  int t04[T(__is_convertible_to(void, void))];
+  int t05[T(__is_convertible_to(cvoid, void))];
+  int t06[T(__is_convertible_to(void, cvoid))];
+  int t07[T(__is_convertible_to(cvoid, cvoid))];
+  int t08[T(__is_convertible_to(int, FromInt))];
+  int t09[T(__is_convertible_to(long, FromInt))];
+  int t10[T(__is_convertible_to(double, FromInt))];
+  int t11[T(__is_convertible_to(const int, FromInt))];
+  int t12[T(__is_convertible_to(const int&, FromInt))];
+  int t13[T(__is_convertible_to(ToInt, int))];
+  int t14[T(__is_convertible_to(ToInt, const int&))];
+  int t15[T(__is_convertible_to(ToInt, long))];
+  int t16[F(__is_convertible_to(ToInt, int&))];
+  int t17[F(__is_convertible_to(ToInt, FromInt))];
+  int t18[T(__is_convertible_to(IntAr&, IntAr&))];
+  int t19[T(__is_convertible_to(IntAr&, const IntAr&))];
+  int t20[F(__is_convertible_to(const IntAr&, IntAr&))];
+  int t21[F(__is_convertible_to(Function, Function))];
+}





More information about the cfe-commits mailing list