Index: clang/test/Analysis/clangsa_unsupported_features/handle_constructors_for_default_arguments.cpp =================================================================== --- /dev/null +++ clang/test/Analysis/clangsa_unsupported_features/handle_constructors_for_default_arguments.cpp @@ -0,0 +1,86 @@ +// RUN: %clang_cc1 -fsyntax-only -analyze \ +// RUN: -analyzer-checker=core,debug.ExprInspection %s -verify +// REQUIRES: non-existing-system + +// These test cases demonstrate lack of Static Analyzer features. +// Remove REQUIRES line, when the feature gets implemented. + +// Handle constructors for default arguments +// Default arguments in C++ are recomputed at every call, +// and are therefore local, and not static, variables. +void clang_analyzer_eval(bool); +void clang_analyzer_warnIfReached(); + +struct init_with_list { + int a; + init_with_list() : a(1) {} +}; + +struct init_in_body { + int a; + init_in_body() { a = 1; } +}; + +struct init_default_member { + int a = 1; +}; + +struct basic_struct { + int a; +}; + +//top-level analyzed function +void top_f(init_with_list l = init_with_list()) { + //We expect that the analyzer doesn't assume anything about the parameter + clang_analyzer_eval(l.a == 1); // expected-warning {{TRUE}} expected-warning {{FALSE}} +} + +void top_g(init_in_body l = init_in_body()) { + //We expect that the analyzer doesn't assume anything about the parameter + clang_analyzer_eval(l.a == 1); // expected-warning {{TRUE}} expected-warning {{FALSE}} +} + +void top_h(init_default_member l = init_default_member()) { + //We expect that the analyzer doesn't assume anything about the parameter + clang_analyzer_eval(l.a == 1); // expected-warning {{TRUE}} expected-warning {{FALSE}} +} + +// not-top level analyze functions +int called_f(init_with_list l = init_with_list()) { + return l.a; +} + +int called_g(init_in_body l = init_in_body()) { + //We expect that the analyzer assumes the default value (call site test2) + return l.a; +} + +int called_h(init_default_member l = init_default_member()) { + //We expect that the analyzer assumes the default value (call site test3) + return l.a; +} + +int plain_parameter_passing(basic_struct l) { + return l.a; +} + +void test1() { + basic_struct b; + b.a = 1; + clang_analyzer_eval(plain_parameter_passing(b) == 1); //expected-warning {{TRUE}} +} + +void test2() { + //We expect that the analyzer assumes the default value + clang_analyzer_eval(called_f() == 1); //expected-warning {{TRUE}} +} + +void test3() { + //We expect that the analyzer assumes the default value + clang_analyzer_eval(called_g() == 1); //expected-warning {{TRUE}} +} + +void test4() { + //We expect that the analyzer assumes the default value + clang_analyzer_eval(called_h() == 1); //expected-warning {{TRUE}} +} Index: clang/test/Analysis/clangsa_unsupported_features/handle_constructors_with_new_array.cpp =================================================================== --- /dev/null +++ clang/test/Analysis/clangsa_unsupported_features/handle_constructors_with_new_array.cpp @@ -0,0 +1,81 @@ +// RUN: %clang_cc1 -fsyntax-only -analyze \ +// RUN: -analyzer-checker=core,debug.ExprInspection %s -verify +// REQUIRES: non-existing-system + +// These test cases demonstrate lack of Static Analyzer features. +// Remove REQUIRES line, when the feature gets implemented. + +// Handle constructors within new[] + +// When an array of objects is allocated using the operator new[], +// constructors for all elements of the array are called. +// We should model (potentially some of) such evaluations, +// and the same applies for destructors called from operator delete[]. + +void clang_analyzer_eval(bool); + +struct init_with_list { + int a; + init_with_list() : a(1) {} +}; + +struct init_in_body { + int a; + init_in_body() { a = 1; } +}; + +struct init_default_member { + int a = 1; +}; + +void test_automatic() { + + init_with_list a1; + init_in_body a2; + init_default_member a3; + + clang_analyzer_eval(a1.a == 1); // expected-warning {{TRUE}} + clang_analyzer_eval(a2.a == 1); // expected-warning {{TRUE}} + clang_analyzer_eval(a3.a == 1); // expected-warning {{TRUE}} +} + +void test_dynamic() { + + auto *a1 = new init_with_list; + auto *a2 = new init_in_body; + auto *a3 = new init_default_member; + + clang_analyzer_eval(a1->a == 1); // expected-warning {{TRUE}} + clang_analyzer_eval(a2->a == 1); // expected-warning {{TRUE}} + clang_analyzer_eval(a3->a == 1); // expected-warning {{TRUE}} + + delete a1; + delete a2; + delete a3; +} + +void test_automatic_aggregate() { + + init_with_list a1[1]; + init_in_body a2[1]; + init_default_member a3[1]; + + clang_analyzer_eval(a1[0].a == 1); // expected-warning {{TRUE}} + clang_analyzer_eval(a2[0].a == 1); // expected-warning {{TRUE}} + clang_analyzer_eval(a3[0].a == 1); // expected-warning {{TRUE}} +} + +void test_dynamic_aggregate() { + + auto *a1 = new init_with_list[1]; + auto *a2 = new init_in_body[1]; + auto *a3 = new init_default_member[1]; + + clang_analyzer_eval(a1[0].a == 1); // expected-warning {{TRUE}} + clang_analyzer_eval(a2[0].a == 1); // expected-warning {{TRUE}} + clang_analyzer_eval(a3[0].a == 1); // expected-warning {{TRUE}} + + delete[] a1; + delete[] a2; + delete[] a3; +} Index: clang/www/analyzer/open_projects.html =================================================================== --- clang/www/analyzer/open_projects.html +++ clang/www/analyzer/open_projects.html @@ -95,6 +95,7 @@ We should model (potentially some of) such evaluations, and the same applies for destructors called from operator delete[]. + See tests cases in handle_constructors_with_new_array.cpp.

@@ -117,6 +118,7 @@

Default arguments in C++ are recomputed at every call, and are therefore local, and not static, variables.

+ See tests cases in handle_constructors_for_default_arguments.cpp.
  • Enhance the modeling of the standard library.