From: Francois Pichet Date: Tue, 7 Dec 2010 00:08:36 +0000 (+0000) Subject: Type traits intrinsic implementation: __is_base_of(T, U) X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6ad6f2848d7652ab2991286eb48be440d3493b28;p=clang Type traits intrinsic implementation: __is_base_of(T, U) 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 --- diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 3c699c44c7..d7dc56b4a9 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -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(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 { diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index bad4689bb5..c5b450f2c6 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -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())); diff --git a/include/clang/Basic/StmtNodes.td b/include/clang/Basic/StmtNodes.td index 9e444bd251..56db943025 100644 --- a/include/clang/Basic/StmtNodes.td +++ b/include/clang/Basic/StmtNodes.td @@ -100,6 +100,7 @@ def CXXNewExpr : DStmt; def CXXDeleteExpr : DStmt; def CXXPseudoDestructorExpr : DStmt; def UnaryTypeTraitExpr : DStmt; +def BinaryTypeTraitExpr : DStmt; def DependentScopeDeclRefExpr : DStmt; def CXXConstructExpr : DStmt; def CXXBindTemporaryExpr : DStmt; diff --git a/include/clang/Basic/TypeTraits.h b/include/clang/Basic/TypeTraits.h index 36b830069f..7c67634d9c 100644 --- a/include/clang/Basic/TypeTraits.h +++ b/include/clang/Basic/TypeTraits.h @@ -36,6 +36,10 @@ namespace clang { UTT_IsLiteral }; + /// BinaryTypeTrait - Names for the binary type traits. + enum BinaryTypeTrait { + BTT_IsBaseOf, + }; } #endif diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 75263823cc..6063237323 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -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 diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 838e4bc2ff..8b157bdeb8 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -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, diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h index edce6b0018..3e96fd6047 100644 --- a/include/clang/Serialization/ASTBitCodes.h +++ b/include/clang/Serialization/ASTBitCodes.h @@ -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 diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index a6d6f48606..b67e82453d 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -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, diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp index 3788dc743f..76e98865ec 100644 --- a/lib/AST/ExprClassification.cpp +++ b/lib/AST/ExprClassification.cpp @@ -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: diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index a79ae82a34..7479d9d9be 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -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: diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index aba4d7e389..b1f6df37cc 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -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()); diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp index 10cba341af..abcda7303f 100644 --- a/lib/AST/StmtProfile.cpp +++ b/lib/AST/StmtProfile.cpp @@ -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); diff --git a/lib/Checker/GRExprEngine.cpp b/lib/Checker/GRExprEngine.cpp index 4d6dc13c36..bee2db36cf 100644 --- a/lib/Checker/GRExprEngine.cpp +++ b/lib/Checker/GRExprEngine.cpp @@ -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: diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index 841f1299d2..62a18dbeab 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -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 diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp index 24790b8df2..b95573227b 100644 --- a/lib/CodeGen/Mangle.cpp +++ b/lib/CodeGen/Mangle.cpp @@ -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: { diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 0accc4bcd8..65b6249877 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -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); diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index 1d09fe2a1a..964205b18f 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -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. diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 5b377cc778..7be1c3307a 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -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, diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 8d3d4018ce..816a1701d8 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -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::TransformUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) { E->getLocEnd()); } +template +ExprResult +TreeTransform::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 ExprResult TreeTransform::TransformDependentScopeDeclRefExpr( diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp index 6c63180e12..f00b10743e 100644 --- a/lib/Serialization/ASTReaderStmt.cpp +++ b/lib/Serialization/ASTReaderStmt.cpp @@ -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; diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp index 80f9a2980c..5e00b86cf3 100644 --- a/lib/Serialization/ASTWriterStmt.cpp +++ b/lib/Serialization/ASTWriterStmt.cpp @@ -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()); diff --git a/test/SemaCXX/type-traits.cpp b/test/SemaCXX/type-traits.cpp index d75fd6644f..7962dffe32 100644 --- a/test/SemaCXX/type-traits.cpp +++ b/test/SemaCXX/type-traits.cpp @@ -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 struct BaseA { T a; }; +template struct DerivedB : BaseA { }; +template struct CrazyDerived : T { }; + + +class class_forward; // expected-note {{forward declaration of 'class_forward'}} + +template +void isBaseOfT() { + int t[T(__is_base_of(Base, Derived))]; +}; +template +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, DerivedB))]; + int t11[F(__is_base_of(DerivedB, BaseA))]; + int t12[T(__is_base_of(Base, CrazyDerived))]; + 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(); + isBaseOfF(); + + isBaseOfT >(); + isBaseOfF, Base>(); + + isBaseOfT, DerivedB >(); + isBaseOfF, BaseA >(); +} diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index 81280f4866..e386180ab9 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -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()) diff --git a/tools/libclang/CXCursor.cpp b/tools/libclang/CXCursor.cpp index 14643d7eb8..ab4053260e 100644 --- a/tools/libclang/CXCursor.cpp +++ b/tools/libclang/CXCursor.cpp @@ -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: