aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h3
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h10
-rw-r--r--lib/StaticAnalyzer/Core/RegionStore.cpp20
-rw-r--r--lib/StaticAnalyzer/Core/SymbolManager.cpp3
-rw-r--r--test/Analysis/array-struct-region.cpp87
-rw-r--r--test/Analysis/reference.cpp14
6 files changed, 13 insertions, 124 deletions
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h b/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h
index 94c20153e1..fb393548b1 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h
@@ -93,9 +93,6 @@ public:
/// Returns the type of the APSInt used to store values of the given QualType.
APSIntType getAPSIntType(QualType T) const {
assert(T->isIntegerType() || Loc::isLocType(T));
- // Make sure all locations have the same representation in the analyzer.
- if (Loc::isLocType(T))
- T = Ctx.VoidPtrTy;
return APSIntType(Ctx.getTypeSize(T),
!T->isSignedIntegerOrEnumerationType());
}
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
index 52e52e0faa..e0b5f64b90 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
@@ -246,16 +246,8 @@ public:
}
static inline bool isLocType(QualType T) {
- // Why are record types included here? Because we want to make sure a
- // record, even a record rvalue, is always represented with a region.
- // This is especially necessary in C++, where you can call methods on
- // struct prvalues, which then need to have a valid 'this' pointer.
- //
- // This necessitates a bit of extra hackery in the Store to deal with
- // the case of binding a "struct value" into a struct region; in
- // practice it just means "dereferencing" the value before binding.
return T->isAnyPointerType() || T->isBlockPointerType() ||
- T->isReferenceType() || T->isRecordType();
+ T->isReferenceType();
}
};
diff --git a/lib/StaticAnalyzer/Core/RegionStore.cpp b/lib/StaticAnalyzer/Core/RegionStore.cpp
index 96342260a0..b3cf208000 100644
--- a/lib/StaticAnalyzer/Core/RegionStore.cpp
+++ b/lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -1744,26 +1744,6 @@ StoreRef RegionStoreManager::BindStruct(Store store, const TypedValueRegion* R,
if (!RD->isCompleteDefinition())
return StoreRef(store, *this);
- // Handle Loc values by automatically dereferencing the location.
- // This is necessary because we treat all struct values as regions even if
- // they are rvalues; we may then be asked to bind one of these
- // "rvalue regions" to an actual struct region.
- // (This is necessary for many of the test cases in array-struct-region.cpp.)
- //
- // This also handles the case of a struct argument passed by value to an
- // inlined function. In this case, the C++ standard says that the value
- // is copy-constructed into the parameter variable. However, the copy-
- // constructor is processed before we actually know if we're going to inline
- // the function, and thus we don't actually have the parameter's region
- // available. Instead, we use a temporary-object region, then copy the
- // bindings over by value.
- //
- // FIXME: This will be a problem when we handle the destructors of
- // temporaries; the inlined function will modify the parameter region,
- // but the destructor will act on the temporary region.
- if (const loc::MemRegionVal *MRV = dyn_cast<loc::MemRegionVal>(&V))
- V = getBinding(store, *MRV);
-
// Handle lazy compound values and symbolic values.
if (isa<nonloc::LazyCompoundVal>(V) || isa<nonloc::SymbolVal>(V))
return BindAggregate(store, R, V);
diff --git a/lib/StaticAnalyzer/Core/SymbolManager.cpp b/lib/StaticAnalyzer/Core/SymbolManager.cpp
index 65356a9458..c21df4c318 100644
--- a/lib/StaticAnalyzer/Core/SymbolManager.cpp
+++ b/lib/StaticAnalyzer/Core/SymbolManager.cpp
@@ -365,6 +365,9 @@ bool SymbolManager::canSymbolicate(QualType T) {
if (T->isIntegerType())
return T->isScalarType();
+ if (T->isRecordType() && !T->isUnionType())
+ return true;
+
return false;
}
diff --git a/test/Analysis/array-struct-region.cpp b/test/Analysis/array-struct-region.cpp
deleted file mode 100644
index 3581566bdc..0000000000
--- a/test/Analysis/array-struct-region.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection -verify -x c %s
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection -verify -x c++ -analyzer-config c++-inlining=constructors %s
-
-void clang_analyzer_eval(int);
-
-struct S {
- int field;
-
-#if __cplusplus
- const struct S *getThis() const { return this; }
-#endif
-};
-
-struct S getS();
-
-
-void testAssignment() {
- struct S s = getS();
-
- if (s.field != 42) return;
- clang_analyzer_eval(s.field == 42); // expected-warning{{TRUE}}
-
- s.field = 0;
- clang_analyzer_eval(s.field == 0); // expected-warning{{TRUE}}
-
-#if __cplusplus
- clang_analyzer_eval(s.getThis() == &s); // expected-warning{{TRUE}}
-#endif
-}
-
-
-void testImmediateUse() {
- int x = getS().field;
-
- if (x != 42) return;
- clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
-
-#if __cplusplus
- clang_analyzer_eval((void *)getS().getThis() == (void *)&x); // expected-warning{{FALSE}}
-#endif
-}
-
-int getConstrainedField(struct S s) {
- if (s.field != 42) return 42;
- return s.field;
-}
-
-int getAssignedField(struct S s) {
- s.field = 42;
- return s.field;
-}
-
-void testArgument() {
- clang_analyzer_eval(getConstrainedField(getS()) == 42); // expected-warning{{TRUE}}
- clang_analyzer_eval(getAssignedField(getS()) == 42); // expected-warning{{TRUE}}
-}
-
-
-//--------------------
-// C++-only tests
-//--------------------
-
-#if __cplusplus
-void testReferenceAssignment() {
- const S &s = getS();
-
- if (s.field != 42) return;
- clang_analyzer_eval(s.field == 42); // expected-warning{{TRUE}}
-
- clang_analyzer_eval(s.getThis() == &s); // expected-warning{{TRUE}}
-}
-
-
-int getConstrainedFieldRef(const S &s) {
- if (s.field != 42) return 42;
- return s.field;
-}
-
-bool checkThis(const S &s) {
- return s.getThis() == &s;
-}
-
-void testReferenceArgument() {
- clang_analyzer_eval(getConstrainedFieldRef(getS()) == 42); // expected-warning{{TRUE}}
- clang_analyzer_eval(checkThis(getS())); // expected-warning{{TRUE}}
-}
-#endif
diff --git a/test/Analysis/reference.cpp b/test/Analysis/reference.cpp
index ce0ee8ed57..4a2cbb8e25 100644
--- a/test/Analysis/reference.cpp
+++ b/test/Analysis/reference.cpp
@@ -116,11 +116,8 @@ void testReferenceAddress(int &x) {
struct S { int &x; };
- extern S getS();
- clang_analyzer_eval(&getS().x != 0); // expected-warning{{TRUE}}
-
- extern S *getSP();
- clang_analyzer_eval(&getSP()->x != 0); // expected-warning{{TRUE}}
+ extern S *getS();
+ clang_analyzer_eval(&getS()->x != 0); // expected-warning{{TRUE}}
}
@@ -153,3 +150,10 @@ namespace rdar11212286 {
return *x; // should warn here!
}
}
+
+void testReferenceFieldAddress() {
+ struct S { int &x; };
+
+ extern S getS();
+ clang_analyzer_eval(&getS().x != 0); // expected-warning{{UNKNOWN}}
+}