diff options
-rw-r--r-- | include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h | 3 | ||||
-rw-r--r-- | include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h | 10 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/RegionStore.cpp | 20 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/SymbolManager.cpp | 3 | ||||
-rw-r--r-- | test/Analysis/array-struct-region.cpp | 87 | ||||
-rw-r--r-- | test/Analysis/reference.cpp | 14 |
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}} +} |