diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/ExprCXX.cpp | 8 | ||||
-rw-r--r-- | lib/AST/ExprClassification.cpp | 1 | ||||
-rw-r--r-- | lib/AST/ExprConstant.cpp | 5 | ||||
-rw-r--r-- | lib/AST/StmtPrinter.cpp | 17 | ||||
-rw-r--r-- | lib/AST/StmtProfile.cpp | 7 | ||||
-rw-r--r-- | lib/Checker/GRExprEngine.cpp | 1 | ||||
-rw-r--r-- | lib/CodeGen/CGExprScalar.cpp | 4 | ||||
-rw-r--r-- | lib/CodeGen/Mangle.cpp | 1 | ||||
-rw-r--r-- | lib/Parse/ParseExpr.cpp | 3 | ||||
-rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 46 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 71 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 33 | ||||
-rw-r--r-- | lib/Serialization/ASTReaderStmt.cpp | 16 | ||||
-rw-r--r-- | lib/Serialization/ASTWriterStmt.cpp | 11 |
14 files changed, 222 insertions, 2 deletions
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. /// @@ -5667,6 +5679,27 @@ TreeTransform<Derived>::TransformUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) { 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( DependentScopeDeclRefExpr *E) { NestedNameSpecifier *NNS 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()); |