Skip to content

Commit cd8c960

Browse files
committed
Rule 7.0.6: Correctly handle constructor exception
Improve handling for constructors with default arguments.
1 parent 1af908a commit cd8c960

File tree

3 files changed

+72
-42
lines changed

3 files changed

+72
-42
lines changed

cpp/misra/src/rules/RULE-7-0-6/NumericAssignmentTypeMismatch.ql

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,18 +60,29 @@ predicate isValidTypeMatch(NumericType sourceType, NumericType targetType) {
6060
sourceType.getRealSize() = targetType.getRealSize()
6161
}
6262

63+
/**
64+
* A constructor that can be called with a single argument
65+
*/
66+
private class CallableWithASingleArgumentConstructor extends Constructor {
67+
CallableWithASingleArgumentConstructor() {
68+
// Either a constructor with a single parameter
69+
this.getNumberOfParameters() = 1
70+
or
71+
// Or the second (and later parameters) all have defaults
72+
exists(this.getParameter(1).getInitializer())
73+
}
74+
}
75+
6376
predicate hasConstructorException(FunctionCall call) {
64-
exists(Constructor ctor, Class c |
77+
exists(CallableWithASingleArgumentConstructor ctor, Class c |
6578
call.getTarget() = ctor and
6679
c = ctor.getDeclaringType() and
6780
// Constructor callable with single numeric argument
68-
ctor.getNumberOfParameters() = 1 and
6981
ctor.getParameter(0).getType() instanceof NumericType and
7082
// No other single-argument constructors except copy/move
71-
not exists(Constructor other |
83+
not exists(CallableWithASingleArgumentConstructor other |
7284
other.getDeclaringType() = c and
7385
other != ctor and
74-
other.getNumberOfParameters() = 1 and
7586
not other instanceof CopyConstructor and
7687
not other instanceof MoveConstructor
7788
)

cpp/misra/test/rules/RULE-7-0-6/NumericAssignmentTypeMismatch.expected

Lines changed: 39 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -49,42 +49,45 @@
4949
| test.cpp:289:6:289:8 | u32 | Assignment between incompatible numeric types from 'uint32_t' to 'size_t'. |
5050
| test.cpp:294:12:294:14 | s16 | Assignment between incompatible numeric types from 'int16_t' to 'int32_t'. |
5151
| test.cpp:313:9:313:10 | 42 | Assignment between incompatible numeric types from 'int' to 'long'. |
52-
| test.cpp:346:25:346:27 | u32 | Assignment between incompatible numeric types from 'uint32_t' to 'unsigned long'. |
53-
| test.cpp:358:19:358:25 | ... + ... | Assignment between incompatible numeric types from 'int' to 'int16_t'. |
54-
| test.cpp:363:10:363:12 | u32 | Assignment between incompatible numeric types from 'uint32_t' to 'int32_t'. |
55-
| test.cpp:396:8:396:9 | l6 | Assignment between incompatible numeric types from 'uint32_t &' to 'uint8_t'. |
56-
| test.cpp:397:8:397:9 | l7 | Assignment between incompatible numeric types from 'int8_t &' to 'uint8_t'. |
57-
| test.cpp:398:9:398:10 | l8 | Assignment between incompatible numeric types from 'float &' to 'int32_t'. |
58-
| test.cpp:409:6:409:7 | l3 | Assignment between incompatible numeric types from 'uint8_t &' to 'int64_t'. |
59-
| test.cpp:410:6:410:7 | l4 | Assignment between incompatible numeric types from 'uint16_t &' to 'int32_t'. |
60-
| test.cpp:421:8:421:9 | l3 | Assignment between incompatible numeric types from 'uint8_t &' to 'int8_t'. |
61-
| test.cpp:422:8:422:9 | l4 | Assignment between incompatible numeric types from 'int8_t &' to 'uint8_t'. |
62-
| test.cpp:435:9:435:10 | l4 | Assignment between incompatible numeric types from 'float &' to 'int32_t'. |
63-
| test.cpp:436:7:436:8 | l5 | Assignment between incompatible numeric types from 'double &' to 'float'. |
64-
| test.cpp:437:7:437:8 | l6 | Assignment between incompatible numeric types from 'int32_t &' to 'float'. |
65-
| test.cpp:448:8:448:14 | ... + ... | Assignment between incompatible numeric types from 'int' to 'uint8_t'. |
66-
| test.cpp:466:7:466:8 | l3 | Assignment between incompatible numeric types from 'uint16_t &' to 'uint32_t'. |
67-
| test.cpp:469:7:469:8 | l5 | Assignment between incompatible numeric types from 'uint64_t &' to 'uint32_t'. |
68-
| test.cpp:518:12:518:13 | l1 | Assignment between incompatible numeric types from 'uint32_t' to 'uint8_t'. |
69-
| test.cpp:519:12:519:13 | l1 | Assignment between incompatible numeric types from 'uint32_t' to 'uint16_t'. |
70-
| test.cpp:521:12:521:13 | l2 | Assignment between incompatible numeric types from 'int32_t' to 'int8_t'. |
71-
| test.cpp:522:12:522:13 | l2 | Assignment between incompatible numeric types from 'int32_t' to 'int16_t'. |
72-
| test.cpp:542:12:542:14 | 300 | Assignment between incompatible numeric types from 'int' to 'uint8_t'. |
73-
| test.cpp:543:12:543:16 | 70000 | Assignment between incompatible numeric types from 'int' to 'uint16_t'. |
74-
| test.cpp:544:12:544:27 | 4294967296 | Assignment between incompatible numeric types from 'unsigned long long' to 'uint32_t'. |
75-
| test.cpp:545:12:545:14 | 200 | Assignment between incompatible numeric types from 'int' to 'int8_t'. |
76-
| test.cpp:546:12:546:16 | 40000 | Assignment between incompatible numeric types from 'int' to 'int16_t'. |
77-
| test.cpp:547:12:547:26 | 4294967296 | Assignment between incompatible numeric types from 'long long' to 'int32_t'. |
78-
| test.cpp:548:12:548:14 | 1.0 | Assignment between incompatible numeric types from 'double' to 'float'. |
79-
| test.cpp:549:12:549:15 | 1.0 | Assignment between incompatible numeric types from 'float' to 'double'. |
80-
| test.cpp:554:12:554:18 | ... + ... | Assignment between incompatible numeric types from 'int' to 'uint8_t'. |
81-
| test.cpp:555:12:555:18 | ... + ... | Assignment between incompatible numeric types from 'int' to 'uint16_t'. |
82-
| test.cpp:556:12:556:18 | ... + ... | Assignment between incompatible numeric types from 'int' to 'uint32_t'. |
83-
| test.cpp:558:12:558:13 | l1 | Assignment between incompatible numeric types from 'uint8_t' to 'int16_t'. |
84-
| test.cpp:559:12:559:13 | l1 | Assignment between incompatible numeric types from 'uint8_t' to 'int32_t'. |
85-
| test.cpp:560:12:560:13 | l1 | Assignment between incompatible numeric types from 'uint8_t' to 'float'. |
86-
| test.cpp:561:12:561:13 | l1 | Assignment between incompatible numeric types from 'uint8_t' to 'double'. |
87-
| test.cpp:591:9:591:37 | static_cast<int16_t>... | Assignment between incompatible numeric types from 'int16_t' to 'int32_t'. |
52+
| test.cpp:339:12:339:13 | s8 | Assignment between incompatible numeric types from 'int8_t' to 'int32_t'. |
53+
| test.cpp:340:12:340:13 | s8 | Assignment between incompatible numeric types from 'int8_t' to 'int32_t'. |
54+
| test.cpp:342:32:342:33 | s8 | Assignment between incompatible numeric types from 'int8_t' to 'int32_t'. |
55+
| test.cpp:362:25:362:27 | u32 | Assignment between incompatible numeric types from 'uint32_t' to 'unsigned long'. |
56+
| test.cpp:374:19:374:25 | ... + ... | Assignment between incompatible numeric types from 'int' to 'int16_t'. |
57+
| test.cpp:379:10:379:12 | u32 | Assignment between incompatible numeric types from 'uint32_t' to 'int32_t'. |
58+
| test.cpp:412:8:412:9 | l6 | Assignment between incompatible numeric types from 'uint32_t &' to 'uint8_t'. |
59+
| test.cpp:413:8:413:9 | l7 | Assignment between incompatible numeric types from 'int8_t &' to 'uint8_t'. |
60+
| test.cpp:414:9:414:10 | l8 | Assignment between incompatible numeric types from 'float &' to 'int32_t'. |
61+
| test.cpp:425:6:425:7 | l3 | Assignment between incompatible numeric types from 'uint8_t &' to 'int64_t'. |
62+
| test.cpp:426:6:426:7 | l4 | Assignment between incompatible numeric types from 'uint16_t &' to 'int32_t'. |
63+
| test.cpp:437:8:437:9 | l3 | Assignment between incompatible numeric types from 'uint8_t &' to 'int8_t'. |
64+
| test.cpp:438:8:438:9 | l4 | Assignment between incompatible numeric types from 'int8_t &' to 'uint8_t'. |
65+
| test.cpp:451:9:451:10 | l4 | Assignment between incompatible numeric types from 'float &' to 'int32_t'. |
66+
| test.cpp:452:7:452:8 | l5 | Assignment between incompatible numeric types from 'double &' to 'float'. |
67+
| test.cpp:453:7:453:8 | l6 | Assignment between incompatible numeric types from 'int32_t &' to 'float'. |
68+
| test.cpp:464:8:464:14 | ... + ... | Assignment between incompatible numeric types from 'int' to 'uint8_t'. |
69+
| test.cpp:482:7:482:8 | l3 | Assignment between incompatible numeric types from 'uint16_t &' to 'uint32_t'. |
70+
| test.cpp:485:7:485:8 | l5 | Assignment between incompatible numeric types from 'uint64_t &' to 'uint32_t'. |
71+
| test.cpp:534:12:534:13 | l1 | Assignment between incompatible numeric types from 'uint32_t' to 'uint8_t'. |
72+
| test.cpp:535:12:535:13 | l1 | Assignment between incompatible numeric types from 'uint32_t' to 'uint16_t'. |
73+
| test.cpp:537:12:537:13 | l2 | Assignment between incompatible numeric types from 'int32_t' to 'int8_t'. |
74+
| test.cpp:538:12:538:13 | l2 | Assignment between incompatible numeric types from 'int32_t' to 'int16_t'. |
75+
| test.cpp:558:12:558:14 | 300 | Assignment between incompatible numeric types from 'int' to 'uint8_t'. |
76+
| test.cpp:559:12:559:16 | 70000 | Assignment between incompatible numeric types from 'int' to 'uint16_t'. |
77+
| test.cpp:560:12:560:27 | 4294967296 | Assignment between incompatible numeric types from 'unsigned long long' to 'uint32_t'. |
78+
| test.cpp:561:12:561:14 | 200 | Assignment between incompatible numeric types from 'int' to 'int8_t'. |
79+
| test.cpp:562:12:562:16 | 40000 | Assignment between incompatible numeric types from 'int' to 'int16_t'. |
80+
| test.cpp:563:12:563:26 | 4294967296 | Assignment between incompatible numeric types from 'long long' to 'int32_t'. |
81+
| test.cpp:564:12:564:14 | 1.0 | Assignment between incompatible numeric types from 'double' to 'float'. |
82+
| test.cpp:565:12:565:15 | 1.0 | Assignment between incompatible numeric types from 'float' to 'double'. |
83+
| test.cpp:570:12:570:18 | ... + ... | Assignment between incompatible numeric types from 'int' to 'uint8_t'. |
84+
| test.cpp:571:12:571:18 | ... + ... | Assignment between incompatible numeric types from 'int' to 'uint16_t'. |
85+
| test.cpp:572:12:572:18 | ... + ... | Assignment between incompatible numeric types from 'int' to 'uint32_t'. |
86+
| test.cpp:574:12:574:13 | l1 | Assignment between incompatible numeric types from 'uint8_t' to 'int16_t'. |
87+
| test.cpp:575:12:575:13 | l1 | Assignment between incompatible numeric types from 'uint8_t' to 'int32_t'. |
88+
| test.cpp:576:12:576:13 | l1 | Assignment between incompatible numeric types from 'uint8_t' to 'float'. |
89+
| test.cpp:577:12:577:13 | l1 | Assignment between incompatible numeric types from 'uint8_t' to 'double'. |
90+
| test.cpp:607:9:607:37 | static_cast<int16_t>... | Assignment between incompatible numeric types from 'int16_t' to 'int32_t'. |
8891
| test_aggregate.cpp:29:22:29:24 | u16 | Assignment between incompatible numeric types from 'uint16_t' to 'uint8_t'. |
8992
| test_aggregate.cpp:31:26:31:28 | u32 | Assignment between incompatible numeric types from 'uint32_t' to 'uint16_t'. |
9093
| test_aggregate.cpp:33:31:33:33 | u32 | Assignment between incompatible numeric types from 'uint32_t' to 'int32_t'. |

cpp/misra/test/rules/RULE-7-0-6/test.cpp

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -317,13 +317,29 @@ void test_member_function_not_overload_independent() {
317317
struct MyInt {
318318
explicit MyInt(std::int32_t l1) {}
319319
MyInt(std::int32_t l1, std::int32_t l2) {}
320+
// Move and copy constructors are allowed
321+
MyInt(MyInt const &) = default;
322+
MyInt(MyInt &&) = default;
323+
};
324+
325+
struct ConstructorException {
326+
explicit ConstructorException(std::int32_t l1, std::int32_t l2 = 2) {}
327+
};
328+
329+
struct NotInConstructorException {
330+
explicit NotInConstructorException(std::int32_t l1) {}
331+
NotInConstructorException(std::int16_t l1, std::int32_t l2 = 2) {}
320332
};
321333

322334
void f9(MyInt l1) {}
323335

324336
void test_constructor_exception() {
325-
f9(MyInt{s8}); // COMPLIANT
326-
MyInt l1{s8}; // COMPLIANT
337+
f9(MyInt{s8}); // COMPLIANT
338+
MyInt l1{s8}; // COMPLIANT
339+
f9(MyInt{s8, 10}); // NON_COMPLIANT - not covered by exception
340+
MyInt l2{s8, 10}; // NON_COMPLIANT - not covered by exception
341+
ConstructorException l3{s8}; // COMPLIANT
342+
NotInConstructorException l4{s8}; // NON_COMPLIANT - ambiguous constructor
327343
}
328344

329345
template <typename T> struct D {

0 commit comments

Comments
 (0)