aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2011-02-17 10:25:35 +0000
committerJohn McCall <rjmccall@apple.com>2011-02-17 10:25:35 +0000
commit56ca35d396d8692c384c785f9aeebcf22563fe1e (patch)
treecd52281e952ff00244a59c5d47e34459c22fd7c0 /lib
parent05c699e97aea64ee8cea1faaca900a39f977350c (diff)
Change the representation of GNU ?: expressions to use a different expression
class and to bind the shared value using OpaqueValueExpr. This fixes an unnoticed problem with deserialization of these expressions where the deserialized form would lose the vital pointer-equality trait; or rather, it fixes it because this patch also does the right thing for deserializing OVEs. Change OVEs to not be a "temporary object" in the sense that copy elision is permitted. This new representation is not totally unawkward to work with, but I think that's really part and parcel with the semantics we're modelling here. In particular, it's much easier to fix things like the copy elision bug and to make the CFG look right. I've tried to update the analyzer to deal with this in at least some obvious cases, and I think we get a much better CFG out, but the printing of OpaqueValueExprs probably needs some work. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@125744 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/AST/Expr.cpp4
-rw-r--r--lib/AST/ExprClassification.cpp21
-rw-r--r--lib/AST/ExprConstant.cpp171
-rw-r--r--lib/AST/ItaniumMangle.cpp12
-rw-r--r--lib/AST/StmtDumper.cpp7
-rw-r--r--lib/AST/StmtPrinter.cpp19
-rw-r--r--lib/AST/StmtProfile.cpp4
-rw-r--r--lib/Analysis/CFG.cpp88
-rw-r--r--lib/Analysis/ReachableCode.cpp4
-rw-r--r--lib/Analysis/UninitializedValues.cpp11
-rw-r--r--lib/CodeGen/CGException.cpp3
-rw-r--r--lib/CodeGen/CGExpr.cpp81
-rw-r--r--lib/CodeGen/CGExprAgg.cpp19
-rw-r--r--lib/CodeGen/CGExprComplex.cpp31
-rw-r--r--lib/CodeGen/CGExprScalar.cpp85
-rw-r--r--lib/CodeGen/CodeGenFunction.cpp27
-rw-r--r--lib/CodeGen/CodeGenFunction.h133
-rw-r--r--lib/Rewrite/RewriteObjC.cpp3
-rw-r--r--lib/Sema/SemaChecking.cpp12
-rw-r--r--lib/Sema/SemaExpr.cpp58
-rw-r--r--lib/Sema/SemaExprCXX.cpp17
-rw-r--r--lib/Sema/TreeTransform.h34
-rw-r--r--lib/Serialization/ASTReaderStmt.cpp46
-rw-r--r--lib/Serialization/ASTWriterStmt.cpp22
-rw-r--r--lib/StaticAnalyzer/Checkers/ExprEngine.cpp17
-rw-r--r--lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp3
-rw-r--r--lib/StaticAnalyzer/Core/BugReporter.cpp10
-rw-r--r--lib/StaticAnalyzer/Core/CoreEngine.cpp4
-rw-r--r--lib/StaticAnalyzer/Core/PathDiagnostic.cpp1
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());