Update aosp/master Clang for rebase to r222490.
Change-Id: Ic557ac55e97fbf6ee08771c7b7c3594777b0aefd
diff --git a/test/Analysis/Inputs/Models/modeledFunction.model b/test/Analysis/Inputs/Models/modeledFunction.model
new file mode 100644
index 0000000..3aff5fc
--- /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 0000000..2616102
--- /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 0000000..b290ffe
--- /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 5a596d4..fca02aa 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 3106636..d10020d 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 4b34926..402ce2c 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 b606f23..49358f6 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 855b05d..84176c9 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 c64bfce..d368889 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 9024ed5..886df12 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 62a7d17..f9ef079 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 dfd9456..d0d7037 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 0000000..b141301
--- /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 69d281a..824aa7c 100644
--- a/test/Analysis/bstring.c
+++ b/test/Analysis/bstring.c
@@ -257,6 +257,45 @@
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 72d5ad2..d3afab5 100644
--- a/test/Analysis/builtin-functions.cpp
+++ b/test/Analysis/builtin-functions.cpp
@@ -22,3 +22,31 @@
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 65060b1..28cc440 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 @@
}
+// 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/dead-stores.c b/test/Analysis/dead-stores.c
index 5b2c2a1..da8e8bd 100644
--- a/test/Analysis/dead-stores.c
+++ b/test/Analysis/dead-stores.c
@@ -11,7 +11,7 @@
char *c = (char*)b; // no-warning
char *d = b+1; // expected-warning {{never read}} expected-warning{{unused variable 'd'}}
printf("%s", c); // expected-warning{{implicitly declaring library function 'printf' with type 'int (const char *, ...)'}} \
- // expected-note{{please include the header <stdio.h> or explicitly provide a declaration for 'printf'}}
+ // expected-note{{include the header <stdio.h> or explicitly provide a declaration for 'printf'}}
}
int f();
diff --git a/test/Analysis/disable-all-checks.c b/test/Analysis/disable-all-checks.c
new file mode 100644
index 0000000..461e6d9
--- /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/exercise-ps.c b/test/Analysis/exercise-ps.c
index 675dd4e..03b6874 100644
--- a/test/Analysis/exercise-ps.c
+++ b/test/Analysis/exercise-ps.c
@@ -19,5 +19,5 @@
F12_typedef* x;
x = f2_helper();
memcpy((&x[1]), (buf), 1); // expected-warning{{implicitly declaring library function 'memcpy' with type 'void *(void *, const void *}} \
- // expected-note{{please include the header <string.h> or explicitly provide a declaration for 'memcpy'}}
+ // expected-note{{include the header <string.h> or explicitly provide a declaration for 'memcpy'}}
}
diff --git a/test/Analysis/identical-expressions.cpp b/test/Analysis/identical-expressions.cpp
index 85e3322..46dd562 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 @@
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 afaa2f1..0b63bc9 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 0000000..f056f0f
--- /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 0000000..8589975
--- /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 6da9604..ad7393b 100644
--- a/test/Analysis/misc-ps.m
+++ b/test/Analysis/misc-ps.m
@@ -118,19 +118,6 @@
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 0000000..24d6e93
--- /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 0cea80b..c21360d 100644
--- a/test/Analysis/nonnull.m
+++ b/test/Analysis/nonnull.m
@@ -75,3 +75,121 @@
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 c23192e..73386f4 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 2a59e0f..a6e29e7 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 @@
}
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 5fb33d3..491c68e 100644
--- a/test/Analysis/temp-obj-dtors-cfg-output.cpp
+++ b/test/Analysis/temp-obj-dtors-cfg-output.cpp
@@ -324,7 +324,7 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 c57d984..6e47633 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 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 @@
(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 @@
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 @@
}
}
}
+ // 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 @@
}
}
+ 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 0000000..86c702d
--- /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 c3319b0..8ce1d41 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 @@
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 0000000..f94bea9
--- /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);
+}