]> granicus.if.org Git - clang/commitdiff
Type traits intrinsic implementation: __is_base_of(T, U)
authorFrancois Pichet <pichet2000@gmail.com>
Tue, 7 Dec 2010 00:08:36 +0000 (00:08 +0000)
committerFrancois Pichet <pichet2000@gmail.com>
Tue, 7 Dec 2010 00:08:36 +0000 (00:08 +0000)
New AST node introduced: BinaryTypeTraitExpr; to be reused for more intrinsics.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@121074 91177308-0d34-0410-b5e6-96231b3b80d8

24 files changed:
include/clang/AST/ExprCXX.h
include/clang/AST/RecursiveASTVisitor.h
include/clang/Basic/StmtNodes.td
include/clang/Basic/TypeTraits.h
include/clang/Parse/Parser.h
include/clang/Sema/Sema.h
include/clang/Serialization/ASTBitCodes.h
lib/AST/ExprCXX.cpp
lib/AST/ExprClassification.cpp
lib/AST/ExprConstant.cpp
lib/AST/StmtPrinter.cpp
lib/AST/StmtProfile.cpp
lib/Checker/GRExprEngine.cpp
lib/CodeGen/CGExprScalar.cpp
lib/CodeGen/Mangle.cpp
lib/Parse/ParseExpr.cpp
lib/Parse/ParseExprCXX.cpp
lib/Sema/SemaExprCXX.cpp
lib/Sema/TreeTransform.h
lib/Serialization/ASTReaderStmt.cpp
lib/Serialization/ASTWriterStmt.cpp
test/SemaCXX/type-traits.cpp
tools/libclang/CIndex.cpp
tools/libclang/CXCursor.cpp

index 3c699c44c760f5051cc0fe99e099e7fd38ef699f..d7dc56b4a9877a49990fb542f68abb54d53192f7 100644 (file)
@@ -1452,6 +1452,72 @@ public:
   friend class ASTStmtReader;
 };
 
+/// BinaryTypeTraitExpr - A GCC or MS binary type trait, as used in the
+/// implementation of TR1/C++0x type trait templates.
+/// Example:
+/// __is_base_of(Base, Derived) == true
+class BinaryTypeTraitExpr : public Expr {
+  /// BTT - The trait. A BinaryTypeTrait enum in MSVC compat unsigned.
+  unsigned BTT : 8;
+
+  /// The value of the type trait. Unspecified if dependent.
+  bool Value : 1;
+
+  /// Loc - The location of the type trait keyword.
+  SourceLocation Loc;
+
+  /// RParen - The location of the closing paren.
+  SourceLocation RParen;
+
+  /// The lhs type being queried.
+  TypeSourceInfo *LhsType;
+
+  /// The rhs type being queried.
+  TypeSourceInfo *RhsType;
+
+public:
+  BinaryTypeTraitExpr(SourceLocation loc, BinaryTypeTrait btt, 
+                     TypeSourceInfo *lhsType, TypeSourceInfo *rhsType, 
+                     bool value, SourceLocation rparen, QualType ty)
+    : Expr(BinaryTypeTraitExprClass, ty, VK_RValue, OK_Ordinary, false, 
+           lhsType->getType()->isDependentType() ||
+           rhsType->getType()->isDependentType()),
+      BTT(btt), Value(value), Loc(loc), RParen(rparen),
+      LhsType(lhsType), RhsType(rhsType) { }
+
+
+  explicit BinaryTypeTraitExpr(EmptyShell Empty)
+    : Expr(BinaryTypeTraitExprClass, Empty), BTT(0), Value(false),
+      LhsType() { }
+
+  virtual SourceRange getSourceRange() const {
+    return SourceRange(Loc, RParen);
+  }
+
+  BinaryTypeTrait getTrait() const {
+    return static_cast<BinaryTypeTrait>(BTT);
+  }
+
+  QualType getLhsType() const { return LhsType->getType(); }
+  QualType getRhsType() const { return RhsType->getType(); }
+
+  TypeSourceInfo *getLhsTypeSourceInfo() const { return LhsType; }
+  TypeSourceInfo *getRhsTypeSourceInfo() const { return RhsType; }
+  
+  bool getValue() const { assert(!isTypeDependent()); 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 bad4689bb527feb372b1276220f872f3ff7bb231..c5b450f2c660ba5047cfcffadcf80b6e24585beb 100644 (file)
@@ -1735,6 +1735,11 @@ DEF_TRAVERSE_STMT(UnaryTypeTraitExpr, {
     TRY_TO(TraverseTypeLoc(S->getQueriedTypeSourceInfo()->getTypeLoc()));
   })
 
+DEF_TRAVERSE_STMT(BinaryTypeTraitExpr, {
+    TRY_TO(TraverseTypeLoc(S->getLhsTypeSourceInfo()->getTypeLoc()));
+    TRY_TO(TraverseTypeLoc(S->getRhsTypeSourceInfo()->getTypeLoc()));
+  })
+
 DEF_TRAVERSE_STMT(VAArgExpr, {
     // The child-iterator will pick up the expression argument.
     TRY_TO(TraverseTypeLoc(S->getWrittenTypeInfo()->getTypeLoc()));
index 9e444bd251f6776773f65a928470b13fc9c32a36..56db943025467c8c95c6a5f62e7a9cf19dfa6c7b 100644 (file)
@@ -100,6 +100,7 @@ def CXXNewExpr : DStmt<Expr>;
 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>;
index 36b830069f867bc3a64c009a395db843a43b855d..7c67634d9cda9f3ec6ca2069a299ac189490480e 100644 (file)
@@ -36,6 +36,10 @@ namespace clang {
     UTT_IsLiteral
   };
 
+  /// BinaryTypeTrait - Names for the binary type traits.
+  enum BinaryTypeTrait {
+    BTT_IsBaseOf,
+  };
 }
 
 #endif
index 75263823ccef28e05610688e3f7ef02e54b8f005..6063237323a7e365123a09cc4090bbd8c9d8c687 100644 (file)
@@ -1636,6 +1636,7 @@ private:
   //===--------------------------------------------------------------------===//
   // GNU G++: Type Traits [Type-Traits.html in the GCC manual]
   ExprResult ParseUnaryTypeTrait();
+  ExprResult ParseBinaryTypeTrait();
 
   //===--------------------------------------------------------------------===//
   // Preprocessor code-completion pass-through
index 838e4bc2ffbc927a483ff99c600b4b1f8a2e00e2..8b157bdeb869fce093ab0ed4419689b089d8a638 100644 (file)
@@ -2330,6 +2330,20 @@ public:
                                  TypeSourceInfo *T,
                                  SourceLocation RParen);
 
+  /// ActOnBinaryTypeTrait - Parsed one of the bianry type trait support
+  /// pseudo-functions.
+  ExprResult ActOnBinaryTypeTrait(BinaryTypeTrait OTT,
+                                  SourceLocation KWLoc,
+                                  ParsedType LhsTy,
+                                  ParsedType RhsTy,
+                                  SourceLocation RParen);
+
+  ExprResult BuildBinaryTypeTrait(BinaryTypeTrait BTT,
+                                  SourceLocation KWLoc,
+                                  TypeSourceInfo *LhsT,
+                                  TypeSourceInfo *RhsT,
+                                  SourceLocation RParen);
+
   ExprResult ActOnStartCXXMemberReference(Scope *S,
                                           Expr *Base,
                                           SourceLocation OpLoc,
index edce6b0018528398d231f4a3b1299bf3cfd42eaf..3e96fd6047eb785261e16e0b901b863ac651281f 100644 (file)
@@ -926,7 +926,8 @@ namespace clang {
       EXPR_CXX_UNARY_TYPE_TRAIT,  // UnaryTypeTraitExpr
       EXPR_CXX_NOEXCEPT,          // CXXNoexceptExpr
 
-      EXPR_OPAQUE_VALUE           // OpaqueValueExpr
+      EXPR_OPAQUE_VALUE,          // OpaqueValueExpr
+      EXPR_CXX_BINARY_TYPE_TRAIT  // BinaryTypeTraitExpr
     };
 
     /// \brief The kinds of designators that can occur in a
index a6d6f48606d6ac12a2b7ec5c325d6d6d4daa0a72..b67e82453dcc28d71f7256a817f54a4b84de2ed3 100644 (file)
@@ -304,6 +304,14 @@ Stmt::child_iterator UnaryTypeTraitExpr::child_end() {
   return child_iterator();
 }
 
+//BinaryTypeTraitExpr
+Stmt::child_iterator BinaryTypeTraitExpr::child_begin() {
+  return child_iterator();
+}
+Stmt::child_iterator BinaryTypeTraitExpr::child_end() {
+  return child_iterator();
+}
+
 // DependentScopeDeclRefExpr
 DependentScopeDeclRefExpr *
 DependentScopeDeclRefExpr::Create(ASTContext &C,
index 3788dc743fd5f8878704fd99a0bbcab76f52af62..76e98865ec712d603fa954ed6b57e69121cc5507 100644 (file)
@@ -146,6 +146,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
   case Expr::CXXNoexceptExprClass:
   case Expr::CXXScalarValueInitExprClass:
   case Expr::UnaryTypeTraitExprClass:
+  case Expr::BinaryTypeTraitExprClass:
   case Expr::ObjCSelectorExprClass:
   case Expr::ObjCProtocolExprClass:
   case Expr::ObjCStringLiteralClass:
index a79ae82a34bf1e7c7c1058947832cab634c05d5d..7479d9d9be21d405cca4ce3a73e0b9574aea98ef 100644 (file)
@@ -964,6 +964,10 @@ public:
     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));
   }
@@ -2526,6 +2530,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
   case Expr::CXXScalarValueInitExprClass:
   case Expr::TypesCompatibleExprClass:
   case Expr::UnaryTypeTraitExprClass:
+  case Expr::BinaryTypeTraitExprClass:
   case Expr::CXXNoexceptExprClass:
     return NoDiag();
   case Expr::CallExprClass:
index aba4d7e38980e720542706663c970176053ab18d..b1f6df37cc1c640de4448b53c0ff307a39fc1027 100644 (file)
@@ -1206,7 +1206,6 @@ void StmtPrinter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *Node) {
 
 static const char *getTypeTraitName(UnaryTypeTrait UTT) {
   switch (UTT) {
-  default: assert(false && "Unknown type trait");
   case UTT_HasNothrowAssign:      return "__has_nothrow_assign";
   case UTT_HasNothrowCopy:        return "__has_nothrow_copy";
   case UTT_HasNothrowConstructor: return "__has_nothrow_constructor";
@@ -1223,6 +1222,16 @@ static const char *getTypeTraitName(UnaryTypeTrait UTT) {
   case UTT_IsPolymorphic:         return "__is_polymorphic";
   case UTT_IsUnion:               return "__is_union";
   }
+  llvm_unreachable("Unknown unary type trait");
+  return "";
+}
+
+static const char *getTypeTraitName(BinaryTypeTrait BTT) {
+  switch (BTT) {
+  case BTT_IsBaseOf:      return "__is_base_of";
+  }
+  llvm_unreachable("Unknown binary type trait");
+  return "";
 }
 
 void StmtPrinter::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) {
@@ -1230,6 +1239,12 @@ void StmtPrinter::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) {
      << E->getQueriedType().getAsString(Policy) << ")";
 }
 
+void StmtPrinter::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) {
+  OS << getTypeTraitName(E->getTrait()) << "("
+     << E->getLhsType().getAsString(Policy) << ","
+     << E->getRhsType().getAsString(Policy) << ")";
+}
+
 void StmtPrinter::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) {
   OS << "noexcept(";
   PrintExpr(E->getOperand());
index 10cba341afa19a18751fa5639b7984a2f95de370..abcda7303f600d358fe6dbe675d2111ad53401c4 100644 (file)
@@ -780,6 +780,13 @@ void StmtProfiler::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *S) {
   VisitType(S->getQueriedType());
 }
 
+void StmtProfiler::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *S) {
+  VisitExpr(S);
+  ID.AddInteger(S->getTrait());
+  VisitType(S->getLhsType());
+  VisitType(S->getRhsType());
+}
+
 void
 StmtProfiler::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *S) {
   VisitExpr(S);
index 4d6dc13c361712dfac484096820afb2bc260337c..bee2db36cf90cdd877ff7a6d03bcfa5b9915e73a 100644 (file)
@@ -809,6 +809,7 @@ void GRExprEngine::Visit(const Stmt* S, ExplodedNode* Pred,
     case Stmt::CXXScalarValueInitExprClass:
     case Stmt::DependentScopeDeclRefExprClass:
     case Stmt::UnaryTypeTraitExprClass:
+    case Stmt::BinaryTypeTraitExprClass:
     case Stmt::UnresolvedLookupExprClass:
     case Stmt::UnresolvedMemberExprClass:
     case Stmt::CXXNoexceptExprClass:
index 841f1299d243f28e650691d7bea07427c3451f10..62a18dbeabfa4a2516b97264fc515c608291f82a 100644 (file)
@@ -353,6 +353,10 @@ public:
     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:
     //   The result shall only be used as the operand for the function call
index 24790b8df20cbf0f349fbfffc09d0d4ac8709c11..b95573227b61662b1193b27106acb9979da8263b 100644 (file)
@@ -1664,6 +1664,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {
   case Expr::StmtExprClass:
   case Expr::TypesCompatibleExprClass:
   case Expr::UnaryTypeTraitExprClass:
+  case Expr::BinaryTypeTraitExprClass:
   case Expr::VAArgExprClass:
   case Expr::CXXUuidofExprClass:
   case Expr::CXXNoexceptExprClass: {
index 0accc4bcd8b0563231f51bc359f31d77757f66b0..65b62498778aa98bfb4deb06911a15a574f9e7a8 100644 (file)
@@ -987,6 +987,9 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
   case tok::kw___has_virtual_destructor:
     return ParseUnaryTypeTrait();
 
+  case tok::kw___is_base_of:
+    return ParseBinaryTypeTrait();
+
   case tok::at: {
     SourceLocation AtLoc = ConsumeToken();
     return ParseObjCAtExpression(AtLoc);
index 1d09fe2a1afbe0a06e69210b1725a883901ece63..964205b18f93144128895b6e025fb3b04bbdeefc 100644 (file)
@@ -1800,7 +1800,6 @@ Parser::ParseCXXDeleteExpression(bool UseGlobal, SourceLocation Start) {
 
 static UnaryTypeTrait UnaryTypeTraitFromTokKind(tok::TokenKind kind) {
   switch(kind) {
-  default: assert(false && "Not a known unary type trait.");
   case tok::kw___has_nothrow_assign:      return UTT_HasNothrowAssign;
   case tok::kw___has_nothrow_copy:        return UTT_HasNothrowCopy;
   case tok::kw___has_nothrow_constructor: return UTT_HasNothrowConstructor;
@@ -1818,6 +1817,14 @@ static UnaryTypeTrait UnaryTypeTraitFromTokKind(tok::TokenKind kind) {
   case tok::kw___is_union:                return UTT_IsUnion;
   case tok::kw___is_literal:              return UTT_IsLiteral;
   }
+  llvm_unreachable("Not a known unary type trait");
+}
+
+static BinaryTypeTrait BinaryTypeTraitFromTokKind(tok::TokenKind kind) {
+  switch(kind) {
+  case tok::kw___is_base_of:      return BTT_IsBaseOf;
+  }
+  llvm_unreachable("Not a known binary type trait");
 }
 
 /// ParseUnaryTypeTrait - Parse the built-in unary type-trait
@@ -1848,6 +1855,43 @@ ExprResult Parser::ParseUnaryTypeTrait() {
   return Actions.ActOnUnaryTypeTrait(UTT, Loc, Ty.get(), RParen);
 }
 
+/// ParseBinaryTypeTrait - Parse the built-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 LhsTy = ParseTypeName();
+  if (LhsTy.isInvalid()) {
+    SkipUntil(tok::r_paren);
+    return ExprError();
+  }
+
+  if (ExpectAndConsume(tok::comma, diag::err_expected_comma)) {
+    SkipUntil(tok::r_paren);
+    return ExprError();
+  }
+
+  TypeResult RhsTy = ParseTypeName();
+  if (RhsTy.isInvalid()) {
+    SkipUntil(tok::r_paren);
+    return ExprError();
+  }
+
+  SourceLocation RParen = MatchRHSPunctuation(tok::r_paren, LParen);
+
+  return Actions.ActOnBinaryTypeTrait(BTT, Loc, LhsTy.get(), RhsTy.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 5b377cc7785f2963e762eda57b9d6c6f5235d90b..7be1c3307af404a8ca91228979e28e6883312415 100644 (file)
@@ -2342,6 +2342,77 @@ ExprResult Sema::BuildUnaryTypeTrait(UnaryTypeTrait UTT,
                                                 RParen, Context.BoolTy));
 }
 
+ExprResult Sema::ActOnBinaryTypeTrait(BinaryTypeTrait BTT,
+                                      SourceLocation KWLoc,
+                                      ParsedType LhsTy,
+                                      ParsedType RhsTy,
+                                      SourceLocation RParen) {
+  TypeSourceInfo *LhsTSInfo;
+  QualType LhsT = GetTypeFromParser(LhsTy, &LhsTSInfo);
+  if (!LhsTSInfo)
+    LhsTSInfo = Context.getTrivialTypeSourceInfo(LhsT);
+
+  TypeSourceInfo *RhsTSInfo;
+  QualType RhsT = GetTypeFromParser(RhsTy, &RhsTSInfo);
+  if (!RhsTSInfo)
+    RhsTSInfo = Context.getTrivialTypeSourceInfo(RhsT);
+
+  return BuildBinaryTypeTrait(BTT, KWLoc, LhsTSInfo, RhsTSInfo, RParen);
+}
+
+static bool EvaluateBinaryTypeTrait(Sema &Self, BinaryTypeTrait BTT,
+                                    QualType LhsT, QualType RhsT,
+                                    SourceLocation KeyLoc) {
+  assert((!LhsT->isDependentType() || RhsT->isDependentType()) &&
+         "Cannot evaluate traits for dependent types.");
+
+  switch(BTT) {
+  case BTT_IsBaseOf:
+    // C++0x [meta.rel]p2
+    // Base is a base class of Derived  without regard to cv-qualifiers or
+    // Base and Derived are not unions and name the same class type without
+    // regard to cv-qualifiers.
+    if (Self.IsDerivedFrom(RhsT, LhsT) || 
+        (!LhsT->isUnionType() &&  !RhsT->isUnionType()
+         && LhsT->getAsCXXRecordDecl() == RhsT->getAsCXXRecordDecl()))
+      return true;
+
+    return false;
+  }
+  llvm_unreachable("Unknown type trait or not implemented");
+}
+
+ExprResult Sema::BuildBinaryTypeTrait(BinaryTypeTrait BTT,
+                                      SourceLocation KWLoc,
+                                      TypeSourceInfo *LhsTSInfo,
+                                      TypeSourceInfo *RhsTSInfo,
+                                      SourceLocation RParen) {
+  QualType LhsT = LhsTSInfo->getType();
+  QualType RhsT = RhsTSInfo->getType();
+  
+  if (BTT == BTT_IsBaseOf) {
+    // C++0x [meta.rel]p2
+    // If Base and Derived are class types and are different types
+    // (ignoring possible cv-qualifiers) then Derived shall be a complete
+    // type. []
+    CXXRecordDecl *LhsDecl = LhsT->getAsCXXRecordDecl();
+    CXXRecordDecl *RhsDecl = RhsT->getAsCXXRecordDecl();
+    if (!LhsT->isDependentType() && !RhsT->isDependentType() &&
+        LhsDecl && RhsDecl && LhsT != RhsT &&
+        RequireCompleteType(KWLoc, RhsT,
+                            diag::err_incomplete_type_used_in_type_trait_expr))
+      return ExprError();
+  }
+
+  bool Value = false;
+  if (!LhsT->isDependentType() && !RhsT->isDependentType())
+    Value = EvaluateBinaryTypeTrait(*this, BTT, LhsT, RhsT, KWLoc);
+
+  return Owned(new (Context) BinaryTypeTraitExpr(KWLoc, BTT, LhsTSInfo,
+                                                 RhsTSInfo, Value, RParen,
+                                                 Context.BoolTy));
+}
+
 QualType Sema::CheckPointerToMemberOperands(Expr *&lex, Expr *&rex,
                                             ExprValueKind &VK,
                                             SourceLocation Loc,
index 8d3d4018ce425c63b7161b69afc7825704e146e6..816a1701d8639113c652e90e3612045e399862bc 100644 (file)
@@ -1657,6 +1657,18 @@ public:
     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 *LhsT,
+                                    TypeSourceInfo *RhsT,
+                                    SourceLocation RParenLoc) {
+    return getSema().BuildBinaryTypeTrait(Trait, StartLoc, LhsT, RhsT, RParenLoc);
+  }
+
   /// \brief Build a new (previously unresolved) declaration reference
   /// expression.
   ///
@@ -5665,6 +5677,27 @@ TreeTransform<Derived>::TransformUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) {
                                             E->getLocEnd());
 }
 
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) {
+  TypeSourceInfo *LhsT = getDerived().TransformType(E->getLhsTypeSourceInfo());
+  if (!LhsT)
+    return ExprError();
+
+  TypeSourceInfo *RhsT = getDerived().TransformType(E->getRhsTypeSourceInfo());
+  if (!RhsT)
+    return ExprError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      LhsT == E->getLhsTypeSourceInfo() && RhsT == E->getRhsTypeSourceInfo())
+    return SemaRef.Owned(E);
+
+  return getDerived().RebuildBinaryTypeTrait(E->getTrait(),
+                                            E->getLocStart(),
+                                            LhsT, RhsT,
+                                            E->getLocEnd());
+}
+
 template<typename Derived>
 ExprResult
 TreeTransform<Derived>::TransformDependentScopeDeclRefExpr(
index 6c63180e1295748bb1cef78a19c3361462afb838..f00b10743e758a4d58e604c1115bac67923d99c0 100644 (file)
@@ -175,6 +175,7 @@ namespace clang {
     void VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E);
 
     void VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E);
+    void VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E);
     void VisitCXXNoexceptExpr(CXXNoexceptExpr *E);
 
     void VisitOpaqueValueExpr(OpaqueValueExpr *E);
@@ -1275,6 +1276,17 @@ void ASTStmtReader::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) {
   E->QueriedType = GetTypeSourceInfo(Record, Idx);
 }
 
+void ASTStmtReader::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) {
+  VisitExpr(E);
+  E->BTT = (BinaryTypeTrait)Record[Idx++];
+  E->Value = (bool)Record[Idx++];
+  SourceRange Range = ReadSourceRange(Record, Idx);
+  E->Loc = Range.getBegin();
+  E->RParen = Range.getEnd();
+  E->LhsType = GetTypeSourceInfo(Record, Idx);
+  E->RhsType = GetTypeSourceInfo(Record, Idx);
+}
+
 void ASTStmtReader::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) {
   VisitExpr(E);
   E->Value = (bool)Record[Idx++];
@@ -1800,6 +1812,10 @@ Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) {
       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);
       break;
index 80f9a2980cd71ed3d787a35ca2c79b37b6427253..5e00b86cf34165a103d1b490d2b1428c2a89110a 100644 (file)
@@ -149,6 +149,7 @@ namespace clang {
     void VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E);
 
     void VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E);
+    void VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E);
     void VisitCXXNoexceptExpr(CXXNoexceptExpr *E);
 
     void VisitOpaqueValueExpr(OpaqueValueExpr *E);
@@ -1285,6 +1286,16 @@ void ASTStmtWriter::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) {
   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->getLhsTypeSourceInfo(), Record);
+  Writer.AddTypeSourceInfo(E->getRhsTypeSourceInfo(), Record);
+  Code = serialization::EXPR_CXX_BINARY_TYPE_TRAIT;
+}
+
 void ASTStmtWriter::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) {
   VisitExpr(E);
   Record.push_back(E->getValue());
index d75fd6644f74d89ebf3db01ad2d4e2d784460847..7962dffe32a3602ca91b93fda6b255777031ee10 100644 (file)
@@ -446,3 +446,54 @@ void has_virtual_destructor() {
   int t22[F(__has_virtual_destructor(void))];
   int t23[F(__has_virtual_destructor(cvoid))];
 }
+
+
+class Base {};
+class Derived : Base {};
+class Derived2a : Derived {};
+class Derived2b : Derived {};
+class Derived3 : virtual Derived2a, virtual Derived2b {};
+template<typename T> struct BaseA { T a;  };
+template<typename T> struct DerivedB : BaseA<T> { };
+template<typename T> struct CrazyDerived : T { };
+
+
+class class_forward; // expected-note {{forward declaration of 'class_forward'}}
+
+template <typename Base, typename Derived>
+void isBaseOfT() {
+  int t[T(__is_base_of(Base, Derived))];
+};
+template <typename Base, typename Derived>
+void isBaseOfF() {
+  int t[F(__is_base_of(Base, Derived))];
+};
+
+
+void is_base_of() {
+  int t01[T(__is_base_of(Base, Derived))];
+  int t02[T(__is_base_of(const Base, Derived))];
+  int t03[F(__is_base_of(Derived, Base))];
+  int t04[F(__is_base_of(Derived, int))];
+  int t05[T(__is_base_of(Base, Base))];
+  int t06[T(__is_base_of(Base, Derived3))];
+  int t07[T(__is_base_of(Derived, Derived3))];
+  int t08[T(__is_base_of(Derived2b, Derived3))];
+  int t09[T(__is_base_of(Derived2a, Derived3))];
+  int t10[T(__is_base_of(BaseA<int>, DerivedB<int>))];
+  int t11[F(__is_base_of(DerivedB<int>, BaseA<int>))];
+  int t12[T(__is_base_of(Base, CrazyDerived<Base>))];
+  int t13[F(__is_base_of(Union, Union))];
+  int t14[T(__is_base_of(Empty, Empty))];
+  int t15[T(__is_base_of(class_forward, class_forward))];
+  int t16[F(__is_base_of(Empty, class_forward))]; // expected-error {{incomplete type 'class_forward' used in type trait expression}}   
+
+  isBaseOfT<Base, Derived>();
+  isBaseOfF<Derived, Base>();
+
+  isBaseOfT<Base, CrazyDerived<Base> >();
+  isBaseOfF<CrazyDerived<Base>, Base>();
+
+  isBaseOfT<BaseA<int>, DerivedB<int> >();
+  isBaseOfF<DerivedB<int>, BaseA<int> >();
+}
index 81280f48667d84911eed459d97dbb74e396b506c..e386180ab95ce28f0a65914369116b4228de2bee 100644 (file)
@@ -1608,6 +1608,7 @@ public:
   void VisitTypesCompatibleExpr(TypesCompatibleExpr *E);
   void VisitWhileStmt(WhileStmt *W);
   void VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E);
+  void VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E);
   void VisitUnresolvedMemberExpr(UnresolvedMemberExpr *U);
   void VisitVAArgExpr(VAArgExpr *E);
 
@@ -1890,6 +1891,12 @@ void EnqueueVisitor::VisitWhileStmt(WhileStmt *W) {
 void EnqueueVisitor::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) {
   AddTypeLoc(E->getQueriedTypeSourceInfo());
 }
+
+void EnqueueVisitor::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) {
+  AddTypeLoc(E->getLhsTypeSourceInfo());
+  AddTypeLoc(E->getRhsTypeSourceInfo());
+}
+
 void EnqueueVisitor::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *U) {
   VisitOverloadExpr(U);
   if (!U->isImplicitAccess())
index 14643d7eb80141faaef90ab92f561b0d74d18ad7..ab4053260eb901119d957ffb3d25322fe31c8775 100644 (file)
@@ -149,6 +149,7 @@ CXCursor cxcursor::MakeCXCursor(Stmt *S, Decl *Parent,
   case Stmt::CXXPseudoDestructorExprClass:
   case Stmt::UnresolvedLookupExprClass:   
   case Stmt::UnaryTypeTraitExprClass:     
+  case Stmt::BinaryTypeTraitExprClass:     
   case Stmt::DependentScopeDeclRefExprClass:  
   case Stmt::CXXBindTemporaryExprClass:   
   case Stmt::ExprWithCleanupsClass: