diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2015-01-18 16:23:48 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2015-01-18 16:23:48 +0000 |
commit | 06d4ba388873e6d1cfa9cd715a8935ecc8cd2097 (patch) | |
tree | 3eb853da77d46cc77c4b017525a422f9ddb1385b /test/Analysis | |
parent | 30d791273d07fac9c0c1641a0731191bca6e8606 (diff) |
Notes
Diffstat (limited to 'test/Analysis')
32 files changed, 1149 insertions, 125 deletions
diff --git a/test/Analysis/Inputs/Models/modeledFunction.model b/test/Analysis/Inputs/Models/modeledFunction.model new file mode 100644 index 0000000000000..3aff5fc1b4435 --- /dev/null +++ b/test/Analysis/Inputs/Models/modeledFunction.model @@ -0,0 +1,3 @@ +void modelled(intptr p) { + ++*p; +}
\ No newline at end of file diff --git a/test/Analysis/Inputs/Models/notzero.model b/test/Analysis/Inputs/Models/notzero.model new file mode 100644 index 0000000000000..26161029d6ed6 --- /dev/null +++ b/test/Analysis/Inputs/Models/notzero.model @@ -0,0 +1,3 @@ +bool notzero(int i) { + return i != 0; +}
\ No newline at end of file diff --git a/test/Analysis/Inputs/system-header-simulator-for-pthread-lock.h b/test/Analysis/Inputs/system-header-simulator-for-pthread-lock.h new file mode 100644 index 0000000000000..b290ffe8d8799 --- /dev/null +++ b/test/Analysis/Inputs/system-header-simulator-for-pthread-lock.h @@ -0,0 +1,28 @@ +// Like the compiler, the static analyzer treats some functions differently if +// they come from a system header -- for example, pthread_mutex* functions +// should not invalidate regions of their arguments. +#pragma clang system_header + +typedef struct { + void *foo; +} pthread_mutex_t; + +typedef struct { + void *foo; +} pthread_mutexattr_t; + +typedef struct { + void *foo; +} lck_grp_t; + +typedef pthread_mutex_t lck_mtx_t; + +extern int pthread_mutex_lock(pthread_mutex_t *); +extern int pthread_mutex_unlock(pthread_mutex_t *); +extern int pthread_mutex_trylock(pthread_mutex_t *); +extern int pthread_mutex_destroy(pthread_mutex_t *); +extern int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr); +extern int lck_mtx_lock(lck_mtx_t *); +extern int lck_mtx_unlock(lck_mtx_t *); +extern int lck_mtx_try_lock(lck_mtx_t *); +extern void lck_mtx_destroy(lck_mtx_t *lck, lck_grp_t *grp); diff --git a/test/Analysis/Malloc+MismatchedDeallocator+NewDelete.cpp b/test/Analysis/Malloc+MismatchedDeallocator+NewDelete.cpp index 5a596d47eca80..fca02aa278fdd 100644 --- a/test/Analysis/Malloc+MismatchedDeallocator+NewDelete.cpp +++ b/test/Analysis/Malloc+MismatchedDeallocator+NewDelete.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,unix.MismatchedDeallocator,cplusplus.NewDelete -std=c++11 -verify %s -// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,unix.MismatchedDeallocator,cplusplus.NewDelete,alpha.cplusplus.NewDeleteLeaks -DLEAKS -std=c++11 -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,unix.MismatchedDeallocator,cplusplus.NewDelete,cplusplus.NewDeleteLeaks -DLEAKS -std=c++11 -verify %s #include "Inputs/system-header-simulator-for-malloc.h" diff --git a/test/Analysis/Malloc+NewDelete_intersections.cpp b/test/Analysis/Malloc+NewDelete_intersections.cpp index 310663646a109..d10020dc8e66d 100644 --- a/test/Analysis/Malloc+NewDelete_intersections.cpp +++ b/test/Analysis/Malloc+NewDelete_intersections.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,cplusplus.NewDelete -std=c++11 -verify %s -// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,cplusplus.NewDelete,alpha.cplusplus.NewDeleteLeaks -std=c++11 -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,cplusplus.NewDelete,cplusplus.NewDeleteLeaks -std=c++11 -verify %s typedef __typeof(sizeof(int)) size_t; void *malloc(size_t); diff --git a/test/Analysis/NSContainers.m b/test/Analysis/NSContainers.m index 4b3492645682e..402ce2c90a179 100644 --- a/test/Analysis/NSContainers.m +++ b/test/Analysis/NSContainers.m @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.NonNilReturnValue,osx.cocoa.NilArg,osx.cocoa.Loops,debug.ExprInspection -verify -Wno-objc-root-class %s +// RUN: %clang_cc1 -Wno-objc-literal-conversion -analyze -analyzer-checker=core,osx.cocoa.NonNilReturnValue,osx.cocoa.NilArg,osx.cocoa.Loops,debug.ExprInspection -verify -Wno-objc-root-class %s void clang_analyzer_eval(int); diff --git a/test/Analysis/NewDelete+MismatchedDeallocator_intersections.cpp b/test/Analysis/NewDelete+MismatchedDeallocator_intersections.cpp index b606f23ec8cc7..49358f6a2abae 100644 --- a/test/Analysis/NewDelete+MismatchedDeallocator_intersections.cpp +++ b/test/Analysis/NewDelete+MismatchedDeallocator_intersections.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -analyze -analyzer-checker=core,cplusplus.NewDelete,unix.MismatchedDeallocator -std=c++11 -verify %s -// RUN: %clang_cc1 -analyze -analyzer-checker=core,cplusplus.NewDelete,alpha.cplusplus.NewDeleteLeaks,unix.MismatchedDeallocator -DLEAKS -std=c++11 -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core,cplusplus.NewDelete,cplusplus.NewDeleteLeaks,unix.MismatchedDeallocator -DLEAKS -std=c++11 -verify %s // expected-no-diagnostics typedef __typeof(sizeof(int)) size_t; diff --git a/test/Analysis/NewDelete-checker-test.cpp b/test/Analysis/NewDelete-checker-test.cpp index 855b05d663331..84176c9097ca8 100644 --- a/test/Analysis/NewDelete-checker-test.cpp +++ b/test/Analysis/NewDelete-checker-test.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -analyze -analyzer-checker=core,cplusplus.NewDelete -std=c++11 -fblocks -verify %s -// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.cplusplus.NewDeleteLeaks -DLEAKS -std=c++11 -fblocks -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core,cplusplus.NewDeleteLeaks -DLEAKS -std=c++11 -fblocks -verify %s #include "Inputs/system-header-simulator-cxx.h" typedef __typeof__(sizeof(int)) size_t; diff --git a/test/Analysis/NewDelete-custom.cpp b/test/Analysis/NewDelete-custom.cpp index c64bfce2dee39..d368889c968e8 100644 --- a/test/Analysis/NewDelete-custom.cpp +++ b/test/Analysis/NewDelete-custom.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -analyze -analyzer-checker=core,cplusplus.NewDelete,unix.Malloc -std=c++11 -fblocks -verify %s -// RUN: %clang_cc1 -analyze -analyzer-checker=core,cplusplus.NewDelete,alpha.cplusplus.NewDeleteLeaks,unix.Malloc -std=c++11 -DLEAKS -fblocks -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core,cplusplus.NewDelete,cplusplus.NewDeleteLeaks,unix.Malloc -std=c++11 -DLEAKS -fblocks -verify %s #include "Inputs/system-header-simulator-cxx.h" #ifndef LEAKS diff --git a/test/Analysis/NewDelete-intersections.mm b/test/Analysis/NewDelete-intersections.mm index 9024ed57668b8..886df1268f9f6 100644 --- a/test/Analysis/NewDelete-intersections.mm +++ b/test/Analysis/NewDelete-intersections.mm @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -analyze -analyzer-checker=core,cplusplus.NewDelete -std=c++11 -fblocks -verify %s -// RUN: %clang_cc1 -analyze -analyzer-checker=core,cplusplus.NewDelete,alpha.cplusplus.NewDeleteLeaks -std=c++11 -DLEAKS -fblocks -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core,cplusplus.NewDelete,cplusplus.NewDeleteLeaks -std=c++11 -DLEAKS -fblocks -verify %s #include "Inputs/system-header-simulator-cxx.h" #include "Inputs/system-header-simulator-objc.h" diff --git a/test/Analysis/NewDelete-variadic.cpp b/test/Analysis/NewDelete-variadic.cpp index 62a7d17e1b2ad..f9ef079bfe802 100644 --- a/test/Analysis/NewDelete-variadic.cpp +++ b/test/Analysis/NewDelete-variadic.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=core,cplusplus.NewDelete,alpha.cplusplus.NewDeleteLeaks,unix.Malloc -std=c++11 -fblocks -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core,cplusplus.NewDelete,cplusplus.NewDeleteLeaks,unix.Malloc -std=c++11 -fblocks -verify %s // expected-no-diagnostics namespace std { diff --git a/test/Analysis/NewDeleteLeaks-PR18394.cpp b/test/Analysis/NewDeleteLeaks-PR18394.cpp index dfd94561628f8..d0d70375f5a2b 100644 --- a/test/Analysis/NewDeleteLeaks-PR18394.cpp +++ b/test/Analysis/NewDeleteLeaks-PR18394.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyzer-config graph-trim-interval=1 -analyzer-max-loop 1 -analyze -analyzer-checker=core,alpha.cplusplus.NewDeleteLeaks -verify %s +// RUN: %clang_cc1 -analyzer-config graph-trim-interval=1 -analyzer-max-loop 1 -analyze -analyzer-checker=core,cplusplus.NewDeleteLeaks -verify %s // expected-no-diagnostics class A { diff --git a/test/Analysis/NewDeleteLeaks-PR19102.cpp b/test/Analysis/NewDeleteLeaks-PR19102.cpp new file mode 100644 index 0000000000000..b141301e456f2 --- /dev/null +++ b/test/Analysis/NewDeleteLeaks-PR19102.cpp @@ -0,0 +1,43 @@ +// RUN: %clang_cc1 -analyze -analyzer-checker=core,cplusplus.NewDeleteLeaks -verify %s + +class A0 {}; + +class A1 { +public: + A1(int); +}; + +struct S{ + int i; +}; + +class A2 { +public: + A2(); + A2(S); + A2(int*); + A2(S*); + A2(S&, int); + A2(int, S**); +}; + +void test() { + new int; // expected-warning@+1 {{Potential memory leak}} + new A0; // expected-warning@+1 {{Potential memory leak}} + new A1(0); // expected-warning@+1 {{Potential memory leak}} + new A2; // expected-warning@+1 {{Potential memory leak}} + S s; + s.i = 1; + S* ps = new S; + new A2(s); // expected-warning@+1 {{Potential memory leak}} + new A2(&(s.i)); // expected-warning@+1 {{Potential memory leak}} + new A2(ps); // no warning + new A2(*ps, 1); // no warning + new A2(1, &ps); // no warning + + // Tests to ensure that leaks are reported for consumed news no matter what the arguments are. + A2 *a2p1 = new A2; // expected-warning@+1 {{Potential leak of memory}} + A2 *a2p2 = new A2(ps); // expected-warning@+1 {{Potential leak of memory}} + A2 *a2p3 = new A2(*ps, 1); // expected-warning@+1 {{Potential leak of memory}} + A2 *a2p4 = new A2(1, &ps); // expected-warning@+1 {{Potential leak of memory}} +} diff --git a/test/Analysis/bstring.c b/test/Analysis/bstring.c index 69d281afee4a1..824aa7c063b78 100644 --- a/test/Analysis/bstring.c +++ b/test/Analysis/bstring.c @@ -257,6 +257,45 @@ void mempcpy13() { mempcpy(a, 0, 0); // no-warning } +void mempcpy14() { + int src[] = {1, 2, 3, 4}; + int dst[5] = {0}; + int *p; + + p = mempcpy(dst, src, 4 * sizeof(int)); + + clang_analyzer_eval(p == &dst[4]); // expected-warning{{TRUE}} +} + +struct st { + int i; + int j; +}; + +void mempcpy15() { + struct st s1 = {0}; + struct st s2; + struct st *p1; + struct st *p2; + + p1 = (&s2) + 1; + p2 = mempcpy(&s2, &s1, sizeof(struct st)); + + clang_analyzer_eval(p1 == p2); // expected-warning{{TRUE}} +} + +void mempcpy16() { + struct st s1[10] = {{0}}; + struct st s2[10]; + struct st *p1; + struct st *p2; + + p1 = (&s2[0]) + 5; + p2 = mempcpy(&s2[0], &s1[0], 5 * sizeof(struct st)); + + clang_analyzer_eval(p1 == p2); // expected-warning{{TRUE}} +} + void mempcpy_unknown_size_warn (size_t n) { char a[4]; void *result = mempcpy(a, 0, n); // expected-warning{{Null pointer argument in call to memory copy function}} diff --git a/test/Analysis/builtin-functions.cpp b/test/Analysis/builtin-functions.cpp index 72d5ad23b16e8..d3afab5bd6150 100644 --- a/test/Analysis/builtin-functions.cpp +++ b/test/Analysis/builtin-functions.cpp @@ -22,3 +22,31 @@ void testSize() { clang_analyzer_eval(i == 0); // expected-warning{{TRUE}} } + +void test_assume_aligned_1(char *p) { + char *q; + + q = (char*) __builtin_assume_aligned(p, 16); + clang_analyzer_eval(p == q); // expected-warning{{TRUE}} +} + +void test_assume_aligned_2(char *p) { + char *q; + + q = (char*) __builtin_assume_aligned(p, 16, 8); + clang_analyzer_eval(p == q); // expected-warning{{TRUE}} +} + +void test_assume_aligned_3(char *p) { + void *q; + + q = __builtin_assume_aligned(p, 16, 8); + clang_analyzer_eval(p == q); // expected-warning{{TRUE}} +} + +void test_assume_aligned_4(char *p) { + char *q; + + q = (char*) __builtin_assume_aligned(p + 1, 16); + clang_analyzer_eval(p == q); // expected-warning{{FALSE}} +} diff --git a/test/Analysis/cfg.cpp b/test/Analysis/cfg.cpp index 65060b1687449..28cc440c46fcb 100644 --- a/test/Analysis/cfg.cpp +++ b/test/Analysis/cfg.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=debug.DumpCFG -triple x86_64-apple-darwin12 -std=c++11 %s > %t 2>&1 +// RUN: %clang_cc1 -analyze -analyzer-checker=debug.DumpCFG -triple x86_64-apple-darwin12 -analyzer-config cfg-temporary-dtors=true -std=c++11 %s > %t 2>&1 // RUN: FileCheck --input-file=%t %s // CHECK-LABEL: void checkWrap(int i) @@ -377,6 +377,61 @@ void test_placement_new_array() { } +// CHECK-LABEL: void test_lifetime_extended_temporaries() +// CHECK: [B1] +struct LifetimeExtend { LifetimeExtend(int); ~LifetimeExtend(); }; +struct Aggregate { const LifetimeExtend a; const LifetimeExtend b; }; +struct AggregateRef { const LifetimeExtend &a; const LifetimeExtend &b; }; +void test_lifetime_extended_temporaries() { + // CHECK: LifetimeExtend(1); + // CHECK-NEXT: : 1 + // CHECK-NEXT: ~LifetimeExtend() + // CHECK-NOT: ~LifetimeExtend() + { + const LifetimeExtend &l = LifetimeExtend(1); + 1; + } + // CHECK: LifetimeExtend(2) + // CHECK-NEXT: ~LifetimeExtend() + // CHECK-NEXT: : 2 + // CHECK-NOT: ~LifetimeExtend() + { + // No life-time extension. + const int &l = (LifetimeExtend(2), 2); + 2; + } + // CHECK: LifetimeExtend(3) + // CHECK-NEXT: : 3 + // CHECK-NEXT: ~LifetimeExtend() + // CHECK-NOT: ~LifetimeExtend() + { + // The last one is lifetime extended. + const LifetimeExtend &l = (3, LifetimeExtend(3)); + 3; + } + // CHECK: LifetimeExtend(4) + // CHECK-NEXT: ~LifetimeExtend() + // CHECK-NEXT: ~LifetimeExtend() + // CHECK-NEXT: : 4 + // CHECK-NOT: ~LifetimeExtend() + { + Aggregate a{LifetimeExtend(4), LifetimeExtend(4)}; + 4; + } + // CHECK: LifetimeExtend(5) + // CHECK-NEXT: : 5 + // FIXME: We want to emit the destructors of the lifetime + // extended variables here. + // CHECK-NOT: ~LifetimeExtend() + { + AggregateRef a{LifetimeExtend(5), LifetimeExtend(5)}; + 5; + } + // FIXME: Add tests for lifetime extension via subobject + // references (LifetimeExtend().some_member). +} + + // CHECK-LABEL: int *PR18472() // CHECK: [B2 (ENTRY)] // CHECK-NEXT: Succs (1): B1 diff --git a/test/Analysis/debug-CallGraph.c b/test/Analysis/debug-CallGraph.c index 4523c789351b3..64259e2069a49 100644 --- a/test/Analysis/debug-CallGraph.c +++ b/test/Analysis/debug-CallGraph.c @@ -23,11 +23,22 @@ void bbb(int y) { foo(x, y); }(); } +void ccc(); +void ddd() { ccc(); } +void ccc() {} + +void eee(); +void eee() {} +void fff() { eee(); } // CHECK:--- Call graph Dump --- -// CHECK: Function: < root > calls: mmm foo aaa < > bbb -// CHECK: Function: bbb calls: < > -// CHECK: Function: < > calls: foo -// CHECK: Function: aaa calls: foo -// CHECK: Function: foo calls: mmm -// CHECK: Function: mmm calls: +// CHECK-NEXT: {{Function: < root > calls: mmm foo aaa < > bbb ccc ddd eee fff $}} +// CHECK-NEXT: {{Function: fff calls: eee $}} +// CHECK-NEXT: {{Function: eee calls: $}} +// CHECK-NEXT: {{Function: ddd calls: ccc $}} +// CHECK-NEXT: {{Function: ccc calls: $}} +// CHECK-NEXT: {{Function: bbb calls: < > $}} +// CHECK-NEXT: {{Function: < > calls: foo $}} +// CHECK-NEXT: {{Function: aaa calls: foo $}} +// CHECK-NEXT: {{Function: foo calls: mmm $}} +// CHECK-NEXT: {{Function: mmm calls: $}} diff --git a/test/Analysis/disable-all-checks.c b/test/Analysis/disable-all-checks.c new file mode 100644 index 0000000000000..461e6d9bf94a0 --- /dev/null +++ b/test/Analysis/disable-all-checks.c @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-store=region -analyzer-disable-all-checks -verify %s +// RUN: %clang_cc1 -analyze -analyzer-disable-all-checks -analyzer-checker=core -analyzer-store=region -verify %s +// RUN: %clang --analyze -Xanalyzer -analyzer-disable-all-checks -Xclang -verify %s +// RUN: not %clang_cc1 -analyze -analyzer-checker=core -analyzer-store=region -analyzer-disable-checker -verify %s 2>&1 | FileCheck %s +// expected-no-diagnostics + +// CHECK: use -analyzer-disable-all-checks to disable all static analyzer checkers +int buggy() { + int x = 0; + return 5/x; // no warning +}
\ No newline at end of file diff --git a/test/Analysis/identical-expressions.cpp b/test/Analysis/identical-expressions.cpp index 85e3322002dd8..46dd56289c4ef 100644 --- a/test/Analysis/identical-expressions.cpp +++ b/test/Analysis/identical-expressions.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core.IdenticalExpr -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core.IdenticalExpr -w -verify %s /* Only one expected warning per function allowed at the very end. */ @@ -1511,3 +1511,22 @@ void test_nowarn_chained_if_stmts_3(int x) { else if (x++) // no-warning ; } + +void test_warn_wchar() { + const wchar_t * a = 0 ? L"Warning" : L"Warning"; // expected-warning {{identical expressions on both sides of ':' in conditional expression}} +} +void test_nowarn_wchar() { + const wchar_t * a = 0 ? L"No" : L"Warning"; +} + +void test_nowarn_long() { + int a = 0, b = 0; + long c; + if (0) { + b -= a; + c = 0; + } else { // no-warning + b -= a; + c = 0LL; + } +} diff --git a/test/Analysis/logical-ops.c b/test/Analysis/logical-ops.c index afaa2f1077807..0b63bc9ec835b 100644 --- a/test/Analysis/logical-ops.c +++ b/test/Analysis/logical-ops.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify %s +// RUN: %clang_cc1 -Wno-pointer-bool-conversion -analyze -analyzer-checker=core,debug.ExprInspection -verify %s void clang_analyzer_eval(int); diff --git a/test/Analysis/malloc-protoype.c b/test/Analysis/malloc-protoype.c new file mode 100644 index 0000000000000..f056f0f2855d5 --- /dev/null +++ b/test/Analysis/malloc-protoype.c @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -w -analyze -analyzer-checker=core,unix.Malloc -verify %s +// expected-no-diagnostics + +// Test that strange prototypes doesn't crash the analyzer + +void malloc(int i); +void valloc(int i); + +void test1() +{ + malloc(1); +} + +void test2() +{ + valloc(1); +} diff --git a/test/Analysis/malloc-sizeof.cpp b/test/Analysis/malloc-sizeof.cpp new file mode 100644 index 0000000000000..8589975f8fc26 --- /dev/null +++ b/test/Analysis/malloc-sizeof.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -analyze -analyzer-checker=unix.MallocSizeof -verify %s + +#include <stddef.h> + +void *malloc(size_t size); +void *calloc(size_t nmemb, size_t size); +void *realloc(void *ptr, size_t size); +void free(void *ptr); + +struct A {}; +struct B {}; + +void foo(unsigned int unsignedInt, unsigned int readSize) { + // Sanity check the checker is working as expected. + A* a = static_cast<A*>(malloc(sizeof(int))); // expected-warning {{Result of 'malloc' is converted to a pointer of type 'struct A', which is incompatible with sizeof operand type 'int'}} + free(a); +} + +void bar() { + A *x = static_cast<A*>(calloc(10, sizeof(void*))); // expected-warning {{Result of 'calloc' is converted to a pointer of type 'struct A', which is incompatible with sizeof operand type 'void *'}} + // sizeof(void*) is compatible with any pointer. + A **y = static_cast<A**>(calloc(10, sizeof(void*))); // no-warning + free(x); + free(y); +} + diff --git a/test/Analysis/misc-ps.m b/test/Analysis/misc-ps.m index 6da9604467de7..ad7393b82d30e 100644 --- a/test/Analysis/misc-ps.m +++ b/test/Analysis/misc-ps.m @@ -118,19 +118,6 @@ __m128i vec128i(long long __q1, long long __q0) { return __extension__ (__m128i)(__v2di){ __q0, __q1 }; } -// Zero-sized VLAs. -void check_zero_sized_VLA(int x) { - if (x) - return; - - int vla[x]; // expected-warning{{Declared variable-length array (VLA) has zero size}} -} - -void check_uninit_sized_VLA() { - int x; - int vla[x]; // expected-warning{{Declared variable-length array (VLA) uses a garbage value as its size}} -} - // sizeof(void) // - Tests a regression reported in PR 3211: http://llvm.org/bugs/show_bug.cgi?id=3211 void handle_sizeof_void(unsigned flag) { diff --git a/test/Analysis/model-file.cpp b/test/Analysis/model-file.cpp new file mode 100644 index 0000000000000..24d6e9312da9f --- /dev/null +++ b/test/Analysis/model-file.cpp @@ -0,0 +1,288 @@ +// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-config faux-bodies=true,model-path=%S/Inputs/Models -analyzer-output=plist-multi-file -verify %s -o %t +// RUN: FileCheck --input-file=%t %s + +typedef int* intptr; + +// This function is modeled and the p pointer is dereferenced in the model +// function and there is no function definition available. The modeled +// function can use any types that are available in the original translation +// unit, for example intptr in this case. +void modeledFunction(intptr p); + +// This function is modeled and returns true if the parameter is not zero +// and there is no function definition available. +bool notzero(int i); + +// This functions is not modeled and there is no function definition. +// available +bool notzero_notmodeled(int i); + +int main() { + // There is a nullpointer dereference inside this function. + modeledFunction(0); + + int p = 0; + if (notzero(p)) { + // It is known that p != 0 because of the information provided by the + // model of the notzero function. + int j = 5 / p; + } + + if (notzero_notmodeled(p)) { + // There is no information about the value of p, because + // notzero_notmodeled is not modeled and the function definition + // is not available. + int j = 5 / p; // expected-warning {{Division by zero}} + } + + return 0; +} + +// CHECK: <key>diagnostics</key> +// CHECK-NEXT: <array> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>path</key> +// CHECK-NEXT: <array> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>kind</key><string>control</string> +// CHECK-NEXT: <key>edges</key> +// CHECK-NEXT: <array> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>start</key> +// CHECK-NEXT: <array> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>22</integer> +// CHECK-NEXT: <key>col</key><integer>3</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>22</integer> +// CHECK-NEXT: <key>col</key><integer>17</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: </array> +// CHECK-NEXT: <key>end</key> +// CHECK-NEXT: <array> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>24</integer> +// CHECK-NEXT: <key>col</key><integer>3</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>24</integer> +// CHECK-NEXT: <key>col</key><integer>5</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: </array> +// CHECK-NEXT: </dict> +// CHECK-NEXT: </array> +// CHECK-NEXT: </dict> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>kind</key><string>event</string> +// CHECK-NEXT: <key>location</key> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>24</integer> +// CHECK-NEXT: <key>col</key><integer>3</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: <key>ranges</key> +// CHECK-NEXT: <array> +// CHECK-NEXT: <array> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>24</integer> +// CHECK-NEXT: <key>col</key><integer>3</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>24</integer> +// CHECK-NEXT: <key>col</key><integer>7</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: </array> +// CHECK-NEXT: </array> +// CHECK-NEXT: <key>depth</key><integer>0</integer> +// CHECK-NEXT: <key>extended_message</key> +// CHECK-NEXT: <string>'p' initialized to 0</string> +// CHECK-NEXT: <key>message</key> +// CHECK-NEXT: <string>'p' initialized to 0</string> +// CHECK-NEXT: </dict> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>kind</key><string>control</string> +// CHECK-NEXT: <key>edges</key> +// CHECK-NEXT: <array> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>start</key> +// CHECK-NEXT: <array> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>24</integer> +// CHECK-NEXT: <key>col</key><integer>3</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>24</integer> +// CHECK-NEXT: <key>col</key><integer>5</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: </array> +// CHECK-NEXT: <key>end</key> +// CHECK-NEXT: <array> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>25</integer> +// CHECK-NEXT: <key>col</key><integer>3</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>25</integer> +// CHECK-NEXT: <key>col</key><integer>4</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: </array> +// CHECK-NEXT: </dict> +// CHECK-NEXT: </array> +// CHECK-NEXT: </dict> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>kind</key><string>control</string> +// CHECK-NEXT: <key>edges</key> +// CHECK-NEXT: <array> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>start</key> +// CHECK-NEXT: <array> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>25</integer> +// CHECK-NEXT: <key>col</key><integer>3</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>25</integer> +// CHECK-NEXT: <key>col</key><integer>4</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: </array> +// CHECK-NEXT: <key>end</key> +// CHECK-NEXT: <array> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>31</integer> +// CHECK-NEXT: <key>col</key><integer>3</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>31</integer> +// CHECK-NEXT: <key>col</key><integer>4</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: </array> +// CHECK-NEXT: </dict> +// CHECK-NEXT: </array> +// CHECK-NEXT: </dict> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>kind</key><string>control</string> +// CHECK-NEXT: <key>edges</key> +// CHECK-NEXT: <array> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>start</key> +// CHECK-NEXT: <array> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>31</integer> +// CHECK-NEXT: <key>col</key><integer>3</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>31</integer> +// CHECK-NEXT: <key>col</key><integer>4</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: </array> +// CHECK-NEXT: <key>end</key> +// CHECK-NEXT: <array> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>31</integer> +// CHECK-NEXT: <key>col</key><integer>7</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>31</integer> +// CHECK-NEXT: <key>col</key><integer>24</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: </array> +// CHECK-NEXT: </dict> +// CHECK-NEXT: </array> +// CHECK-NEXT: </dict> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>kind</key><string>control</string> +// CHECK-NEXT: <key>edges</key> +// CHECK-NEXT: <array> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>start</key> +// CHECK-NEXT: <array> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>31</integer> +// CHECK-NEXT: <key>col</key><integer>7</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>31</integer> +// CHECK-NEXT: <key>col</key><integer>24</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: </array> +// CHECK-NEXT: <key>end</key> +// CHECK-NEXT: <array> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>35</integer> +// CHECK-NEXT: <key>col</key><integer>15</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>35</integer> +// CHECK-NEXT: <key>col</key><integer>15</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: </array> +// CHECK-NEXT: </dict> +// CHECK-NEXT: </array> +// CHECK-NEXT: </dict> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>kind</key><string>event</string> +// CHECK-NEXT: <key>location</key> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>35</integer> +// CHECK-NEXT: <key>col</key><integer>15</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: <key>ranges</key> +// CHECK-NEXT: <array> +// CHECK-NEXT: <array> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>35</integer> +// CHECK-NEXT: <key>col</key><integer>13</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>35</integer> +// CHECK-NEXT: <key>col</key><integer>17</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: </array> +// CHECK-NEXT: </array> +// CHECK-NEXT: <key>depth</key><integer>0</integer> +// CHECK-NEXT: <key>extended_message</key> +// CHECK-NEXT: <string>Division by zero</string> +// CHECK-NEXT: <key>message</key> +// CHECK-NEXT: <string>Division by zero</string> +// CHECK-NEXT: </dict> +// CHECK-NEXT: </array> +// CHECK-NEXT: <key>description</key><string>Division by zero</string> +// CHECK-NEXT: <key>category</key><string>Logic error</string> +// CHECK-NEXT: <key>type</key><string>Division by zero</string> +// CHECK-NEXT: <key>issue_context_kind</key><string>function</string> +// CHECK-NEXT: <key>issue_context</key><string>main</string> +// CHECK-NEXT: <key>issue_hash</key><string>15</string> +// CHECK-NEXT: <key>location</key> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>35</integer> +// CHECK-NEXT: <key>col</key><integer>15</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: </dict> +// CHECK-NEXT: </array>
\ No newline at end of file diff --git a/test/Analysis/nonnull.m b/test/Analysis/nonnull.m index 0cea80b536d80..c21360ded8d10 100644 --- a/test/Analysis/nonnull.m +++ b/test/Analysis/nonnull.m @@ -75,3 +75,121 @@ int rdar16153464(union rdar16153464_full_ctx_t inner) rdar16153464_check(inner); // no-warning rdar16153464_check(0); // expected-warning{{nonnull}} } + +// Multiple attributes, the basic case +void multipleAttributes_1(char *p, char *q) __attribute((nonnull(1))) __attribute((nonnull(2))); + +void testMultiple_1(void) { + char c; + multipleAttributes_1(&c, &c); // no-warning +} + +void testMultiple_2(void) { + char c; + multipleAttributes_1(0, &c); // expected-warning{{nonnull}} +} + +void testMultiple_3(void) { + char c; + multipleAttributes_1(&c, 0); // expected-warning{{nonnull}} +} + +void testMultiple_4(void) { + multipleAttributes_1(0, 0);// expected-warning{{nonnull}} +} + +// Multiple attributes, multiple prototypes +void multipleAttributes_2(char *p, char *q) __attribute((nonnull(1))); +void multipleAttributes_2(char *p, char *q) __attribute((nonnull(2))); + +void testMultiple_5(void) { + char c; + multipleAttributes_2(0, &c);// expected-warning{{nonnull}} +} + +void testMultiple_6(void) { + char c; + multipleAttributes_2(&c, 0);// expected-warning{{nonnull}} +} + +void testMultiple_7(void) { + multipleAttributes_2(0, 0);// expected-warning{{nonnull}} +} + +// Multiple attributes, same index +void multipleAttributes_3(char *p, char *q) __attribute((nonnull(1))) __attribute((nonnull(1))); + +void testMultiple_8(void) { + char c; + multipleAttributes_3(0, &c); // expected-warning{{nonnull}} +} + +void testMultiple_9(void) { + char c; + multipleAttributes_3(&c, 0); // no-warning +} + +// Multiple attributes, the middle argument is missing an attribute +void multipleAttributes_4(char *p, char *q, char *r) __attribute((nonnull(1))) __attribute((nonnull(3))); + +void testMultiple_10(void) { + char c; + multipleAttributes_4(0, &c, &c); // expected-warning{{nonnull}} +} + +void testMultiple_11(void) { + char c; + multipleAttributes_4(&c, 0, &c); // no-warning +} + +void testMultiple_12(void) { + char c; + multipleAttributes_4(&c, &c, 0); // expected-warning{{nonnull}} +} + + +// Multiple attributes, when the last is without index +void multipleAttributes_all_1(char *p, char *q) __attribute((nonnull(1))) __attribute((nonnull)); + +void testMultiple_13(void) { + char c; + multipleAttributes_all_1(0, &c); // expected-warning{{nonnull}} +} + +void testMultiple_14(void) { + char c; + multipleAttributes_all_1(&c, 0); // expected-warning{{nonnull}} +} + +// Multiple attributes, when the first is without index +void multipleAttributes_all_2(char *p, char *q) __attribute((nonnull)) __attribute((nonnull(2))); + +void testMultiple_15(void) { + char c; + multipleAttributes_all_2(0, &c); // expected-warning{{nonnull}} +} + +void testMultiple_16(void) { + char c; + multipleAttributes_all_2(&c, 0); // expected-warning{{nonnull}} +} + +void testVararg(int k, void *p) { + extern void testVararg_check(int, ...) __attribute__((nonnull)); + void *n = 0; + testVararg_check(0); + testVararg_check(1, p); + if (k == 1) + testVararg_check(1, n); // expected-warning{{nonnull}} + testVararg_check(2, p, p); + if (k == 2) + testVararg_check(2, n, p); // expected-warning{{nonnull}} + if (k == 3) + testVararg_check(2, p, n); // expected-warning{{nonnull}} +} + +void testNotPtr() { + struct S { int a; int b; int c; } s = {}; + extern void testNotPtr_check(struct S, int) __attribute__((nonnull(1, 2))); + testNotPtr_check(s, 0); +} diff --git a/test/Analysis/objc-boxing.m b/test/Analysis/objc-boxing.m index c23192e17e5d6..73386f463bc81 100644 --- a/test/Analysis/objc-boxing.m +++ b/test/Analysis/objc-boxing.m @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,osx.cocoa.NonNilReturnValue,debug.ExprInspection -analyzer-store=region -verify %s +// RUN: %clang_cc1 -Wno-objc-literal-conversion -analyze -analyzer-checker=core,unix.Malloc,osx.cocoa.NonNilReturnValue,debug.ExprInspection -analyzer-store=region -verify %s void clang_analyzer_eval(int); diff --git a/test/Analysis/pthreadlock.c b/test/Analysis/pthreadlock.c index 2a59e0ffe98ac..a6e29e78ff380 100644 --- a/test/Analysis/pthreadlock.c +++ b/test/Analysis/pthreadlock.c @@ -2,31 +2,10 @@ // Tests performing normal locking patterns and wrong locking orders -typedef struct { - void *foo; -} pthread_mutex_t; - -typedef struct { - void *foo; -} pthread_mutexattr_t; - -typedef struct { - void *foo; -} lck_grp_t; - -typedef pthread_mutex_t lck_mtx_t; - -extern int pthread_mutex_lock(pthread_mutex_t *); -extern int pthread_mutex_unlock(pthread_mutex_t *); -extern int pthread_mutex_trylock(pthread_mutex_t *); -extern int pthread_mutex_destroy(pthread_mutex_t *); -extern int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr); -extern int lck_mtx_lock(lck_mtx_t *); -extern int lck_mtx_unlock(lck_mtx_t *); -extern int lck_mtx_try_lock(lck_mtx_t *); -extern void lck_mtx_destroy(lck_mtx_t *lck, lck_grp_t *grp); +#include "Inputs/system-header-simulator-for-pthread-lock.h" pthread_mutex_t mtx1, mtx2; +pthread_mutex_t *pmtx; lck_mtx_t lck1, lck2; lck_grp_t grp1; @@ -184,6 +163,21 @@ ok20(void) } void +ok21(void) { + pthread_mutex_lock(pmtx); // no-warning + pthread_mutex_unlock(pmtx); // no-warning +} + +void +ok22(void) { + pthread_mutex_lock(pmtx); // no-warning + pthread_mutex_unlock(pmtx); // no-warning + pthread_mutex_lock(pmtx); // no-warning + pthread_mutex_unlock(pmtx); // no-warning +} + + +void bad1(void) { pthread_mutex_lock(&mtx1); // no-warning diff --git a/test/Analysis/temp-obj-dtors-cfg-output.cpp b/test/Analysis/temp-obj-dtors-cfg-output.cpp index 5fb33d36b8552..491c68e1bc8b0 100644 --- a/test/Analysis/temp-obj-dtors-cfg-output.cpp +++ b/test/Analysis/temp-obj-dtors-cfg-output.cpp @@ -324,7 +324,7 @@ int testConsistencyNestedNormalReturn(bool value) { // CHECK: [B3] // CHECK: 1: [B5.8] && [B4.5] // CHECK: 2: [B5.3]([B3.1]) -// CHECK: T: (Temp Dtor) [B5.8] && ... +// CHECK: T: (Temp Dtor) [B4.2] // CHECK: Preds (2): B4 B5 // CHECK: Succs (2): B2 B1 // CHECK: [B4] @@ -354,7 +354,7 @@ int testConsistencyNestedNormalReturn(bool value) { // CHECK: [B7] // CHECK: 1: [B9.5] && [B8.5] // CHECK: 2: bool a = A() && B(); -// CHECK: T: (Temp Dtor) [B9.5] && ... +// CHECK: T: (Temp Dtor) [B8.2] // CHECK: Preds (2): B8 B9 // CHECK: Succs (2): B6 B5 // CHECK: [B8] @@ -390,9 +390,9 @@ int testConsistencyNestedNormalReturn(bool value) { // CHECK: [B3] // CHECK: 1: [B5.8] || [B4.5] // CHECK: 2: [B5.3]([B3.1]) -// CHECK: T: (Temp Dtor) [B5.8] || ... +// CHECK: T: (Temp Dtor) [B4.2] // CHECK: Preds (2): B4 B5 -// CHECK: Succs (2): B1 B2 +// CHECK: Succs (2): B2 B1 // CHECK: [B4] // CHECK: 1: B() (CXXConstructExpr, class B) // CHECK: 2: [B4.1] (BindTemporary) @@ -420,9 +420,9 @@ int testConsistencyNestedNormalReturn(bool value) { // CHECK: [B7] // CHECK: 1: [B9.5] || [B8.5] // CHECK: 2: bool a = A() || B(); -// CHECK: T: (Temp Dtor) [B9.5] || ... +// CHECK: T: (Temp Dtor) [B8.2] // CHECK: Preds (2): B8 B9 -// CHECK: Succs (2): B5 B6 +// CHECK: Succs (2): B6 B5 // CHECK: [B8] // CHECK: 1: B() (CXXConstructExpr, class B) // CHECK: 2: [B8.1] (BindTemporary) @@ -492,9 +492,9 @@ int testConsistencyNestedNormalReturn(bool value) { // CHECK: 3: [B7.2] // CHECK: 4: [B7.3] (CXXConstructExpr, class A) // CHECK: 5: A a = B() ? A() : A(B()); -// CHECK: T: (Temp Dtor) [B10.5] ? ... : ... +// CHECK: T: (Temp Dtor) [B9.2] // CHECK: Preds (2): B8 B9 -// CHECK: Succs (2): B5 B6 +// CHECK: Succs (2): B6 B5 // CHECK: [B8] // CHECK: 1: A() (CXXConstructExpr, class A) // CHECK: 2: [B8.1] (BindTemporary) @@ -533,7 +533,6 @@ int testConsistencyNestedNormalReturn(bool value) { // CHECK: Succs (2): B8 B9 // CHECK: [B0 (EXIT)] // CHECK: Preds (1): B1 -// CHECK: C() : b_(true) // CHECK: [B2 (ENTRY)] // CHECK: Succs (1): B1 // CHECK: [B1] @@ -543,12 +542,10 @@ int testConsistencyNestedNormalReturn(bool value) { // CHECK: Succs (1): B0 // CHECK: [B0 (EXIT)] // CHECK: Preds (1): B1 -// CHECK: ~C() // CHECK: [B1 (ENTRY)] // CHECK: Succs (1): B0 // CHECK: [B0 (EXIT)] // CHECK: Preds (1): B1 -// CHECK: operator bool() // CHECK: [B2 (ENTRY)] // CHECK: Succs (1): B1 // CHECK: [B1] @@ -560,7 +557,6 @@ int testConsistencyNestedNormalReturn(bool value) { // CHECK: Succs (1): B0 // CHECK: [B0 (EXIT)] // CHECK: Preds (1): B1 -// CHECK: D() : b_(true) // CHECK: [B2 (ENTRY)] // CHECK: Succs (1): B1 // CHECK: [B1] @@ -570,7 +566,6 @@ int testConsistencyNestedNormalReturn(bool value) { // CHECK: Succs (1): B0 // CHECK: [B0 (EXIT)] // CHECK: Preds (1): B1 -// CHECK: operator bool() // CHECK: [B2 (ENTRY)] // CHECK: Succs (1): B1 // CHECK: [B1] @@ -582,7 +577,6 @@ int testConsistencyNestedNormalReturn(bool value) { // CHECK: Succs (1): B0 // CHECK: [B0 (EXIT)] // CHECK: Preds (1): B1 -// CHECK: int test_cond_unnamed_custom_destructor() // CHECK: [B4 (ENTRY)] // CHECK: Succs (1): B3 // CHECK: [B1] @@ -607,7 +601,6 @@ int testConsistencyNestedNormalReturn(bool value) { // CHECK: Succs (2): B2 B1 // CHECK: [B0 (EXIT)] // CHECK: Preds (2): B1 B2 -// CHECK: int test_cond_named_custom_destructor() // CHECK: [B5 (ENTRY)] // CHECK: Succs (1): B4 // CHECK: [B1] @@ -642,7 +635,6 @@ int testConsistencyNestedNormalReturn(bool value) { // CHECK: Succs (2): B3 B2 // CHECK: [B0 (EXIT)] // CHECK: Preds (3): B1 B2 B3 -// CHECK: int test_cond_unnamed_auto_destructor() // CHECK: [B4 (ENTRY)] // CHECK: Succs (1): B3 // CHECK: [B1] @@ -665,7 +657,6 @@ int testConsistencyNestedNormalReturn(bool value) { // CHECK: Succs (2): B2 B1 // CHECK: [B0 (EXIT)] // CHECK: Preds (2): B1 B2 -// CHECK: int test_cond_named_auto_destructor() // CHECK: [B4 (ENTRY)] // CHECK: Succs (1): B3 // CHECK: [B1] @@ -718,9 +709,9 @@ int testConsistencyNestedNormalReturn(bool value) { // CHECK: 2: [B4.1] (ImplicitCastExpr, NoOp, const class A) // CHECK: 3: [B4.2] // CHECK: 4: [B7.3]([B4.3]) -// CHECK: T: (Temp Dtor) [B7.8] ? ... : ... +// CHECK: T: (Temp Dtor) [B6.2] // CHECK: Preds (2): B5 B6 -// CHECK: Succs (2): B2 B3 +// CHECK: Succs (2): B3 B2 // CHECK: [B5] // CHECK: 1: A() (CXXConstructExpr, class A) // CHECK: 2: [B5.1] (BindTemporary) @@ -775,9 +766,9 @@ int testConsistencyNestedNormalReturn(bool value) { // CHECK: 2: [B10.1] (ImplicitCastExpr, NoOp, const class A) // CHECK: 3: [B10.2] // CHECK: 4: const A &a = B() ? A() : A(B()); -// CHECK: T: (Temp Dtor) [B13.5] ? ... : ... +// CHECK: T: (Temp Dtor) [B12.2] // CHECK: Preds (2): B11 B12 -// CHECK: Succs (2): B8 B9 +// CHECK: Succs (2): B9 B8 // CHECK: [B11] // CHECK: 1: A() (CXXConstructExpr, class A) // CHECK: 2: [B11.1] (BindTemporary) @@ -819,9 +810,8 @@ int testConsistencyNestedNormalReturn(bool value) { // CHECK: [B8 (ENTRY)] // CHECK: Succs (1): B7 // CHECK: [B1] -// CHECK: 1: ~A() (Temporary object destructor) -// CHECK: 2: int b; -// CHECK: 3: [B4.5].~A() (Implicit destructor) +// CHECK: 1: int b; +// CHECK: 2: [B4.5].~A() (Implicit destructor) // CHECK: Preds (2): B2 B3 // CHECK: Succs (1): B0 // CHECK: [B2] @@ -839,9 +829,9 @@ int testConsistencyNestedNormalReturn(bool value) { // CHECK: 3: [B4.2] // CHECK: 4: [B4.3] (CXXConstructExpr, class A) // CHECK: 5: A a = A() ?: A(); -// CHECK: T: (Temp Dtor) [B7.5] ? ... : ... +// CHECK: T: (Temp Dtor) [B6.2] // CHECK: Preds (2): B5 B6 -// CHECK: Succs (2): B2 B3 +// CHECK: Succs (2): B3 B2 // CHECK: [B5] // CHECK: 1: [B7.2] (ImplicitCastExpr, NoOp, const class A) // CHECK: 2: [B5.1] @@ -872,9 +862,8 @@ int testConsistencyNestedNormalReturn(bool value) { // CHECK: [B13 (ENTRY)] // CHECK: Succs (1): B12 // CHECK: [B1] -// CHECK: 1: ~A() (Temporary object destructor) -// CHECK: 2: int b; -// CHECK: 3: [B9.4].~A() (Implicit destructor) +// CHECK: 1: int b; +// CHECK: 2: [B9.4].~A() (Implicit destructor) // CHECK: Preds (2): B2 B3 // CHECK: Succs (1): B0 // CHECK: [B2] @@ -887,15 +876,15 @@ int testConsistencyNestedNormalReturn(bool value) { // CHECK: Preds (1): B4 // CHECK: Succs (1): B1 // CHECK: [B4] -// CHECK: 1: [B7.5] ?: [B6.6] +// CHECK: 1: [B7.4] ?: [B6.6] // CHECK: 2: [B4.1] (ImplicitCastExpr, NoOp, const class A) // CHECK: 3: [B4.2] -// CHECK: 4: [B7.3]([B4.3]) -// CHECK: T: (Temp Dtor) [B7.8] ? ... : ... +// CHECK: 4: [B7.2]([B4.3]) +// CHECK: T: (Temp Dtor) [B6.2] // CHECK: Preds (2): B5 B6 -// CHECK: Succs (2): B2 B3 +// CHECK: Succs (2): B3 B2 // CHECK: [B5] -// CHECK: 1: [B7.5] (ImplicitCastExpr, NoOp, const class A) +// CHECK: 1: [B7.4] (ImplicitCastExpr, NoOp, const class A) // CHECK: 2: [B5.1] // CHECK: 3: [B5.2] (CXXConstructExpr, class A) // CHECK: 4: [B5.3] (BindTemporary) @@ -911,16 +900,15 @@ int testConsistencyNestedNormalReturn(bool value) { // CHECK: Preds (1): B7 // CHECK: Succs (1): B4 // CHECK: [B7] -// CHECK: 1: ~A() (Temporary object destructor) -// CHECK: 2: foo -// CHECK: 3: [B7.2] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(const class A &)) -// CHECK: 4: A() (CXXConstructExpr, class A) -// CHECK: 5: [B7.4] (BindTemporary) -// CHECK: 6: [B7.5].operator bool -// CHECK: 7: [B7.5] -// CHECK: 8: [B7.7] (ImplicitCastExpr, UserDefinedConversion, _Bool) -// CHECK: T: [B7.8] ? ... : ... -// CHECK: Preds (2): B9 B8 +// CHECK: 1: foo +// CHECK: 2: [B7.1] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(const class A &)) +// CHECK: 3: A() (CXXConstructExpr, class A) +// CHECK: 4: [B7.3] (BindTemporary) +// CHECK: 5: [B7.4].operator bool +// CHECK: 6: [B7.4] +// CHECK: 7: [B7.6] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: T: [B7.7] ? ... : ... +// CHECK: Preds (2): B8 B9 // CHECK: Succs (2): B5 B6 // CHECK: [B8] // CHECK: 1: ~A() (Temporary object destructor) @@ -931,9 +919,9 @@ int testConsistencyNestedNormalReturn(bool value) { // CHECK: 2: [B9.1] (ImplicitCastExpr, NoOp, const class A) // CHECK: 3: [B9.2] // CHECK: 4: const A &a = A() ?: A(); -// CHECK: T: (Temp Dtor) [B12.5] ? ... : ... +// CHECK: T: (Temp Dtor) [B11.2] // CHECK: Preds (2): B10 B11 -// CHECK: Succs (2): B7 B8 +// CHECK: Succs (2): B8 B7 // CHECK: [B10] // CHECK: 1: [B12.2] (ImplicitCastExpr, NoOp, const class A) // CHECK: 2: [B10.1] @@ -1089,6 +1077,7 @@ int testConsistencyNestedNormalReturn(bool value) { // CHECK: Succs (1): B2 // CHECK: [B1] // CHECK: 1: int b; +// CHECK: Preds (1): B2(Unreachable) // CHECK: Succs (1): B0 // CHECK: [B2 (NORETURN)] // CHECK: 1: int a; @@ -1105,6 +1094,7 @@ int testConsistencyNestedNormalReturn(bool value) { // CHECK: Succs (1): B2 // CHECK: [B1] // CHECK: 1: int b; +// CHECK: Preds (1): B2(Unreachable) // CHECK: Succs (1): B0 // CHECK: [B2 (NORETURN)] // CHECK: 1: int a; @@ -1117,7 +1107,6 @@ int testConsistencyNestedNormalReturn(bool value) { // CHECK: Succs (1): B0 // CHECK: [B0 (EXIT)] // CHECK: Preds (2): B1 B2 -// CHECK: int testConsistencyNestedSimple(bool value) // CHECK: [B9 (ENTRY)] // CHECK: Succs (1): B8 // CHECK: [B1] @@ -1132,7 +1121,7 @@ int testConsistencyNestedNormalReturn(bool value) { // CHECK: Succs (1): B0 // CHECK: [B3] // CHECK: T: if [B5.1] -// CHECK: Preds (1): B5 +// CHECK: Preds (2): B4(Unreachable) B5 // CHECK: Succs (2): B2 B1 // CHECK: [B4 (NORETURN)] // CHECK: 1: ~NoReturn() (Temporary object destructor) @@ -1140,9 +1129,9 @@ int testConsistencyNestedNormalReturn(bool value) { // CHECK: Succs (1): B0 // CHECK: [B5] // CHECK: 1: [B7.3] || [B6.7] -// CHECK: T: (Temp Dtor) [B7.3] || ... +// CHECK: T: (Temp Dtor) [B6.4] // CHECK: Preds (2): B6 B7 -// CHECK: Succs (2): B3 B4 +// CHECK: Succs (2): B4 B3 // CHECK: [B6] // CHECK: 1: check // CHECK: 2: [B6.1] (ImplicitCastExpr, FunctionToPointerDecay, _Bool (*)(const class NoReturn &)) @@ -1168,7 +1157,6 @@ int testConsistencyNestedNormalReturn(bool value) { // CHECK: Succs (2): B7 B1 // CHECK: [B0 (EXIT)] // CHECK: Preds (3): B1 B2 B4 -// CHECK: int testConsistencyNestedComplex(bool value) // CHECK: [B10 (ENTRY)] // CHECK: Succs (1): B9 // CHECK: [B1] @@ -1183,7 +1171,7 @@ int testConsistencyNestedNormalReturn(bool value) { // CHECK: Succs (1): B0 // CHECK: [B3] // CHECK: T: if [B5.1] -// CHECK: Preds (1): B5 +// CHECK: Preds (2): B4(Unreachable) B5 // CHECK: Succs (2): B2 B1 // CHECK: [B4 (NORETURN)] // CHECK: 1: ~NoReturn() (Temporary object destructor) @@ -1191,9 +1179,9 @@ int testConsistencyNestedNormalReturn(bool value) { // CHECK: Succs (1): B0 // CHECK: [B5] // CHECK: 1: [B8.3] || [B7.3] || [B6.7] -// CHECK: T: (Temp Dtor) [B8.3] || [B7.3] || ... +// CHECK: T: (Temp Dtor) [B6.4] // CHECK: Preds (3): B6 B7 B8 -// CHECK: Succs (2): B3 B4 +// CHECK: Succs (2): B4 B3 // CHECK: [B6] // CHECK: 1: check // CHECK: 2: [B6.1] (ImplicitCastExpr, FunctionToPointerDecay, _Bool (*)(const class NoReturn &)) @@ -1226,7 +1214,6 @@ int testConsistencyNestedNormalReturn(bool value) { // CHECK: Succs (2): B8 B1 // CHECK: [B0 (EXIT)] // CHECK: Preds (3): B1 B2 B4 -// CHECK: int testConsistencyNestedNormalReturn(bool value) // CHECK: [B10 (ENTRY)] // CHECK: Succs (1): B9 // CHECK: [B1] @@ -1241,7 +1228,7 @@ int testConsistencyNestedNormalReturn(bool value) { // CHECK: Succs (1): B0 // CHECK: [B3] // CHECK: T: if [B5.1] -// CHECK: Preds (1): B5 +// CHECK: Preds (2): B4(Unreachable) B5 // CHECK: Succs (2): B2 B1 // CHECK: [B4 (NORETURN)] // CHECK: 1: ~NoReturn() (Temporary object destructor) @@ -1249,9 +1236,9 @@ int testConsistencyNestedNormalReturn(bool value) { // CHECK: Succs (1): B0 // CHECK: [B5] // CHECK: 1: [B8.3] || [B7.2] || [B6.7] -// CHECK: T: (Temp Dtor) [B8.3] || [B7.2] || ... +// CHECK: T: (Temp Dtor) [B6.4] // CHECK: Preds (3): B6 B7 B8 -// CHECK: Succs (2): B3 B4 +// CHECK: Succs (2): B4 B3 // CHECK: [B6] // CHECK: 1: check // CHECK: 2: [B6.1] (ImplicitCastExpr, FunctionToPointerDecay, _Bool (*)(const class NoReturn &)) diff --git a/test/Analysis/temporaries.cpp b/test/Analysis/temporaries.cpp index c57d984a1dc84..6e476339cb773 100644 --- a/test/Analysis/temporaries.cpp +++ b/test/Analysis/temporaries.cpp @@ -1,8 +1,9 @@ // RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify -w -std=c++03 %s // RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify -w -std=c++11 %s -// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -DTEMPORARY_DTORS -verify -w -analyzer-config cfg-temporary-dtors=true %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -DTEMPORARY_DTORS -verify -w -analyzer-config cfg-temporary-dtors=true %s -std=c++11 extern bool clang_analyzer_eval(bool); +extern bool clang_analyzer_warnIfReached(); struct Trivial { Trivial(int x) : value(x) {} @@ -111,13 +112,13 @@ namespace compound_literals { } namespace destructors { - void testPR16664andPR18159Crash() { - struct Dtor { - ~Dtor(); - }; - extern bool coin(); - extern bool check(const Dtor &); + struct Dtor { + ~Dtor(); + }; + extern bool coin(); + extern bool check(const Dtor &); + void testPR16664andPR18159Crash() { // Regression test: we used to assert here when tmp dtors are enabled. // PR16664 and PR18159 if (coin() && (coin() || coin() || check(Dtor()))) { @@ -193,8 +194,7 @@ namespace destructors { (i == 4 || i == 4 || compute(i == 5 && (i == 4 || check(NoReturnDtor()))))) || i != 4) { - // FIXME: This shouldn't cause a warning. - clang_analyzer_eval(true); // expected-warning{{TRUE}} + clang_analyzer_eval(true); // no warning, unreachable code } } @@ -211,8 +211,7 @@ namespace destructors { void testConsistencyNestedComplex(bool value) { if (value) { if (!value || !value || check(NoReturnDtor())) { - // FIXME: This shouldn't cause a warning. - clang_analyzer_eval(true); // expected-warning{{TRUE}} + clang_analyzer_eval(true); // no warning, unreachable code } } } @@ -225,6 +224,120 @@ namespace destructors { } } } + // PR16664 and PR18159 + void testConsistencyNestedComplexMidBranch(bool value) { + if (value) { + if (!value || !value || check(NoReturnDtor()) || value) { + clang_analyzer_eval(true); // no warning, unreachable code + } + } + } + + // PR16664 and PR18159 + void testConsistencyNestedComplexNestedBranch(bool value) { + if (value) { + if (!value || (!value || check(NoReturnDtor()) || value)) { + clang_analyzer_eval(true); // no warning, unreachable code + } + } + } + + // PR16664 and PR18159 + void testConsistencyNestedVariableModification(bool value) { + bool other = true; + if (value) { + if (!other || !value || (other = false) || check(NoReturnDtor()) || + !other) { + clang_analyzer_eval(true); // no warning, unreachable code + } + } + } + + void testTernaryNoReturnTrueBranch(bool value) { + if (value) { + bool b = value && (value ? check(NoReturnDtor()) : true); + clang_analyzer_eval(true); // no warning, unreachable code + } + } + void testTernaryNoReturnFalseBranch(bool value) { + if (value) { + bool b = !value && !value ? true : check(NoReturnDtor()); + clang_analyzer_eval(true); // no warning, unreachable code + } + } + void testTernaryIgnoreNoreturnBranch(bool value) { + if (value) { + bool b = !value && !value ? check(NoReturnDtor()) : true; + clang_analyzer_eval(true); // expected-warning{{TRUE}} + } + } + void testTernaryTrueBranchReached(bool value) { + value ? clang_analyzer_warnIfReached() : // expected-warning{{REACHABLE}} + check(NoReturnDtor()); + } + void testTernaryFalseBranchReached(bool value) { + value ? check(NoReturnDtor()) : + clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} + } + + void testLoop() { + for (int i = 0; i < 10; ++i) { + if (i < 3 && (i >= 2 || check(NoReturnDtor()))) { + clang_analyzer_eval(true); // no warning, unreachable code + } + } + } + + bool testRecursiveFrames(bool isInner) { + if (isInner || + (clang_analyzer_warnIfReached(), false) || // expected-warning{{REACHABLE}} + check(NoReturnDtor()) || + testRecursiveFrames(true)) { + clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} + } + } + void testRecursiveFramesStart() { testRecursiveFrames(false); } + + void testLambdas() { + // This is the test we would like to write: + // []() { check(NoReturnDtor()); } != nullptr || check(Dtor()); + // But currently the analyzer stops when it encounters a lambda: + [] {}; + // The CFG for this now looks correct, but we still do not reach the line + // below. + clang_analyzer_warnIfReached(); // FIXME: Should warn. + } + + void testGnuExpressionStatements(int v) { + ({ ++v; v == 10 || check(NoReturnDtor()); v == 42; }) || v == 23; + clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} + + ({ ++v; check(NoReturnDtor()); v == 42; }) || v == 23; + clang_analyzer_warnIfReached(); // no warning, unreachable code + } + + void testGnuExpressionStatementsDestructionPoint(int v) { + // In normal context, the temporary destructor runs at the end of the full + // statement, thus the last statement is reached. + (++v, check(NoReturnDtor()), v == 42), + clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} + + // GNU expression statements execute temporary destructors within the + // blocks, thus the last statement is not reached. + ({ ++v; check(NoReturnDtor()); v == 42; }), + clang_analyzer_warnIfReached(); // no warning, unreachable code + } + + void testMultipleTemporaries(bool value) { + if (value) { + // FIXME: Find a way to verify construction order. + // ~Dtor should run before ~NoReturnDtor() because construction order is + // guaranteed by comma operator. + if (!value || check((NoReturnDtor(), Dtor())) || value) { + clang_analyzer_eval(true); // no warning, unreachable code + } + } + } void testBinaryOperatorShortcut(bool value) { if (value) { @@ -234,6 +347,78 @@ namespace destructors { } } + void testIfAtEndOfLoop() { + int y = 0; + while (true) { + if (y > 0) { + clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} + } + ++y; + // Test that the CFG gets hooked up correctly when temporary destructors + // are handled after a statically known branch condition. + if (true) (void)0; else (void)check(NoReturnDtor()); + } + } + + void testTernaryAtEndOfLoop() { + int y = 0; + while (true) { + if (y > 0) { + clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} + } + ++y; + // Test that the CFG gets hooked up correctly when temporary destructors + // are handled after a statically known branch condition. + true ? (void)0 : (void)check(NoReturnDtor()); + } + } + + void testNoReturnInComplexCondition() { + check(Dtor()) && + (check(NoReturnDtor()) || check(NoReturnDtor())) && check(Dtor()); + clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} + } + + void testSequencingOfConditionalTempDtors(bool b) { + b || (check(Dtor()), check(NoReturnDtor())); + clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} + } + + void testSequencingOfConditionalTempDtors2(bool b) { + (b || check(Dtor())), check(NoReturnDtor()); + clang_analyzer_warnIfReached(); // no warning, unreachable code + } + + void testSequencingOfConditionalTempDtorsWithinBinaryOperators(bool b) { + b || (check(Dtor()) + check(NoReturnDtor())); + clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} + } + + void f(Dtor d = Dtor()); + void testDefaultParameters() { + f(); + } + + struct DefaultParam { + DefaultParam(int, const Dtor& d = Dtor()); + ~DefaultParam(); + }; + void testDefaultParamConstructorsInLoops() { + while (true) { + // FIXME: This exact pattern triggers the temporary cleanup logic + // to fail when adding a 'clean' state. + DefaultParam(42); + DefaultParam(42); + } + } + void testDefaultParamConstructorsInTernariesInLoops(bool value) { + while (true) { + // FIXME: This exact pattern triggers the temporary cleanup logic + // to visit the bind-temporary logic with a state that already has that + // temporary marked as executed. + value ? DefaultParam(42) : DefaultParam(42); + } + } #endif // TEMPORARY_DTORS } diff --git a/test/Analysis/unix-api.c b/test/Analysis/unix-api.c new file mode 100644 index 0000000000000..86c702d725942 --- /dev/null +++ b/test/Analysis/unix-api.c @@ -0,0 +1,75 @@ +// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.API -verify %s + +#ifndef O_RDONLY +#define O_RDONLY 0 +#endif + +#ifndef NULL +#define NULL ((void*) 0) +#endif + +int open(const char *, int, ...); +int close(int fildes); + +void open_1(const char *path) { + int fd; + fd = open(path, O_RDONLY); // no-warning + if (fd > -1) + close(fd); +} + +void open_2(const char *path) { + int fd; + int mode = 0x0; + fd = open(path, O_RDONLY, mode, NULL); // expected-warning{{Call to 'open' with more than three arguments}} + if (fd > -1) + close(fd); +} + +void open_3(const char *path) { + int fd; + fd = open(path, O_RDONLY, NULL); // expected-warning{{Third argument to 'open' is not an integer}} + if (fd > -1) + close(fd); +} + +void open_4(const char *path) { + int fd; + fd = open(path, O_RDONLY, ""); // expected-warning{{Third argument to 'open' is not an integer}} + if (fd > -1) + close(fd); +} + +void open_5(const char *path) { + int fd; + struct { + int val; + } st = {0}; + fd = open(path, O_RDONLY, st); // expected-warning{{Third argument to 'open' is not an integer}} + if (fd > -1) + close(fd); +} + +void open_6(const char *path) { + int fd; + struct { + int val; + } st = {0}; + fd = open(path, O_RDONLY, st.val); // no-warning + if (fd > -1) + close(fd); +} + +void open_7(const char *path) { + int fd; + fd = open(path, O_RDONLY, &open); // expected-warning{{Third argument to 'open' is not an integer}} + if (fd > -1) + close(fd); +} + +void open_8(const char *path) { + int fd; + fd = open(path, O_RDONLY, 0.0f); // expected-warning{{Third argument to 'open' is not an integer}} + if (fd > -1) + close(fd); +} diff --git a/test/Analysis/virtualcall.cpp b/test/Analysis/virtualcall.cpp index c3319b0ac54fc..8ce1d4103b9c1 100644 --- a/test/Analysis/virtualcall.cpp +++ b/test/Analysis/virtualcall.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=alpha.cplusplus.VirtualCall -analyzer-store region -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=alpha.cplusplus.VirtualCall -analyzer-store region -verify -std=c++11 %s class A { public: @@ -46,10 +46,31 @@ C::C() { f(foo()); // expected-warning{{Call virtual functions during construction or destruction will never go to a more derived class}} } +class D : public B { +public: + D() { + foo(); // no-warning + } + ~D() { bar(); } + int foo() final; + void bar() final { foo(); } // no-warning +}; + +class E final : public B { +public: + E() { + foo(); // no-warning + } + ~E() { bar(); } + int foo() override; +}; + int main() { A *a; B *b; C *c; + D *d; + E *e; } #include "virtualcall.h" diff --git a/test/Analysis/vla.c b/test/Analysis/vla.c new file mode 100644 index 0000000000000..f94bea96e8f64 --- /dev/null +++ b/test/Analysis/vla.c @@ -0,0 +1,86 @@ +// RUN: %clang_cc1 -analyze -analyzer-checker=core -verify %s + +// Zero-sized VLAs. +void check_zero_sized_VLA(int x) { + if (x) + return; + + int vla[x]; // expected-warning{{Declared variable-length array (VLA) has zero size}} +} + +void check_uninit_sized_VLA() { + int x; + int vla[x]; // expected-warning{{Declared variable-length array (VLA) uses a garbage value as its size}} +} + +// Negative VLAs. +static void vla_allocate_signed(int x) { + int vla[x]; // expected-warning{{Declared variable-length array (VLA) has negative size}} +} + +static void vla_allocate_unsigned(unsigned int x) { + int vla[x]; // no-warning +} + +void check_negative_sized_VLA_1() { + vla_allocate_signed(-1); +} + +void check_negative_sized_VLA_2() { + vla_allocate_unsigned(-1); +} + +void check_negative_sized_VLA_3() { + int x = -1; + int vla[x]; // expected-warning{{Declared variable-length array (VLA) has negative size}} +} + +void check_negative_sized_VLA_4() { + unsigned int x = -1; + int vla[x]; // no-warning +} + +void check_negative_sized_VLA_5() { + signed char x = -1; + int vla[x]; // expected-warning{{Declared variable-length array (VLA) has negative size}} +} + +void check_negative_sized_VLA_6() { + unsigned char x = -1; + int vla[x]; // no-warning +} + +void check_negative_sized_VLA_7() { + signed char x = -1; + int vla[x + 2]; // no-warning +} + +void check_negative_sized_VLA_8() { + signed char x = 1; + int vla[x - 2]; // expected-warning{{Declared variable-length array (VLA) has negative size}} +} + +void check_negative_sized_VLA_9() { + int x = 1; + int vla[x]; // no-warning +} + +static void check_negative_sized_VLA_10_sub(int x) +{ + int vla[x]; // expected-warning{{Declared variable-length array (VLA) has negative size}} +} + +void check_negative_sized_VLA_10(int x) { + if (x < 0) + check_negative_sized_VLA_10_sub(x); +} + +static void check_negative_sized_VLA_11_sub(int x) +{ + int vla[x]; // no-warning +} + +void check_negative_sized_VLA_11(int x) { + if (x > 0) + check_negative_sized_VLA_11_sub(x); +} |