summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/Expr.cpp4
-rw-r--r--clang/lib/AST/ExprClassification.cpp21
-rw-r--r--clang/lib/AST/ExprConstant.cpp171
-rw-r--r--clang/lib/AST/ItaniumMangle.cpp12
-rw-r--r--clang/lib/AST/StmtDumper.cpp7
-rw-r--r--clang/lib/AST/StmtPrinter.cpp19
-rw-r--r--clang/lib/AST/StmtProfile.cpp4
-rw-r--r--clang/lib/Analysis/CFG.cpp88
-rw-r--r--clang/lib/Analysis/ReachableCode.cpp4
-rw-r--r--clang/lib/Analysis/UninitializedValues.cpp11
-rw-r--r--clang/lib/CodeGen/CGException.cpp3
-rw-r--r--clang/lib/CodeGen/CGExpr.cpp81
-rw-r--r--clang/lib/CodeGen/CGExprAgg.cpp19
-rw-r--r--clang/lib/CodeGen/CGExprComplex.cpp31
-rw-r--r--clang/lib/CodeGen/CGExprScalar.cpp85
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.cpp27
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h133
-rw-r--r--clang/lib/Rewrite/RewriteObjC.cpp3
-rw-r--r--clang/lib/Sema/SemaChecking.cpp12
-rw-r--r--clang/lib/Sema/SemaExpr.cpp58
-rw-r--r--clang/lib/Sema/SemaExprCXX.cpp17
-rw-r--r--clang/lib/Sema/TreeTransform.h34
-rw-r--r--clang/lib/Serialization/ASTReaderStmt.cpp46
-rw-r--r--clang/lib/Serialization/ASTWriterStmt.cpp22
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/ExprEngine.cpp17
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp3
-rw-r--r--clang/lib/StaticAnalyzer/Core/BugReporter.cpp10
-rw-r--r--clang/lib/StaticAnalyzer/Core/CoreEngine.cpp4
-rw-r--r--clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp1
29 files changed, 659 insertions, 288 deletions
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 209e5d3260f..7e46d4fe450 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/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/clang/lib/AST/ExprClassification.cpp b/clang/lib/AST/ExprClassification.cpp
index 593f7830b4e..890898a985e 100644
--- a/clang/lib/AST/ExprClassification.cpp
+++ b/clang/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/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 0c3f6475369..656bb99df98 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/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/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index df6e39b2b3a..2819a7e4b97 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/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/clang/lib/AST/StmtDumper.cpp b/clang/lib/AST/StmtDumper.cpp
index e5e759d9eff..490e2eea6e3 100644
--- a/clang/lib/AST/StmtDumper.cpp
+++ b/clang/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/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index fa1736f3768..a67e269790c 100644
--- a/clang/lib/AST/StmtPrinter.cpp
+++ b/clang/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/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp
index 2ffb807abcd..b54001167b4 100644
--- a/clang/lib/AST/StmtProfile.cpp
+++ b/clang/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/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp
index 6da47844052..abb8df58544 100644
--- a/clang/lib/Analysis/CFG.cpp
+++ b/clang/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/clang/lib/Analysis/ReachableCode.cpp b/clang/lib/Analysis/ReachableCode.cpp
index 802b990143d..7afa586479b 100644
--- a/clang/lib/Analysis/ReachableCode.cpp
+++ b/clang/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/clang/lib/Analysis/UninitializedValues.cpp b/clang/lib/Analysis/UninitializedValues.cpp
index 570743268ed..c08cbedf4b9 100644
--- a/clang/lib/Analysis/UninitializedValues.cpp
+++ b/clang/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;
}
diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp
index 7f3bbb78986..0e717e26ab3 100644
--- a/clang/lib/CodeGen/CGException.cpp
+++ b/clang/lib/CodeGen/CGException.cpp
@@ -1052,7 +1052,8 @@ static void InitCatchParam(CodeGenFunction &CGF,
// The copy expression is defined in terms of an OpaqueValueExpr.
// Find it and map it to the adjusted expression.
CodeGenFunction::OpaqueValueMapping
- opaque(CGF, OpaqueValueExpr::findInCopyConstruct(copyExpr), adjustedExn);
+ opaque(CGF, OpaqueValueExpr::findInCopyConstruct(copyExpr),
+ CGF.MakeAddrLValue(adjustedExn, CatchParam.getType()));
// Call the copy ctor in a terminate scope.
CGF.EHStack.pushTerminate();
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 56a9107a82c..27316526b16 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -581,6 +581,8 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) {
return EmitCompoundLiteralLValue(cast<CompoundLiteralExpr>(E));
case Expr::ConditionalOperatorClass:
return EmitConditionalOperatorLValue(cast<ConditionalOperator>(E));
+ case Expr::BinaryConditionalOperatorClass:
+ return EmitConditionalOperatorLValue(cast<BinaryConditionalOperator>(E));
case Expr::ChooseExprClass:
return EmitLValue(cast<ChooseExpr>(E)->getChosenSubExpr(getContext()));
case Expr::OpaqueValueExprClass:
@@ -1675,68 +1677,64 @@ LValue CodeGenFunction::EmitCompoundLiteralLValue(const CompoundLiteralExpr *E){
return Result;
}
-LValue
-CodeGenFunction::EmitConditionalOperatorLValue(const ConditionalOperator *E) {
- if (!E->isGLValue()) {
+LValue CodeGenFunction::
+EmitConditionalOperatorLValue(const AbstractConditionalOperator *expr) {
+ if (!expr->isGLValue()) {
// ?: here should be an aggregate.
- assert((hasAggregateLLVMType(E->getType()) &&
- !E->getType()->isAnyComplexType()) &&
+ assert((hasAggregateLLVMType(expr->getType()) &&
+ !expr->getType()->isAnyComplexType()) &&
"Unexpected conditional operator!");
- return EmitAggExprToLValue(E);
+ return EmitAggExprToLValue(expr);
}
- if (int Cond = ConstantFoldsToSimpleInteger(E->getCond())) {
- Expr *Live = Cond == 1 ? E->getLHS() : E->getRHS();
- if (Live)
- return EmitLValue(Live);
+ const Expr *condExpr = expr->getCond();
+
+ if (int condValue = ConstantFoldsToSimpleInteger(condExpr)) {
+ const Expr *live = expr->getTrueExpr(), *dead = expr->getFalseExpr();
+ if (condValue == -1) std::swap(live, dead);
+
+ if (!ContainsLabel(dead))
+ return EmitLValue(live);
}
- llvm::BasicBlock *LHSBlock = createBasicBlock("cond.true");
- llvm::BasicBlock *RHSBlock = createBasicBlock("cond.false");
- llvm::BasicBlock *ContBlock = createBasicBlock("cond.end");
+ OpaqueValueMapping binding(*this, expr);
+
+ llvm::BasicBlock *lhsBlock = createBasicBlock("cond.true");
+ llvm::BasicBlock *rhsBlock = createBasicBlock("cond.false");
+ llvm::BasicBlock *contBlock = createBasicBlock("cond.end");
ConditionalEvaluation eval(*this);
-
- if (E->getLHS())
- EmitBranchOnBoolExpr(E->getCond(), LHSBlock, RHSBlock);
- else {
- Expr *save = E->getSAVE();
- assert(save && "VisitConditionalOperator - save is null");
- // Intentianlly not doing direct assignment to ConditionalSaveExprs[save]
- LValue SaveVal = EmitLValue(save);
- ConditionalSaveLValueExprs[save] = SaveVal;
- EmitBranchOnBoolExpr(E->getCond(), LHSBlock, RHSBlock);
- }
+ EmitBranchOnBoolExpr(condExpr, lhsBlock, rhsBlock);
// Any temporaries created here are conditional.
- EmitBlock(LHSBlock);
+ EmitBlock(lhsBlock);
eval.begin(*this);
- LValue LHS = EmitLValue(E->getTrueExpr());
+ LValue lhs = EmitLValue(expr->getTrueExpr());
eval.end(*this);
- if (!LHS.isSimple())
- return EmitUnsupportedLValue(E, "conditional operator");
+ if (!lhs.isSimple())
+ return EmitUnsupportedLValue(expr, "conditional operator");
- LHSBlock = Builder.GetInsertBlock();
- Builder.CreateBr(ContBlock);
+ lhsBlock = Builder.GetInsertBlock();
+ Builder.CreateBr(contBlock);
// Any temporaries created here are conditional.
- EmitBlock(RHSBlock);
+ EmitBlock(rhsBlock);
eval.begin(*this);
- LValue RHS = EmitLValue(E->getRHS());
+ LValue rhs = EmitLValue(expr->getFalseExpr());
eval.end(*this);
- if (!RHS.isSimple())
- return EmitUnsupportedLValue(E, "conditional operator");
- RHSBlock = Builder.GetInsertBlock();
+ if (!rhs.isSimple())
+ return EmitUnsupportedLValue(expr, "conditional operator");
+ rhsBlock = Builder.GetInsertBlock();
- EmitBlock(ContBlock);
+ EmitBlock(contBlock);
- llvm::PHINode *phi = Builder.CreatePHI(LHS.getAddress()->getType(),
+ llvm::PHINode *phi = Builder.CreatePHI(lhs.getAddress()->getType(),
"cond-lvalue");
phi->reserveOperandSpace(2);
- phi->addIncoming(LHS.getAddress(), LHSBlock);
- phi->addIncoming(RHS.getAddress(), RHSBlock);
- return MakeAddrLValue(phi, E->getType());
+ phi->addIncoming(lhs.getAddress(), lhsBlock);
+ phi->addIncoming(rhs.getAddress(), rhsBlock);
+ return MakeAddrLValue(phi, expr->getType());
}
/// EmitCastLValue - Casts are never lvalues unless that cast is a dynamic_cast.
@@ -1892,8 +1890,7 @@ LValue CodeGenFunction::EmitNullInitializationLValue(
LValue CodeGenFunction::EmitOpaqueValueLValue(const OpaqueValueExpr *e) {
assert(e->isGLValue() || e->getType()->isRecordType());
- llvm::Value *value = getOpaqueValueMapping(e);
- return MakeAddrLValue(value, e->getType());
+ return getOpaqueLValueMapping(e);
}
//===--------------------------------------------------------------------===//
diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp
index 0b3a617be15..f992dc7c9cb 100644
--- a/clang/lib/CodeGen/CGExprAgg.cpp
+++ b/clang/lib/CodeGen/CGExprAgg.cpp
@@ -116,7 +116,7 @@ public:
}
void VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E);
- void VisitConditionalOperator(const ConditionalOperator *CO);
+ void VisitAbstractConditionalOperator(const AbstractConditionalOperator *CO);
void VisitChooseExpr(const ChooseExpr *CE);
void VisitInitListExpr(InitListExpr *E);
void VisitImplicitValueInitExpr(ImplicitValueInitExpr *E);
@@ -245,7 +245,7 @@ void AggExprEmitter::EmitFinalDestCopy(const Expr *E, LValue Src, bool Ignore) {
//===----------------------------------------------------------------------===//
void AggExprEmitter::VisitOpaqueValueExpr(OpaqueValueExpr *e) {
- EmitFinalDestCopy(e, CGF.EmitOpaqueValueLValue(e));
+ EmitFinalDestCopy(e, CGF.getOpaqueLValueMapping(e));
}
void AggExprEmitter::VisitCastExpr(CastExpr *E) {
@@ -419,16 +419,15 @@ void AggExprEmitter::VisitBinAssign(const BinaryOperator *E) {
}
}
-void AggExprEmitter::VisitConditionalOperator(const ConditionalOperator *E) {
- if (!E->getLHS()) {
- CGF.ErrorUnsupported(E, "conditional operator with missing LHS");
- return;
- }
-
+void AggExprEmitter::
+VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
llvm::BasicBlock *LHSBlock = CGF.createBasicBlock("cond.true");
llvm::BasicBlock *RHSBlock = CGF.createBasicBlock("cond.false");
llvm::BasicBlock *ContBlock = CGF.createBasicBlock("cond.end");
+ // Bind the common expression if necessary.
+ CodeGenFunction::OpaqueValueMapping binding(CGF, E);
+
CodeGenFunction::ConditionalEvaluation eval(CGF);
CGF.EmitBranchOnBoolExpr(E->getCond(), LHSBlock, RHSBlock);
@@ -437,7 +436,7 @@ void AggExprEmitter::VisitConditionalOperator(const ConditionalOperator *E) {
eval.begin(CGF);
CGF.EmitBlock(LHSBlock);
- Visit(E->getLHS());
+ Visit(E->getTrueExpr());
eval.end(CGF);
assert(CGF.HaveInsertPoint() && "expression evaluation ended with no IP!");
@@ -451,7 +450,7 @@ void AggExprEmitter::VisitConditionalOperator(const ConditionalOperator *E) {
eval.begin(CGF);
CGF.EmitBlock(RHSBlock);
- Visit(E->getRHS());
+ Visit(E->getFalseExpr());
eval.end(CGF);
CGF.EmitBlock(ContBlock);
diff --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp
index 15901eb99a8..8b4ead8b111 100644
--- a/clang/lib/CodeGen/CGExprComplex.cpp
+++ b/clang/lib/CodeGen/CGExprComplex.cpp
@@ -130,12 +130,9 @@ public:
ComplexPairTy VisitArraySubscriptExpr(Expr *E) { return EmitLoadOfLValue(E); }
ComplexPairTy VisitMemberExpr(const Expr *E) { return EmitLoadOfLValue(E); }
ComplexPairTy VisitOpaqueValueExpr(OpaqueValueExpr *E) {
- if (E->isGLValue()) return EmitLoadOfLValue(E);
-
- // Otherwise, the mapping is... what, exactly? Probably a
- // first-class aggregate, but it's really just not worthwhile.
- CGF.ErrorUnsupported(E, "complex opaque r-value");
- return ComplexPairTy();
+ if (E->isGLValue())
+ return EmitLoadOfLValue(CGF.getOpaqueLValueMapping(E));
+ return CGF.getOpaqueRValueMapping(E).getComplexVal();
}
// FIXME: CompoundLiteralExpr
@@ -260,7 +257,8 @@ public:
ComplexPairTy VisitBinComma (const BinaryOperator *E);
- ComplexPairTy VisitConditionalOperator(const ConditionalOperator *CO);
+ ComplexPairTy
+ VisitAbstractConditionalOperator(const AbstractConditionalOperator *CO);
ComplexPairTy VisitChooseExpr(ChooseExpr *CE);
ComplexPairTy VisitInitListExpr(InitListExpr *E);
@@ -647,25 +645,18 @@ ComplexPairTy ComplexExprEmitter::VisitBinComma(const BinaryOperator *E) {
}
ComplexPairTy ComplexExprEmitter::
-VisitConditionalOperator(const ConditionalOperator *E) {
+VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
TestAndClearIgnoreReal();
TestAndClearIgnoreImag();
llvm::BasicBlock *LHSBlock = CGF.createBasicBlock("cond.true");
llvm::BasicBlock *RHSBlock = CGF.createBasicBlock("cond.false");
llvm::BasicBlock *ContBlock = CGF.createBasicBlock("cond.end");
- CodeGenFunction::ConditionalEvaluation eval(CGF);
+ // Bind the common expression if necessary.
+ CodeGenFunction::OpaqueValueMapping binding(CGF, E);
- if (E->getLHS())
- CGF.EmitBranchOnBoolExpr(E->getCond(), LHSBlock, RHSBlock);
- else {
- Expr *save = E->getSAVE();
- assert(save && "VisitConditionalOperator - save is null");
- // Intentionally not doing direct assignment to ConditionalSaveExprs[save] !!
- ComplexPairTy SaveVal = Visit(save);
- CGF.ConditionalSaveComplexExprs[save] = SaveVal;
- CGF.EmitBranchOnBoolExpr(E->getCond(), LHSBlock, RHSBlock);
- }
+ CodeGenFunction::ConditionalEvaluation eval(CGF);
+ CGF.EmitBranchOnBoolExpr(E->getCond(), LHSBlock, RHSBlock);
eval.begin(CGF);
CGF.EmitBlock(LHSBlock);
@@ -676,7 +667,7 @@ VisitConditionalOperator(const ConditionalOperator *E) {
eval.begin(CGF);
CGF.EmitBlock(RHSBlock);
- ComplexPairTy RHS = Visit(E->getRHS());
+ ComplexPairTy RHS = Visit(E->getFalseExpr());
RHSBlock = Builder.GetInsertBlock();
CGF.EmitBlock(ContBlock);
eval.end(CGF);
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index 99f3f0d3231..34e247d7c3f 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -201,10 +201,11 @@ public:
}
Value *VisitOpaqueValueExpr(OpaqueValueExpr *E) {
- if (E->isGLValue()) return EmitLoadOfLValue(E);
+ if (E->isGLValue())
+ return EmitLoadOfLValue(CGF.getOpaqueLValueMapping(E), E->getType());
// Otherwise, assume the mapping is the scalar directly.
- return CGF.getOpaqueValueMapping(E);
+ return CGF.getOpaqueRValueMapping(E).getScalarVal();
}
// l-values.
@@ -496,7 +497,7 @@ public:
// Other Operators.
Value *VisitBlockExpr(const BlockExpr *BE);
- Value *VisitConditionalOperator(const ConditionalOperator *CO);
+ Value *VisitAbstractConditionalOperator(const AbstractConditionalOperator *);
Value *VisitChooseExpr(ChooseExpr *CE);
Value *VisitVAArgExpr(VAArgExpr *VE);
Value *VisitObjCStringLiteral(const ObjCStringLiteral *E) {
@@ -2401,32 +2402,38 @@ static bool isCheapEnoughToEvaluateUnconditionally(const Expr *E,
Value *ScalarExprEmitter::
-VisitConditionalOperator(const ConditionalOperator *E) {
+VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
TestAndClearIgnoreResultAssign();
+
+ // Bind the common expression if necessary.
+ CodeGenFunction::OpaqueValueMapping binding(CGF, E);
+
+ Expr *condExpr = E->getCond();
+ Expr *lhsExpr = E->getTrueExpr();
+ Expr *rhsExpr = E->getFalseExpr();
+
// If the condition constant folds and can be elided, try to avoid emitting
// the condition and the dead arm.
- if (int Cond = CGF.ConstantFoldsToSimpleInteger(E->getCond())){
- Expr *Live = E->getLHS(), *Dead = E->getRHS();
- if (Cond == -1)
- std::swap(Live, Dead);
+ if (int Cond = CGF.ConstantFoldsToSimpleInteger(condExpr)){
+ Expr *live = lhsExpr, *dead = rhsExpr;
+ if (Cond == -1) std::swap(live, dead);
// If the dead side doesn't have labels we need, and if the Live side isn't
// the gnu missing ?: extension (which we could handle, but don't bother
// to), just emit the Live part.
- if ((!Dead || !CGF.ContainsLabel(Dead)) && // No labels in dead part
- Live) // Live part isn't missing.
- return Visit(Live);
+ if (!CGF.ContainsLabel(dead))
+ return Visit(live);
}
// OpenCL: If the condition is a vector, we can treat this condition like
// the select function.
if (CGF.getContext().getLangOptions().OpenCL
- && E->getCond()->getType()->isVectorType()) {
- llvm::Value *CondV = CGF.EmitScalarExpr(E->getCond());
- llvm::Value *LHS = Visit(E->getLHS());
- llvm::Value *RHS = Visit(E->getRHS());
+ && condExpr->getType()->isVectorType()) {
+ llvm::Value *CondV = CGF.EmitScalarExpr(condExpr);
+ llvm::Value *LHS = Visit(lhsExpr);
+ llvm::Value *RHS = Visit(rhsExpr);
- const llvm::Type *condType = ConvertType(E->getCond()->getType());
+ const llvm::Type *condType = ConvertType(condExpr->getType());
const llvm::VectorType *vecTy = cast<llvm::VectorType>(condType);
unsigned numElem = vecTy->getNumElements();
@@ -2467,12 +2474,11 @@ VisitConditionalOperator(const ConditionalOperator *E) {
// If this is a really simple expression (like x ? 4 : 5), emit this as a
// select instead of as control flow. We can only do this if it is cheap and
// safe to evaluate the LHS and RHS unconditionally.
- if (E->getLHS() && isCheapEnoughToEvaluateUnconditionally(E->getLHS(),
- CGF) &&
- isCheapEnoughToEvaluateUnconditionally(E->getRHS(), CGF)) {
- llvm::Value *CondV = CGF.EvaluateExprAsBool(E->getCond());
- llvm::Value *LHS = Visit(E->getLHS());
- llvm::Value *RHS = Visit(E->getRHS());
+ if (isCheapEnoughToEvaluateUnconditionally(lhsExpr, CGF) &&
+ isCheapEnoughToEvaluateUnconditionally(rhsExpr, CGF)) {
+ llvm::Value *CondV = CGF.EvaluateExprAsBool(condExpr);
+ llvm::Value *LHS = Visit(lhsExpr);
+ llvm::Value *RHS = Visit(rhsExpr);
return Builder.CreateSelect(CondV, LHS, RHS, "cond");
}
@@ -2481,40 +2487,11 @@ VisitConditionalOperator(const ConditionalOperator *E) {
llvm::BasicBlock *ContBlock = CGF.createBasicBlock("cond.end");
CodeGenFunction::ConditionalEvaluation eval(CGF);
-
- // If we don't have the GNU missing condition extension, emit a branch on bool
- // the normal way.
- if (E->getLHS()) {
- // Otherwise, just use EmitBranchOnBoolExpr to get small and simple code for
- // the branch on bool.
- CGF.EmitBranchOnBoolExpr(E->getCond(), LHSBlock, RHSBlock);
- } else {
- // Otherwise, for the ?: extension, evaluate the conditional and then
- // convert it to bool the hard way. We do this explicitly because we need
- // the unconverted value for the missing middle value of the ?:.
- Expr *save = E->getSAVE();
- assert(save && "VisitConditionalOperator - save is null");
- // Intentianlly not doing direct assignment to ConditionalSaveExprs[save] !!
- Value *SaveVal = CGF.EmitScalarExpr(save);
- CGF.ConditionalSaveExprs[save] = SaveVal;
- Value *CondVal = Visit(E->getCond());
- // In some cases, EmitScalarConversion will delete the "CondVal" expression
- // if there are no extra uses (an optimization). Inhibit this by making an
- // extra dead use, because we're going to add a use of CondVal later. We
- // don't use the builder for this, because we don't want it to get optimized
- // away. This leaves dead code, but the ?: extension isn't common.
- new llvm::BitCastInst(CondVal, CondVal->getType(), "dummy?:holder",
- Builder.GetInsertBlock());
-
- Value *CondBoolVal =
- CGF.EmitScalarConversion(CondVal, E->getCond()->getType(),
- CGF.getContext().BoolTy);
- Builder.CreateCondBr(CondBoolVal, LHSBlock, RHSBlock);
- }
+ CGF.EmitBranchOnBoolExpr(condExpr, LHSBlock, RHSBlock);
CGF.EmitBlock(LHSBlock);
eval.begin(CGF);
- Value *LHS = Visit(E->getTrueExpr());
+ Value *LHS = Visit(lhsExpr);
eval.end(CGF);
LHSBlock = Builder.GetInsertBlock();
@@ -2522,7 +2499,7 @@ VisitConditionalOperator(const ConditionalOperator *E) {
CGF.EmitBlock(RHSBlock);
eval.begin(CGF);
- Value *RHS = Visit(E->getRHS());
+ Value *RHS = Visit(rhsExpr);
eval.end(CGF);
RHSBlock = Builder.GetInsertBlock();
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index b316fa86f1e..96716ad9ccf 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -762,3 +762,30 @@ void CodeGenFunction::EmitDeclRefExprDbgValue(const DeclRefExpr *E,
if (CGDebugInfo *Dbg = getDebugInfo())
Dbg->EmitGlobalVariable(E->getDecl(), Init);
}
+
+CodeGenFunction::PeepholeProtection
+CodeGenFunction::protectFromPeepholes(RValue rvalue) {
+ // At the moment, the only aggressive peephole we do in IR gen
+ // is trunc(zext) folding, but if we add more, we can easily
+ // extend this protection.
+
+ if (!rvalue.isScalar()) return PeepholeProtection();
+ llvm::Value *value = rvalue.getScalarVal();
+ if (!isa<llvm::ZExtInst>(value)) return PeepholeProtection();
+
+ // Just make an extra bitcast.
+ assert(HaveInsertPoint());
+ llvm::Instruction *inst = new llvm::BitCastInst(value, value->getType(), "",
+ Builder.GetInsertBlock());
+
+ PeepholeProtection protection;
+ protection.Inst = inst;
+ return protection;
+}
+
+void CodeGenFunction::unprotectFromPeepholes(PeepholeProtection protection) {
+ if (!protection.Inst) return;
+
+ // In theory, we could try to duplicate the peepholes now, but whatever.
+ protection.Inst->eraseFromParent();
+}
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index adbc223afc6..d35a400f7de 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -840,28 +840,105 @@ public:
}
};
+ /// An object which temporarily prevents a value from being
+ /// destroyed by aggressive peephole optimizations that assume that
+ /// all uses of a value have been realized in the IR.
+ class PeepholeProtection {
+ llvm::Instruction *Inst;
+ friend class CodeGenFunction;
+
+ public:
+ PeepholeProtection() : Inst(0) {}
+ };
+
/// An RAII object to set (and then clear) a mapping for an OpaqueValueExpr.
class OpaqueValueMapping {
CodeGenFunction &CGF;
const OpaqueValueExpr *OpaqueValue;
+ bool BoundLValue;
+ CodeGenFunction::PeepholeProtection Protection;
public:
+ static bool shouldBindAsLValue(const Expr *expr) {
+ return expr->isGLValue() || expr->getType()->isRecordType();
+ }
+
+ /// Build the opaque value mapping for the given conditional
+ /// operator if it's the GNU ?: extension. This is a common
+ /// enough pattern that the convenience operator is really
+ /// helpful.
+ ///
+ OpaqueValueMapping(CodeGenFunction &CGF,
+ const AbstractConditionalOperator *op) : CGF(CGF) {
+ if (isa<ConditionalOperator>(op)) {
+ OpaqueValue = 0;
+ BoundLValue = false;
+ return;
+ }
+
+ const BinaryConditionalOperator *e = cast<BinaryConditionalOperator>(op);
+ init(e->getOpaqueValue(), e->getCommon());
+ }
+
OpaqueValueMapping(CodeGenFunction &CGF,
const OpaqueValueExpr *opaqueValue,
- llvm::Value *value)
- : CGF(CGF), OpaqueValue(opaqueValue) {
+ LValue lvalue)
+ : CGF(CGF), OpaqueValue(opaqueValue), BoundLValue(true) {
assert(opaqueValue && "no opaque value expression!");
- CGF.OpaqueValues.insert(std::make_pair(opaqueValue, value));
+ assert(shouldBindAsLValue(opaqueValue));
+ initLValue(lvalue);
+ }
+
+ OpaqueValueMapping(CodeGenFunction &CGF,
+ const OpaqueValueExpr *opaqueValue,
+ RValue rvalue)
+ : CGF(CGF), OpaqueValue(opaqueValue), BoundLValue(false) {
+ assert(opaqueValue && "no opaque value expression!");
+ assert(!shouldBindAsLValue(opaqueValue));
+ initRValue(rvalue);
}
void pop() {
assert(OpaqueValue && "mapping already popped!");
- CGF.OpaqueValues.erase(OpaqueValue);
+ popImpl();
OpaqueValue = 0;
}
~OpaqueValueMapping() {
- if (OpaqueValue) CGF.OpaqueValues.erase(OpaqueValue);
+ if (OpaqueValue) popImpl();
+ }
+
+ private:
+ void popImpl() {
+ if (BoundLValue)
+ CGF.OpaqueLValues.erase(OpaqueValue);
+ else {
+ CGF.OpaqueRValues.erase(OpaqueValue);
+ CGF.unprotectFromPeepholes(Protection);
+ }
+ }
+
+ void init(const OpaqueValueExpr *ov, const Expr *e) {
+ OpaqueValue = ov;
+ BoundLValue = shouldBindAsLValue(ov);
+ assert(BoundLValue == shouldBindAsLValue(e)
+ && "inconsistent expression value kinds!");
+ if (BoundLValue)
+ initLValue(CGF.EmitLValue(e));
+ else
+ initRValue(CGF.EmitAnyExpr(e));
+ }
+
+ void initLValue(const LValue &lv) {
+ CGF.OpaqueLValues.insert(std::make_pair(OpaqueValue, lv));
+ }
+
+ void initRValue(const RValue &rv) {
+ // Work around an extremely aggressive peephole optimization in
+ // EmitScalarConversion which assumes that all other uses of a
+ // value are extant.
+ Protection = CGF.protectFromPeepholes(rv);
+ CGF.OpaqueRValues.insert(std::make_pair(OpaqueValue, rv));
}
};
@@ -909,9 +986,10 @@ private:
/// statement range in current switch instruction.
llvm::BasicBlock *CaseRangeBlock;
- /// OpaqueValues - Keeps track of the current set of opaque value
+ /// OpaqueLValues - Keeps track of the current set of opaque value
/// expressions.
- llvm::DenseMap<const OpaqueValueExpr *, llvm::Value*> OpaqueValues;
+ llvm::DenseMap<const OpaqueValueExpr *, LValue> OpaqueLValues;
+ llvm::DenseMap<const OpaqueValueExpr *, RValue> OpaqueRValues;
// VLASizeMap - This keeps track of the associated size for each VLA type.
// We track this by the size expression rather than the type itself because
@@ -1308,13 +1386,25 @@ public:
return Res;
}
- /// getOpaqueValueMapping - Given an opaque value expression (which
- /// must be mapped), return its mapping. Whether this is an address
- /// or a value depends on the expression's type and value kind.
- llvm::Value *getOpaqueValueMapping(const OpaqueValueExpr *e) {
- llvm::DenseMap<const OpaqueValueExpr*,llvm::Value*>::iterator
- it = OpaqueValues.find(e);
- assert(it != OpaqueValues.end() && "no mapping for opaque value!");
+ /// getOpaqueLValueMapping - Given an opaque value expression (which
+ /// must be mapped to an l-value), return its mapping.
+ const LValue &getOpaqueLValueMapping(const OpaqueValueExpr *e) {
+ assert(OpaqueValueMapping::shouldBindAsLValue(e));
+
+ llvm::DenseMap<const OpaqueValueExpr*,LValue>::iterator
+ it = OpaqueLValues.find(e);
+ assert(it != OpaqueLValues.end() && "no mapping for opaque value!");
+ return it->second;
+ }
+
+ /// getOpaqueRValueMapping - Given an opaque value expression (which
+ /// must be mapped to an r-value), return its mapping.
+ const RValue &getOpaqueRValueMapping(const OpaqueValueExpr *e) {
+ assert(!OpaqueValueMapping::shouldBindAsLValue(e));
+
+ llvm::DenseMap<const OpaqueValueExpr*,RValue>::iterator
+ it = OpaqueRValues.find(e);
+ assert(it != OpaqueRValues.end() && "no mapping for opaque value!");
return it->second;
}
@@ -1477,6 +1567,18 @@ public:
/// EmitParmDecl - Emit a ParmVarDecl or an ImplicitParamDecl.
void EmitParmDecl(const VarDecl &D, llvm::Value *Arg);
+ /// protectFromPeepholes - Protect a value that we're intending to
+ /// store to the side, but which will probably be used later, from
+ /// aggressive peepholing optimizations that might delete it.
+ ///
+ /// Pass the result to unprotectFromPeepholes to declare that
+ /// protection is no longer required.
+ ///
+ /// There's no particular reason why this shouldn't apply to
+ /// l-values, it's just that no existing peepholes work on pointers.
+ PeepholeProtection protectFromPeepholes(RValue rvalue);
+ void unprotectFromPeepholes(PeepholeProtection protection);
+
//===--------------------------------------------------------------------===//
// Statement Emission
//===--------------------------------------------------------------------===//
@@ -1646,7 +1748,7 @@ public:
LValue EmitMemberExpr(const MemberExpr *E);
LValue EmitObjCIsaExpr(const ObjCIsaExpr *E);
LValue EmitCompoundLiteralLValue(const CompoundLiteralExpr *E);
- LValue EmitConditionalOperatorLValue(const ConditionalOperator *E);
+ LValue EmitConditionalOperatorLValue(const AbstractConditionalOperator *E);
LValue EmitCastLValue(const CastExpr *E);
LValue EmitNullInitializationLValue(const CXXScalarValueInitExpr *E);
LValue EmitOpaqueValueLValue(const OpaqueValueExpr *e);
@@ -1687,6 +1789,7 @@ public:
LValue EmitPointerToDataMemberBinaryExpr(const BinaryOperator *E);
LValue EmitObjCSelectorLValue(const ObjCSelectorExpr *E);
void EmitDeclRefExprDbgValue(const DeclRefExpr *E, llvm::Constant *Init);
+
//===--------------------------------------------------------------------===//
// Scalar Expression Emission
//===--------------------------------------------------------------------===//
diff --git a/clang/lib/Rewrite/RewriteObjC.cpp b/clang/lib/Rewrite/RewriteObjC.cpp
index 1e9b9d30330..875a0c7a84c 100644
--- a/clang/lib/Rewrite/RewriteObjC.cpp
+++ b/clang/lib/Rewrite/RewriteObjC.cpp
@@ -3121,7 +3121,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
ConditionalOperator *CondExpr =
new (Context) ConditionalOperator(lessThanExpr,
SourceLocation(), CE,
- SourceLocation(), STCE, (Expr*)0,
+ SourceLocation(), STCE,
returnType, VK_RValue, OK_Ordinary);
ReplacingStmt = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
CondExpr);
@@ -4656,7 +4656,6 @@ Stmt *RewriteObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) {
new (Context) ConditionalOperator(CONDExp,
SourceLocation(), cast<Expr>(LHSStmt),
SourceLocation(), cast<Expr>(RHSStmt),
- (Expr*)0,
Exp->getType(), VK_RValue, OK_Ordinary);
return CondExpr;
} else if (const ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(BlockExp)) {
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 6a3ee12b170..9913edb4347 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -885,11 +885,12 @@ bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall,
return false;
switch (E->getStmtClass()) {
+ case Stmt::BinaryConditionalOperatorClass:
case Stmt::ConditionalOperatorClass: {
- const ConditionalOperator *C = cast<ConditionalOperator>(E);
+ const AbstractConditionalOperator *C = cast<AbstractConditionalOperator>(E);
return SemaCheckStringLiteral(C->getTrueExpr(), TheCall, HasVAListArg,
format_idx, firstDataArg, isPrintf)
- && SemaCheckStringLiteral(C->getRHS(), TheCall, HasVAListArg,
+ && SemaCheckStringLiteral(C->getFalseExpr(), TheCall, HasVAListArg,
format_idx, firstDataArg, isPrintf);
}
@@ -910,6 +911,13 @@ bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall,
goto tryAgain;
}
+ case Stmt::OpaqueValueExprClass:
+ if (const Expr *src = cast<OpaqueValueExpr>(E)->getSourceExpr()) {
+ E = src;
+ goto tryAgain;
+ }
+ return false;
+
case Stmt::DeclRefExprClass: {
const DeclRefExpr *DR = cast<DeclRefExpr>(E);
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 052dd4b956f..4bba2402311 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -5232,8 +5232,7 @@ ExprResult Sema::ActOnParenOrParenListExpr(SourceLocation L,
/// In that case, lhs = cond.
/// C99 6.5.15
QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
- Expr *&SAVE, ExprValueKind &VK,
- ExprObjectKind &OK,
+ ExprValueKind &VK, ExprObjectKind &OK,
SourceLocation QuestionLoc) {
// If both LHS and RHS are overloaded functions, try to resolve them.
if (Context.hasSameType(LHS->getType(), RHS->getType()) &&
@@ -5252,18 +5251,13 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
// C++ is sufficiently different to merit its own checker.
if (getLangOptions().CPlusPlus)
- return CXXCheckConditionalOperands(Cond, LHS, RHS, SAVE,
- VK, OK, QuestionLoc);
+ return CXXCheckConditionalOperands(Cond, LHS, RHS, VK, OK, QuestionLoc);
VK = VK_RValue;
OK = OK_Ordinary;
UsualUnaryConversions(Cond);
- if (SAVE) {
- SAVE = LHS = Cond;
- }
- else
- UsualUnaryConversions(LHS);
+ UsualUnaryConversions(LHS);
UsualUnaryConversions(RHS);
QualType CondTy = Cond->getType();
QualType LHSTy = LHS->getType();
@@ -5610,28 +5604,50 @@ QualType Sema::FindCompositeObjCPointerType(Expr *&LHS, Expr *&RHS,
/// ActOnConditionalOp - Parse a ?: operation. Note that 'LHS' may be null
/// in the case of a the GNU conditional expr extension.
ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc,
- SourceLocation ColonLoc,
- Expr *CondExpr, Expr *LHSExpr,
- Expr *RHSExpr) {
+ SourceLocation ColonLoc,
+ Expr *CondExpr, Expr *LHSExpr,
+ Expr *RHSExpr) {
// If this is the gnu "x ?: y" extension, analyze the types as though the LHS
// was the condition.
- bool isLHSNull = LHSExpr == 0;
- Expr *SAVEExpr = 0;
- if (isLHSNull) {
- LHSExpr = SAVEExpr = CondExpr;
+ OpaqueValueExpr *opaqueValue = 0;
+ Expr *commonExpr = 0;
+ if (LHSExpr == 0) {
+ commonExpr = CondExpr;
+
+ // We usually want to apply unary conversions *before* saving, except
+ // in the special case of a C++ l-value conditional.
+ if (!(getLangOptions().CPlusPlus
+ && !commonExpr->isTypeDependent()
+ && commonExpr->getValueKind() == RHSExpr->getValueKind()
+ && commonExpr->isGLValue()
+ && commonExpr->isOrdinaryOrBitFieldObject()
+ && RHSExpr->isOrdinaryOrBitFieldObject()
+ && Context.hasSameType(commonExpr->getType(), RHSExpr->getType()))) {
+ UsualUnaryConversions(commonExpr);
+ }
+
+ opaqueValue = new (Context) OpaqueValueExpr(commonExpr->getExprLoc(),
+ commonExpr->getType(),
+ commonExpr->getValueKind(),
+ commonExpr->getObjectKind());
+ LHSExpr = CondExpr = opaqueValue;
}
ExprValueKind VK = VK_RValue;
ExprObjectKind OK = OK_Ordinary;
QualType result = CheckConditionalOperands(CondExpr, LHSExpr, RHSExpr,
- SAVEExpr, VK, OK, QuestionLoc);
+ VK, OK, QuestionLoc);
if (result.isNull())
return ExprError();
- return Owned(new (Context) ConditionalOperator(CondExpr, QuestionLoc,
- LHSExpr, ColonLoc,
- RHSExpr, SAVEExpr,
- result, VK, OK));
+ if (!commonExpr)
+ return Owned(new (Context) ConditionalOperator(CondExpr, QuestionLoc,
+ LHSExpr, ColonLoc,
+ RHSExpr, result, VK, OK));
+
+ return Owned(new (Context)
+ BinaryConditionalOperator(commonExpr, opaqueValue, CondExpr, LHSExpr,
+ RHSExpr, QuestionLoc, ColonLoc, result, VK, OK));
}
// checkPointerTypesForAssignment - This is a very tricky routine (despite
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index e9f595549f2..6fa22a97769 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -2927,8 +2927,7 @@ static bool ConvertForConditional(Sema &Self, Expr *&E, QualType T) {
/// See C++ [expr.cond]. Note that LHS is never null, even for the GNU x ?: y
/// extension. In this case, LHS == Cond. (But they're not aliases.)
QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
- Expr *&SAVE, ExprValueKind &VK,
- ExprObjectKind &OK,
+ ExprValueKind &VK, ExprObjectKind &OK,
SourceLocation QuestionLoc) {
// FIXME: Handle C99's complex types, vector types, block pointers and Obj-C++
// interface pointers.
@@ -2936,12 +2935,6 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
// C++0x 5.16p1
// The first expression is contextually converted to bool.
if (!Cond->isTypeDependent()) {
- if (SAVE && Cond->getType()->isArrayType()) {
- QualType CondTy = Cond->getType();
- CondTy = Context.getArrayDecayedType(CondTy);
- ImpCastExprToType(Cond, CondTy, CK_ArrayToPointerDecay);
- SAVE = LHS = Cond;
- }
if (CheckCXXBooleanCondition(Cond))
return QualType();
}
@@ -3037,12 +3030,10 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
// l-values.
bool Same = Context.hasSameType(LTy, RTy);
if (Same &&
- LHS->getValueKind() != VK_RValue &&
+ LHS->isGLValue() &&
LHS->getValueKind() == RHS->getValueKind() &&
- (LHS->getObjectKind() == OK_Ordinary ||
- LHS->getObjectKind() == OK_BitField) &&
- (RHS->getObjectKind() == OK_Ordinary ||
- RHS->getObjectKind() == OK_BitField)) {
+ LHS->isOrdinaryOrBitFieldObject() &&
+ RHS->isOrdinaryOrBitFieldObject()) {
VK = LHS->getValueKind();
if (LHS->getObjectKind() == OK_BitField ||
RHS->getObjectKind() == OK_BitField)
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index cb0d4250fca..1fc36754dff 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -1415,10 +1415,10 @@ public:
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
ExprResult RebuildConditionalOperator(Expr *Cond,
- SourceLocation QuestionLoc,
- Expr *LHS,
- SourceLocation ColonLoc,
- Expr *RHS) {
+ SourceLocation QuestionLoc,
+ Expr *LHS,
+ SourceLocation ColonLoc,
+ Expr *RHS) {
return getSema().ActOnConditionalOp(QuestionLoc, ColonLoc, Cond,
LHS, RHS);
}
@@ -5523,6 +5523,32 @@ TreeTransform<Derived>::TransformCompoundAssignOperator(
}
template<typename Derived>
+ExprResult TreeTransform<Derived>::
+TransformBinaryConditionalOperator(BinaryConditionalOperator *e) {
+ // Just rebuild the common and RHS expressions and see whether we
+ // get any changes.
+
+ ExprResult commonExpr = getDerived().TransformExpr(e->getCommon());
+ if (commonExpr.isInvalid())
+ return ExprError();
+
+ ExprResult rhs = getDerived().TransformExpr(e->getFalseExpr());
+ if (rhs.isInvalid())
+ return ExprError();
+
+ if (!getDerived().AlwaysRebuild() &&
+ commonExpr.get() == e->getCommon() &&
+ rhs.get() == e->getFalseExpr())
+ return SemaRef.Owned(e);
+
+ return getDerived().RebuildConditionalOperator(commonExpr.take(),
+ e->getQuestionLoc(),
+ 0,
+ e->getColonLoc(),
+ rhs.get());
+}
+
+template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformConditionalOperator(ConditionalOperator *E) {
ExprResult Cond = getDerived().TransformExpr(E->getCond());
diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp
index bd597378255..4e91c989260 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -105,6 +105,7 @@ namespace clang {
void VisitBinaryOperator(BinaryOperator *E);
void VisitCompoundAssignOperator(CompoundAssignOperator *E);
void VisitConditionalOperator(ConditionalOperator *E);
+ void VisitBinaryConditionalOperator(BinaryConditionalOperator *E);
void VisitImplicitCastExpr(ImplicitCastExpr *E);
void VisitExplicitCastExpr(ExplicitCastExpr *E);
void VisitCStyleCastExpr(CStyleCastExpr *E);
@@ -626,12 +627,25 @@ void ASTStmtReader::VisitCompoundAssignOperator(CompoundAssignOperator *E) {
void ASTStmtReader::VisitConditionalOperator(ConditionalOperator *E) {
VisitExpr(E);
- E->setCond(Reader.ReadSubExpr());
- E->setLHS(Reader.ReadSubExpr());
- E->setRHS(Reader.ReadSubExpr());
- E->setSAVE(Reader.ReadSubExpr());
- E->setQuestionLoc(ReadSourceLocation(Record, Idx));
- E->setColonLoc(ReadSourceLocation(Record, Idx));
+ E->SubExprs[ConditionalOperator::COND] = Reader.ReadSubExpr();
+ E->SubExprs[ConditionalOperator::LHS] = Reader.ReadSubExpr();
+ E->SubExprs[ConditionalOperator::RHS] = Reader.ReadSubExpr();
+ E->QuestionLoc = ReadSourceLocation(Record, Idx);
+ E->ColonLoc = ReadSourceLocation(Record, Idx);
+}
+
+void
+ASTStmtReader::VisitBinaryConditionalOperator(BinaryConditionalOperator *E) {
+ VisitExpr(E);
+ E->OpaqueValue = cast<OpaqueValueExpr>(Reader.ReadSubExpr());
+ E->SubExprs[BinaryConditionalOperator::COMMON] = Reader.ReadSubExpr();
+ E->SubExprs[BinaryConditionalOperator::COND] = Reader.ReadSubExpr();
+ E->SubExprs[BinaryConditionalOperator::LHS] = Reader.ReadSubExpr();
+ E->SubExprs[BinaryConditionalOperator::RHS] = Reader.ReadSubExpr();
+ E->QuestionLoc = ReadSourceLocation(Record, Idx);
+ E->ColonLoc = ReadSourceLocation(Record, Idx);
+
+ E->getOpaqueValue()->setSourceExpr(E->getCommon());
}
void ASTStmtReader::VisitImplicitCastExpr(ImplicitCastExpr *E) {
@@ -1322,6 +1336,7 @@ void ASTStmtReader::VisitSubstNonTypeTemplateParmPackExpr(
void ASTStmtReader::VisitOpaqueValueExpr(OpaqueValueExpr *E) {
VisitExpr(E);
+ Idx++; // skip ID
E->Loc = ReadSourceLocation(Record, Idx);
}
@@ -1602,6 +1617,10 @@ Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) {
S = new (Context) ConditionalOperator(Empty);
break;
+ case EXPR_BINARY_CONDITIONAL_OPERATOR:
+ S = new (Context) BinaryConditionalOperator(Empty);
+ break;
+
case EXPR_IMPLICIT_CAST:
S = ImplicitCastExpr::CreateEmpty(*Context,
/*PathSize*/ Record[ASTStmtReader::NumExprFields]);
@@ -1880,9 +1899,20 @@ Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) {
S = new (Context) SubstNonTypeTemplateParmPackExpr(Empty);
break;
- case EXPR_OPAQUE_VALUE:
- S = new (Context) OpaqueValueExpr(Empty);
+ case EXPR_OPAQUE_VALUE: {
+ unsigned key = Record[ASTStmtReader::NumExprFields];
+ OpaqueValueExpr *&expr = OpaqueValueExprs[key];
+
+ // If we already have an entry for this opaque value expression,
+ // don't bother reading it again.
+ if (expr) {
+ StmtStack.push_back(expr);
+ continue;
+ }
+
+ S = expr = new (Context) OpaqueValueExpr(Empty);
break;
+ }
case EXPR_CUDA_KERNEL_CALL:
S = new (Context) CUDAKernelCallExpr(*Context, Empty);
diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp
index b043f2ee2c2..8a5ffe96db1 100644
--- a/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -76,6 +76,7 @@ namespace clang {
void VisitBinaryOperator(BinaryOperator *E);
void VisitCompoundAssignOperator(CompoundAssignOperator *E);
void VisitConditionalOperator(ConditionalOperator *E);
+ void VisitBinaryConditionalOperator(BinaryConditionalOperator *E);
void VisitImplicitCastExpr(ImplicitCastExpr *E);
void VisitExplicitCastExpr(ExplicitCastExpr *E);
void VisitCStyleCastExpr(CStyleCastExpr *E);
@@ -611,12 +612,24 @@ void ASTStmtWriter::VisitConditionalOperator(ConditionalOperator *E) {
Writer.AddStmt(E->getCond());
Writer.AddStmt(E->getLHS());
Writer.AddStmt(E->getRHS());
- Writer.AddStmt(E->getSAVE());
Writer.AddSourceLocation(E->getQuestionLoc(), Record);
Writer.AddSourceLocation(E->getColonLoc(), Record);
Code = serialization::EXPR_CONDITIONAL_OPERATOR;
}
+void
+ASTStmtWriter::VisitBinaryConditionalOperator(BinaryConditionalOperator *E) {
+ VisitExpr(E);
+ Writer.AddStmt(E->getOpaqueValue());
+ Writer.AddStmt(E->getCommon());
+ Writer.AddStmt(E->getCond());
+ Writer.AddStmt(E->getTrueExpr());
+ Writer.AddStmt(E->getFalseExpr());
+ Writer.AddSourceLocation(E->getQuestionLoc(), Record);
+ Writer.AddSourceLocation(E->getColonLoc(), Record);
+ Code = serialization::EXPR_BINARY_CONDITIONAL_OPERATOR;
+}
+
void ASTStmtWriter::VisitImplicitCastExpr(ImplicitCastExpr *E) {
VisitCastExpr(E);
Code = serialization::EXPR_IMPLICIT_CAST;
@@ -1320,6 +1333,7 @@ void ASTStmtWriter::VisitSubstNonTypeTemplateParmPackExpr(
void ASTStmtWriter::VisitOpaqueValueExpr(OpaqueValueExpr *E) {
VisitExpr(E);
+ Record.push_back(Writer.getOpaqueValueID(E));
Writer.AddSourceLocation(E->getLocation(), Record);
Code = serialization::EXPR_OPAQUE_VALUE;
}
@@ -1356,6 +1370,12 @@ void ASTWriter::ClearSwitchCaseIDs() {
SwitchCaseIDs.clear();
}
+unsigned ASTWriter::getOpaqueValueID(OpaqueValueExpr *e) {
+ unsigned &entry = OpaqueValues[e];
+ if (!entry) entry = OpaqueValues.size();
+ return entry;
+}
+
/// \brief Write the given substatement or subexpression to the
/// bitstream.
void ASTWriter::WriteSubStmt(Stmt *S) {
diff --git a/clang/lib/StaticAnalyzer/Checkers/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Checkers/ExprEngine.cpp
index 50b1e37c132..ab8d56471c5 100644
--- a/clang/lib/StaticAnalyzer/Checkers/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/ExprEngine.cpp
@@ -859,7 +859,6 @@ void ExprEngine::Visit(const Stmt* S, ExplodedNode* Pred,
case Stmt::LabelStmtClass:
case Stmt::NoStmtClass:
case Stmt::NullStmtClass:
- case Stmt::OpaqueValueExprClass:
llvm_unreachable("Stmt should not be in analyzer evaluation loop");
break;
@@ -894,6 +893,7 @@ void ExprEngine::Visit(const Stmt* S, ExplodedNode* Pred,
case Stmt::ShuffleVectorExprClass:
case Stmt::VAArgExprClass:
case Stmt::CUDAKernelCallExprClass:
+ case Stmt::OpaqueValueExprClass:
// Fall through.
// Cases we intentionally don't evaluate, since they don't need
@@ -1003,9 +1003,11 @@ void ExprEngine::Visit(const Stmt* S, ExplodedNode* Pred,
VisitCompoundLiteralExpr(cast<CompoundLiteralExpr>(S), Pred, Dst);
break;
+ case Stmt::BinaryConditionalOperatorClass:
case Stmt::ConditionalOperatorClass: { // '?' operator
- const ConditionalOperator* C = cast<ConditionalOperator>(S);
- VisitGuardedExpr(C, C->getLHS(), C->getRHS(), Pred, Dst);
+ const AbstractConditionalOperator *C
+ = cast<AbstractConditionalOperator>(S);
+ VisitGuardedExpr(C, C->getTrueExpr(), C->getFalseExpr(), Pred, Dst);
break;
}
@@ -1206,9 +1208,10 @@ const GRState* ExprEngine::MarkBranch(const GRState* state,
return state->BindExpr(B, UndefinedVal(Ex));
}
+ case Stmt::BinaryConditionalOperatorClass:
case Stmt::ConditionalOperatorClass: { // ?:
-
- const ConditionalOperator* C = cast<ConditionalOperator>(Terminator);
+ const AbstractConditionalOperator* C
+ = cast<AbstractConditionalOperator>(Terminator);
// For ?, if branchTaken == true then the value is either the LHS or
// the condition itself. (GNU extension).
@@ -1216,9 +1219,9 @@ const GRState* ExprEngine::MarkBranch(const GRState* state,
const Expr* Ex;
if (branchTaken)
- Ex = C->getLHS() ? C->getLHS() : C->getCond();
+ Ex = C->getTrueExpr();
else
- Ex = C->getRHS();
+ Ex = C->getFalseExpr();
return state->BindExpr(C, UndefinedVal(Ex));
}
diff --git a/clang/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp
index 70d5a8b5f05..b8111c44ffe 100644
--- a/clang/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp
@@ -711,7 +711,8 @@ bool IdempotentOperationChecker::CanVary(const Expr *Ex,
return CanVary(cast<const ChooseExpr>(Ex)->getChosenSubExpr(
AC->getASTContext()), AC);
case Stmt::ConditionalOperatorClass:
- return CanVary(cast<const ConditionalOperator>(Ex)->getCond(), AC);
+ case Stmt::BinaryConditionalOperatorClass:
+ return CanVary(cast<AbstractConditionalOperator>(Ex)->getCond(), AC);
}
}
diff --git a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
index d945639ee46..9a84045ebd9 100644
--- a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -93,6 +93,7 @@ static const Stmt* GetNextStmt(const ExplodedNode* N) {
// not actual statement points.
switch (S->getStmtClass()) {
case Stmt::ChooseExprClass:
+ case Stmt::BinaryConditionalOperatorClass: continue;
case Stmt::ConditionalOperatorClass: continue;
case Stmt::BinaryOperatorClass: {
BinaryOperatorKind Op = cast<BinaryOperator>(S)->getOpcode();
@@ -279,10 +280,11 @@ PathDiagnosticBuilder::getEnclosingStmtLocation(const Stmt *S) {
return PathDiagnosticLocation(Parent, SMgr);
else
return PathDiagnosticLocation(S, SMgr);
+ case Stmt::BinaryConditionalOperatorClass:
case Stmt::ConditionalOperatorClass:
// For '?', if we are referring to condition, just have the edge point
// to the entire '?' expression.
- if (cast<ConditionalOperator>(Parent)->getCond() == S)
+ if (cast<AbstractConditionalOperator>(Parent)->getCond() == S)
return PathDiagnosticLocation(Parent, SMgr);
else
return PathDiagnosticLocation(S, SMgr);
@@ -635,6 +637,7 @@ static void GenerateMinimalPathDiagnostic(PathDiagnostic& PD,
}
// Determine control-flow for ternary '?'.
+ case Stmt::BinaryConditionalOperatorClass:
case Stmt::ConditionalOperatorClass: {
std::string sbuf;
llvm::raw_string_ostream os(sbuf);
@@ -810,7 +813,7 @@ static bool IsControlFlowExpr(const Stmt *S) {
E = E->IgnoreParenCasts();
- if (isa<ConditionalOperator>(E))
+ if (isa<AbstractConditionalOperator>(E))
return true;
if (const BinaryOperator *B = dyn_cast<BinaryOperator>(E))
@@ -859,8 +862,9 @@ class EdgeBuilder {
S = cast<ParenExpr>(S)->IgnoreParens();
firstCharOnly = true;
continue;
+ case Stmt::BinaryConditionalOperatorClass:
case Stmt::ConditionalOperatorClass:
- S = cast<ConditionalOperator>(S)->getCond();
+ S = cast<AbstractConditionalOperator>(S)->getCond();
firstCharOnly = true;
continue;
case Stmt::ChooseExprClass:
diff --git a/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp b/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
index e8143617770..070042a641f 100644
--- a/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
@@ -346,8 +346,10 @@ void CoreEngine::HandleBlockExit(const CFGBlock * B, ExplodedNode* Pred) {
HandleBranch(cast<BinaryOperator>(Term)->getLHS(), Term, B, Pred);
return;
+ case Stmt::BinaryConditionalOperatorClass:
case Stmt::ConditionalOperatorClass:
- HandleBranch(cast<ConditionalOperator>(Term)->getCond(), Term, B, Pred);
+ HandleBranch(cast<AbstractConditionalOperator>(Term)->getCond(),
+ Term, B, Pred);
return;
// FIXME: Use constant-folding in CFG construction to simplify this
diff --git a/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp b/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
index efdf5f91b47..872bbfe9e16 100644
--- a/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
+++ b/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
@@ -173,6 +173,7 @@ PathDiagnosticRange PathDiagnosticLocation::asRange() const {
case Stmt::ChooseExprClass:
case Stmt::IndirectGotoStmtClass:
case Stmt::SwitchStmtClass:
+ case Stmt::BinaryConditionalOperatorClass:
case Stmt::ConditionalOperatorClass:
case Stmt::ObjCForCollectionStmtClass: {
SourceLocation L = S->getLocStart();
OpenPOWER on IntegriCloud