aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJordan Rose <jordan_rose@apple.com>2012-08-08 18:23:36 +0000
committerJordan Rose <jordan_rose@apple.com>2012-08-08 18:23:36 +0000
commit919e8a1c6698bfa6848571d366430126bced727d (patch)
tree4bef9e45540652da3c9e6add30a8a7c677f6922d
parent0d53ab4024488d0c6cd283992be3fd4b67099bd3 (diff)
[analyzer] Clean up the printing of FieldRegions for leaks.
Unfortunately, generalized region printing is very difficult: - ElementRegions are used both for casting and as actual elements. - Accessing values through a pointer means going through an intermediate SymbolRegionValue; symbolic regions are untyped. - Referring to implicitly-defined variables like 'this' and 'self' could be very confusing if they come from another stack frame. We fall back to simply not printing the region name if we can't be sure it will print well. This will allow us to improve in the future. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@161512 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h12
-rw-r--r--lib/StaticAnalyzer/Checkers/MallocChecker.cpp5
-rw-r--r--lib/StaticAnalyzer/Core/MemRegion.cpp22
-rw-r--r--test/Analysis/malloc.c12
4 files changed, 37 insertions, 14 deletions
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
index 9bdeb3e09b..2018bd2e44 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
@@ -150,8 +150,11 @@ public:
void dump() const;
+ /// \brief Returns true if this region can be printed in a user-friendly way.
+ virtual bool canPrintPretty() const;
+
/// \brief Print the region for use in diagnostics.
- virtual void dumpPretty(raw_ostream &os) const;
+ virtual void printPretty(raw_ostream &os) const;
Kind getKind() const { return kind; }
@@ -846,7 +849,8 @@ public:
return R->getKind() == VarRegionKind;
}
- void dumpPretty(raw_ostream &os) const;
+ bool canPrintPretty() const;
+ void printPretty(raw_ostream &os) const;
};
/// CXXThisRegion - Represents the region for the implicit 'this' parameter
@@ -905,7 +909,9 @@ public:
}
void dumpToStream(raw_ostream &os) const;
- void dumpPretty(raw_ostream &os) const;
+
+ bool canPrintPretty() const;
+ void printPretty(raw_ostream &os) const;
};
class ObjCIvarRegion : public DeclRegion {
diff --git a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
index d384bc34f9..56221801e5 100644
--- a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -1000,10 +1000,9 @@ void MallocChecker::reportLeak(SymbolRef Sym, ExplodedNode *N,
SmallString<200> buf;
llvm::raw_svector_ostream os(buf);
os << "Memory is never released; potential leak";
- // FIXME: Make all region pretty-printing nice enough to show.
- if (Region && isa<VarRegion>(Region)) {
+ if (Region && Region->canPrintPretty()) {
os << " of memory pointed to by '";
- Region->dumpPretty(os);
+ Region->printPretty(os);
os << '\'';
}
diff --git a/lib/StaticAnalyzer/Core/MemRegion.cpp b/lib/StaticAnalyzer/Core/MemRegion.cpp
index f3a1ff447c..b2e7055c31 100644
--- a/lib/StaticAnalyzer/Core/MemRegion.cpp
+++ b/lib/StaticAnalyzer/Core/MemRegion.cpp
@@ -546,17 +546,29 @@ void StackLocalsSpaceRegion::dumpToStream(raw_ostream &os) const {
os << "StackLocalsSpaceRegion";
}
-void MemRegion::dumpPretty(raw_ostream &os) const {
+bool MemRegion::canPrintPretty() const {
+ return false;
+}
+
+void MemRegion::printPretty(raw_ostream &os) const {
return;
}
-void VarRegion::dumpPretty(raw_ostream &os) const {
+bool VarRegion::canPrintPretty() const {
+ return true;
+}
+
+void VarRegion::printPretty(raw_ostream &os) const {
os << getDecl()->getName();
}
-void FieldRegion::dumpPretty(raw_ostream &os) const {
- superRegion->dumpPretty(os);
- os << "->" << getDecl();
+bool FieldRegion::canPrintPretty() const {
+ return superRegion->canPrintPretty();
+}
+
+void FieldRegion::printPretty(raw_ostream &os) const {
+ superRegion->printPretty(os);
+ os << "." << getDecl()->getName();
}
//===----------------------------------------------------------------------===//
diff --git a/test/Analysis/malloc.c b/test/Analysis/malloc.c
index 24fa30baa8..f60271f39f 100644
--- a/test/Analysis/malloc.c
+++ b/test/Analysis/malloc.c
@@ -19,7 +19,7 @@ char *fooRetPtr();
void f1() {
int *p = malloc(12);
- return; // expected-warning{{Memory is never released; potential leak}}
+ return; // expected-warning{{Memory is never released; potential leak of memory pointed to by 'p'}}
}
void f2() {
@@ -44,7 +44,7 @@ void reallocNotNullPtr(unsigned sizeIn) {
char *p = (char*)malloc(size);
if (p) {
char *q = (char*)realloc(p, sizeIn);
- char x = *q; // expected-warning {{Memory is never released; potential leak}}
+ char x = *q; // expected-warning {{Memory is never released; potential leak of memory pointed to by 'q'}}
}
}
@@ -102,7 +102,7 @@ void reallocSizeZero5() {
}
void reallocPtrZero1() {
- char *r = realloc(0, 12); // expected-warning {{Memory is never released; potential leak}}
+ char *r = realloc(0, 12); // expected-warning {{Memory is never released; potential leak of memory pointed to by 'r'}}
}
void reallocPtrZero2() {
@@ -529,6 +529,12 @@ int *testMalloc3() {
return y; // no-warning
}
+void testStructLeak() {
+ StructWithPtr St;
+ St.memP = malloc(12);
+ return; // expected-warning {{Memory is never released; potential leak of memory pointed to by 'St.memP'}}
+}
+
void testElemRegion1() {
char *x = (void*)malloc(2);
int *ix = (int*)x;