ddcc updated this revision to Diff 113619.
ddcc added a comment.

Rebase, factor out floating-point changes, fix Z3 type bug, support general 
APSInt comparison


https://reviews.llvm.org/D28955

Files:
  include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h
  include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
  include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
  lib/StaticAnalyzer/Checkers/BoolAssignmentChecker.cpp
  lib/StaticAnalyzer/Core/ProgramState.cpp
  lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
  lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp
  lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
  lib/StaticAnalyzer/Core/Store.cpp
  lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp
  test/Analysis/PR3991.m
  test/Analysis/dead-stores.m
  test/Analysis/explain-svals.cpp
  test/Analysis/malloc.c
  test/Analysis/misc-ps-eager-assume.m
  test/Analysis/std-c-library-functions.c

Index: test/Analysis/std-c-library-functions.c
===================================================================
--- test/Analysis/std-c-library-functions.c
+++ test/Analysis/std-c-library-functions.c
@@ -146,7 +146,7 @@
 void test_isgraph_isprint(int x) {
   char y = x;
   if (isgraph(y))
-    clang_analyzer_eval(isprint(x)); // expected-warning{{TRUE}}
+    clang_analyzer_eval(isprint(y)); // expected-warning{{TRUE}}
 }
 
 int isdigit(int);
Index: test/Analysis/misc-ps-eager-assume.m
===================================================================
--- test/Analysis/misc-ps-eager-assume.m
+++ test/Analysis/misc-ps-eager-assume.m
@@ -1,5 +1,4 @@
 // RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core -analyzer-store=region -verify -fblocks %s -analyzer-eagerly-assume
-// expected-no-diagnostics
 
 // Delta-reduced header stuff (needed for test cases).
 typedef signed char BOOL;
@@ -56,7 +55,7 @@
 void handle_symbolic_cast_in_condition(void) {
   NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
 
-  BOOL needsAnArray = [@"aString" isEqualToString:@"anotherString"];
+  BOOL needsAnArray = [@"aString" isEqualToString:@"anotherString"]; // expected-warning {{Assignment of a non-Boolean value}}
   NSMutableArray* array = needsAnArray ? [[NSMutableArray alloc] init] : 0;
   if(needsAnArray)
     [array release];
Index: test/Analysis/malloc.c
===================================================================
--- test/Analysis/malloc.c
+++ test/Analysis/malloc.c
@@ -1656,13 +1656,13 @@
 void testOffsetPassedToStrlen() {
   char * string = malloc(sizeof(char)*10);
   string += 1;
-  int length = strlen(string); // expected-warning {{Potential leak of memory pointed to by 'string'}}
+  size_t length = strlen(string); // expected-warning {{Potential leak of memory pointed to by 'string'}}
 }
 
 void testOffsetPassedToStrlenThenFree() {
   char * string = malloc(sizeof(char)*10);
   string += 1;
-  int length = strlen(string);
+  size_t length = strlen(string);
   free(string); // expected-warning {{Argument to free() is offset by 1 byte from the start of memory allocated by malloc()}}
 }
 
@@ -1705,7 +1705,7 @@
 }
 
 char *dupstrNoWarn(const char *s) {
-  const int len = strlen(s);
+  const size_t len = strlen(s);
   char *p = (char*) smallocNoWarn(len + 1);
   strcpy(p, s); // no-warning
   return p;
@@ -1721,7 +1721,7 @@
 }
 
 char *dupstrWarn(const char *s) {
-  const int len = strlen(s);
+  const size_t len = strlen(s);
   char *p = (char*) smallocWarn(len + 1);
   strcpy(p, s); // expected-warning{{String copy function overflows destination buffer}}
   return p;
Index: test/Analysis/explain-svals.cpp
===================================================================
--- test/Analysis/explain-svals.cpp
+++ test/Analysis/explain-svals.cpp
@@ -41,11 +41,19 @@
 
 void test_2(char *ptr, int ext) {
   clang_analyzer_explain((void *) "asdf"); // expected-warning-re{{{{^pointer to element of type 'char' with index 0 of string literal "asdf"$}}}}
+#ifdef ANALYZER_CM_Z3
+  clang_analyzer_explain(strlen(ptr)); // expected-warning-re{{{{^cast of type 'int' of metadata of type 'unsigned long' tied to pointee of argument 'ptr'$}}}}
+#else
   clang_analyzer_explain(strlen(ptr)); // expected-warning-re{{{{^metadata of type 'unsigned long' tied to pointee of argument 'ptr'$}}}}
+#endif
   clang_analyzer_explain(conjure()); // expected-warning-re{{{{^symbol of type 'int' conjured at statement 'conjure\(\)'$}}}}
   clang_analyzer_explain(glob); // expected-warning-re{{{{^value derived from \(symbol of type 'int' conjured at statement 'conjure\(\)'\) for global variable 'glob'$}}}}
   clang_analyzer_explain(glob_ptr); // expected-warning-re{{{{^value derived from \(symbol of type 'int' conjured at statement 'conjure\(\)'\) for global variable 'glob_ptr'$}}}}
+#ifdef ANALYZER_CM_Z3
+  clang_analyzer_explain(clang_analyzer_getExtent(ptr)); // expected-warning-re{{{{^cast of type 'int' of extent of pointee of argument 'ptr'$}}}}
+#else
   clang_analyzer_explain(clang_analyzer_getExtent(ptr)); // expected-warning-re{{{{^extent of pointee of argument 'ptr'$}}}}
+#endif
   int *x = new int[ext];
   clang_analyzer_explain(x); // expected-warning-re{{{{^pointer to element of type 'int' with index 0 of heap segment that starts at symbol of type 'int \*' conjured at statement 'new int \[ext\]'$}}}}
   // Sic! What gets computed is the extent of the element-region.
Index: test/Analysis/dead-stores.m
===================================================================
--- test/Analysis/dead-stores.m
+++ test/Analysis/dead-stores.m
@@ -1,5 +1,4 @@
 // RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core -analyzer-checker=deadcode.DeadStores,osx.cocoa.RetainCount -fblocks -verify -Wno-objc-root-class %s
-// expected-no-diagnostics
 
 typedef signed char BOOL;
 typedef unsigned int NSUInteger;
@@ -55,7 +54,7 @@
 - (void) bar_rbar8527823
 {
  @synchronized(self) {
-   BOOL isExec = baz_rdar8527823(); // no-warning
+   BOOL isExec = baz_rdar8527823(); // expected-warning {{Assignment of a non-Boolean value}}
    if (isExec) foo_rdar8527823();
  }
 }
Index: test/Analysis/PR3991.m
===================================================================
--- test/Analysis/PR3991.m
+++ test/Analysis/PR3991.m
@@ -1,9 +1,11 @@
 // RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core -analyzer-store=region -verify -triple x86_64-apple-darwin9 -Wno-incomplete-implementation %s
-// expected-no-diagnostics
 
 //===----------------------------------------------------------------------===//
 // Delta-debugging produced forward declarations.
 //===----------------------------------------------------------------------===//
+#ifdef ANALYZER_CM_Z3
+// expected-no-diagnostics
+#endif
 
 typedef signed char BOOL;
 typedef struct _NSZone NSZone;
@@ -40,7 +42,7 @@
 - (unsigned int)currentPathComponentIndex;
 - (void)setCurrentPathComponentIndex:(unsigned int)aCurrentPathComponentIndex;
 - (NSURL *)folderFeedURL;
-@end  
+@end
 
 @implementation IHGoogleDocsAdapter    - (id)initWithUsername:(NSString *)inUsername password:(NSString *)inPassword owner:(NSObject <IHGoogleDocsAdapterDelegate> *)owner {
   return 0;
@@ -55,9 +57,17 @@
 //===----------------------------------------------------------------------===//
 
 - (void)docListListFetchTicket:(GDataServiceTicket *)ticket               finishedWithFeed:(GDataFeedDocList *)feed {
+#ifdef ANALYZER_CM_Z3
   BOOL doGetDir = self.directoryPathComponents != 0 && self.currentPathComponentIndex < [self.directoryPathComponents count];
+#else
+  BOOL doGetDir = self.directoryPathComponents != 0 && self.currentPathComponentIndex < [self.directoryPathComponents count]; // expected-warning{{Assignment of a non-Boolean value}}
+#endif
   if (doGetDir)  {
+#ifdef ANALYZER_CM_Z3
     BOOL isDirExisting = [[self.feedDocList entries] count] > 0;
+#else
+    BOOL isDirExisting = [[self.feedDocList entries] count] > 0; // expected-warning{{Assignment of a non-Boolean value}}
+#endif
     if (isDirExisting)   {
       if (self.folderFeedURL != 0)    {
         if (++self.currentPathComponentIndex == [self.directoryPathComponents count])     {
Index: lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp
===================================================================
--- lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp
+++ lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp
@@ -681,12 +681,14 @@
       Z3_get_numeral_uint64(Z3Context::ZC, AST,
                             reinterpret_cast<__uint64 *>(&Value[0]));
       if (Sort.getBitvectorSortSize() <= 64) {
-        Int = llvm::APSInt(llvm::APInt(Int.getBitWidth(), Value[0]), true);
+        Int = llvm::APSInt(llvm::APInt(Int.getBitWidth(), Value[0]),
+                           Int.isUnsigned());
       } else if (Sort.getBitvectorSortSize() == 128) {
         Z3Expr ASTHigh = Z3Expr(Z3_mk_extract(Z3Context::ZC, 127, 64, AST));
         Z3_get_numeral_uint64(Z3Context::ZC, AST,
                               reinterpret_cast<__uint64 *>(&Value[1]));
-        Int = llvm::APSInt(llvm::APInt(Int.getBitWidth(), Value), true);
+        Int = llvm::APSInt(llvm::APInt(Int.getBitWidth(), Value),
+                           Int.isUnsigned());
       } else {
         assert(false && "Bitwidth not supported!");
         return false;
@@ -702,7 +704,7 @@
           llvm::APInt(Int.getBitWidth(),
                       Z3_get_bool_value(Z3Context::ZC, AST) == Z3_L_TRUE ? 1
                                                                          : 0),
-          true);
+          Int.isUnsigned());
       return true;
     }
   }
@@ -904,6 +906,8 @@
 
   bool canReasonAbout(SVal X) const override;
 
+  bool canReasonAboutSymbolicExtTrunc() const override;
+
   ConditionTruthVal checkNull(ProgramStateRef State, SymbolRef Sym) override;
 
   const llvm::APSInt *getSymVal(ProgramStateRef State,
@@ -1117,6 +1121,10 @@
   return true;
 }
 
+bool Z3ConstraintManager::canReasonAboutSymbolicExtTrunc() const {
+  return true;
+}
+
 ConditionTruthVal Z3ConstraintManager::checkNull(ProgramStateRef State,
                                                  SymbolRef Sym) {
   QualType RetTy;
Index: lib/StaticAnalyzer/Core/Store.cpp
===================================================================
--- lib/StaticAnalyzer/Core/Store.cpp
+++ lib/StaticAnalyzer/Core/Store.cpp
@@ -447,9 +447,6 @@
   // Pointer of any type can be cast and used as array base.
   const ElementRegion *ElemR = dyn_cast<ElementRegion>(BaseRegion);
 
-  // Convert the offset to the appropriate size and signedness.
-  Offset = svalBuilder.convertToArrayIndex(Offset).castAs<NonLoc>();
-
   if (!ElemR) {
     //
     // If the base region is not an ElementRegion, create one.
@@ -460,6 +457,9 @@
     //
     //  Observe that 'p' binds to an AllocaRegion.
     //
+
+    // Convert the offset to the appropriate size and signedness.
+    Offset = svalBuilder.convertToArrayIndex(Offset).castAs<NonLoc>();
     return loc::MemRegionVal(MRMgr.getElementRegion(elementType, Offset,
                                                     BaseRegion, Ctx));
   }
@@ -483,7 +483,9 @@
         elementType, Offset, cast<SubRegion>(ElemR->getSuperRegion()), Ctx));
   }
 
-  const llvm::APSInt& OffI = Offset.castAs<nonloc::ConcreteInt>().getValue();
+  // FIXME: This isn't quite correct, but avoids casting the Offset symbol
+  llvm::APSInt OffI = APSIntType(BaseIdxI).convert(
+      Offset.castAs<nonloc::ConcreteInt>().getValue());
   assert(BaseIdxI.isSigned());
 
   // Compute the new index.
Index: lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
===================================================================
--- lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
+++ lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
@@ -74,35 +74,46 @@
 }
 
 SVal SimpleSValBuilder::evalCastFromNonLoc(NonLoc val, QualType castTy) {
+  ConstraintManager &CM = getStateManager().getConstraintManager();
+
   bool isLocType = Loc::isLocType(castTy);
   if (val.getAs<nonloc::PointerToMember>())
     return val;
 
   if (Optional<nonloc::LocAsInteger> LI = val.getAs<nonloc::LocAsInteger>()) {
     if (isLocType)
       return LI->getLoc();
+
     // FIXME: Correctly support promotions/truncations.
-    unsigned castSize = Context.getIntWidth(castTy);
-    if (castSize == LI->getNumBits())
+    unsigned castSize = Context.getTypeSize(castTy);
+    if (!CM.canReasonAboutSymbolicExtTrunc() && castSize == LI->getNumBits())
       return val;
+
     return makeLocAsInteger(LI->getLoc(), castSize);
   }
 
   if (const SymExpr *se = val.getAsSymbolicExpression()) {
     QualType T = Context.getCanonicalType(se->getType());
-    // If types are the same or both are integers, ignore the cast.
+    // If types are the same, ignore the cast.
+    if (haveSameType(T, castTy))
+      return val;
+
+    // If types are both integers, ignore the cast.
     // FIXME: Remove this hack when we support symbolic truncation/extension.
     // HACK: If both castTy and T are integers, ignore the cast.  This is
     // not a permanent solution.  Eventually we want to precisely handle
     // extension/truncation of symbolic integers.  This prevents us from losing
     // precision when we assign 'x = y' and 'y' is symbolic and x and y are
     // different integer types.
-   if (haveSameType(T, castTy))
+    if (!CM.canReasonAboutSymbolicExtTrunc() &&
+        T->isIntegralOrEnumerationType() &&
+        castTy->isIntegralOrEnumerationType())
       return val;
 
-    if (!isLocType)
-      return makeNonLoc(se, T, castTy);
-    return UnknownVal();
+    if (isLocType)
+      return UnknownVal();
+
+    return makeNonLoc(se, T, castTy);
   }
 
   // If value is a non-integer constant, produce unknown.
Index: lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp
===================================================================
--- lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp
+++ lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp
@@ -121,7 +121,8 @@
 
   case nonloc::ConcreteIntKind: {
     const llvm::APSInt &IntVal = Value.castAs<nonloc::ConcreteInt>().getValue();
-    bool IsInRange = IntVal >= From && IntVal <= To;
+    bool IsInRange = llvm::APSInt::compareValues(IntVal, From) != -1 &&
+                     llvm::APSInt::compareValues(IntVal, To) != 1;
     bool isFeasible = (IsInRange == InRange);
     return isFeasible ? State : nullptr;
   }
Index: lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
===================================================================
--- lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
+++ lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
@@ -293,6 +293,8 @@
 
   bool canReasonAbout(SVal X) const override;
 
+  bool canReasonAboutSymbolicExtTrunc() const override;
+
   ConditionTruthVal checkNull(ProgramStateRef State, SymbolRef Sym) override;
 
   const llvm::APSInt *getSymVal(ProgramStateRef State,
@@ -425,6 +427,10 @@
   return true;
 }
 
+bool RangeConstraintManager::canReasonAboutSymbolicExtTrunc() const {
+  return false;
+}
+
 ConditionTruthVal RangeConstraintManager::checkNull(ProgramStateRef State,
                                                     SymbolRef Sym) {
   const RangeSet *Ranges = State->get<ConstraintRange>(Sym);
Index: lib/StaticAnalyzer/Core/ProgramState.cpp
===================================================================
--- lib/StaticAnalyzer/Core/ProgramState.cpp
+++ lib/StaticAnalyzer/Core/ProgramState.cpp
@@ -262,12 +262,12 @@
   // about).
   if (!T.isNull()) {
     if (SymbolRef sym = V.getAsSymbol()) {
-      if (const llvm::APSInt *Int = getStateManager()
-                                    .getConstraintManager()
-                                    .getSymVal(this, sym)) {
+      ConstraintManager &CM = getStateManager().getConstraintManager();
+
+      if (const llvm::APSInt *Int = CM.getSymVal(this, sym)) {
         // FIXME: Because we don't correctly model (yet) sign-extension
         // and truncation of symbolic values, we need to convert
-        // the integer value to the correct signedness and bitwidth.
+        // the integer value to the correct signedness and
         //
         // This shows up in the following:
         //
@@ -279,12 +279,13 @@
         //  The symbolic value stored to 'x' is actually the conjured
         //  symbol for the call to foo(); the type of that symbol is 'char',
         //  not unsigned.
-        const llvm::APSInt &NewV = getBasicVals().Convert(T, *Int);
+        if (!CM.canReasonAboutSymbolicExtTrunc())
+          Int = &getBasicVals().Convert(T, *Int);
 
         if (V.getAs<Loc>())
-          return loc::ConcreteInt(NewV);
+          return loc::ConcreteInt(*Int);
         else
-          return nonloc::ConcreteInt(NewV);
+          return nonloc::ConcreteInt(*Int);
       }
     }
   }
Index: lib/StaticAnalyzer/Checkers/BoolAssignmentChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/BoolAssignmentChecker.cpp
+++ lib/StaticAnalyzer/Checkers/BoolAssignmentChecker.cpp
@@ -69,87 +69,26 @@
   // Get the value of the right-hand side.  We only care about values
   // that are defined (UnknownVals and UndefinedVals are handled by other
   // checkers).
-  Optional<DefinedSVal> DV = val.getAs<DefinedSVal>();
-  if (!DV)
+  Optional<NonLoc> NV = val.getAs<NonLoc>();
+  if (!NV)
     return;
 
   // Check if the assigned value meets our criteria for correctness.  It must
   // be a value that is either 0 or 1.  One way to check this is to see if
   // the value is possibly < 0 (for a negative value) or greater than 1.
   ProgramStateRef state = C.getState();
   SValBuilder &svalBuilder = C.getSValBuilder();
+  BasicValueFactory &BVF = svalBuilder.getBasicValueFactory();
   ConstraintManager &CM = C.getConstraintManager();
 
-  // First, ensure that the value is >= 0.
-  DefinedSVal zeroVal = svalBuilder.makeIntVal(0, valTy);
-  SVal greaterThanOrEqualToZeroVal =
-    svalBuilder.evalBinOp(state, BO_GE, *DV, zeroVal,
-                          svalBuilder.getConditionType());
+  llvm::APSInt Zero = BVF.getValue(0, valTy);
+  llvm::APSInt One = BVF.getValue(1, valTy);
 
-  Optional<DefinedSVal> greaterThanEqualToZero =
-      greaterThanOrEqualToZeroVal.getAs<DefinedSVal>();
+  ProgramStateRef StIn, StOut;
+  std::tie(StIn, StOut) = CM.assumeInclusiveRangeDual(state, *NV, Zero, One);
 
-  if (!greaterThanEqualToZero) {
-    // The SValBuilder cannot construct a valid SVal for this condition.
-    // This means we cannot properly reason about it.
-    return;
-  }
-
-  ProgramStateRef stateLT, stateGE;
-  std::tie(stateGE, stateLT) = CM.assumeDual(state, *greaterThanEqualToZero);
-
-  // Is it possible for the value to be less than zero?
-  if (stateLT) {
-    // It is possible for the value to be less than zero.  We only
-    // want to emit a warning, however, if that value is fully constrained.
-    // If it it possible for the value to be >= 0, then essentially the
-    // value is underconstrained and there is nothing left to be done.
-    if (!stateGE)
-      emitReport(stateLT, C);
-
-    // In either case, we are done.
-    return;
-  }
-
-  // If we reach here, it must be the case that the value is constrained
-  // to only be >= 0.
-  assert(stateGE == state);
-
-  // At this point we know that the value is >= 0.
-  // Now check to ensure that the value is <= 1.
-  DefinedSVal OneVal = svalBuilder.makeIntVal(1, valTy);
-  SVal lessThanEqToOneVal =
-    svalBuilder.evalBinOp(state, BO_LE, *DV, OneVal,
-                          svalBuilder.getConditionType());
-
-  Optional<DefinedSVal> lessThanEqToOne =
-      lessThanEqToOneVal.getAs<DefinedSVal>();
-
-  if (!lessThanEqToOne) {
-    // The SValBuilder cannot construct a valid SVal for this condition.
-    // This means we cannot properly reason about it.
-    return;
-  }
-
-  ProgramStateRef stateGT, stateLE;
-  std::tie(stateLE, stateGT) = CM.assumeDual(state, *lessThanEqToOne);
-
-  // Is it possible for the value to be greater than one?
-  if (stateGT) {
-    // It is possible for the value to be greater than one.  We only
-    // want to emit a warning, however, if that value is fully constrained.
-    // If it is possible for the value to be <= 1, then essentially the
-    // value is underconstrained and there is nothing left to be done.
-    if (!stateLE)
-      emitReport(stateGT, C);
-
-    // In either case, we are done.
-    return;
-  }
-
-  // If we reach here, it must be the case that the value is constrained
-  // to only be <= 1.
-  assert(stateLE == state);
+  if (StOut)
+    emitReport(StOut, C);
 }
 
 void ento::registerBoolAssignmentChecker(CheckerManager &mgr) {
Index: include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
===================================================================
--- include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
+++ include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
@@ -71,16 +71,8 @@
 
   virtual ~SValBuilder() {}
 
-  bool haveSameType(const SymExpr *Sym1, const SymExpr *Sym2) {
-    return haveSameType(Sym1->getType(), Sym2->getType());
-  }
-
   bool haveSameType(QualType Ty1, QualType Ty2) {
-    // FIXME: Remove the second disjunct when we support symbolic
-    // truncation/extension.
-    return (Context.getCanonicalType(Ty1) == Context.getCanonicalType(Ty2) ||
-            (Ty1->isIntegralOrEnumerationType() &&
-             Ty2->isIntegralOrEnumerationType()));
+    return (Context.getCanonicalType(Ty1) == Context.getCanonicalType(Ty2));
   }
 
   SVal evalCast(SVal val, QualType castTy, QualType originalType);
Index: include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
===================================================================
--- include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
+++ include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
@@ -159,6 +159,11 @@
     return checkNull(State, Sym);
   }
 
+  /// canReasonAboutSymbolicExtTrunc - Not all ConstraintManagers can reason
+  ///  symbolic extension and truncation. Used this to ask directly when
+  ///  building SVals.
+  virtual bool canReasonAboutSymbolicExtTrunc() const = 0;
+
 protected:
   /// A flag to indicate that clients should be notified of assumptions.
   /// By default this is the case, but sometimes this needs to be restricted
Index: include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h
===================================================================
--- include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h
+++ include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h
@@ -138,12 +138,12 @@
 
     return getValue(TargetType.convert(From));
   }
-  
+
   const llvm::APSInt &Convert(QualType T, const llvm::APSInt &From) {
     APSIntType TargetType = getAPSIntType(T);
     if (TargetType == APSIntType(From))
       return From;
-    
+
     return getValue(TargetType.convert(From));
   }
 
@@ -193,8 +193,9 @@
     return getValue(X, Ctx.getTypeSize(Ctx.VoidPtrTy), isUnsigned);
   }
 
-  inline const llvm::APSInt& getTruthValue(bool b, QualType T) {
-    return getValue(b ? 1 : 0, Ctx.getTypeSize(T), false);
+  inline const llvm::APSInt &getTruthValue(bool b, QualType T) {
+    return getValue(b ? 1 : 0, Ctx.getTypeSize(T),
+                    !T->isSignedIntegerOrEnumerationType());
   }
 
   inline const llvm::APSInt& getTruthValue(bool b) {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to