diff options
author | Anders Carlsson <andersca@mac.com> | 2007-11-30 19:04:31 +0000 |
---|---|---|
committer | Anders Carlsson <andersca@mac.com> | 2007-11-30 19:04:31 +0000 |
commit | 3907323dd6665c0c4e383435cb145233f4533406 (patch) | |
tree | 14734649e3ede0685322f84ce7c4153fc9ab0746 | |
parent | b0ff33a9f4b2a75b6949976bbf3782ff0d839cb1 (diff) |
GCC has an extension where the left hand side of the ? : operator can be omitted. Handle this in a few more places.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@44462 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | AST/Expr.cpp | 8 | ||||
-rw-r--r-- | Analysis/UninitializedValues.cpp | 8 | ||||
-rw-r--r-- | Sema/SemaChecking.cpp | 20 | ||||
-rw-r--r-- | test/Analysis/conditional-op-missing-lhs.c | 26 |
4 files changed, 50 insertions, 12 deletions
diff --git a/AST/Expr.cpp b/AST/Expr.cpp index 682b4bd92b..0aee702c65 100644 --- a/AST/Expr.cpp +++ b/AST/Expr.cpp @@ -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; } diff --git a/Analysis/UninitializedValues.cpp b/Analysis/UninitializedValues.cpp index 8a27b71b8f..35d6124e62 100644 --- a/Analysis/UninitializedValues.cpp +++ b/Analysis/UninitializedValues.cpp @@ -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) { diff --git a/Sema/SemaChecking.cpp b/Sema/SemaChecking.cpp index 20f0b81b43..81a18c9645 100644 --- a/Sema/SemaChecking.cpp +++ b/Sema/SemaChecking.cpp @@ -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. diff --git a/test/Analysis/conditional-op-missing-lhs.c b/test/Analysis/conditional-op-missing-lhs.c new file mode 100644 index 0000000000..917212d387 --- /dev/null +++ b/test/Analysis/conditional-op-missing-lhs.c @@ -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]; +} + |