forked from OSchip/llvm-project
GCC has an extension where the left hand side of the ? : operator can be omitted. Handle this in a few more places.
llvm-svn: 44462
This commit is contained in:
parent
907703cecd
commit
801c5c7467
|
@ -494,7 +494,8 @@ bool Expr::isConstantExpr(ASTContext &Ctx, SourceLocation *Loc) const {
|
|||
case ConditionalOperatorClass: {
|
||||
const ConditionalOperator *Exp = cast<ConditionalOperator>(this);
|
||||
if (!Exp->getCond()->isConstantExpr(Ctx, Loc) ||
|
||||
!Exp->getLHS()->isConstantExpr(Ctx, Loc) ||
|
||||
// Handle the GNU extension for missing LHS.
|
||||
!(Exp->getLHS() && Exp->getLHS()->isConstantExpr(Ctx, Loc)) ||
|
||||
!Exp->getRHS()->isConstantExpr(Ctx, Loc))
|
||||
return false;
|
||||
return true;
|
||||
|
@ -809,10 +810,11 @@ bool Expr::isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx,
|
|||
if (Result == 0) std::swap(TrueExp, FalseExp);
|
||||
|
||||
// Evaluate the false one first, discard the result.
|
||||
if (!FalseExp->isIntegerConstantExpr(Result, Ctx, Loc, false))
|
||||
if (FalseExp && !FalseExp->isIntegerConstantExpr(Result, Ctx, Loc, false))
|
||||
return false;
|
||||
// Evalute the true one, capture the result.
|
||||
if (!TrueExp->isIntegerConstantExpr(Result, Ctx, Loc, isEvaluated))
|
||||
if (TrueExp &&
|
||||
!TrueExp->isIntegerConstantExpr(Result, Ctx, Loc, isEvaluated))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -145,7 +145,13 @@ bool TransferFuncs::VisitUnaryOperator(UnaryOperator* U) {
|
|||
|
||||
bool TransferFuncs::VisitConditionalOperator(ConditionalOperator* C) {
|
||||
Visit(C->getCond());
|
||||
return Visit(C->getLHS()) & Visit(C->getRHS()); // Yes: we want &, not &&.
|
||||
|
||||
bool rhsResult = Visit(C->getRHS());
|
||||
// Handle the GNU extension for missing LHS.
|
||||
if (Expr *lhs = C->getLHS())
|
||||
return Visit(lhs) & rhsResult; // Yes: we want &, not &&.
|
||||
else
|
||||
return rhsResult;
|
||||
}
|
||||
|
||||
bool TransferFuncs::VisitStmt(Stmt* S) {
|
||||
|
|
|
@ -564,10 +564,12 @@ static DeclRefExpr* EvalAddr(Expr *E) {
|
|||
case Stmt::ConditionalOperatorClass: {
|
||||
ConditionalOperator *C = cast<ConditionalOperator>(E);
|
||||
|
||||
if (DeclRefExpr* LHS = EvalAddr(C->getLHS()))
|
||||
return LHS;
|
||||
else
|
||||
return EvalAddr(C->getRHS());
|
||||
// Handle the GNU extension for missing LHS.
|
||||
if (Expr *lhsExpr = C->getLHS())
|
||||
if (DeclRefExpr* LHS = EvalAddr(lhsExpr))
|
||||
return LHS;
|
||||
|
||||
return EvalAddr(C->getRHS());
|
||||
}
|
||||
|
||||
// For implicit casts, we need to handle conversions from arrays to
|
||||
|
@ -674,10 +676,12 @@ static DeclRefExpr* EvalVal(Expr *E) {
|
|||
// non-NULL DeclRefExpr's. If one is non-NULL, we return it.
|
||||
ConditionalOperator *C = cast<ConditionalOperator>(E);
|
||||
|
||||
if (DeclRefExpr *LHS = EvalVal(C->getLHS()))
|
||||
return LHS;
|
||||
else
|
||||
return EvalVal(C->getRHS());
|
||||
// Handle the GNU extension for missing LHS.
|
||||
if (Expr *lhsExpr = C->getLHS())
|
||||
if (DeclRefExpr *LHS = EvalVal(lhsExpr))
|
||||
return LHS;
|
||||
|
||||
return EvalVal(C->getRHS());
|
||||
}
|
||||
|
||||
// Accesses to members are potential references to data on the stack.
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
// RUN: clang -warn-dead-stores -warn-uninit-values -verify %s
|
||||
|
||||
void f1()
|
||||
{
|
||||
int i;
|
||||
|
||||
int j = i ? : 1; // expected-warning{{use of uninitialized variable}}
|
||||
}
|
||||
|
||||
void *f2(int *i)
|
||||
{
|
||||
return i ? : 0;
|
||||
}
|
||||
|
||||
void *f3(int *i)
|
||||
{
|
||||
int a;
|
||||
|
||||
return &a ? : i;
|
||||
}
|
||||
|
||||
void f4()
|
||||
{
|
||||
char c[1 ? : 2];
|
||||
}
|
||||
|
Loading…
Reference in New Issue