if (val.isUnknownOrUndef() || castTy == originalTy)
return val;
+ if (castTy->isBooleanType()) {
+ if (val.isUnknownOrUndef())
+ return val;
+ if (val.isConstant())
+ return makeTruthVal(!val.isZeroConstant(), castTy);
+ if (SymbolRef Sym = val.getAsSymbol()) {
+ BasicValueFactory &BVF = getBasicValueFactory();
+ // FIXME: If we had a state here, we could see if the symbol is known to
+ // be zero, but we don't.
+ return makeNonLoc(Sym, BO_NE, BVF.getValue(0, Sym->getType()), castTy);
+ }
+
+ assert(val.getAs<Loc>());
+ return makeTruthVal(true, castTy);
+ }
+
// For const casts, casts to void, just propagate the value.
if (!castTy->isVariableArrayType() && !originalTy->isVariableArrayType())
if (shouldBeModeledWithNoOp(Context, Context.getPointerType(castTy),
case BO_GE:
case BO_EQ:
case BO_NE:
+ assert(resultTy->isBooleanType() ||
+ resultTy == getConditionType());
+ assert(symIntExpr->getType()->isBooleanType() ||
+ getContext().hasSameUnqualifiedType(symIntExpr->getType(),
+ getConditionType()));
// Negate the comparison and make a value.
opc = BinaryOperator::negateComparisonOp(opc);
- assert(symIntExpr->getType() == resultTy);
return makeNonLoc(symIntExpr->getLHS(), opc,
symIntExpr->getRHS(), resultTy);
}
// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core.BoolAssignment -analyzer-store=region -verify -std=c99 -Dbool=_Bool %s
// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core.BoolAssignment -analyzer-store=region -verify -x c++ %s
-// Test C++'s bool and C's _Bool
+// Test C++'s bool and C's _Bool.
+// FIXME: We stopped warning on these when SValBuilder got smarter about
+// casts to bool. Arguably, however, these conversions are okay; the result
+// is always 'true' or 'false'.
void test_stdbool_initialization(int y) {
+ bool constant = 2; // no-warning
if (y < 0) {
- bool x = y; // expected-warning {{Assignment of a non-Boolean value}}
+ bool x = y; // no-warning
return;
}
if (y > 1) {
- bool x = y; // expected-warning {{Assignment of a non-Boolean value}}
+ bool x = y; // no-warning
return;
}
bool x = y; // no-warning
void test_stdbool_assignment(int y) {
bool x = 0; // no-warning
if (y < 0) {
- x = y; // expected-warning {{Assignment of a non-Boolean value}}
+ x = y; // no-warning
return;
}
if (y > 1) {
- x = y; // expected-warning {{Assignment of a non-Boolean value}}
+ x = y; // no-warning
return;
}
x = y; // no-warning
typedef signed char BOOL;
void test_BOOL_initialization(int y) {
+ BOOL constant = 2; // expected-warning {{Assignment of a non-Boolean value}}
if (y < 0) {
BOOL x = y; // expected-warning {{Assignment of a non-Boolean value}}
return;
typedef unsigned char Boolean;
void test_Boolean_initialization(int y) {
+ Boolean constant = 2; // expected-warning {{Assignment of a non-Boolean value}}
if (y < 0) {
Boolean x = y; // expected-warning {{Assignment of a non-Boolean value}}
return;
-// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -analyze -analyzer-checker=core,alpha.core -analyzer-store=region -verify %s
-// RUN: %clang_cc1 -triple i386-apple-darwin9 -analyze -analyzer-checker=core,alpha.core -analyzer-store=region -verify %s
-// expected-no-diagnostics
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection -analyzer-store=region -verify %s
+// RUN: %clang_cc1 -triple i386-apple-darwin9 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection -analyzer-store=region -verify %s
+
+extern void clang_analyzer_eval(_Bool);
// Test if the 'storage' region gets properly initialized after it is cast to
// 'struct sockaddr *'.
}
return 0;
}
+
+void castsToBool() {
+ clang_analyzer_eval(0); // expected-warning{{FALSE}}
+ clang_analyzer_eval(0U); // expected-warning{{FALSE}}
+ clang_analyzer_eval((void *)0); // expected-warning{{FALSE}}
+
+ clang_analyzer_eval(1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(1U); // expected-warning{{TRUE}}
+ clang_analyzer_eval(-1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(0x100); // expected-warning{{TRUE}}
+ clang_analyzer_eval(0x100U); // expected-warning{{TRUE}}
+ clang_analyzer_eval((void *)0x100); // expected-warning{{TRUE}}
+
+ extern int symbolicInt;
+ clang_analyzer_eval(symbolicInt); // expected-warning{{UNKNOWN}}
+ if (symbolicInt)
+ clang_analyzer_eval(symbolicInt); // expected-warning{{TRUE}}
+
+ extern void *symbolicPointer;
+ clang_analyzer_eval(symbolicPointer); // expected-warning{{UNKNOWN}}
+ if (symbolicPointer)
+ clang_analyzer_eval(symbolicPointer); // expected-warning{{TRUE}}
+
+ int localInt;
+ clang_analyzer_eval(&localInt); // expected-warning{{TRUE}}
+ clang_analyzer_eval(&castsToBool); // expected-warning{{TRUE}}
+ clang_analyzer_eval("abc"); // expected-warning{{TRUE}}
+
+ extern float globalFloat;
+ clang_analyzer_eval(globalFloat); // expected-warning{{UNKNOWN}}
+}
// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-store=region -verify %s
-// FIXME: Only the stack-address checking in Sema catches this right now, and
-// the stack analyzer doesn't handle the ImplicitCastExpr (lvalue).
+typedef __INTPTR_TYPE__ intptr_t;
+
const int& g() {
int s;
return s; // expected-warning{{Address of stack memory associated with local variable 's' returned}} expected-warning{{reference to stack memory associated with local variable 's' returned}}
return p; // expected-warning {{stack memory associated with local variable 'p' returned to caller}}
}
+namespace rdar13296133 {
+ class ConvertsToBool {
+ public:
+ operator bool() const { return this; }
+ };
+
+ class ConvertsToIntptr {
+ public:
+ operator intptr_t() const { return reinterpret_cast<intptr_t>(this); }
+ };
+
+ class ConvertsToPointer {
+ public:
+ operator const void *() const { return this; }
+ };
+
+ intptr_t returnAsNonLoc() {
+ ConvertsToIntptr obj;
+ return obj; // expected-warning{{Address of stack memory associated with local variable 'obj' returned to caller}}
+ }
+
+ bool returnAsBool() {
+ ConvertsToBool obj;
+ return obj; // no-warning
+ }
+
+ intptr_t returnAsNonLocViaPointer() {
+ ConvertsToPointer obj;
+ return reinterpret_cast<intptr_t>(static_cast<const void *>(obj)); // expected-warning{{Address of stack memory associated with local variable 'obj' returned to caller}}
+ }
+
+ bool returnAsBoolViaPointer() {
+ ConvertsToPointer obj;
+ return obj; // no-warning
+ }
+}
+
-// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-store region -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core -verify -std=c99 -Dbool=_Bool %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core -verify -x c++ %s
+typedef __INTPTR_TYPE__ intptr_t;
char const *p;
void f0() {
void f2() {
p = (const char *) __builtin_alloca(12);
-} // expected-warning{{Address of stack memory allocated by call to alloca() on line 17 is still referred to by the global variable 'p' upon returning to the caller. This will be a dangling reference}}
+} // expected-warning{{Address of stack memory allocated by call to alloca() on line 19 is still referred to by the global variable 'p' upon returning to the caller. This will be a dangling reference}}
// PR 7383 - previosly the stack address checker would crash on this example
// because it would attempt to do a direct load from 'pr7383_list'.
a = &x;
b = &x;
} // expected-warning{{Address of stack memory associated with local variable 'x' is still referred to by the global variable 'a' upon returning}} expected-warning{{Address of stack memory associated with local variable 'x' is still referred to by the global variable 'b' upon returning}}
+
+intptr_t returnAsNonLoc() {
+ int x;
+ return (intptr_t)&x; // expected-warning{{Address of stack memory associated with local variable 'x' returned to caller}}
+}
+
+bool returnAsBool() {
+ int x;
+ return &x; // no-warning
+}
+
+void assignAsNonLoc() {
+ extern intptr_t ip;
+ int x;
+ ip = (intptr_t)&x;
+} // expected-warning{{Address of stack memory associated with local variable 'x' is still referred to by the global variable 'ip' upon returning}}
+
+void assignAsBool() {
+ extern bool b;
+ int x;
+ b = &x;
+} // no-warning
int SValBuilderLogicNoCrash(int *x) {
return 3 - (int)(x +3);
}
+
+// http://llvm.org/bugs/show_bug.cgi?id=15863
+// Don't crash when mixing 'bool' and 'int' in implicit comparisons to 0.
+void pr15863() {
+ extern int getBool();
+ _Bool a = getBool();
+ (void)!a; // no-warning
+}