const SubRegion *Top) {
BindingKey TopKey = BindingKey::Make(Top, BindingKey::Default);
const MemRegion *ClusterHead = TopKey.getBaseRegion();
+ const ClusterBindings *Cluster = B.lookup(ClusterHead);
+
if (Top == ClusterHead) {
// We can remove an entire cluster's bindings all in one go.
return B.remove(Top);
}
- const ClusterBindings *Cluster = B.lookup(ClusterHead);
- if (!Cluster)
+ if (!Cluster) {
+ // If we're invalidating a region with a symbolic offset, we need to make
+ // sure we don't treat the base region as uninitialized anymore.
+ if (TopKey.hasSymbolicOffset()) {
+ const SubRegion *Concrete = TopKey.getConcreteOffsetRegion();
+ return B.addBinding(Concrete, BindingKey::Default, UnknownVal());
+ }
return B;
+ }
SmallVector<BindingPair, 32> Bindings;
collectSubRegionBindings(Bindings, svalBuilder, *Cluster, Top, TopKey,
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix -verify %s
-// expected-no-diagnostics
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix,debug.ExprInspection -verify %s
int printf(const char *restrict,...);
}
return 0;
}
+
+int concreteOffsetBindingIsInvalidatedBySymbolicOffsetAssignment(int length,
+ int i) {
+ int values[length];
+ values[i] = 4;
+ return values[0]; // no-warning
+}
+
+struct X{
+ int mem;
+};
+int initStruct(struct X *st);
+int structOffsetBindingIsInvalidated(int length, int i){
+ struct X l;
+ initStruct(&l);
+ return l.mem; // no-warning
+}
+
+void clang_analyzer_eval(int);
+void testConstraintOnRegionOffset(int *values, int length, int i){
+ if (values[1] == 4) {
+ values[i] = 5;
+ clang_analyzer_eval(values[1] == 4);// expected-warning {{UNKNOWN}}
+ }
+}
+
+int initArray(int *values);
+void testConstraintOnRegionOffsetStack(int *values, int length, int i) {
+ if (values[0] == 4) {
+ initArray(values);
+ clang_analyzer_eval(values[0] == 4);// expected-warning {{UNKNOWN}}
+ }
+}