summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorEli Friedman <eli.friedman@gmail.com>2013-07-20 00:40:58 +0000
committerEli Friedman <eli.friedman@gmail.com>2013-07-20 00:40:58 +0000
commit75807f239e06e94cb177eed61955790e6dc6e306 (patch)
tree1a5218c565964125bfd63cdbdfcbc53f93677110 /clang/lib
parent19b4986b80c92dfdf55af1320c888dbc3bde8d5a (diff)
downloadbcm5719-llvm-75807f239e06e94cb177eed61955790e6dc6e306.tar.gz
bcm5719-llvm-75807f239e06e94cb177eed61955790e6dc6e306.zip
Make IgnoreParens() look through ChooseExprs.
This is the same way GenericSelectionExpr works, and it's generally a more consistent approach. A large part of this patch is devoted to caching the value of the condition of a ChooseExpr; it's needed to avoid threading an ASTContext into IgnoreParens(). Fixes <rdar://problem/14438917>. llvm-svn: 186738
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/Expr.cpp99
-rw-r--r--clang/lib/AST/ExprClassification.cpp2
-rw-r--r--clang/lib/AST/ExprConstant.cpp4
-rw-r--r--clang/lib/CodeGen/CGExpr.cpp2
-rw-r--r--clang/lib/CodeGen/CGExprAgg.cpp2
-rw-r--r--clang/lib/CodeGen/CGExprComplex.cpp2
-rw-r--r--clang/lib/CodeGen/CGExprConstant.cpp2
-rw-r--r--clang/lib/CodeGen/CGExprScalar.cpp2
-rw-r--r--clang/lib/Sema/SemaExceptionSpec.cpp2
-rw-r--r--clang/lib/Sema/SemaExpr.cpp6
-rw-r--r--clang/lib/Sema/SemaPseudoObject.cpp19
-rw-r--r--clang/lib/Serialization/ASTReaderStmt.cpp1
-rw-r--r--clang/lib/Serialization/ASTWriterStmt.cpp1
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp15
14 files changed, 61 insertions, 98 deletions
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 37f7d267d97..8473c096afe 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -1929,6 +1929,9 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc,
case GenericSelectionExprClass:
return cast<GenericSelectionExpr>(this)->getResultExpr()->
isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx);
+ case ChooseExprClass:
+ return cast<ChooseExpr>(this)->getChosenSubExpr()->
+ isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx);
case UnaryOperatorClass: {
const UnaryOperator *UO = cast<UnaryOperator>(this);
@@ -2295,6 +2298,12 @@ Expr* Expr::IgnoreParens() {
continue;
}
}
+ if (ChooseExpr* P = dyn_cast<ChooseExpr>(E)) {
+ if (!P->isConditionDependent()) {
+ E = P->getChosenSubExpr();
+ continue;
+ }
+ }
return E;
}
}
@@ -2304,26 +2313,11 @@ Expr* Expr::IgnoreParens() {
Expr *Expr::IgnoreParenCasts() {
Expr *E = this;
while (true) {
- if (ParenExpr* P = dyn_cast<ParenExpr>(E)) {
- E = P->getSubExpr();
- continue;
- }
+ E = E->IgnoreParens();
if (CastExpr *P = dyn_cast<CastExpr>(E)) {
E = P->getSubExpr();
continue;
}
- if (UnaryOperator* P = dyn_cast<UnaryOperator>(E)) {
- if (P->getOpcode() == UO_Extension) {
- E = P->getSubExpr();
- continue;
- }
- }
- if (GenericSelectionExpr* P = dyn_cast<GenericSelectionExpr>(E)) {
- if (!P->isResultDependent()) {
- E = P->getResultExpr();
- continue;
- }
- }
if (MaterializeTemporaryExpr *Materialize
= dyn_cast<MaterializeTemporaryExpr>(E)) {
E = Materialize->GetTemporaryExpr();
@@ -2345,24 +2339,12 @@ Expr *Expr::IgnoreParenCasts() {
Expr *Expr::IgnoreParenLValueCasts() {
Expr *E = this;
while (true) {
- if (ParenExpr *P = dyn_cast<ParenExpr>(E)) {
- E = P->getSubExpr();
- continue;
- } else if (CastExpr *P = dyn_cast<CastExpr>(E)) {
+ E = E->IgnoreParens();
+ if (CastExpr *P = dyn_cast<CastExpr>(E)) {
if (P->getCastKind() == CK_LValueToRValue) {
E = P->getSubExpr();
continue;
}
- } else if (UnaryOperator* P = dyn_cast<UnaryOperator>(E)) {
- if (P->getOpcode() == UO_Extension) {
- E = P->getSubExpr();
- continue;
- }
- } else if (GenericSelectionExpr* P = dyn_cast<GenericSelectionExpr>(E)) {
- if (!P->isResultDependent()) {
- E = P->getResultExpr();
- continue;
- }
} else if (MaterializeTemporaryExpr *Materialize
= dyn_cast<MaterializeTemporaryExpr>(E)) {
E = Materialize->GetTemporaryExpr();
@@ -2380,10 +2362,7 @@ Expr *Expr::IgnoreParenLValueCasts() {
Expr *Expr::ignoreParenBaseCasts() {
Expr *E = this;
while (true) {
- if (ParenExpr *P = dyn_cast<ParenExpr>(E)) {
- E = P->getSubExpr();
- continue;
- }
+ E = E->IgnoreParens();
if (CastExpr *CE = dyn_cast<CastExpr>(E)) {
if (CE->getCastKind() == CK_DerivedToBase ||
CE->getCastKind() == CK_UncheckedDerivedToBase ||
@@ -2400,26 +2379,11 @@ Expr *Expr::ignoreParenBaseCasts() {
Expr *Expr::IgnoreParenImpCasts() {
Expr *E = this;
while (true) {
- if (ParenExpr *P = dyn_cast<ParenExpr>(E)) {
- E = P->getSubExpr();
- continue;
- }
+ E = E->IgnoreParens();
if (ImplicitCastExpr *P = dyn_cast<ImplicitCastExpr>(E)) {
E = P->getSubExpr();
continue;
}
- if (UnaryOperator* P = dyn_cast<UnaryOperator>(E)) {
- if (P->getOpcode() == UO_Extension) {
- E = P->getSubExpr();
- continue;
- }
- }
- if (GenericSelectionExpr* P = dyn_cast<GenericSelectionExpr>(E)) {
- if (!P->isResultDependent()) {
- E = P->getResultExpr();
- continue;
- }
- }
if (MaterializeTemporaryExpr *Materialize
= dyn_cast<MaterializeTemporaryExpr>(E)) {
E = Materialize->GetTemporaryExpr();
@@ -2448,10 +2412,7 @@ Expr *Expr::IgnoreConversionOperator() {
Expr *Expr::IgnoreParenNoopCasts(ASTContext &Ctx) {
Expr *E = this;
while (true) {
- if (ParenExpr *P = dyn_cast<ParenExpr>(E)) {
- E = P->getSubExpr();
- continue;
- }
+ E = E->IgnoreParens();
if (CastExpr *P = dyn_cast<CastExpr>(E)) {
// We ignore integer <-> casts that are of the same width, ptr<->ptr and
@@ -2473,20 +2434,6 @@ Expr *Expr::IgnoreParenNoopCasts(ASTContext &Ctx) {
}
}
- if (UnaryOperator* P = dyn_cast<UnaryOperator>(E)) {
- if (P->getOpcode() == UO_Extension) {
- E = P->getSubExpr();
- continue;
- }
- }
-
- if (GenericSelectionExpr* P = dyn_cast<GenericSelectionExpr>(E)) {
- if (!P->isResultDependent()) {
- E = P->getResultExpr();
- continue;
- }
- }
-
if (SubstNonTypeTemplateParmExpr *NTTP
= dyn_cast<SubstNonTypeTemplateParmExpr>(E)) {
E = NTTP->getReplacement();
@@ -2728,7 +2675,9 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef) const {
return cast<GenericSelectionExpr>(this)->getResultExpr()
->isConstantInitializer(Ctx, IsForRef);
case ChooseExprClass:
- return cast<ChooseExpr>(this)->getChosenSubExpr(Ctx)
+ if (cast<ChooseExpr>(this)->isConditionDependent())
+ return false;
+ return cast<ChooseExpr>(this)->getChosenSubExpr()
->isConstantInitializer(Ctx, IsForRef);
case UnaryOperatorClass: {
const UnaryOperator* Exp = cast<UnaryOperator>(this);
@@ -2887,7 +2836,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx) const {
HasSideEffects(Ctx);
case ChooseExprClass:
- return cast<ChooseExpr>(this)->getChosenSubExpr(Ctx)->HasSideEffects(Ctx);
+ return cast<ChooseExpr>(this)->getChosenSubExpr()->HasSideEffects(Ctx);
case CXXDefaultArgExprClass:
return cast<CXXDefaultArgExpr>(this)->getExpr()->HasSideEffects(Ctx);
@@ -3082,7 +3031,13 @@ Expr::isNullPointerConstant(ASTContext &Ctx,
return PE->getSubExpr()->isNullPointerConstant(Ctx, NPC);
} else if (const GenericSelectionExpr *GE =
dyn_cast<GenericSelectionExpr>(this)) {
+ if (GE->isResultDependent())
+ return NPCK_NotNull;
return GE->getResultExpr()->isNullPointerConstant(Ctx, NPC);
+ } else if (const ChooseExpr *CE = dyn_cast<ChooseExpr>(this)) {
+ if (CE->isConditionDependent())
+ return NPCK_NotNull;
+ return CE->getChosenSubExpr()->isNullPointerConstant(Ctx, NPC);
} else if (const CXXDefaultArgExpr *DefaultArg
= dyn_cast<CXXDefaultArgExpr>(this)) {
// See through default argument expressions.
@@ -3567,10 +3522,6 @@ StringRef ObjCBridgedCastExpr::getBridgeKindName() const {
llvm_unreachable("Invalid BridgeKind!");
}
-bool ChooseExpr::isConditionTrue(const ASTContext &C) const {
- return getCond()->EvaluateKnownConstInt(C) != 0;
-}
-
ShuffleVectorExpr::ShuffleVectorExpr(ASTContext &C, ArrayRef<Expr*> args,
QualType Type, SourceLocation BLoc,
SourceLocation RP)
diff --git a/clang/lib/AST/ExprClassification.cpp b/clang/lib/AST/ExprClassification.cpp
index 72f17669ed1..1c91af7d47f 100644
--- a/clang/lib/AST/ExprClassification.cpp
+++ b/clang/lib/AST/ExprClassification.cpp
@@ -286,7 +286,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
// __builtin_choose_expr is equivalent to the chosen expression.
case Expr::ChooseExprClass:
- return ClassifyInternal(Ctx, cast<ChooseExpr>(E)->getChosenSubExpr(Ctx));
+ return ClassifyInternal(Ctx, cast<ChooseExpr>(E)->getChosenSubExpr());
// Extended vector element access is an lvalue unless there are duplicates
// in the shuffle expression.
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 28473f0bdbd..ddfb64c44d5 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -3585,7 +3585,7 @@ public:
RetTy VisitUnaryPlus(const UnaryOperator *E)
{ return StmtVisitorTy::Visit(E->getSubExpr()); }
RetTy VisitChooseExpr(const ChooseExpr *E)
- { return StmtVisitorTy::Visit(E->getChosenSubExpr(Info.Ctx)); }
+ { return StmtVisitorTy::Visit(E->getChosenSubExpr()); }
RetTy VisitGenericSelectionExpr(const GenericSelectionExpr *E)
{ return StmtVisitorTy::Visit(E->getResultExpr()); }
RetTy VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr *E)
@@ -8263,7 +8263,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
case Expr::CXXDefaultInitExprClass:
return CheckICE(cast<CXXDefaultInitExpr>(E)->getExpr(), Ctx);
case Expr::ChooseExprClass: {
- return CheckICE(cast<ChooseExpr>(E)->getChosenSubExpr(Ctx), Ctx);
+ return CheckICE(cast<ChooseExpr>(E)->getChosenSubExpr(), Ctx);
}
}
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index b283174514e..d6ff93f5fb7 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -851,7 +851,7 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) {
case Expr::BinaryConditionalOperatorClass:
return EmitConditionalOperatorLValue(cast<BinaryConditionalOperator>(E));
case Expr::ChooseExprClass:
- return EmitLValue(cast<ChooseExpr>(E)->getChosenSubExpr(getContext()));
+ return EmitLValue(cast<ChooseExpr>(E)->getChosenSubExpr());
case Expr::OpaqueValueExprClass:
return EmitOpaqueValueLValue(cast<OpaqueValueExpr>(E));
case Expr::SubstNonTypeTemplateParmExprClass:
diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp
index 902bf1605a2..8268c86c9a1 100644
--- a/clang/lib/CodeGen/CGExprAgg.cpp
+++ b/clang/lib/CodeGen/CGExprAgg.cpp
@@ -920,7 +920,7 @@ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
}
void AggExprEmitter::VisitChooseExpr(const ChooseExpr *CE) {
- Visit(CE->getChosenSubExpr(CGF.getContext()));
+ Visit(CE->getChosenSubExpr());
}
void AggExprEmitter::VisitVAArgExpr(VAArgExpr *VE) {
diff --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp
index 5ba13175d53..fcff8e9439c 100644
--- a/clang/lib/CodeGen/CGExprComplex.cpp
+++ b/clang/lib/CodeGen/CGExprComplex.cpp
@@ -778,7 +778,7 @@ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
}
ComplexPairTy ComplexExprEmitter::VisitChooseExpr(ChooseExpr *E) {
- return Visit(E->getChosenSubExpr(CGF.getContext()));
+ return Visit(E->getChosenSubExpr());
}
ComplexPairTy ComplexExprEmitter::VisitInitListExpr(InitListExpr *E) {
diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp
index 4a6f90a30e7..431ee3c47ff 100644
--- a/clang/lib/CodeGen/CGExprConstant.cpp
+++ b/clang/lib/CodeGen/CGExprConstant.cpp
@@ -610,7 +610,7 @@ public:
}
llvm::Constant *VisitChooseExpr(ChooseExpr *CE) {
- return Visit(CE->getChosenSubExpr(CGM.getContext()));
+ return Visit(CE->getChosenSubExpr());
}
llvm::Constant *VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index bfd880a7e36..7d98764548f 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -3101,7 +3101,7 @@ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
}
Value *ScalarExprEmitter::VisitChooseExpr(ChooseExpr *E) {
- return Visit(E->getChosenSubExpr(CGF.getContext()));
+ return Visit(E->getChosenSubExpr());
}
Value *ScalarExprEmitter::VisitVAArgExpr(VAArgExpr *VE) {
diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp
index 0385c7783e3..0d662c8f393 100644
--- a/clang/lib/Sema/SemaExceptionSpec.cpp
+++ b/clang/lib/Sema/SemaExceptionSpec.cpp
@@ -1025,7 +1025,7 @@ CanThrowResult Sema::canThrow(const Expr *E) {
case Expr::ChooseExprClass:
if (E->isTypeDependent() || E->isValueDependent())
return CT_Dependent;
- return canThrow(cast<ChooseExpr>(E)->getChosenSubExpr(Context));
+ return canThrow(cast<ChooseExpr>(E)->getChosenSubExpr());
case Expr::GenericSelectionExprClass:
if (cast<GenericSelectionExpr>(E)->isResultDependent())
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index f397c5bb2ef..2c933147f44 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -9868,6 +9868,7 @@ ExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc,
ExprObjectKind OK = OK_Ordinary;
QualType resType;
bool ValueDependent = false;
+ bool CondIsTrue = false;
if (CondExpr->isTypeDependent() || CondExpr->isValueDependent()) {
resType = Context.DependentTy;
ValueDependent = true;
@@ -9880,9 +9881,10 @@ ExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc,
if (CondICE.isInvalid())
return ExprError();
CondExpr = CondICE.take();
+ CondIsTrue = condEval.getZExtValue();
// If the condition is > zero, then the AST type is the same as the LSHExpr.
- Expr *ActiveExpr = condEval.getZExtValue() ? LHSExpr : RHSExpr;
+ Expr *ActiveExpr = CondIsTrue ? LHSExpr : RHSExpr;
resType = ActiveExpr->getType();
ValueDependent = ActiveExpr->isValueDependent();
@@ -9891,7 +9893,7 @@ ExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc,
}
return Owned(new (Context) ChooseExpr(BuiltinLoc, CondExpr, LHSExpr, RHSExpr,
- resType, VK, OK, RPLoc,
+ resType, VK, OK, RPLoc, CondIsTrue,
resType->isDependentType(),
ValueDependent));
}
diff --git a/clang/lib/Sema/SemaPseudoObject.cpp b/clang/lib/Sema/SemaPseudoObject.cpp
index a10612a8b07..106250fe0f5 100644
--- a/clang/lib/Sema/SemaPseudoObject.cpp
+++ b/clang/lib/Sema/SemaPseudoObject.cpp
@@ -101,6 +101,25 @@ namespace {
resultIndex);
}
+ if (ChooseExpr *ce = dyn_cast<ChooseExpr>(e)) {
+ assert(!ce->isConditionDependent());
+
+ Expr *LHS = ce->getLHS(), *RHS = ce->getRHS();
+ Expr *&rebuiltExpr = ce->isConditionTrue() ? LHS : RHS;
+ rebuiltExpr = rebuild(rebuiltExpr);
+
+ return new (S.Context) ChooseExpr(ce->getBuiltinLoc(),
+ ce->getCond(),
+ LHS, RHS,
+ rebuiltExpr->getType(),
+ rebuiltExpr->getValueKind(),
+ rebuiltExpr->getObjectKind(),
+ ce->getRParenLoc(),
+ ce->isConditionTrue(),
+ rebuiltExpr->isTypeDependent(),
+ rebuiltExpr->isValueDependent());
+ }
+
llvm_unreachable("bad expression to rebuild!");
}
};
diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp
index 113b12ff59b..ed07b0532f1 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -835,6 +835,7 @@ void ASTStmtReader::VisitChooseExpr(ChooseExpr *E) {
E->setRHS(Reader.ReadSubExpr());
E->setBuiltinLoc(ReadSourceLocation(Record, Idx));
E->setRParenLoc(ReadSourceLocation(Record, Idx));
+ E->setIsConditionTrue(Record[Idx++]);
}
void ASTStmtReader::VisitGNUNullExpr(GNUNullExpr *E) {
diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp
index 8d47158f941..d8b852136c9 100644
--- a/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -773,6 +773,7 @@ void ASTStmtWriter::VisitChooseExpr(ChooseExpr *E) {
Writer.AddStmt(E->getRHS());
Writer.AddSourceLocation(E->getBuiltinLoc(), Record);
Writer.AddSourceLocation(E->getRParenLoc(), Record);
+ Record.push_back(E->isConditionDependent() ? false : E->isConditionTrue());
Code = serialization::EXPR_CHOOSE;
}
diff --git a/clang/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp
index 271ba4702c5..d756c629568 100644
--- a/clang/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp
@@ -678,19 +678,8 @@ bool IdempotentOperationChecker::CanVary(const Expr *Ex,
return CanVary(B->getRHS(), AC)
|| CanVary(B->getLHS(), AC);
}
- case Stmt::UnaryOperatorClass: {
- const UnaryOperator *U = cast<const UnaryOperator>(Ex);
- // Handle trivial case first
- switch (U->getOpcode()) {
- case UO_Extension:
- return false;
- default:
- return CanVary(U->getSubExpr(), AC);
- }
- }
- case Stmt::ChooseExprClass:
- return CanVary(cast<const ChooseExpr>(Ex)->getChosenSubExpr(
- AC->getASTContext()), AC);
+ case Stmt::UnaryOperatorClass:
+ return CanVary(cast<UnaryOperator>(Ex)->getSubExpr(), AC);
case Stmt::ConditionalOperatorClass:
case Stmt::BinaryConditionalOperatorClass:
return CanVary(cast<AbstractConditionalOperator>(Ex)->getCond(), AC);
OpenPOWER on IntegriCloud