[analyzer] Display the checker name in the text output

Exactly what it says on the tin! There is no reason I think not to have this.

Also, I added test files for checkers that emit warning under the wrong name.

Differential Revision: https://reviews.llvm.org/D76605
This commit is contained in:
Kirstóf Umann 2020-03-20 16:45:53 +01:00
parent 2df6a02fd7
commit a2b6ece1fd
9 changed files with 175 additions and 13 deletions

View File

@ -310,6 +310,10 @@ ANALYZER_OPTION(bool, ShouldApplyFixIts, "apply-fixits",
"Apply the fix-it hints to the files",
false)
ANALYZER_OPTION(bool, ShouldDisplayCheckerNameForText, "display-checker-name",
"Display the checker name for textual outputs",
true)
//===----------------------------------------------------------------------===//
// Unsigned analyzer options.
//===----------------------------------------------------------------------===//

View File

@ -35,17 +35,19 @@ namespace {
/// diagnostics in textual format for the 'text' output type.
class TextDiagnostics : public PathDiagnosticConsumer {
DiagnosticsEngine &DiagEng;
LangOptions LO;
const LangOptions &LO;
const bool IncludePath = false;
const bool ShouldEmitAsError = false;
const bool ApplyFixIts = false;
const bool ShouldDisplayCheckerName = false;
public:
TextDiagnostics(DiagnosticsEngine &DiagEng, LangOptions LO,
TextDiagnostics(DiagnosticsEngine &DiagEng, const LangOptions &LO,
bool ShouldIncludePath, const AnalyzerOptions &AnOpts)
: DiagEng(DiagEng), LO(LO), IncludePath(ShouldIncludePath),
ShouldEmitAsError(AnOpts.AnalyzerWerror),
ApplyFixIts(AnOpts.ShouldApplyFixIts) {}
ApplyFixIts(AnOpts.ShouldApplyFixIts),
ShouldDisplayCheckerName(AnOpts.ShouldDisplayCheckerNameForText) {}
~TextDiagnostics() override {}
StringRef getName() const override { return "TextDiagnostics"; }
@ -90,9 +92,13 @@ public:
E = Diags.end();
I != E; ++I) {
const PathDiagnostic *PD = *I;
std::string WarningMsg =
(ShouldDisplayCheckerName ? " [" + PD->getCheckerName() + "]" : "")
.str();
reportPiece(WarnID, PD->getLocation().asLocation(),
PD->getShortDescription(), PD->path.back()->getRanges(),
PD->path.back()->getFixits());
(PD->getShortDescription() + WarningMsg).str(),
PD->path.back()->getRanges(), PD->path.back()->getFixits());
// First, add extra notes, even if paths should not be included.
for (const auto &Piece : PD->path) {
@ -100,7 +106,8 @@ public:
continue;
reportPiece(NoteID, Piece->getLocation().asLocation(),
Piece->getString(), Piece->getRanges(), Piece->getFixits());
Piece->getString(), Piece->getRanges(),
Piece->getFixits());
}
if (!IncludePath)
@ -113,7 +120,8 @@ public:
continue;
reportPiece(NoteID, Piece->getLocation().asLocation(),
Piece->getString(), Piece->getRanges(), Piece->getFixits());
Piece->getString(), Piece->getRanges(),
Piece->getFixits());
}
}

View File

@ -52,6 +52,7 @@
// CHECK-NEXT: debug.AnalysisOrder:PreStmtCastExpr = false
// CHECK-NEXT: debug.AnalysisOrder:PreStmtOffsetOfExpr = false
// CHECK-NEXT: debug.AnalysisOrder:RegionChanges = false
// CHECK-NEXT: display-checker-name = true
// CHECK-NEXT: display-ctu-progress = false
// CHECK-NEXT: eagerly-assume = true
// CHECK-NEXT: elide-constructors = true
@ -100,4 +101,4 @@
// CHECK-NEXT: unroll-loops = false
// CHECK-NEXT: widen-loops = false
// CHECK-NEXT: [stats]
// CHECK-NEXT: num-entries = 97
// CHECK-NEXT: num-entries = 98

View File

@ -1,5 +1,14 @@
// RUN: %clang_analyze_cc1 -w -fblocks -analyzer-checker=core,osx.API,unix.Malloc -verify %s
// RUN: %clang_analyze_cc1 -w -fblocks -fobjc-arc -analyzer-checker=core,osx.API,unix.Malloc -verify %s
// RUN: %clang_analyze_cc1 -w -fblocks -verify %s \
// RUN: -analyzer-checker=core \
// RUN: -analyzer-checker=osx.API \
// RUN: -analyzer-checker=unix.Malloc \
// RUN: -analyzer-config display-checker-name=false
// RUN: %clang_analyze_cc1 -w -fblocks -fobjc-arc -verify %s \
// RUN: -analyzer-checker=core \
// RUN: -analyzer-checker=osx.API \
// RUN: -analyzer-checker=unix.Malloc \
// RUN: -analyzer-config display-checker-name=false
#include "Inputs/system-header-simulator-objc.h"

View File

@ -1,4 +1,8 @@
// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core.builtin,debug.ExprInspection,unix.cstring -verify %s
// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -verify %s \
// RUN: -analyzer-checker=core.builtin \
// RUN: -analyzer-checker=debug.ExprInspection \
// RUN: -analyzer-checker=unix.cstring \
// RUN: -analyzer-config display-checker-name=false
struct S {
int z;

View File

@ -1,4 +1,8 @@
// RUN: %clang_analyze_cc1 -std=c++14 -triple i386-apple-darwin10 -analyzer-checker=core.builtin,debug.ExprInspection,unix.cstring -verify %s
// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -verify %s \
// RUN: -analyzer-checker=core.builtin \
// RUN: -analyzer-checker=debug.ExprInspection \
// RUN: -analyzer-checker=unix.cstring \
// RUN: -analyzer-config display-checker-name=false
typedef unsigned long size_t;

View File

@ -1,4 +1,7 @@
// RUN: %clang_analyze_cc1 -w -triple i386-apple-darwin10 -fblocks -analyzer-checker=core.builtin,debug.ExprInspection -verify %s
// RUN: %clang_analyze_cc1 -w -triple i386-apple-darwin10 -fblocks -verify %s \
// RUN: -analyzer-checker=core.builtin \
// RUN: -analyzer-checker=debug.ExprInspection \
// RUN: -analyzer-config display-checker-name=false
#include "Inputs/system-header-simulator-objc.h"

View File

@ -0,0 +1,13 @@
// RUN: %clang_analyze_cc1 -verify %s -fblocks \
// RUN: -analyzer-checker=core \
// RUN: -analyzer-output=text
int* stack_addr_escape_base() {
int x = 0;
// FIXME: This shouldn't be tied to a modeling checker.
return &x; // expected-warning{{Address of stack memory associated with local variable 'x' returned to caller [core.StackAddrEscapeBase]}}
// expected-note-re@-1{{{{^Address of stack memory associated with local variable 'x' returned to caller$}}}}
// Just a regular compiler warning.
// expected-warning@-3{{address of stack memory associated with local variable 'x' returned}}
}

View File

@ -0,0 +1,116 @@
// RUN: %clang_analyze_cc1 -fblocks -verify %s -Wno-objc-root-class \
// RUN: -analyzer-checker=core \
// RUN: -analyzer-checker=nullability \
// RUN: -analyzer-checker=osx
#include "Inputs/system-header-simulator-for-nullability.h"
#include "os_object_base.h"
struct OSIterator : public OSObject {
static const OSMetaClass * const metaClass;
};
@interface TestObject : NSObject
- (int *_Nonnull)returnsNonnull;
- (int *_Nullable)returnsNullable;
- (int *)returnsUnspecified;
- (void)takesNonnull:(int *_Nonnull)p;
- (void)takesNullable:(int *_Nullable)p;
- (void)takesUnspecified:(int *)p;
@property(readonly, strong) NSString *stuff;
@end
TestObject * getUnspecifiedTestObject();
TestObject *_Nonnull getNonnullTestObject();
TestObject *_Nullable getNullableTestObject();
int getRandom();
typedef struct Dummy { int val; } Dummy;
void takesNullable(Dummy *_Nullable);
void takesNonnull(Dummy *_Nonnull);
void takesUnspecified(Dummy *);
Dummy *_Nullable returnsNullable();
Dummy *_Nonnull returnsNonnull();
Dummy *returnsUnspecified();
int *_Nullable returnsNullableInt();
template <typename T> T *eraseNullab(T *p) { return p; }
void takesAttrNonnull(Dummy *p) __attribute((nonnull(1)));
void testBasicRules() {
// FIXME: None of these should be tied to a modeling checker.
Dummy *p = returnsNullable();
int *ptr = returnsNullableInt();
// Make every dereference a different path to avoid sinks after errors.
switch (getRandom()) {
case 0: {
Dummy &r = *p; // expected-warning {{Nullable pointer is dereferenced [nullability.NullabilityBase]}}
} break;
case 1: {
int b = p->val; // expected-warning {{Nullable pointer is dereferenced [nullability.NullabilityBase]}}
} break;
case 2: {
int stuff = *ptr; // expected-warning {{Nullable pointer is dereferenced [nullability.NullabilityBase]}}
} break;
case 3:
takesNonnull(p); // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter [nullability.NullabilityBase]}}
break;
case 4: {
Dummy d;
takesNullable(&d);
Dummy dd(d);
break;
}
case 5: takesAttrNonnull(p); break; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null [nullability.NullabilityBase]}}
default: { Dummy d = *p; } break; // expected-warning {{Nullable pointer is dereferenced [nullability.NullabilityBase]}}
}
if (p) {
takesNonnull(p);
if (getRandom()) {
Dummy &r = *p;
} else {
int b = p->val;
}
}
Dummy *q = 0;
if (getRandom()) {
takesNullable(q);
// FIXME: This shouldn't be tied to a modeling checker.
takesNonnull(q); // expected-warning {{Null passed to a callee that requires a non-null 1st parameter [nullability.NullabilityBase]}}
}
Dummy a;
Dummy *_Nonnull nonnull = &a;
// FIXME: This shouldn't be tied to a modeling checker.
nonnull = q; // expected-warning {{Null assigned to a pointer which is expected to have non-null value [nullability.NullabilityBase]}}
q = &a;
takesNullable(q);
takesNonnull(q);
}
typedef int NSInteger;
typedef struct _NSZone NSZone;
@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator;
@class NSDictionary;
@interface NSError : NSObject <NSCopying, NSCoding> {}
+ (id)errorWithDomain:(NSString *)domain code:(NSInteger)code userInfo:(NSDictionary *)dict;
@end
struct __CFError {};
typedef struct __CFError* CFErrorRef;
void foo(CFErrorRef* error) { // expected-warning{{Function accepting CFErrorRef* should have a non-void return value to indicate whether or not an error occurred [osx.coreFoundation.CFError]}}
// FIXME: This shouldn't be tied to a modeling checker.
*error = 0; // expected-warning {{Potential null dereference. According to coding standards documented in CoreFoundation/CFError.h the parameter may be null [osx.NSOrCFErrorDerefChecker]}}
}
bool write_into_out_param_on_success(OS_RETURNS_RETAINED OSObject **obj);
void use_out_param_leak() {
OSObject *obj;
// FIXME: This shouldn't be tied to a modeling checker.
write_into_out_param_on_success(&obj); // expected-warning{{Potential leak of an object stored into 'obj' [osx.cocoa.RetainCountBase]}}
}