From: Anna Zaks Date: Fri, 12 Apr 2013 18:40:27 +0000 (+0000) Subject: [analyzer] Print a diagnostic note even if the region cannot be printed. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8713e1a5c3f6658d54061e176b5baa9fadf14675;p=clang [analyzer] Print a diagnostic note even if the region cannot be printed. There are few cases where we can track the region, but cannot print the note, which makes the testing limited. (Though, I’ve tested this manually by making all regions non-printable.) Even though the applicability is limited now, the enhancement will be more relevant as we start tracking more regions. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@179396 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp index 92159de168..4fbaec5d5f 100644 --- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -511,9 +511,6 @@ PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ, } } - if (!R->canPrintPretty()) - return 0; - // Okay, we've found the binding. Emit an appropriate message. SmallString<256> sbuf; llvm::raw_svector_ostream os(sbuf); @@ -525,9 +522,11 @@ PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ, const VarRegion *VR = dyn_cast(R); if (DS) { - action = "initialized to "; + action = R->canPrintPretty() ? "initialized to " : + "Initializing to "; } else if (isa(S)) { - action = "captured by block as "; + action = R->canPrintPretty() ? "captured by block as " : + "Capturing by block as "; if (VR) { // See if we can get the BlockVarRegion. ProgramStateRef State = StoreSite->getState(); @@ -545,9 +544,11 @@ PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ, } if (action) { - R->printPretty(os); - os << " "; - + if (R->canPrintPretty()) { + R->printPretty(os); + os << " "; + } + if (V.getAs()) { bool b = false; if (R->isBoundable()) { @@ -569,14 +570,18 @@ PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ, if (V.isUndef()) { if (isa(R)) { const VarDecl *VD = cast(DS->getSingleDecl()); - if (VD->getInit()) - os << "initialized to a garbage value"; - else - os << "declared without an initial value"; + if (VD->getInit()) { + os << (R->canPrintPretty() ? "initialized" : "Initializing") + << " to a garbage value"; + } else { + os << (R->canPrintPretty() ? "declared" : "Declaring") + << " without an initial value"; + } } } else { - os << "initialized here"; + os << (R->canPrintPretty() ? "initialized" : "Initializing") + << " here"; } } } @@ -602,8 +607,11 @@ PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ, // Printed parameter indexes are 1-based, not 0-based. unsigned Idx = Param->getFunctionScopeIndex() + 1; - os << " via " << Idx << llvm::getOrdinalSuffix(Idx) << " parameter "; - R->printPretty(os); + os << " via " << Idx << llvm::getOrdinalSuffix(Idx) << " parameter"; + if (R->canPrintPretty()) { + os << " "; + R->printPretty(os); + } } } @@ -613,25 +621,28 @@ PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ, if (R->isBoundable()) { if (const TypedValueRegion *TR = dyn_cast(R)) { if (TR->getValueType()->isObjCObjectPointerType()) { - os << "nil object reference stored to "; + os << "nil object reference stored"; b = true; } } } if (!b) - os << "Null pointer value stored to "; + os << "Null pointer value stored"; } else if (V.isUndef()) { - os << "Uninitialized value stored to "; + os << "Uninitialized value stored"; } else if (Optional CV = V.getAs()) { - os << "The value " << CV->getValue() << " is assigned to "; + os << "The value " << CV->getValue() << " is assigned"; } else - os << "Value assigned to "; + os << "Value assigned"; - R->printPretty(os); + if (R->canPrintPretty()) { + os << " to "; + R->printPretty(os); + } } // Construct a new PathDiagnosticPiece. diff --git a/test/Analysis/inlining/path-notes.cpp b/test/Analysis/inlining/path-notes.cpp index 8293095efe..d13bb5446c 100644 --- a/test/Analysis/inlining/path-notes.cpp +++ b/test/Analysis/inlining/path-notes.cpp @@ -206,6 +206,13 @@ void testPathNoteOnInitializer() { // expected-note@-1 {{Calling constructor for 'FooWithInitializer'}} } +int testNonPrintableAssignment(int **p) { + int *&y = *p; // expected-note {{'y' initialized here}} + y = 0; // expected-note {{Null pointer value stored}} + return *y; // expected-warning {{Dereference of null pointer (loaded from variable 'y')}} + // expected-note@-1 {{Dereference of null pointer (loaded from variable 'y')}} +} + // CHECK: diagnostics // CHECK-NEXT: // CHECK-NEXT: @@ -3606,4 +3613,210 @@ void testPathNoteOnInitializer() { // 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: line210 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: ranges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line210 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line210 +// CHECK-NEXT: col9 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: depth0 +// CHECK-NEXT: extended_message +// CHECK-NEXT: 'y' initialized here +// CHECK-NEXT: message +// CHECK-NEXT: 'y' initialized here +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line210 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line210 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line211 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line211 +// 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: line211 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: ranges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line211 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line211 +// CHECK-NEXT: col7 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: depth0 +// CHECK-NEXT: extended_message +// CHECK-NEXT: Null pointer value stored +// CHECK-NEXT: message +// CHECK-NEXT: Null pointer value stored +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line211 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line211 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line212 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line212 +// CHECK-NEXT: col8 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line212 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line212 +// CHECK-NEXT: col8 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line212 +// CHECK-NEXT: col10 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line212 +// CHECK-NEXT: col10 +// 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: line212 +// CHECK-NEXT: col10 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: ranges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line212 +// CHECK-NEXT: col11 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line212 +// CHECK-NEXT: col11 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: depth0 +// CHECK-NEXT: extended_message +// CHECK-NEXT: Dereference of null pointer (loaded from variable 'y') +// CHECK-NEXT: message +// CHECK-NEXT: Dereference of null pointer (loaded from variable 'y') +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: descriptionDereference of null pointer (loaded from variable 'y') +// CHECK-NEXT: categoryLogic error +// CHECK-NEXT: typeDereference of null pointer +// CHECK-NEXT: issue_context_kindfunction +// CHECK-NEXT: issue_contexttestNonPrintableAssignment +// CHECK-NEXT: issue_hash3 +// CHECK-NEXT: location +// CHECK-NEXT: +// CHECK-NEXT: line212 +// CHECK-NEXT: col10 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: // CHECK-NEXT: