return UnknownVal();
}
- if (!isa<TypedValueRegion>(MR)) {
- if (T.isNull()) {
- if (const TypedRegion *TR = dyn_cast<TypedRegion>(MR))
- T = TR->getLocationType()->getPointeeType();
- else if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(MR))
- T = SR->getPointeeStaticType();
- }
- assert(!T.isNull() && "Unable to auto-detect binding type!");
- assert(!T->isVoidType() && "Attempting to dereference a void pointer!");
+ // Auto-detect the binding type.
+ if (T.isNull()) {
+ if (const auto *TVR = dyn_cast<TypedValueRegion>(MR))
+ T = TVR->getValueType();
+ else if (const auto *TR = dyn_cast<TypedRegion>(MR))
+ T = TR->getLocationType()->getPointeeType();
+ else if (const auto *SR = dyn_cast<SymbolicRegion>(MR))
+ T = SR->getPointeeStaticType();
+ }
+ assert(!T.isNull() && "Unable to auto-detect binding type!");
+ assert(!T->isVoidType() && "Attempting to dereference a void pointer!");
+
+ if (!isa<TypedValueRegion>(MR))
MR = GetElementZeroRegion(cast<SubRegion>(MR), T);
- } else {
- T = cast<TypedValueRegion>(MR)->getValueType();
- }
// FIXME: Perhaps this method should just take a 'const MemRegion*' argument
// instead of 'Loc', and have the other Loc cases handled at a higher level.
-// RUN: %clang_analyze_cc1 -Wno-unused-value -std=c++14 -analyzer-checker=core,debug.ExprInspection,alpha.core.PointerArithm -verify %s
+// RUN: %clang_analyze_cc1 -Wno-unused-value -std=c++14 -verify %s -triple x86_64-pc-linux-gnu \
+// RUN: -analyzer-checker=core,debug.ExprInspection,alpha.core.PointerArithm
+
+// RUN: %clang_analyze_cc1 -Wno-unused-value -std=c++14 -verify %s -triple x86_64-pc-linux-gnu \
+// RUN: -analyzer-config support-symbolic-integer-casts=true \
+// RUN: -analyzer-checker=core,debug.ExprInspection,alpha.core.PointerArithm
template <typename T> void clang_analyzer_dump(T);
return bits->b; // no-warning
}
} // namespace Bug_55934
+
+void LValueToRValueBitCast_dumps(void *p, char (*array)[8]) {
+ clang_analyzer_dump(p);
+ clang_analyzer_dump(array);
+ // expected-warning@-2 {{&SymRegion{reg_$0<void * p>}}}
+ // expected-warning@-2 {{&SymRegion{reg_$1<char (*)[8] array>}}}
+ clang_analyzer_dump((unsigned long)p);
+ clang_analyzer_dump(__builtin_bit_cast(unsigned long, p));
+ // expected-warning@-2 {{&SymRegion{reg_$0<void * p>} [as 64 bit integer]}}
+ // expected-warning@-2 {{&SymRegion{reg_$0<void * p>} [as 64 bit integer]}}
+ clang_analyzer_dump((unsigned long)array);
+ clang_analyzer_dump(__builtin_bit_cast(unsigned long, array));
+ // expected-warning@-2 {{&SymRegion{reg_$1<char (*)[8] array>} [as 64 bit integer]}}
+ // expected-warning@-2 {{&SymRegion{reg_$1<char (*)[8] array>} [as 64 bit integer]}}
+}
+
+unsigned long ptr_arithmetic(void *p) {
+ return __builtin_bit_cast(unsigned long, p) + 1; // no-crash
+}
// RUN: %clang_analyze_cc1 -analyzer-checker debug.ExprInspection -Wno-deprecated-non-prototype -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker debug.ExprInspection -Wno-deprecated-non-prototype -verify %s \
+// RUN: -analyzer-config support-symbolic-integer-casts=true
+
void clang_analyzer_denote(int, const char *);
void clang_analyzer_express(int);
+void clang_analyzer_dump(int);
+void clang_analyzer_dump_ptr(int *);
void SymbolCast_of_float_type_aux(int *p) {
+ clang_analyzer_dump_ptr(p); // expected-warning {{&x}}
+ clang_analyzer_dump(*p); // expected-warning {{Unknown}}
+ // Storing to the memory region of 'float x' as 'int' will
+ // materialize a fresh conjured symbol to regain accuracy.
*p += 0;
- // FIXME: Ideally, all unknown values should be symbolicated.
- clang_analyzer_denote(*p, "$x"); // expected-warning{{Not a symbol}}
+ clang_analyzer_dump_ptr(p); // expected-warning {{&x}}
+ clang_analyzer_dump(*p); // expected-warning {{conj_$0{int}}
+ clang_analyzer_denote(*p, "$x");
*p += 1;
// This should NOT be (float)$x + 1. Symbol $x was never casted to float.
- // FIXME: Ideally, this should be $x + 1.
- clang_analyzer_express(*p); // expected-warning{{Not a symbol}}
+ clang_analyzer_express(*p); // expected-warning{{$x + 1}}
}
void SymbolCast_of_float_type(void) {