diff options
Diffstat (limited to 'lib')
29 files changed, 659 insertions, 288 deletions
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 209e5d3260..7e46d4fe45 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -2003,6 +2003,10 @@ bool Expr::isTemporaryObject(ASTContext &C, const CXXRecordDecl *TempTy) const { if (isa<MemberExpr>(E)) return false; + // - opaque values (all) + if (isa<OpaqueValueExpr>(E)) + return false; + return true; } diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp index 593f7830b4..890898a985 100644 --- a/lib/AST/ExprClassification.cpp +++ b/lib/AST/ExprClassification.cpp @@ -29,7 +29,8 @@ static Cl::Kinds ClassifyUnnamed(ASTContext &Ctx, QualType T); static Cl::Kinds ClassifyMemberExpr(ASTContext &Ctx, const MemberExpr *E); static Cl::Kinds ClassifyBinaryOp(ASTContext &Ctx, const BinaryOperator *E); static Cl::Kinds ClassifyConditional(ASTContext &Ctx, - const ConditionalOperator *E); + const Expr *trueExpr, + const Expr *falseExpr); static Cl::ModifiableType IsModifiable(ASTContext &Ctx, const Expr *E, Cl::Kinds Kind, SourceLocation &Loc); @@ -274,10 +275,18 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { if (!Lang.CPlusPlus) return Cl::CL_PRValue; return ClassifyUnnamed(Ctx, cast<ExplicitCastExpr>(E)->getTypeAsWritten()); - case Expr::ConditionalOperatorClass: + case Expr::BinaryConditionalOperatorClass: { + if (!Lang.CPlusPlus) return Cl::CL_PRValue; + const BinaryConditionalOperator *co = cast<BinaryConditionalOperator>(E); + return ClassifyConditional(Ctx, co->getTrueExpr(), co->getFalseExpr()); + } + + case Expr::ConditionalOperatorClass: { // Once again, only C++ is interesting. if (!Lang.CPlusPlus) return Cl::CL_PRValue; - return ClassifyConditional(Ctx, cast<ConditionalOperator>(E)); + const ConditionalOperator *co = cast<ConditionalOperator>(E); + return ClassifyConditional(Ctx, co->getTrueExpr(), co->getFalseExpr()); + } // ObjC message sends are effectively function calls, if the target function // is known. @@ -447,13 +456,11 @@ static Cl::Kinds ClassifyBinaryOp(ASTContext &Ctx, const BinaryOperator *E) { return Cl::CL_PRValue; } -static Cl::Kinds ClassifyConditional(ASTContext &Ctx, - const ConditionalOperator *E) { +static Cl::Kinds ClassifyConditional(ASTContext &Ctx, const Expr *True, + const Expr *False) { assert(Ctx.getLangOptions().CPlusPlus && "This is only relevant for C++."); - Expr *True = E->getTrueExpr(); - Expr *False = E->getFalseExpr(); // C++ [expr.cond]p2 // If either the second or the third operand has type (cv) void, [...] // the result [...] is a prvalue. diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 0c3f647536..656bb99df9 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -48,6 +48,14 @@ struct EvalInfo { /// EvalResult - Contains information about the evaluation. Expr::EvalResult &EvalResult; + llvm::DenseMap<const OpaqueValueExpr*, APValue> OpaqueValues; + const APValue *getOpaqueValue(const OpaqueValueExpr *e) { + llvm::DenseMap<const OpaqueValueExpr*, APValue>::iterator + i = OpaqueValues.find(e); + if (i == OpaqueValues.end()) return 0; + return &i->second; + } + EvalInfo(const ASTContext &ctx, Expr::EvalResult& evalresult) : Ctx(ctx), EvalResult(evalresult) {} }; @@ -73,12 +81,24 @@ namespace { APSInt &getComplexIntReal() { return IntReal; } APSInt &getComplexIntImag() { return IntImag; } - void moveInto(APValue &v) { + void moveInto(APValue &v) const { if (isComplexFloat()) v = APValue(FloatReal, FloatImag); else v = APValue(IntReal, IntImag); } + void setFrom(const APValue &v) { + assert(v.isComplexFloat() || v.isComplexInt()); + if (v.isComplexFloat()) { + makeComplexFloat(); + FloatReal = v.getComplexFloatReal(); + FloatImag = v.getComplexFloatImag(); + } else { + makeComplexInt(); + IntReal = v.getComplexIntReal(); + IntImag = v.getComplexIntImag(); + } + } }; struct LValue { @@ -88,12 +108,18 @@ namespace { Expr *getLValueBase() { return Base; } CharUnits getLValueOffset() { return Offset; } - void moveInto(APValue &v) { + void moveInto(APValue &v) const { v = APValue(Base, Offset); } + void setFrom(const APValue &v) { + assert(v.isLValue()); + Base = v.getLValueBase(); + Offset = v.getLValueOffset(); + } }; } +static bool Evaluate(EvalInfo &info, const Expr *E); static bool EvaluateLValue(const Expr *E, LValue &Result, EvalInfo &Info); static bool EvaluatePointer(const Expr *E, LValue &Result, EvalInfo &Info); static bool EvaluateInteger(const Expr *E, APSInt &Result, EvalInfo &Info); @@ -295,6 +321,30 @@ public: bool VisitSizeOfPackExpr(SizeOfPackExpr *) { return false; } }; +class OpaqueValueEvaluation { + EvalInfo &info; + OpaqueValueExpr *opaqueValue; + +public: + OpaqueValueEvaluation(EvalInfo &info, OpaqueValueExpr *opaqueValue, + Expr *value) + : info(info), opaqueValue(opaqueValue) { + + // If evaluation fails, fail immediately. + if (!Evaluate(info, value)) { + this->opaqueValue = 0; + return; + } + info.OpaqueValues[opaqueValue] = info.EvalResult.Val; + } + + bool hasError() const { return opaqueValue == 0; } + + ~OpaqueValueEvaluation() { + if (opaqueValue) info.OpaqueValues.erase(opaqueValue); + } +}; + } // end anonymous namespace //===----------------------------------------------------------------------===// @@ -468,11 +518,14 @@ public: } bool VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) { return Success((Expr*)0); } + bool VisitBinaryConditionalOperator(BinaryConditionalOperator *E); bool VisitConditionalOperator(ConditionalOperator *E); bool VisitChooseExpr(ChooseExpr *E) { return Visit(E->getChosenSubExpr(Info.Ctx)); } bool VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E) { return Success((Expr*)0); } + + bool VisitOpaqueValueExpr(OpaqueValueExpr *E); // FIXME: Missing: @protocol, @selector }; } // end anonymous namespace @@ -616,6 +669,26 @@ bool PointerExprEvaluator::VisitCallExpr(CallExpr *E) { return false; } +bool PointerExprEvaluator::VisitOpaqueValueExpr(OpaqueValueExpr *e) { + const APValue *value = Info.getOpaqueValue(e); + if (!value) + return (e->getSourceExpr() ? Visit(e->getSourceExpr()) : false); + Result.setFrom(*value); + return true; +} + +bool PointerExprEvaluator:: +VisitBinaryConditionalOperator(BinaryConditionalOperator *e) { + OpaqueValueEvaluation opaque(Info, e->getOpaqueValue(), e->getCommon()); + if (opaque.hasError()) return false; + + bool cond; + if (!HandleConversionToBool(e->getCond(), cond, Info)) + return false; + + return Visit(cond ? e->getTrueExpr() : e->getFalseExpr()); +} + bool PointerExprEvaluator::VisitConditionalOperator(ConditionalOperator *E) { bool BoolResult; if (!HandleConversionToBool(E->getCond(), BoolResult, Info)) @@ -912,6 +985,15 @@ public: return Success(E->getValue(), E); } + bool VisitOpaqueValueExpr(OpaqueValueExpr *e) { + const APValue *value = Info.getOpaqueValue(e); + if (!value) { + if (e->getSourceExpr()) return Visit(e->getSourceExpr()); + return Error(e->getExprLoc(), diag::note_invalid_subexpr_in_ice, e); + } + return Success(value->getInt(), e); + } + bool CheckReferencedDecl(const Expr *E, const Decl *D); bool VisitDeclRefExpr(const DeclRefExpr *E) { return CheckReferencedDecl(E, E->getDecl()); @@ -930,6 +1012,7 @@ public: bool VisitOffsetOfExpr(const OffsetOfExpr *E); bool VisitUnaryOperator(const UnaryOperator *E); bool VisitConditionalOperator(const ConditionalOperator *E); + bool VisitBinaryConditionalOperator(const BinaryConditionalOperator *E); bool VisitCastExpr(CastExpr* E); bool VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr *E); @@ -1463,6 +1546,18 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { } } +bool IntExprEvaluator:: +VisitBinaryConditionalOperator(const BinaryConditionalOperator *e) { + OpaqueValueEvaluation opaque(Info, e->getOpaqueValue(), e->getCommon()); + if (opaque.hasError()) return false; + + bool cond; + if (!HandleConversionToBool(e->getCond(), cond, Info)) + return false; + + return Visit(cond ? e->getTrueExpr() : e->getFalseExpr()); +} + bool IntExprEvaluator::VisitConditionalOperator(const ConditionalOperator *E) { bool Cond; if (!HandleConversionToBool(E->getCond(), Cond, Info)) @@ -1784,6 +1879,7 @@ public: bool VisitCastExpr(CastExpr *E); bool VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E); bool VisitConditionalOperator(ConditionalOperator *E); + bool VisitBinaryConditionalOperator(BinaryConditionalOperator *E); bool VisitChooseExpr(const ChooseExpr *E) { return Visit(E->getChosenSubExpr(Info.Ctx)); } @@ -1794,6 +1890,14 @@ public: bool VisitDeclRefExpr(const DeclRefExpr *E); + bool VisitOpaqueValueExpr(const OpaqueValueExpr *e) { + const APValue *value = Info.getOpaqueValue(e); + if (!value) + return (e->getSourceExpr() ? Visit(e->getSourceExpr()) : false); + Result = value->getFloat(); + return true; + } + // FIXME: Missing: array subscript of vector, member of vector, // ImplicitValueInitExpr }; @@ -2047,6 +2151,18 @@ bool FloatExprEvaluator::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) return true; } +bool FloatExprEvaluator:: +VisitBinaryConditionalOperator(BinaryConditionalOperator *e) { + OpaqueValueEvaluation opaque(Info, e->getOpaqueValue(), e->getCommon()); + if (opaque.hasError()) return false; + + bool cond; + if (!HandleConversionToBool(e->getCond(), cond, Info)) + return false; + + return Visit(cond ? e->getTrueExpr() : e->getFalseExpr()); +} + bool FloatExprEvaluator::VisitConditionalOperator(ConditionalOperator *E) { bool Cond; if (!HandleConversionToBool(E->getCond(), Cond, Info)) @@ -2086,10 +2202,18 @@ public: bool VisitBinaryOperator(const BinaryOperator *E); bool VisitUnaryOperator(const UnaryOperator *E); bool VisitConditionalOperator(const ConditionalOperator *E); + bool VisitBinaryConditionalOperator(const BinaryConditionalOperator *E); bool VisitChooseExpr(const ChooseExpr *E) { return Visit(E->getChosenSubExpr(Info.Ctx)); } bool VisitUnaryExtension(const UnaryOperator *E) { return Visit(E->getSubExpr()); } + bool VisitOpaqueValueExpr(const OpaqueValueExpr *e) { + const APValue *value = Info.getOpaqueValue(e); + if (!value) + return (e->getSourceExpr() ? Visit(e->getSourceExpr()) : false); + Result.setFrom(*value); + return true; + } // FIXME Missing: ImplicitValueInitExpr }; } // end anonymous namespace @@ -2410,6 +2534,18 @@ bool ComplexExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { } } +bool ComplexExprEvaluator:: +VisitBinaryConditionalOperator(const BinaryConditionalOperator *e) { + OpaqueValueEvaluation opaque(Info, e->getOpaqueValue(), e->getCommon()); + if (opaque.hasError()) return false; + + bool cond; + if (!HandleConversionToBool(e->getCond(), cond, Info)) + return false; + + return Visit(cond ? e->getTrueExpr() : e->getFalseExpr()); +} + bool ComplexExprEvaluator::VisitConditionalOperator(const ConditionalOperator *E) { bool Cond; if (!HandleConversionToBool(E->getCond(), Cond, Info)) @@ -2422,20 +2558,15 @@ bool ComplexExprEvaluator::VisitConditionalOperator(const ConditionalOperator *E // Top level Expr::Evaluate method. //===----------------------------------------------------------------------===// -/// Evaluate - Return true if this is a constant which we can fold using -/// any crazy technique (that has nothing to do with language standards) that -/// we want to. If this function returns true, it returns the folded constant -/// in Result. -bool Expr::Evaluate(EvalResult &Result, const ASTContext &Ctx) const { - const Expr *E = this; - EvalInfo Info(Ctx, Result); +static bool Evaluate(EvalInfo &Info, const Expr *E) { if (E->getType()->isVectorType()) { if (!EvaluateVector(E, Info.EvalResult.Val, Info)) return false; } else if (E->getType()->isIntegerType()) { if (!IntExprEvaluator(Info, Info.EvalResult.Val).Visit(const_cast<Expr*>(E))) return false; - if (Result.Val.isLValue() && !IsGlobalLValue(Result.Val.getLValueBase())) + if (Info.EvalResult.Val.isLValue() && + !IsGlobalLValue(Info.EvalResult.Val.getLValueBase())) return false; } else if (E->getType()->hasPointerRepresentation()) { LValue LV; @@ -2461,6 +2592,15 @@ bool Expr::Evaluate(EvalResult &Result, const ASTContext &Ctx) const { return true; } +/// Evaluate - Return true if this is a constant which we can fold using +/// any crazy technique (that has nothing to do with language standards) that +/// we want to. If this function returns true, it returns the folded constant +/// in Result. +bool Expr::Evaluate(EvalResult &Result, const ASTContext &Ctx) const { + EvalInfo Info(Ctx, Result); + return ::Evaluate(Info, this); +} + bool Expr::EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx) const { EvalResult Scratch; @@ -2845,6 +2985,17 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { return NoDiag(); return ICEDiag(2, E->getLocStart()); } + case Expr::BinaryConditionalOperatorClass: { + const BinaryConditionalOperator *Exp = cast<BinaryConditionalOperator>(E); + ICEDiag CommonResult = CheckICE(Exp->getCommon(), Ctx); + if (CommonResult.Val == 2) return CommonResult; + ICEDiag FalseResult = CheckICE(Exp->getFalseExpr(), Ctx); + if (FalseResult.Val == 2) return FalseResult; + if (CommonResult.Val == 1) return CommonResult; + if (FalseResult.Val == 1 && + Exp->getCommon()->EvaluateAsInt(Ctx) == 0) return NoDiag(); + return FalseResult; + } case Expr::ConditionalOperatorClass: { const ConditionalOperator *Exp = cast<ConditionalOperator>(E); // If the condition (ignoring parens) is a __builtin_constant_p call, diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp index df6e39b2b3..2819a7e4b9 100644 --- a/lib/AST/ItaniumMangle.cpp +++ b/lib/AST/ItaniumMangle.cpp @@ -1753,6 +1753,18 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { break; } + // Even gcc-4.5 doesn't mangle this. + case Expr::BinaryConditionalOperatorClass: { + Diagnostic &Diags = Context.getDiags(); + unsigned DiagID = + Diags.getCustomDiagID(Diagnostic::Error, + "?: operator with omitted middle operand cannot be mangled"); + Diags.Report(E->getExprLoc(), DiagID) + << E->getStmtClassName() << E->getSourceRange(); + break; + } + + // These are used for internal purposes and cannot be meaningfully mangled. case Expr::OpaqueValueExprClass: llvm_unreachable("cannot mangle opaque value; mangling wrong thing?"); diff --git a/lib/AST/StmtDumper.cpp b/lib/AST/StmtDumper.cpp index e5e759d9ef..490e2eea6e 100644 --- a/lib/AST/StmtDumper.cpp +++ b/lib/AST/StmtDumper.cpp @@ -65,13 +65,6 @@ namespace { OS << '\n'; DumpSubTree(*CI++); } - if (const ConditionalOperator *CO = - dyn_cast<ConditionalOperator>(S)) { - if (CO->getSAVE()) { - OS << '\n'; - DumpSubTree(CO->getSAVE()); - } - } } } OS << ')'; diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index fa1736f376..a67e269790 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -792,21 +792,20 @@ void StmtPrinter::VisitCompoundAssignOperator(CompoundAssignOperator *Node) { } void StmtPrinter::VisitConditionalOperator(ConditionalOperator *Node) { PrintExpr(Node->getCond()); - - if (Node->getLHS()) { - OS << " ? "; - PrintExpr(Node->getLHS()); - OS << " : "; - } - else { // Handle GCC extension where LHS can be NULL. - OS << " ?: "; - } - + OS << " ? "; + PrintExpr(Node->getLHS()); + OS << " : "; PrintExpr(Node->getRHS()); } // GNU extensions. +void +StmtPrinter::VisitBinaryConditionalOperator(BinaryConditionalOperator *Node) { + PrintExpr(Node->getCommon()); + OS << " ?: "; + PrintExpr(Node->getFalseExpr()); +} void StmtPrinter::VisitAddrLabelExpr(AddrLabelExpr *Node) { OS << "&&" << Node->getLabel()->getName(); } diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp index 2ffb807abc..b54001167b 100644 --- a/lib/AST/StmtProfile.cpp +++ b/lib/AST/StmtProfile.cpp @@ -349,6 +349,10 @@ void StmtProfiler::VisitConditionalOperator(ConditionalOperator *S) { VisitExpr(S); } +void StmtProfiler::VisitBinaryConditionalOperator(BinaryConditionalOperator *S){ + VisitExpr(S); +} + void StmtProfiler::VisitAddrLabelExpr(AddrLabelExpr *S) { VisitExpr(S); VisitDecl(S->getLabel()); diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp index 6da4784405..abb8df5854 100644 --- a/lib/Analysis/CFG.cpp +++ b/lib/Analysis/CFG.cpp @@ -290,7 +290,8 @@ private: CFGBlock *VisitCaseStmt(CaseStmt *C); CFGBlock *VisitChooseExpr(ChooseExpr *C, AddStmtChoice asc); CFGBlock *VisitCompoundStmt(CompoundStmt *C); - CFGBlock *VisitConditionalOperator(ConditionalOperator *C, AddStmtChoice asc); + CFGBlock *VisitConditionalOperator(AbstractConditionalOperator *C, + AddStmtChoice asc); CFGBlock *VisitContinueStmt(ContinueStmt *C); CFGBlock *VisitDeclStmt(DeclStmt *DS); CFGBlock *VisitDeclSubExpr(DeclStmt* DS); @@ -326,8 +327,9 @@ private: CFGBlock *VisitBinaryOperatorForTemporaryDtors(BinaryOperator *E); CFGBlock *VisitCXXBindTemporaryExprForTemporaryDtors(CXXBindTemporaryExpr *E, bool BindToTemporary); - CFGBlock *VisitConditionalOperatorForTemporaryDtors(ConditionalOperator *E, - bool BindToTemporary); + CFGBlock * + VisitConditionalOperatorForTemporaryDtors(AbstractConditionalOperator *E, + bool BindToTemporary); // NYS == Not Yet Supported CFGBlock* NYS() { @@ -785,6 +787,9 @@ tryAgain: case Stmt::AddrLabelExprClass: return VisitAddrLabelExpr(cast<AddrLabelExpr>(S), asc); + case Stmt::BinaryConditionalOperatorClass: + return VisitConditionalOperator(cast<BinaryConditionalOperator>(S), asc); + case Stmt::BinaryOperatorClass: return VisitBinaryOperator(cast<BinaryOperator>(S), asc); @@ -1174,8 +1179,11 @@ CFGBlock* CFGBuilder::VisitCompoundStmt(CompoundStmt* C) { return LastBlock; } -CFGBlock *CFGBuilder::VisitConditionalOperator(ConditionalOperator *C, +CFGBlock *CFGBuilder::VisitConditionalOperator(AbstractConditionalOperator *C, AddStmtChoice asc) { + const BinaryConditionalOperator *BCO = dyn_cast<BinaryConditionalOperator>(C); + const OpaqueValueExpr *opaqueValue = (BCO ? BCO->getOpaqueValue() : NULL); + // Create the confluence block that will "merge" the results of the ternary // expression. CFGBlock* ConfluenceBlock = Block ? Block : createBlock(); @@ -1191,9 +1199,10 @@ CFGBlock *CFGBuilder::VisitConditionalOperator(ConditionalOperator *C, // e.g: x ?: y is shorthand for: x ? x : y; Succ = ConfluenceBlock; Block = NULL; - CFGBlock* LHSBlock = NULL; - if (C->getLHS()) { - LHSBlock = Visit(C->getLHS(), alwaysAdd); + CFGBlock* LHSBlock = 0; + const Expr *trueExpr = C->getTrueExpr(); + if (trueExpr != opaqueValue) { + LHSBlock = Visit(C->getTrueExpr(), alwaysAdd); if (badCFG) return 0; Block = NULL; @@ -1201,7 +1210,7 @@ CFGBlock *CFGBuilder::VisitConditionalOperator(ConditionalOperator *C, // Create the block for the RHS expression. Succ = ConfluenceBlock; - CFGBlock* RHSBlock = Visit(C->getRHS(), alwaysAdd); + CFGBlock* RHSBlock = Visit(C->getFalseExpr(), alwaysAdd); if (badCFG) return 0; @@ -1210,33 +1219,15 @@ CFGBlock *CFGBuilder::VisitConditionalOperator(ConditionalOperator *C, // See if this is a known constant. const TryResult& KnownVal = tryEvaluateBool(C->getCond()); - if (LHSBlock) { + if (LHSBlock) addSuccessor(Block, KnownVal.isFalse() ? NULL : LHSBlock); - } else { - if (KnownVal.isFalse()) { - // If we know the condition is false, add NULL as the successor for - // the block containing the condition. In this case, the confluence - // block will have just one predecessor. - addSuccessor(Block, 0); - assert(ConfluenceBlock->pred_size() == 1); - } else { - // If we have no LHS expression, add the ConfluenceBlock as a direct - // successor for the block containing the condition. Moreover, we need to - // reverse the order of the predecessors in the ConfluenceBlock because - // the RHSBlock will have been added to the succcessors already, and we - // want the first predecessor to the the block containing the expression - // for the case when the ternary expression evaluates to true. - addSuccessor(Block, ConfluenceBlock); - // Note that there can possibly only be one predecessor if one of the - // subexpressions resulted in calling a noreturn function. - std::reverse(ConfluenceBlock->pred_begin(), - ConfluenceBlock->pred_end()); - } - } - addSuccessor(Block, KnownVal.isTrue() ? NULL : RHSBlock); Block->setTerminator(C); - return addStmt(C->getCond()); + CFGBlock *result; + Expr *condExpr = C->getCond(); + if (condExpr != opaqueValue) result = addStmt(condExpr); + if (BCO) result = addStmt(BCO->getCommon()); + return result; } CFGBlock *CFGBuilder::VisitDeclStmt(DeclStmt *DS) { @@ -2485,9 +2476,10 @@ tryAgain: return VisitCXXBindTemporaryExprForTemporaryDtors( cast<CXXBindTemporaryExpr>(E), BindToTemporary); + case Stmt::BinaryConditionalOperatorClass: case Stmt::ConditionalOperatorClass: return VisitConditionalOperatorForTemporaryDtors( - cast<ConditionalOperator>(E), BindToTemporary); + cast<AbstractConditionalOperator>(E), BindToTemporary); case Stmt::ImplicitCastExprClass: // For implicit cast we want BindToTemporary to be passed further. @@ -2602,7 +2594,7 @@ CFGBlock *CFGBuilder::VisitCXXBindTemporaryExprForTemporaryDtors( } CFGBlock *CFGBuilder::VisitConditionalOperatorForTemporaryDtors( - ConditionalOperator *E, bool BindToTemporary) { + AbstractConditionalOperator *E, bool BindToTemporary) { // First add destructors for condition expression. Even if this will // unnecessarily create a block, this block will be used at least by the full // expression. @@ -2610,21 +2602,26 @@ CFGBlock *CFGBuilder::VisitConditionalOperatorForTemporaryDtors( CFGBlock *ConfluenceBlock = VisitForTemporaryDtors(E->getCond()); if (badCFG) return NULL; - - // Try to add block with destructors for LHS expression. - CFGBlock *LHSBlock = NULL; - if (E->getLHS()) { - Succ = ConfluenceBlock; - Block = NULL; - LHSBlock = VisitForTemporaryDtors(E->getLHS(), BindToTemporary); + if (BinaryConditionalOperator *BCO + = dyn_cast<BinaryConditionalOperator>(E)) { + ConfluenceBlock = VisitForTemporaryDtors(BCO->getCommon()); if (badCFG) return NULL; } + // Try to add block with destructors for LHS expression. + CFGBlock *LHSBlock = NULL; + Succ = ConfluenceBlock; + Block = NULL; + LHSBlock = VisitForTemporaryDtors(E->getTrueExpr(), BindToTemporary); + if (badCFG) + return NULL; + // Try to add block with destructors for RHS expression; Succ = ConfluenceBlock; Block = NULL; - CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getRHS(), BindToTemporary); + CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getFalseExpr(), + BindToTemporary); if (badCFG) return NULL; @@ -2969,7 +2966,7 @@ public: OS << "try ..."; } - void VisitConditionalOperator(ConditionalOperator* C) { + void VisitAbstractConditionalOperator(AbstractConditionalOperator* C) { C->getCond()->printPretty(OS, Helper, Policy); OS << " ? ... : ..."; } @@ -3307,6 +3304,10 @@ Stmt* CFGBlock::getTerminatorCondition() { E = cast<SwitchStmt>(Terminator)->getCond(); break; + case Stmt::BinaryConditionalOperatorClass: + E = cast<BinaryConditionalOperator>(Terminator)->getCond(); + break; + case Stmt::ConditionalOperatorClass: E = cast<ConditionalOperator>(Terminator)->getCond(); break; @@ -3338,6 +3339,7 @@ bool CFGBlock::hasBinaryBranchTerminator() const { case Stmt::DoStmtClass: case Stmt::IfStmtClass: case Stmt::ChooseExprClass: + case Stmt::BinaryConditionalOperatorClass: case Stmt::ConditionalOperatorClass: case Stmt::BinaryOperatorClass: return true; diff --git a/lib/Analysis/ReachableCode.cpp b/lib/Analysis/ReachableCode.cpp index 802b990143..7afa586479 100644 --- a/lib/Analysis/ReachableCode.cpp +++ b/lib/Analysis/ReachableCode.cpp @@ -78,8 +78,10 @@ static SourceLocation GetUnreachableLoc(const CFGBlock &b, SourceRange &R1, R2 = CAO->getRHS()->getSourceRange(); return CAO->getOperatorLoc(); } + case Expr::BinaryConditionalOperatorClass: case Expr::ConditionalOperatorClass: { - const ConditionalOperator *CO = cast<ConditionalOperator>(S); + const AbstractConditionalOperator *CO = + cast<AbstractConditionalOperator>(S); return CO->getQuestionLoc(); } case Expr::MemberExprClass: { diff --git a/lib/Analysis/UninitializedValues.cpp b/lib/Analysis/UninitializedValues.cpp index 570743268e..c08cbedf4b 100644 --- a/lib/Analysis/UninitializedValues.cpp +++ b/lib/Analysis/UninitializedValues.cpp @@ -72,7 +72,7 @@ public: bool VisitStmt(Stmt* S); bool VisitCallExpr(CallExpr* C); bool VisitDeclStmt(DeclStmt* D); - bool VisitConditionalOperator(ConditionalOperator* C); + bool VisitAbstractConditionalOperator(AbstractConditionalOperator* C); bool BlockStmt_VisitObjCForCollectionStmt(ObjCForCollectionStmt* S); bool Visit(Stmt *S); @@ -213,13 +213,14 @@ TransferFuncs::BlockStmt_VisitObjCForCollectionStmt(ObjCForCollectionStmt* S) { } -bool TransferFuncs::VisitConditionalOperator(ConditionalOperator* C) { +bool TransferFuncs:: +VisitAbstractConditionalOperator(AbstractConditionalOperator* C) { Visit(C->getCond()); - bool rhsResult = Visit(C->getRHS()); + bool rhsResult = Visit(C->getFalseExpr()); // Handle the GNU extension for missing LHS. - if (Expr *lhs = C->getLHS()) - return Visit(lhs) & rhsResult; // Yes: we want &, not &&. + if (isa<ConditionalOperator>(C)) + return Visit(C->getTrueExpr()) & rhsResult; // Yes: we want &, not &&. else return rhsResult |