From 79d0cceb8847bfe6dc9da8eb2ea2f3c6bb73b813 Mon Sep 17 00:00:00 2001 From: Anna Zaks Date: Mon, 15 Apr 2013 22:37:59 +0000 Subject: [PATCH] [analyzer] Address code review for r179395 Mostly refactoring + handle the nested fields by printing the innermost field only. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@179572 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Core/PathSensitive/MemRegion.h | 17 ++- lib/StaticAnalyzer/Core/MemRegion.cpp | 39 +++--- test/Analysis/inlining/path-notes.c | 121 ++++++++++++++++++ 3 files changed, 158 insertions(+), 19 deletions(-) diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h index 7ae432e389..0d513f8326 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h @@ -169,7 +169,15 @@ public: /// \brief Print the region for use in diagnostics. virtual void printPretty(raw_ostream &os) const; - virtual void printPrettyNoQuotes(raw_ostream &os) const; + /// \brief Returns true if this region's textual representation can be used + /// as part of a larger expression. + virtual bool canPrintPrettyAsExpr() const; + + /// \brief Print the region as expression. + /// + /// When this region represents a subexpression, the method is for printing + /// an expression containing it. + virtual void printPrettyAsExpr(raw_ostream &os) const; Kind getKind() const { return kind; } @@ -878,7 +886,7 @@ public: bool canPrintPretty() const; - void printPrettyNoQuotes(raw_ostream &os) const; + void printPrettyAsExpr(raw_ostream &os) const; }; /// CXXThisRegion - Represents the region for the implicit 'this' parameter @@ -940,7 +948,8 @@ public: bool canPrintPretty() const; void printPretty(raw_ostream &os) const; - void printPrettyNoQuotes(raw_ostream &os) const; + bool canPrintPrettyAsExpr() const; + void printPrettyAsExpr(raw_ostream &os) const; }; class ObjCIvarRegion : public DeclRegion { @@ -957,7 +966,7 @@ public: QualType getValueType() const; bool canPrintPretty() const; - void printPrettyNoQuotes(raw_ostream &os) const; + void printPrettyAsExpr(raw_ostream &os) const; void dumpToStream(raw_ostream &os) const; diff --git a/lib/StaticAnalyzer/Core/MemRegion.cpp b/lib/StaticAnalyzer/Core/MemRegion.cpp index e244d31afa..32e7f7713b 100644 --- a/lib/StaticAnalyzer/Core/MemRegion.cpp +++ b/lib/StaticAnalyzer/Core/MemRegion.cpp @@ -558,16 +558,20 @@ bool MemRegion::canPrintPretty() const { return false; } +bool MemRegion::canPrintPrettyAsExpr() const { + return canPrintPretty(); +} + void MemRegion::printPretty(raw_ostream &os) const { assert(canPrintPretty() && "This region cannot be printed pretty."); os << "'"; - printPrettyNoQuotes(os); + printPrettyAsExpr(os); os << "'"; return; } -void MemRegion::printPrettyNoQuotes(raw_ostream &os) const { - assert(canPrintPretty() && "This region cannot be printed pretty."); +void MemRegion::printPrettyAsExpr(raw_ostream &os) const { + llvm_unreachable("This region cannot be printed pretty."); return; } @@ -575,7 +579,7 @@ bool VarRegion::canPrintPretty() const { return true; } -void VarRegion::printPrettyNoQuotes(raw_ostream &os) const { +void VarRegion::printPrettyAsExpr(raw_ostream &os) const { os << getDecl()->getName(); } @@ -583,7 +587,7 @@ bool ObjCIvarRegion::canPrintPretty() const { return true; } -void ObjCIvarRegion::printPrettyNoQuotes(raw_ostream &os) const { +void ObjCIvarRegion::printPrettyAsExpr(raw_ostream &os) const { os << getDecl()->getName(); } @@ -591,26 +595,31 @@ bool FieldRegion::canPrintPretty() const { return true; } -void FieldRegion::printPrettyNoQuotes(raw_ostream &os) const { - if (superRegion->canPrintPretty()) { - superRegion->printPrettyNoQuotes(os); - os << "." << getDecl()->getName(); - } else { - os << "field " << "\'" << getDecl()->getName() << "'"; - } +bool FieldRegion::canPrintPrettyAsExpr() const { + return superRegion->canPrintPrettyAsExpr(); +} + +void FieldRegion::printPrettyAsExpr(raw_ostream &os) const { + assert(canPrintPrettyAsExpr()); + superRegion->printPrettyAsExpr(os); + os << "." << getDecl()->getName(); } void FieldRegion::printPretty(raw_ostream &os) const { - if (superRegion->canPrintPretty()) { + if (canPrintPrettyAsExpr()) { os << "\'"; - printPrettyNoQuotes(os); + printPrettyAsExpr(os); os << "'"; } else { - printPrettyNoQuotes(os); + os << "field " << "\'" << getDecl()->getName() << "'"; } return; } +bool FieldRegion::canPrintPrettyAsExpr() const { + return superRegion->canPrintPrettyAsExpr(); +} + //===----------------------------------------------------------------------===// // MemRegionManager methods. //===----------------------------------------------------------------------===// diff --git a/test/Analysis/inlining/path-notes.c b/test/Analysis/inlining/path-notes.c index 15140bdf52..d4fa461e5e 100644 --- a/test/Analysis/inlining/path-notes.c +++ b/test/Analysis/inlining/path-notes.c @@ -121,6 +121,18 @@ int testSetFieldToNull(struct X *x) { // expected-note@-2 {{Dereference of null pointer (loaded from field 'p')}} } +struct Outer { + struct Inner { + int *p; + } inner; +}; + +void test(struct Outer *wrapperPtr) { + wrapperPtr->inner.p = 0; // expected-note {{Null pointer value stored to field 'p'}} + *wrapperPtr->inner.p = 1; //expected-warning {{Dereference of null pointer (loaded from field 'p')}} + // expected-note@-1 {{Dereference of null pointer (loaded from field 'p')}} +} + // CHECK: diagnostics // CHECK-NEXT: // CHECK-NEXT: @@ -2900,4 +2912,113 @@ int testSetFieldToNull(struct X *x) { // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: path +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindevent +// CHECK-NEXT: location +// CHECK-NEXT: +// CHECK-NEXT: line131 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: ranges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line131 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line131 +// CHECK-NEXT: col25 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: depth0 +// CHECK-NEXT: extended_message +// CHECK-NEXT: Null pointer value stored to field 'p' +// CHECK-NEXT: message +// CHECK-NEXT: Null pointer value stored to field 'p' +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line131 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line131 +// CHECK-NEXT: col12 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line132 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line132 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindevent +// CHECK-NEXT: location +// CHECK-NEXT: +// CHECK-NEXT: line132 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: ranges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line132 +// CHECK-NEXT: col22 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line132 +// CHECK-NEXT: col22 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: depth0 +// CHECK-NEXT: extended_message +// CHECK-NEXT: Dereference of null pointer (loaded from field 'p') +// CHECK-NEXT: message +// CHECK-NEXT: Dereference of null pointer (loaded from field 'p') +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: descriptionDereference of null pointer (loaded from field 'p') +// CHECK-NEXT: categoryLogic error +// CHECK-NEXT: typeDereference of null pointer +// CHECK-NEXT: issue_context_kindfunction +// CHECK-NEXT: issue_contexttest +// CHECK-NEXT: issue_hash2 +// CHECK-NEXT: location +// CHECK-NEXT: +// CHECK-NEXT: line132 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: // CHECK-NEXT: -- 2.40.0