AMDG

The attached patch implements __is_base_of and __is_convertible_to.
These are the last intrinsics required to compile the <type_traits> header
that ships with MSVC 10.0.

In Christ,
Steven Watanabe

Index: tools/clang/test/SemaCXX/type-traits.cpp
===================================================================
--- tools/clang/test/SemaCXX/type-traits.cpp	(revision 114230)
+++ tools/clang/test/SemaCXX/type-traits.cpp	(working copy)
@@ -434,3 +434,66 @@
   int t22[F(__has_virtual_destructor(void))];
   int t23[F(__has_virtual_destructor(cvoid))];
 }
+
+struct Base {};
+struct VirtualBase {};
+struct VirtDerived : virtual VirtualBase {};
+struct PrivateDerived : private Base {};
+
+struct D1 : Base {};
+struct D2 : Base {};
+struct AmbiguousDerived : D1, D2 {};
+struct MultipleDerived : AmbiguousDerived, private VirtDerived {};
+
+// Make sure that type-traits work in a dependent context,
+// since they're evaluated eagerly.
+template<class T1, class T2>
+struct test_is_base_of {
+  static const bool value = __is_base_of(T1, T2);
+};
+
+void is_base_of() {
+  int t01[F(__is_base_of(Int, Int))];
+  int t02[T(__is_base_of(POD, Derives))];
+  int t03[T(__is_base_of(POD, POD))];
+  int t04[T(__is_base_of(const POD, volatile POD))];
+  int t05[T(__is_base_of(VirtualBase, VirtDerived))];
+  int t06[T(__is_base_of(Base, PrivateDerived))];
+  int t07[T(__is_base_of(Base, D1))];
+  int t08[T(__is_base_of(Base, AmbiguousDerived))];
+  int t09[T(__is_base_of(VirtualBase, MultipleDerived))];
+  int t10[T(__is_base_of(POD, const Derives))];
+  int t11[T(__is_base_of(const POD, Derives))];
+  int t12[F(__is_base_of(POD&, Derives&))];
+  int t13[F(__is_base_of(POD*, Derives*))];
+  int t14[F(__is_base_of(Union, Union))];
+  int t15[T((test_is_base_of<Base, D1>::value))];
+}
+
+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[T(__is_convertible_to(Function, Function))];
+}
Index: tools/clang/include/clang/Basic/StmtNodes.td
===================================================================
--- tools/clang/include/clang/Basic/StmtNodes.td	(revision 114230)
+++ tools/clang/include/clang/Basic/StmtNodes.td	(working copy)
@@ -100,6 +100,7 @@
 def CXXDeleteExpr : DStmt<Expr>;
 def CXXPseudoDestructorExpr : DStmt<Expr>;
 def UnaryTypeTraitExpr : DStmt<Expr>;
+def BinaryTypeTraitExpr : DStmt<Expr>;
 def DependentScopeDeclRefExpr : DStmt<Expr>;
 def CXXConstructExpr : DStmt<Expr>;
 def CXXBindTemporaryExpr : DStmt<Expr>;
@@ -132,3 +133,5 @@
 // Microsoft Extensions.
 def CXXUuidofExpr : DStmt<Expr>; 
 
+// Internal Helper.
+def DummyExpr : DStmt<Expr>;
Index: tools/clang/include/clang/Basic/TypeTraits.h
===================================================================
--- tools/clang/include/clang/Basic/TypeTraits.h	(revision 114230)
+++ tools/clang/include/clang/Basic/TypeTraits.h	(working copy)
@@ -36,6 +36,12 @@
     UTT_IsLiteral
   };
 
+  /// BinaryTypeTrait - Names for the binary type traits
+  enum BinaryTypeTrait {
+    BTT_IsBaseOf,
+    BTT_IsConvertibleTo
+  };
+
 }
 
 #endif
Index: tools/clang/include/clang/Basic/TokenKinds.def
===================================================================
--- tools/clang/include/clang/Basic/TokenKinds.def	(revision 114230)
+++ tools/clang/include/clang/Basic/TokenKinds.def	(working copy)
@@ -322,6 +322,7 @@
 KEYWORD(__is_pod                    , KEYCXX)
 KEYWORD(__is_polymorphic            , KEYCXX)
 KEYWORD(__is_union                  , KEYCXX)
+KEYWORD(__is_convertible_to         , KEYCXX)
 // Tentative name - there's no implementation of std::is_literal_type yet.
 KEYWORD(__is_literal                , KEYCXX)
 // FIXME: Add MS's traits, too.
Index: tools/clang/include/clang/Sema/Sema.h
===================================================================
--- tools/clang/include/clang/Sema/Sema.h	(revision 114230)
+++ tools/clang/include/clang/Sema/Sema.h	(working copy)
@@ -2276,6 +2276,18 @@
                                  TypeSourceInfo *T,
                                  SourceLocation RParen);
 
+  ExprResult ActOnBinaryTypeTrait(BinaryTypeTrait OTT,
+                                  SourceLocation KWLoc,
+                                  ParsedType Ty1,
+                                  ParsedType Ty2,
+                                  SourceLocation RParen);
+
+  ExprResult BuildBinaryTypeTrait(BinaryTypeTrait OTT,
+                                  SourceLocation KWLoc,
+                                  TypeSourceInfo *T1,
+                                  TypeSourceInfo *T2,
+                                  SourceLocation RParen);
+
   ExprResult ActOnStartCXXMemberReference(Scope *S,
                                           Expr *Base,
                                           SourceLocation OpLoc,
Index: tools/clang/include/clang/AST/RecursiveASTVisitor.h
===================================================================
--- tools/clang/include/clang/AST/RecursiveASTVisitor.h	(revision 114230)
+++ tools/clang/include/clang/AST/RecursiveASTVisitor.h	(working copy)
@@ -1785,6 +1785,11 @@
     TRY_TO(TraverseTypeLoc(S->getQueriedTypeSourceInfo()->getTypeLoc()));
   })
 
+DEF_TRAVERSE_STMT(BinaryTypeTraitExpr, {
+    TRY_TO(TraverseType(S->getQueriedType(0)));
+    TRY_TO(TraverseType(S->getQueriedType(1)));
+  })
+
 // These exprs (most of them), do not need any action except iterating
 // over the children.
 DEF_TRAVERSE_STMT(AddrLabelExpr, { })
@@ -1854,6 +1859,8 @@
 DEF_TRAVERSE_STMT(StringLiteral, { })
 DEF_TRAVERSE_STMT(ObjCStringLiteral, { })
 
+DEF_TRAVERSE_STMT(DummyExpr, { })
+
 // FIXME: look at the following tricky-seeming exprs to see if we
 // need to recurse on anything.  These are ones that have methods
 // returning decls or qualtypes or nestednamespecifier -- though I'm
Index: tools/clang/include/clang/AST/Expr.h
===================================================================
--- tools/clang/include/clang/AST/Expr.h	(revision 114230)
+++ tools/clang/include/clang/AST/Expr.h	(working copy)
@@ -3500,6 +3500,28 @@
   virtual child_iterator child_end();
 };
 
+class DummyExpr : public Expr {
+
+  Classification::Kinds Kind;
+
+public:
+  DummyExpr(QualType T, Classification::Kinds kind)
+    : Expr(DummyExprClass, T, false, false), Kind(kind) {}
+
+  virtual SourceRange getSourceRange() const { return SourceRange(); }
+
+  Classification::Kinds getKind() const { return Kind; }
+
+  static bool classof(const Stmt *T) {
+    return T->getStmtClass() == DummyExprClass;
+  }
+  static bool classof(const DummyExpr *) { return true; }
+
+  // Iterators
+  virtual child_iterator child_begin();
+  virtual child_iterator child_end();
+};
+
 }  // end namespace clang
 
 #endif
Index: tools/clang/include/clang/AST/ExprCXX.h
===================================================================
--- tools/clang/include/clang/AST/ExprCXX.h	(revision 114230)
+++ tools/clang/include/clang/AST/ExprCXX.h	(working copy)
@@ -1421,6 +1421,63 @@
   friend class ASTStmtReader;
 };
 
+/// BinaryTypeTraitExpr - A GCC or MS unary type trait, as used in the
+/// implementation of TR1/C++0x type trait templates.
+/// Example:
+class BinaryTypeTraitExpr : public Expr {
+  /// BTT - The trait.
+  unsigned BTT : 31;
+
+  /// The value of the type trait. Unspecified if dependent.
+  unsigned Value : 1;
+
+  /// Loc - The location of the type trait keyword.
+  SourceLocation Loc;
+
+  /// RParen - The location of the closing paren.
+  SourceLocation RParen;
+
+  TypeSourceInfo *QueriedTypes[2];
+
+public:
+  BinaryTypeTraitExpr(SourceLocation loc, BinaryTypeTrait btt,
+                      TypeSourceInfo *queried1, TypeSourceInfo *queried2,
+                      bool value, SourceLocation rparen, QualType ty)
+    : Expr(BinaryTypeTraitExprClass, ty, false,
+           queried1->getType()->isDependentType() ||
+           queried2->getType()->isDependentType()),
+      BTT(btt), Value(value), Loc(loc), RParen(rparen) {
+    QueriedTypes[0] = queried1;
+    QueriedTypes[1] = queried2;
+  }
+
+  explicit BinaryTypeTraitExpr(EmptyShell Empty)
+    : Expr(BinaryTypeTraitExprClass, Empty), BTT(0), Value(false) { }
+
+  virtual SourceRange getSourceRange() const { return SourceRange(Loc, RParen);}
+
+  BinaryTypeTrait getTrait() const { return static_cast<BinaryTypeTrait>(BTT); }
+
+  QualType getQueriedType(int n) const { return QueriedTypes[n]->getType(); }
+  TypeSourceInfo *getQueriedTypeSourceInfo(int n) const {
+      return QueriedTypes[n];
+  }
+
+  bool getValue() const { return Value; }
+
+  static bool classof(const Stmt *T) {
+    return T->getStmtClass() == BinaryTypeTraitExprClass;
+  }
+  static bool classof(const BinaryTypeTraitExpr *) { return true; }
+
+  // Iterators
+  virtual child_iterator child_begin();
+  virtual child_iterator child_end();
+
+  friend class ASTStmtReader;
+};
+
+
 /// \brief A reference to an overloaded function set, either an
 /// \t UnresolvedLookupExpr or an \t UnresolvedMemberExpr.
 class OverloadExpr : public Expr {
Index: tools/clang/include/clang/Parse/Parser.h
===================================================================
--- tools/clang/include/clang/Parse/Parser.h	(revision 114230)
+++ tools/clang/include/clang/Parse/Parser.h	(working copy)
@@ -1566,6 +1566,7 @@
   //===--------------------------------------------------------------------===//
   // GNU G++: Type Traits [Type-Traits.html in the GCC manual]
   ExprResult ParseUnaryTypeTrait();
+  ExprResult ParseBinaryTypeTrait();
 
   //===--------------------------------------------------------------------===//
   // Preprocessor code-completion pass-through
Index: tools/clang/include/clang/Serialization/ASTBitCodes.h
===================================================================
--- tools/clang/include/clang/Serialization/ASTBitCodes.h	(revision 114230)
+++ tools/clang/include/clang/Serialization/ASTBitCodes.h	(working copy)
@@ -899,6 +899,7 @@
       EXPR_CXX_UNRESOLVED_LOOKUP,        // UnresolvedLookupExpr
 
       EXPR_CXX_UNARY_TYPE_TRAIT,  // UnaryTypeTraitExpr
+      EXPR_CXX_BINARY_TYPE_TRAIT, // BinaryTypeTraitExpr
       EXPR_CXX_NOEXCEPT           // CXXNoexceptExpr
     };
 
Index: tools/clang/tools/libclang/CXCursor.cpp
===================================================================
--- tools/clang/tools/libclang/CXCursor.cpp	(revision 114230)
+++ tools/clang/tools/libclang/CXCursor.cpp	(working copy)
@@ -141,6 +141,7 @@
   case Stmt::CXXPseudoDestructorExprClass:
   case Stmt::UnresolvedLookupExprClass:   
   case Stmt::UnaryTypeTraitExprClass:     
+  case Stmt::BinaryTypeTraitExprClass:     
   case Stmt::DependentScopeDeclRefExprClass:  
   case Stmt::CXXBindTemporaryExprClass:   
   case Stmt::CXXExprWithTemporariesClass: 
Index: tools/clang/tools/libclang/CIndex.cpp
===================================================================
--- tools/clang/tools/libclang/CIndex.cpp	(revision 114230)
+++ tools/clang/tools/libclang/CIndex.cpp	(working copy)
@@ -390,6 +390,7 @@
   bool VisitCXXNewExpr(CXXNewExpr *E);
   bool VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E);
   bool VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E);
+  bool VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E);
   bool VisitOverloadExpr(OverloadExpr *E);
   bool VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E);
   bool VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E);
@@ -1787,6 +1788,11 @@
   return Visit(E->getQueriedTypeSourceInfo()->getTypeLoc());
 }
 
+bool CursorVisitor::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) {
+  return Visit(E->getQueriedTypeSourceInfo(0)->getTypeLoc());
+  return Visit(E->getQueriedTypeSourceInfo(1)->getTypeLoc());
+}
+
 bool CursorVisitor::VisitOverloadExpr(OverloadExpr *E) {
   // Visit the nested-name-specifier.
   if (NestedNameSpecifier *Qualifier = E->getQualifier())
Index: tools/clang/lib/Sema/TreeTransform.h
===================================================================
--- tools/clang/lib/Sema/TreeTransform.h	(revision 114230)
+++ tools/clang/lib/Sema/TreeTransform.h	(working copy)
@@ -1646,6 +1646,19 @@
     return getSema().BuildUnaryTypeTrait(Trait, StartLoc, T, RParenLoc);
   }
 
+  /// \brief Build a new binary type trait expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildBinaryTypeTrait(BinaryTypeTrait Trait,
+                                    SourceLocation StartLoc,
+                                    TypeSourceInfo *T1,
+                                    TypeSourceInfo *T2,
+                                    SourceLocation RParenLoc) {
+    return getSema().BuildBinaryTypeTrait(Trait, StartLoc,
+                                          T1, T2, RParenLoc);
+  }
+
   /// \brief Build a new (previously unresolved) declaration reference
   /// expression.
   ///
@@ -5595,6 +5608,28 @@
 
 template<typename Derived>
 ExprResult
+TreeTransform<Derived>::TransformBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) {
+  TypeSourceInfo *T1 =
+    getDerived().TransformType(E->getQueriedTypeSourceInfo(0));
+  TypeSourceInfo *T2 =
+    getDerived().TransformType(E->getQueriedTypeSourceInfo(1));
+  if (!T1 || !T2)
+    return ExprError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      T1 == E->getQueriedTypeSourceInfo(0) &&
+      T2 == E->getQueriedTypeSourceInfo(1))
+    return SemaRef.Owned(E->Retain());
+
+  return getDerived().RebuildBinaryTypeTrait(E->getTrait(),
+                                             E->getLocStart(),
+                                             T1,
+                                             T2,
+                                             E->getLocEnd());
+}
+
+template<typename Derived>
+ExprResult
 TreeTransform<Derived>::TransformDependentScopeDeclRefExpr(
                                                DependentScopeDeclRefExpr *E) {
   NestedNameSpecifier *NNS
@@ -6292,6 +6327,12 @@
                                          ND, NameInfo, 0);
 }
 
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformDummyExpr(DummyExpr *E) {
+  return SemaRef.Owned(E->Retain());
+}
+
 //===----------------------------------------------------------------------===//
 // Type reconstruction
 //===----------------------------------------------------------------------===//
Index: tools/clang/lib/Sema/SemaExprCXX.cpp
===================================================================
--- tools/clang/lib/Sema/SemaExprCXX.cpp	(revision 114230)
+++ tools/clang/lib/Sema/SemaExprCXX.cpp	(working copy)
@@ -1996,6 +1996,15 @@
   return false;
 }
 
+static bool CheckTypeTraitArgument(Sema& S, QualType T, SourceLocation KWLoc) {
+  QualType E = T;
+  if (T->isIncompleteArrayType())
+    E = S.getASTContext().getAsArrayType(T)->getElementType();
+  return !T->isVoidType() &&
+      S.RequireCompleteType(KWLoc, E,
+                            diag::err_incomplete_type_used_in_type_trait_expr);
+}
+
 ExprResult Sema::ActOnUnaryTypeTrait(UnaryTypeTrait UTT,
                                      SourceLocation KWLoc,
                                      ParsedType Ty,
@@ -2234,12 +2243,7 @@
   // all traits except __is_class, __is_enum and __is_union require a the type
   // to be complete, an array of unknown bound, or void.
   if (UTT != UTT_IsClass && UTT != UTT_IsEnum && UTT != UTT_IsUnion) {
-    QualType E = T;
-    if (T->isIncompleteArrayType())
-      E = Context.getAsArrayType(T)->getElementType();
-    if (!T->isVoidType() &&
-        RequireCompleteType(KWLoc, E,
-                            diag::err_incomplete_type_used_in_type_trait_expr))
+    if (CheckTypeTraitArgument(*this, T, KWLoc))
       return ExprError();
   }
 
@@ -2251,6 +2255,82 @@
                                                 RParen, Context.BoolTy));
 }
 
+static bool EvaluateBinaryTypeTrait(Sema& S,
+                                    BinaryTypeTrait BTT,
+                                    QualType T1,
+                                    QualType T2) {
+  assert(!T1->isDependentType() && !T2->isDependentType() &&
+         "Cannot evaluate traits for dependent types.");
+  switch(BTT) {
+  default: assert(false && "Unknown type trait or not implemented");
+  case BTT_IsBaseOf:
+    if (const RecordType *Base = T1->getAs<RecordType>()) {
+      if (const RecordType *Derived = T2->getAs<RecordType>()) {
+        CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(Base->getDecl());
+        CXXRecordDecl *DerivedDecl = cast<CXXRecordDecl>(Derived->getDecl());
+        return DerivedDecl->isDerivedFrom(BaseDecl) ||
+          (!DerivedDecl->isUnion() && DerivedDecl == BaseDecl);
+      }
+    }
+    return false;
+  case BTT_IsConvertibleTo:
+    InitializedEntity To(InitializedEntity::InitializeTemporary(T2));
+    Expr::Classification::Kinds Classification = T1->isLValueReferenceType()?
+      Expr::Classification::CL_LValue :
+      Expr::Classification::CL_PRValue;
+    DummyExpr From(T1.getNonReferenceType(), Classification);
+    Expr *FromPtr = &From;
+    InitializationKind Kind(
+      InitializationKind::CreateCopy(SourceLocation(), SourceLocation()));
+    InitializationSequence Init(S, To, Kind, &FromPtr, 1);
+    return Init;
+  }
+}
+
+ExprResult Sema::ActOnBinaryTypeTrait(BinaryTypeTrait OTT,
+                                      SourceLocation KWLoc,
+                                      ParsedType Ty1,
+                                      ParsedType Ty2,
+                                      SourceLocation RParen) {
+
+  TypeSourceInfo *TSInfo1;
+  TypeSourceInfo *TSInfo2;
+  QualType T1 = GetTypeFromParser(Ty1, &TSInfo1);
+  QualType T2 = GetTypeFromParser(Ty2, &TSInfo2);
+
+  if (!TSInfo1)
+    TSInfo1 = Context.getTrivialTypeSourceInfo(T1);
+
+  if (!TSInfo2)
+    TSInfo2 = Context.getTrivialTypeSourceInfo(T2);
+
+  return BuildBinaryTypeTrait(OTT, KWLoc, TSInfo1, TSInfo2, RParen);
+}
+
+ExprResult Sema::BuildBinaryTypeTrait(BinaryTypeTrait OTT,
+                                      SourceLocation KWLoc,
+                                      TypeSourceInfo *TSInfo1,
+                                      TypeSourceInfo *TSInfo2,
+                                      SourceLocation RParen) {
+  QualType T1 = TSInfo1->getType();
+  QualType T2 = TSInfo2->getType();
+  
+  // According to http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html
+  // all traits except __is_class, __is_enum and __is_union require a the type
+  // to be complete, an array of unknown bound, or void.
+  if (CheckTypeTraitArgument(*this, T1, KWLoc) ||
+      CheckTypeTraitArgument(*this, T2, KWLoc))
+    return ExprError();
+  
+  bool Value = false;
+
+  if (!T1->isDependentType() && !T2->isDependentType())
+    Value = EvaluateBinaryTypeTrait(*this, OTT, T1, T2);
+
+  return Owned(new (Context) BinaryTypeTraitExpr(KWLoc, OTT, TSInfo1, TSInfo2,
+                                                 Value, RParen, Context.BoolTy));
+}
+
 QualType Sema::CheckPointerToMemberOperands(
   Expr *&lex, Expr *&rex, SourceLocation Loc, bool isIndirect) {
   const char *OpSpelling = isIndirect ? "->*" : ".*";
Index: tools/clang/lib/AST/ExprCXX.cpp
===================================================================
--- tools/clang/lib/AST/ExprCXX.cpp	(revision 114230)
+++ tools/clang/lib/AST/ExprCXX.cpp	(working copy)
@@ -295,6 +295,13 @@
 Stmt::child_iterator UnaryTypeTraitExpr::child_end() {
   return child_iterator();
 }
+// UnaryTypeTraitExpr
+Stmt::child_iterator BinaryTypeTraitExpr::child_begin() {
+  return child_iterator();
+}
+Stmt::child_iterator BinaryTypeTraitExpr::child_end() {
+  return child_iterator();
+}
 
 // DependentScopeDeclRefExpr
 DependentScopeDeclRefExpr *

Property changes on: tools\clang\lib\AST\ExprCXX.cpp
___________________________________________________________________
Added: svn:eol-style
   + native

Index: tools/clang/lib/AST/ExprConstant.cpp
===================================================================
--- tools/clang/lib/AST/ExprConstant.cpp	(revision 114230)
+++ tools/clang/lib/AST/ExprConstant.cpp	(working copy)
@@ -951,6 +951,10 @@
     return Success(E->getValue(), E);
   }
 
+  bool VisitBinaryTypeTraitExpr(const BinaryTypeTraitExpr *E) {
+    return Success(E->getValue(), E);
+  }
+
   bool VisitChooseExpr(const ChooseExpr *E) {
     return Visit(E->getChosenSubExpr(Info.Ctx));
   }
@@ -2447,6 +2451,7 @@
   case Expr::CXXScalarValueInitExprClass:
   case Expr::TypesCompatibleExprClass:
   case Expr::UnaryTypeTraitExprClass:
+  case Expr::BinaryTypeTraitExprClass:
   case Expr::CXXNoexceptExprClass:
     return NoDiag();
   case Expr::CallExprClass:
Index: tools/clang/lib/AST/StmtPrinter.cpp
===================================================================
--- tools/clang/lib/AST/StmtPrinter.cpp	(revision 114230)
+++ tools/clang/lib/AST/StmtPrinter.cpp	(working copy)
@@ -1230,11 +1230,25 @@
   }
 }
 
+static const char *getTypeTraitName(BinaryTypeTrait BTT) {
+  switch (BTT) {
+  default: assert(false && "Unknown type trait");
+  case BTT_IsBaseOf:        return "__is_base_of";
+  case BTT_IsConvertibleTo: return "__is_convertible_to";
+  }
+}
+
 void StmtPrinter::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) {
   OS << getTypeTraitName(E->getTrait()) << "("
      << E->getQueriedType().getAsString(Policy) << ")";
 }
 
+void StmtPrinter::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) {
+  OS << getTypeTraitName(E->getTrait()) << "("
+     << E->getQueriedType(0).getAsString(Policy) << ","
+     << E->getQueriedType(1).getAsString(Policy) << ")";
+}
+
 void StmtPrinter::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) {
   OS << "noexcept(";
   PrintExpr(E->getOperand());
@@ -1333,6 +1347,10 @@
 void StmtPrinter::VisitBlockDeclRefExpr(BlockDeclRefExpr *Node) {
   OS << Node->getDecl();
 }
+
+void StmtPrinter::VisitDummyExpr(DummyExpr *Node) {
+  assert(!"DummyExpr is a strictly internal feature.");
+}
 //===----------------------------------------------------------------------===//
 // Stmt method implementations
 //===----------------------------------------------------------------------===//
Index: tools/clang/lib/AST/StmtProfile.cpp
===================================================================
--- tools/clang/lib/AST/StmtProfile.cpp	(revision 114230)
+++ tools/clang/lib/AST/StmtProfile.cpp	(working copy)
@@ -780,6 +780,13 @@
   VisitType(S->getQueriedType());
 }
 
+void StmtProfiler::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *S) {
+  VisitExpr(S);
+  ID.AddInteger(S->getTrait());
+  VisitType(S->getQueriedType(0));
+  VisitType(S->getQueriedType(1));
+}
+
 void
 StmtProfiler::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *S) {
   VisitExpr(S);
@@ -943,6 +950,10 @@
   Name.Profile(ID);
 }
 
+void StmtProfiler::VisitDummyExpr(DummyExpr *) {
+  assert(!"DummyExpr is a strictly internal feature.");
+}
+
 void StmtProfiler::VisitTemplateArguments(const TemplateArgumentLoc *Args,
                                           unsigned NumArgs) {
   ID.AddInteger(NumArgs);
Index: tools/clang/lib/AST/Expr.cpp
===================================================================
--- tools/clang/lib/AST/Expr.cpp	(revision 114230)
+++ tools/clang/lib/AST/Expr.cpp	(working copy)
@@ -2574,3 +2574,6 @@
 
 Stmt::child_iterator BlockDeclRefExpr::child_begin() { return child_iterator();}
 Stmt::child_iterator BlockDeclRefExpr::child_end() { return child_iterator(); }
+
+Stmt::child_iterator DummyExpr::child_begin() { return child_iterator();}
+Stmt::child_iterator DummyExpr::child_end() { return child_iterator(); }
Index: tools/clang/lib/AST/ExprClassification.cpp
===================================================================
--- tools/clang/lib/AST/ExprClassification.cpp	(revision 114230)
+++ tools/clang/lib/AST/ExprClassification.cpp	(working copy)
@@ -119,6 +119,7 @@
   case Expr::CXXNoexceptExprClass:
   case Expr::CXXScalarValueInitExprClass:
   case Expr::UnaryTypeTraitExprClass:
+  case Expr::BinaryTypeTraitExprClass:
   case Expr::ObjCSelectorExprClass:
   case Expr::ObjCProtocolExprClass:
   case Expr::ObjCStringLiteralClass:
@@ -255,6 +256,9 @@
   case Expr::CXXTemporaryObjectExprClass:
     return Cl::CL_ClassTemporary;
 
+  case Expr::DummyExprClass:
+    return cast<DummyExpr>(E)->getKind();
+
   case Expr::VAArgExprClass:
     return ClassifyUnnamed(Ctx, E->getType());
       
Index: tools/clang/lib/CodeGen/CGExprScalar.cpp
===================================================================
--- tools/clang/lib/CodeGen/CGExprScalar.cpp	(revision 114230)
+++ tools/clang/lib/CodeGen/CGExprScalar.cpp	(working copy)
@@ -291,6 +291,9 @@
   Value *VisitUnaryTypeTraitExpr(const UnaryTypeTraitExpr *E) {
     return llvm::ConstantInt::get(Builder.getInt1Ty(), E->getValue());
   }
+  Value *VisitBinaryTypeTraitExpr(const BinaryTypeTraitExpr *E) {
+    return llvm::ConstantInt::get(Builder.getInt1Ty(), E->getValue());
+  }
 
   Value *VisitCXXPseudoDestructorExpr(const CXXPseudoDestructorExpr *E) {
     // C++ [expr.pseudo]p1:
Index: tools/clang/lib/CodeGen/Mangle.cpp
===================================================================
--- tools/clang/lib/CodeGen/Mangle.cpp	(revision 114230)
+++ tools/clang/lib/CodeGen/Mangle.cpp	(working copy)
@@ -1617,6 +1617,7 @@
   case Expr::StmtExprClass:
   case Expr::TypesCompatibleExprClass:
   case Expr::UnaryTypeTraitExprClass:
+  case Expr::BinaryTypeTraitExprClass:
   case Expr::VAArgExprClass:
   case Expr::CXXUuidofExprClass:
   case Expr::CXXNoexceptExprClass: {
Index: tools/clang/lib/Checker/GRExprEngine.cpp
===================================================================
--- tools/clang/lib/Checker/GRExprEngine.cpp	(revision 114230)
+++ tools/clang/lib/Checker/GRExprEngine.cpp	(working copy)
@@ -779,6 +779,7 @@
     case Stmt::CXXScalarValueInitExprClass:
     case Stmt::DependentScopeDeclRefExprClass:
     case Stmt::UnaryTypeTraitExprClass:
+    case Stmt::BinaryTypeTraitExprClass:
     case Stmt::UnresolvedLookupExprClass:
     case Stmt::UnresolvedMemberExprClass:
     case Stmt::CXXNoexceptExprClass:
Index: tools/clang/lib/Parse/ParseExpr.cpp
===================================================================
--- tools/clang/lib/Parse/ParseExpr.cpp	(revision 114230)
+++ tools/clang/lib/Parse/ParseExpr.cpp	(working copy)
@@ -488,7 +488,7 @@
 /// [C++]   'typeid' '(' type-id ')'                                [C++ 5.2p1]
 /// [C++]   'this'          [C++ 9.3.2]
 /// [G++]   unary-type-trait '(' type-id ')'
-/// [G++]   binary-type-trait '(' type-id ',' type-id ')'           [TODO]
+/// [G++]   binary-type-trait '(' type-id ',' type-id ')'
 /// [clang] '^' block-literal
 ///
 ///       constant: [C99 6.4.4]
@@ -536,7 +536,8 @@
 ///                   '__is_union'
 ///
 /// [GNU] binary-type-trait:
-///                   '__is_base_of'                          [TODO]
+///                   '__is_base_of'
+///                   '__is_convertible_to'
 ///
 ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
                                        bool isAddressOfOperand,
@@ -988,6 +989,10 @@
   case tok::kw___has_virtual_destructor:
     return ParseUnaryTypeTrait();
 
+  case tok::kw___is_base_of:
+  case tok::kw___is_convertible_to:
+    return ParseBinaryTypeTrait();
+
   case tok::at: {
     SourceLocation AtLoc = ConsumeToken();
     return ParseObjCAtExpression(AtLoc);
Index: tools/clang/lib/Parse/ParseExprCXX.cpp
===================================================================
--- tools/clang/lib/Parse/ParseExprCXX.cpp	(revision 114230)
+++ tools/clang/lib/Parse/ParseExprCXX.cpp	(working copy)
@@ -1807,6 +1807,14 @@
   }
 }
 
+static BinaryTypeTrait BinaryTypeTraitFromTokKind(tok::TokenKind kind) {
+  switch(kind) {
+  default: assert(false && "Not a known binary type trait.");
+  case tok::kw___is_base_of: return BTT_IsBaseOf;
+  case tok::kw___is_convertible_to: return BTT_IsConvertibleTo;
+  }
+}
+
 /// ParseUnaryTypeTrait - Parse the built-in unary type-trait
 /// pseudo-functions that allow implementation of the TR1/C++0x type traits
 /// templates.
@@ -1835,6 +1843,38 @@
   return Actions.ActOnUnaryTypeTrait(UTT, Loc, Ty.get(), RParen);
 }
 
+/// ParseBinaryTypeTrait - Parse the build-in binary type-trait
+/// pseudo-functions that allow implementation of the TR1/C++0x type traits
+/// templates.
+///
+///       primary-expression:
+/// [GNU]             binary-type-trait '(' type-id ',' type-id ')'
+ExprResult Parser::ParseBinaryTypeTrait() {
+  BinaryTypeTrait BTT = BinaryTypeTraitFromTokKind(Tok.getKind());
+  SourceLocation Loc = ConsumeToken();
+
+  SourceLocation LParen = Tok.getLocation();
+  if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen))
+    return ExprError();
+
+  TypeResult Ty1 = ParseTypeName();
+  if (Ty1.isInvalid())
+    return ExprError();
+
+  SourceLocation Comma = Tok.getLocation();
+  if (ExpectAndConsume(tok::comma, diag::err_expected_comma))
+    return ExprError();
+
+  TypeResult Ty2 = ParseTypeName();
+  if (Ty2.isInvalid())
+    return ExprError();
+
+  SourceLocation RParen = MatchRHSPunctuation(tok::r_paren, LParen);
+
+  return Actions.ActOnBinaryTypeTrait(
+    BTT, Loc, Ty1.get(), Ty2.get(), RParen);
+}
+
 /// ParseCXXAmbiguousParenExpression - We have parsed the left paren of a
 /// parenthesized ambiguous type-id. This uses tentative parsing to disambiguate
 /// based on the context past the parens.
Index: tools/clang/lib/Serialization/ASTReaderStmt.cpp
===================================================================
--- tools/clang/lib/Serialization/ASTReaderStmt.cpp	(revision 114230)
+++ tools/clang/lib/Serialization/ASTReaderStmt.cpp	(working copy)
@@ -156,6 +156,7 @@
     void VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E);
 
     void VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E);
+    void VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E);
     void VisitCXXNoexceptExpr(CXXNoexceptExpr *E);
   };
 }
@@ -1254,6 +1255,17 @@
   E->QueriedType = Reader.GetTypeSourceInfo(DeclsCursor, Record, Idx);
 }
 
+void ASTStmtReader::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) {
+  VisitExpr(E);
+  E->BTT = (BinaryTypeTrait)Record[Idx++];
+  E->Value = (bool)Record[Idx++];
+  SourceRange Range = Reader.ReadSourceRange(Record, Idx);
+  E->Loc = Range.getBegin();
+  E->RParen = Range.getEnd();
+  E->QueriedTypes[0] = Reader.GetTypeSourceInfo(DeclsCursor, Record, Idx);
+  E->QueriedTypes[1] = Reader.GetTypeSourceInfo(DeclsCursor, Record, Idx);
+}
+
 void ASTStmtReader::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) {
   VisitExpr(E);
   E->Value = (bool)Record[Idx++];
@@ -1773,6 +1785,10 @@
     case EXPR_CXX_UNARY_TYPE_TRAIT:
       S = new (Context) UnaryTypeTraitExpr(Empty);
       break;
+      
+    case EXPR_CXX_BINARY_TYPE_TRAIT:
+      S = new (Context) BinaryTypeTraitExpr(Empty);
+      break;
 
     case EXPR_CXX_NOEXCEPT:
       S = new (Context) CXXNoexceptExpr(Empty);
Index: tools/clang/lib/Serialization/ASTWriterStmt.cpp
===================================================================
--- tools/clang/lib/Serialization/ASTWriterStmt.cpp	(revision 114230)
+++ tools/clang/lib/Serialization/ASTWriterStmt.cpp	(working copy)
@@ -152,6 +152,7 @@
     void VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E);
 
     void VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E);
+    void VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E);
     void VisitCXXNoexceptExpr(CXXNoexceptExpr *E);
   };
 }
@@ -1286,6 +1287,16 @@
   Code = serialization::EXPR_CXX_UNARY_TYPE_TRAIT;
 }
 
+void ASTStmtWriter::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) {
+  VisitExpr(E);
+  Record.push_back(E->getTrait());
+  Record.push_back(E->getValue());
+  Writer.AddSourceRange(E->getSourceRange(), Record);
+  Writer.AddTypeSourceInfo(E->getQueriedTypeSourceInfo(0), Record);
+  Writer.AddTypeSourceInfo(E->getQueriedTypeSourceInfo(1), Record);
+  Code = serialization::EXPR_CXX_BINARY_TYPE_TRAIT;
+}
+
 void ASTStmtWriter::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) {
   VisitExpr(E);
   Record.push_back(E->getValue());
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to