]> granicus.if.org Git - clang/commitdiff
GCC has an extension where the left hand side of the ? : operator can be omitted...
authorAnders Carlsson <andersca@mac.com>
Fri, 30 Nov 2007 19:04:31 +0000 (19:04 +0000)
committerAnders Carlsson <andersca@mac.com>
Fri, 30 Nov 2007 19:04:31 +0000 (19:04 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@44462 91177308-0d34-0410-b5e6-96231b3b80d8

AST/Expr.cpp
Analysis/UninitializedValues.cpp
Sema/SemaChecking.cpp
test/Analysis/conditional-op-missing-lhs.c [new file with mode: 0644]

index 682b4bd92be3dcfe39e1e66360c41b4a3750097b..0aee702c65d596dce239212f15a884b3632bace1 100644 (file)
@@ -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;
   }
index 8a27b71b8fd253f9745a9b6f5a1890a3bbdd8288..35d6124e6217eeadff875a8278492482a2f6cd12 100644 (file)
@@ -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) {
index 20f0b81b43068d7da538d9c475921a45dabcc86f..81a18c9645f6575b43c3104bc6f2ab98917429e8 100644 (file)
@@ -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 (file)
index 0000000..917212d
--- /dev/null
@@ -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];
+}
+