diff options
Diffstat (limited to 'clang/test/Analysis/inlining/false-positive-suppression.c')
-rw-r--r-- | clang/test/Analysis/inlining/false-positive-suppression.c | 99 |
1 files changed, 94 insertions, 5 deletions
diff --git a/clang/test/Analysis/inlining/false-positive-suppression.c b/clang/test/Analysis/inlining/false-positive-suppression.c index be485e0c1c6..20cc3114875 100644 --- a/clang/test/Analysis/inlining/false-positive-suppression.c +++ b/clang/test/Analysis/inlining/false-positive-suppression.c @@ -1,9 +1,14 @@ // RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-config suppress-null-return-paths=false -verify %s -// RUN: %clang_cc1 -analyze -analyzer-checker=core -verify -DSUPPRESSED %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core -verify -DSUPPRESSED=1 %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-config avoid-suppressing-null-argument-paths=true -DSUPPRESSED=1 -DNULL_ARGS=1 -verify %s int opaquePropertyCheck(void *object); int coin(); +int *getNull() { + return 0; +} + int *dynCastToInt(void *ptr) { if (opaquePropertyCheck(ptr)) return (int *)ptr; @@ -69,24 +74,108 @@ void testBranchReversed(void *p) { } +// -------------------------- +// "Suppression suppression" +// -------------------------- + +void testDynCastOrNullOfNull() { + // Don't suppress when one of the arguments is NULL. + int *casted = dynCastOrNull(0); + *casted = 1; +#if !SUPPRESSED || NULL_ARGS + // expected-warning@-2 {{Dereference of null pointer}} +#endif +} + +void testDynCastOfNull() { + // Don't suppress when one of the arguments is NULL. + int *casted = dynCastToInt(0); + *casted = 1; +#if !SUPPRESSED || NULL_ARGS + // expected-warning@-2 {{Dereference of null pointer}} +#endif +} + +int *lookUpInt(int unused) { + if (coin()) + return 0; + static int x; + return &x; +} + +void testZeroIsNotNull() { + // /Do/ suppress when the argument is 0 (an integer). + int *casted = lookUpInt(0); + *casted = 1; +#ifndef SUPPRESSED + // expected-warning@-2 {{Dereference of null pointer}} +#endif +} + +void testTrackNull() { + // /Do/ suppress if the null argument came from another call returning null. + int *casted = dynCastOrNull(getNull()); + *casted = 1; +#ifndef SUPPRESSED + // expected-warning@-2 {{Dereference of null pointer}} +#endif +} + +void testTrackNullVariable() { + // /Do/ suppress if the null argument came from another call returning null. + int *ptr; + ptr = getNull(); + int *casted = dynCastOrNull(ptr); + *casted = 1; +#ifndef SUPPRESSED + // expected-warning@-2 {{Dereference of null pointer}} +#endif +} + + // --------------------------------------- // FALSE NEGATIVES (over-suppression) // --------------------------------------- -void testDynCastOrNullOfNull() { +void testNoArguments() { + // In this case the function has no branches, and MUST return null. + int *casted = getNull(); + *casted = 1; +#ifndef SUPPRESSED + // expected-warning@-2 {{Dereference of null pointer}} +#endif +} + +int *getNullIfNonNull(void *input) { + if (input) + return 0; + static int x; + return &x; +} + +void testKnownPath(void *input) { + if (!input) + return; + // In this case we have a known value for the argument, and thus the path // through the function doesn't ever split. - int *casted = dynCastOrNull(0); + int *casted = getNullIfNonNull(input); *casted = 1; #ifndef SUPPRESSED // expected-warning@-2 {{Dereference of null pointer}} #endif } -void testDynCastOfNull() { +int *alwaysReturnNull(void *input) { + if (opaquePropertyCheck(input)) + return 0; + return 0; +} + +void testAlwaysReturnNull(void *input) { // In this case all paths out of the function return 0, but they are all // dominated by a branch whose condition we don't know! - int *casted = dynCastToInt(0); + int *casted = alwaysReturnNull(input); *casted = 1; #ifndef SUPPRESSED // expected-warning@-2 {{Dereference of null pointer}} |