1+ #include < cstdint>
2+ #include < memory>
3+ #include < mutex>
4+
5+ std::mutex g1;
6+ std::mutex g2;
7+
8+ void f1 (std::unique_lock<std::mutex> l1) {
9+ // Function parameter for testing compliant cases
10+ }
11+
12+ void test_explicit_type_conversion_expression_statement () {
13+ // Compliant cases - declarations
14+ std::unique_lock<std::mutex> l1 (g1); // COMPLIANT
15+ std::unique_lock<std::mutex> l2{g1}; // COMPLIANT
16+ std::unique_lock<std::mutex>(l3); // COMPLIANT - declaration with redundant
17+ // parentheses around variable name
18+
19+ // Non-compliant cases - explicit type conversions as expression statements
20+ std::unique_lock<std::mutex>{g1}; // NON_COMPLIANT
21+ std::scoped_lock{g1}; // NON_COMPLIANT
22+ std::scoped_lock (g1, g2); // NON_COMPLIANT
23+ std::lock_guard<std::mutex>{g1}; // NON_COMPLIANT
24+
25+ // Compliant cases - type conversions not as expression statements
26+ f1 (std::unique_lock<std::mutex>(g1)); // COMPLIANT
27+ f1 (std::unique_lock<std::mutex>{g1}); // COMPLIANT
28+ auto l4 = std::unique_lock<std::mutex>(g1); // COMPLIANT
29+ auto l5 = std::unique_lock<std::mutex>{g1}; // COMPLIANT
30+
31+ // The extractor has a bug as of 2.20.7 which means it does not parse
32+ // these two cases separately. We choose to ignore if statements, which
33+ // can cause false negatives, but will prevent false positives
34+ if (std::unique_lock<std::mutex>(g1); true ) { // COMPLIANT - init-statement
35+ }
36+ if (std::unique_lock<std::mutex>{g1}; true ) { // NON_COMPLIANT[FALSE_NEGATIVE]
37+ }
38+
39+ for (std::unique_lock<std::mutex>(g1);;) { // COMPLIANT - init-statement
40+ break ;
41+ }
42+ for (std::unique_lock<std::mutex>{g1};;) { // NON_COMPLIANT - init-statement
43+ break ;
44+ }
45+ }
46+
47+ void test_primitive_type_conversions () {
48+ // Non-compliant cases with primitive types
49+ std::int32_t (42 ); // NON_COMPLIANT
50+ float (3.14 ); // NON_COMPLIANT
51+ double (2.71 ); // NON_COMPLIANT
52+ bool (true ); // NON_COMPLIANT
53+
54+ // Compliant cases
55+ auto l1 = std::int32_t (42 ); // COMPLIANT
56+ auto l2 = float (3.14 ); // COMPLIANT
57+ std::int32_t l3 (42 ); // COMPLIANT - declaration
58+ std::int32_t l4{42 }; // COMPLIANT - declaration
59+ }
60+
61+ struct CustomType {
62+ CustomType (std::int32_t ) {}
63+ };
64+ void test_custom_types () {
65+ // Non-compliant cases
66+ CustomType (42 ); // NON_COMPLIANT
67+ CustomType{42 }; // NON_COMPLIANT
68+
69+ // Compliant cases
70+ CustomType l1 (42 ); // COMPLIANT - declaration
71+ CustomType l2{42 }; // COMPLIANT - declaration
72+ auto l3 = CustomType (42 ); // COMPLIANT
73+ auto l4 = CustomType{42 }; // COMPLIANT
74+ }
0 commit comments