xref: /llvm-project/clang/test/Analysis/cxx-member-initializer-const-field.cpp (revision a504ddc8bf9d5c406ea88b84b8495d7aae200d4c)
168ee5ec0SMarco Antognini // RUN: %clang_analyze_cc1 -analyzer-checker=core -verify %s
268ee5ec0SMarco Antognini 
368ee5ec0SMarco Antognini // This tests false-positive issues related to PR48534.
468ee5ec0SMarco Antognini //
568ee5ec0SMarco Antognini // Essentially, having a default member initializer for a constant member does
668ee5ec0SMarco Antognini // not necessarily imply the member will have the given default value.
768ee5ec0SMarco Antognini 
868ee5ec0SMarco Antognini struct WithConstructor {
968ee5ec0SMarco Antognini   int *const ptr = nullptr;
WithConstructorWithConstructor1068ee5ec0SMarco Antognini   WithConstructor(int *x) : ptr(x) {}
1168ee5ec0SMarco Antognini 
compliantWithConstructor1268ee5ec0SMarco Antognini   static auto compliant() {
13*a504ddc8SKristóf Umann     WithConstructor c(new int{});
1468ee5ec0SMarco Antognini     return *(c.ptr); // no warning
1568ee5ec0SMarco Antognini   }
1668ee5ec0SMarco Antognini 
compliantWithParamWithConstructor1768ee5ec0SMarco Antognini   static auto compliantWithParam(WithConstructor c) {
1868ee5ec0SMarco Antognini     return *(c.ptr); // no warning
1968ee5ec0SMarco Antognini   }
2068ee5ec0SMarco Antognini 
issueWithConstructor2168ee5ec0SMarco Antognini   static auto issue() {
2268ee5ec0SMarco Antognini     WithConstructor c(nullptr);
2368ee5ec0SMarco Antognini     return *(c.ptr); // expected-warning{{Dereference of null pointer (loaded from field 'ptr')}}
2468ee5ec0SMarco Antognini   }
2568ee5ec0SMarco Antognini };
2668ee5ec0SMarco Antognini 
2768ee5ec0SMarco Antognini struct RegularAggregate {
2868ee5ec0SMarco Antognini   int *const ptr = nullptr;
2968ee5ec0SMarco Antognini 
compliantRegularAggregate3068ee5ec0SMarco Antognini   static int compliant() {
31*a504ddc8SKristóf Umann     RegularAggregate c{new int{}};
3268ee5ec0SMarco Antognini     return *(c.ptr); // no warning
3368ee5ec0SMarco Antognini   }
3468ee5ec0SMarco Antognini 
issueRegularAggregate3568ee5ec0SMarco Antognini   static int issue() {
3668ee5ec0SMarco Antognini     RegularAggregate c;
3768ee5ec0SMarco Antognini     return *(c.ptr); // expected-warning{{Dereference of null pointer (loaded from field 'ptr')}}
3868ee5ec0SMarco Antognini   }
3968ee5ec0SMarco Antognini };
4068ee5ec0SMarco Antognini 
4168ee5ec0SMarco Antognini struct WithConstructorAndArithmetic {
4268ee5ec0SMarco Antognini   int const i = 0;
WithConstructorAndArithmeticWithConstructorAndArithmetic4368ee5ec0SMarco Antognini   WithConstructorAndArithmetic(int x) : i(x + 1) {}
4468ee5ec0SMarco Antognini 
compliantWithConstructorAndArithmetic4568ee5ec0SMarco Antognini   static int compliant(int y) {
4668ee5ec0SMarco Antognini     WithConstructorAndArithmetic c(0);
4768ee5ec0SMarco Antognini     return y / c.i; // no warning
4868ee5ec0SMarco Antognini   }
4968ee5ec0SMarco Antognini 
issueWithConstructorAndArithmetic5068ee5ec0SMarco Antognini   static int issue(int y) {
5168ee5ec0SMarco Antognini     WithConstructorAndArithmetic c(-1);
5268ee5ec0SMarco Antognini     return y / c.i; // expected-warning{{Division by zero}}
5368ee5ec0SMarco Antognini   }
5468ee5ec0SMarco Antognini };
5568ee5ec0SMarco Antognini 
5668ee5ec0SMarco Antognini struct WithConstructorDeclarationOnly {
5768ee5ec0SMarco Antognini   int const i = 0;
5868ee5ec0SMarco Antognini   WithConstructorDeclarationOnly(int x); // definition not visible.
5968ee5ec0SMarco Antognini 
compliant1WithConstructorDeclarationOnly6068ee5ec0SMarco Antognini   static int compliant1(int y) {
6168ee5ec0SMarco Antognini     WithConstructorDeclarationOnly c(0);
6268ee5ec0SMarco Antognini     return y / c.i; // no warning
6368ee5ec0SMarco Antognini   }
6468ee5ec0SMarco Antognini 
compliant2WithConstructorDeclarationOnly6568ee5ec0SMarco Antognini   static int compliant2(int y) {
6668ee5ec0SMarco Antognini     WithConstructorDeclarationOnly c(-1);
6768ee5ec0SMarco Antognini     return y / c.i; // no warning
6868ee5ec0SMarco Antognini   }
6968ee5ec0SMarco Antognini };
7068ee5ec0SMarco Antognini 
7168ee5ec0SMarco Antognini // NonAggregateFP is not an aggregate (j is a private non-static field) and has no custom constructor.
7268ee5ec0SMarco Antognini // So we know i and j will always be 0 and 42, respectively.
7368ee5ec0SMarco Antognini // That being said, this is not implemented because it is deemed too rare to be worth the complexity.
7468ee5ec0SMarco Antognini struct NonAggregateFP {
7568ee5ec0SMarco Antognini public:
7668ee5ec0SMarco Antognini   int const i = 0;
7768ee5ec0SMarco Antognini 
7868ee5ec0SMarco Antognini private:
7968ee5ec0SMarco Antognini   int const j = 42;
8068ee5ec0SMarco Antognini 
8168ee5ec0SMarco Antognini public:
falsePositive1NonAggregateFP8268ee5ec0SMarco Antognini   static int falsePositive1(NonAggregateFP c) {
8368ee5ec0SMarco Antognini     return 10 / c.i; // FIXME: Currently, no warning.
8468ee5ec0SMarco Antognini   }
8568ee5ec0SMarco Antognini 
falsePositive2NonAggregateFP8668ee5ec0SMarco Antognini   static int falsePositive2(NonAggregateFP c) {
8768ee5ec0SMarco Antognini     return 10 / (c.j - 42); // FIXME: Currently, no warning.
8868ee5ec0SMarco Antognini   }
8968ee5ec0SMarco Antognini };
9068ee5ec0SMarco Antognini 
9168ee5ec0SMarco Antognini struct NonAggregate {
9268ee5ec0SMarco Antognini public:
9368ee5ec0SMarco Antognini   int const i = 0;
9468ee5ec0SMarco Antognini 
9568ee5ec0SMarco Antognini private:
9668ee5ec0SMarco Antognini   int const j = 42;
9768ee5ec0SMarco Antognini 
9868ee5ec0SMarco Antognini   NonAggregate(NonAggregate const &); // not provided, could set i and j to arbitrary values.
9968ee5ec0SMarco Antognini 
10068ee5ec0SMarco Antognini public:
compliant1NonAggregate10168ee5ec0SMarco Antognini   static int compliant1(NonAggregate c) {
10268ee5ec0SMarco Antognini     return 10 / c.i; // no warning
10368ee5ec0SMarco Antognini   }
10468ee5ec0SMarco Antognini 
compliant2NonAggregate10568ee5ec0SMarco Antognini   static int compliant2(NonAggregate c) {
10668ee5ec0SMarco Antognini     return 10 / (c.j - 42); // no warning
10768ee5ec0SMarco Antognini   }
10868ee5ec0SMarco Antognini };
10968ee5ec0SMarco Antognini 
11068ee5ec0SMarco Antognini struct WithStaticMember {
11168ee5ec0SMarco Antognini   static int const i = 0;
11268ee5ec0SMarco Antognini 
issue1WithStaticMember11368ee5ec0SMarco Antognini   static int issue1(WithStaticMember c) {
11468ee5ec0SMarco Antognini     return 10 / c.i; // expected-warning{{division by zero is undefined}} expected-warning{{Division by zero}}
11568ee5ec0SMarco Antognini   }
11668ee5ec0SMarco Antognini 
issue2WithStaticMember11768ee5ec0SMarco Antognini   static int issue2() {
11868ee5ec0SMarco Antognini     return 10 / WithStaticMember::i; // expected-warning{{division by zero is undefined}} expected-warning{{Division by zero}}
11968ee5ec0SMarco Antognini   }
12068ee5ec0SMarco Antognini };
121