Skip to content

Commit e00b8f6

Browse files
Address feedback
1 parent 26ebb66 commit e00b8f6

File tree

6 files changed

+120
-25
lines changed

6 files changed

+120
-25
lines changed

cpp/misra/src/rules/RULE-13-3-1/MemberSpecifiersNotUsedAppropriately.ql

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,11 @@ where
2525
f.isDeclaredVirtual() and
2626
exists(Specifier s |
2727
s = f.getASpecifier() and
28-
s.getName() = ["final", "override"]
29-
) and
30-
message =
31-
"Member function '" + f.getName() +
32-
"' uses redundant 'virtual' and 'final' specifiers together."
28+
s.getName() = ["final", "override"] and
29+
message =
30+
"Member function '" + f.getName() + "' uses redundant 'virtual' and '" + s.getName() +
31+
"' specifiers together."
32+
)
3333
or
3434
// Case 2: Redundant 'virtual' specifier
3535
f.overrides(_) and

cpp/misra/src/rules/RULE-14-1-1/PrivateAndPublicDataMembersMixed.ql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ where
2727
or
2828
// Public and private data members cannot be mixed.
2929
exists(Field other |
30+
// Allow manual exclusion of 'other' field.
31+
not isExcluded(other, Classes2Package::privateAndPublicDataMembersMixedQuery()) and
3032
other = c.getAMember() and
3133
not other.isStatic() and
3234
other != f and

cpp/misra/src/rules/RULE-15-0-2/InvalidSignatureForSpecialMemberFunction.ql

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,20 +23,21 @@ predicate checkSignature(
2323
MemberFunction f, Boolean noexcept, Boolean lvalueQualified, Boolean rvalueRef, string err
2424
) {
2525
f.getNumberOfParameters() > 1 and
26-
err = "too many parameters"
26+
err = "has too many parameters"
2727
or
2828
noexcept = true and
2929
not f.isNoExcept() and
3030
err = "should be noexcept"
3131
or
32+
// Note: There is no check when `lvalueQualified` is false, only when true. `lvalueQualified` will
33+
// only be false for constructors, and constructors cannot be ref-qualified.
3234
lvalueQualified = true and
3335
not f.isLValueRefQualified() and
3436
err = "should be lvalue-qualified"
3537
or
36-
lvalueQualified = false and
37-
f.isLValueRefQualified() and
38-
err = "should not be lvalue-qualified"
39-
or
38+
// Note: This case is also only here for completeness. `rvalueRef` is only true for move
39+
// constructors and move assignment operators. However, these special member functions by
40+
// definition must take an rvalue reference, so this case cannot hold.
4041
rvalueRef = true and
4142
not isRvalueRefX(f.getParameter(0).getType(), f.getDeclaringType()) and
4243
err = "should take rvalue reference to class or struct type"
@@ -53,6 +54,8 @@ predicate checkSignature(
5354
not f.getType() instanceof VoidType and
5455
err = "should return void or lvalue reference to class or struct type"
5556
or
57+
// Note: this is here for completeness. It is a static error to declare copy or move constructors
58+
// as `explicit`, so this cannot hold.
5659
not f instanceof Constructor and
5760
f.isExplicit() and
5861
err = "should not be explicit"

cpp/misra/test/rules/RULE-13-3-1/MemberSpecifiersNotUsedAppropriately.expected

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22
| test.cpp:15:16:15:17 | f2 | Member function 'f2' uses redundant 'virtual' and 'final' specifiers together. |
33
| test.cpp:33:16:33:25 | m1_virtual | Member function 'm1_virtual' overrides a base function but uses 'virtual' specifier. |
44
| test.cpp:38:16:38:25 | m1_virtual | Member function 'm1_virtual' overrides a base function but uses 'virtual' specifier. |
5-
| test.cpp:38:16:38:25 | m1_virtual | Member function 'm1_virtual' uses redundant 'virtual' and 'final' specifiers together. |
5+
| test.cpp:38:16:38:25 | m1_virtual | Member function 'm1_virtual' uses redundant 'virtual' and 'override' specifiers together. |
66
| test.cpp:43:16:43:25 | m1_virtual | Member function 'm1_virtual' overrides a base function but uses 'virtual' specifier. |
77
| test.cpp:43:16:43:25 | m1_virtual | Member function 'm1_virtual' uses redundant 'virtual' and 'final' specifiers together. |
88
| test.cpp:48:8:48:17 | m1_virtual | Member function 'm1_virtual' uses redundant 'override' and 'final' specifiers together. |
99
| test.cpp:53:8:53:17 | m1_virtual | Member function 'm1_virtual' overrides a base function but lacks 'override' or 'final' specifier. |
1010
| test.cpp:69:16:69:28 | m1_nonvirtual | Member function 'm1_nonvirtual' uses redundant 'virtual' and 'final' specifiers together. |
1111
| test.cpp:90:3:90:6 | ~C12 | Member function '~C12' overrides a base function but lacks 'override' or 'final' specifier. |
1212
| test.cpp:95:11:95:14 | ~C13 | Member function '~C13' overrides a base function but uses 'virtual' specifier. |
13-
| test.cpp:95:11:95:14 | ~C13 | Member function '~C13' uses redundant 'virtual' and 'final' specifiers together. |
13+
| test.cpp:95:11:95:14 | ~C13 | Member function '~C13' uses redundant 'virtual' and 'override' specifiers together. |

cpp/misra/test/rules/RULE-15-0-2/InvalidSignatureForSpecialMemberFunction.expected

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,17 @@
77
| test.cpp:92:3:92:22 | NonCompliantVolatile | Copy constructor on type $@ should take const reference to class or struct type. | test.cpp:89:7:89:26 | NonCompliantVolatile | NonCompliantVolatile |
88
| test.cpp:100:3:100:11 | operator= | Copy assignment operator on type $@ should not be virtual. | test.cpp:96:7:96:25 | NonCompliantVirtual | NonCompliantVirtual |
99
| test.cpp:107:3:107:11 | operator= | Copy assignment operator on type $@ should take const reference to class or struct type. | test.cpp:103:7:103:29 | NonCompliantCopyByValue | NonCompliantCopyByValue |
10-
| test.cpp:113:3:113:30 | NonCompliantDefaultArguments | Move constructor on type $@ too many parameters. | test.cpp:110:7:110:34 | NonCompliantDefaultArguments | NonCompliantDefaultArguments |
10+
| test.cpp:113:3:113:30 | NonCompliantDefaultArguments | Move constructor on type $@ has too many parameters. | test.cpp:110:7:110:34 | NonCompliantDefaultArguments | NonCompliantDefaultArguments |
1111
| test.cpp:158:3:158:20 | NonCompliantStruct | Copy constructor on type $@ should take const reference to class or struct type. | test.cpp:155:8:155:25 | NonCompliantStruct | NonCompliantStruct |
12+
| test.cpp:185:27:185:35 | operator= | Copy assignment operator on type $@ should return void or lvalue reference to class or struct type. | test.cpp:183:7:183:29 | AssignmentReturnByValue | AssignmentReturnByValue |
13+
| test.cpp:187:27:187:35 | operator= | Move assignment operator on type $@ should return void or lvalue reference to class or struct type. | test.cpp:183:7:183:29 | AssignmentReturnByValue | AssignmentReturnByValue |
14+
| test.cpp:193:31:193:39 | operator= | Copy assignment operator on type $@ should return void or lvalue reference to class or struct type. | test.cpp:191:7:191:31 | AssignmentReturnRvalueRef | AssignmentReturnRvalueRef |
15+
| test.cpp:195:31:195:39 | operator= | Move assignment operator on type $@ should return void or lvalue reference to class or struct type. | test.cpp:191:7:191:31 | AssignmentReturnRvalueRef | AssignmentReturnRvalueRef |
16+
| test.cpp:202:15:202:23 | operator= | Copy assignment operator on type $@ should return void or lvalue reference to class or struct type. | test.cpp:200:7:200:32 | WrongClassAssignmentReturn | WrongClassAssignmentReturn |
17+
| test.cpp:204:15:204:23 | operator= | Move assignment operator on type $@ should return void or lvalue reference to class or struct type. | test.cpp:200:7:200:32 | WrongClassAssignmentReturn | WrongClassAssignmentReturn |
18+
| test.cpp:210:7:210:15 | operator= | Copy assignment operator on type $@ should return void or lvalue reference to class or struct type. | test.cpp:208:7:208:22 | ScalarReturnType | ScalarReturnType |
19+
| test.cpp:212:7:212:15 | operator= | Move assignment operator on type $@ should return void or lvalue reference to class or struct type. | test.cpp:208:7:208:22 | ScalarReturnType | ScalarReturnType |
20+
| test.cpp:219:3:219:11 | operator= | Copy assignment operator on type $@ should return void or lvalue reference to class or struct type. | test.cpp:216:7:216:23 | PointerReturnType | PointerReturnType |
21+
| test.cpp:220:22:220:30 | operator= | Move assignment operator on type $@ should return void or lvalue reference to class or struct type. | test.cpp:216:7:216:23 | PointerReturnType | PointerReturnType |
22+
| test.cpp:226:8:226:16 | operator= | Copy assignment operator on type $@ should be lvalue-qualified. | test.cpp:224:7:224:34 | RvalueRefQualifiedAssignment | RvalueRefQualifiedAssignment |
23+
| test.cpp:228:8:228:16 | operator= | Move assignment operator on type $@ should be lvalue-qualified. | test.cpp:224:7:224:34 | RvalueRefQualifiedAssignment | RvalueRefQualifiedAssignment |

cpp/misra/test/rules/RULE-15-0-2/test.cpp

Lines changed: 90 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@
88
class CompliantClass {
99
public:
1010
CompliantClass() = default;
11-
CompliantClass(CompliantClass const &); // COMPLIANT
12-
CompliantClass(CompliantClass &&) noexcept; // COMPLIANT
13-
CompliantClass &operator=(CompliantClass const &) &; // COMPLIANT
14-
CompliantClass &operator=(CompliantClass &&) &noexcept; // COMPLIANT
11+
CompliantClass(CompliantClass const &); // COMPLIANT
12+
CompliantClass(CompliantClass &&) noexcept; // COMPLIANT
13+
CompliantClass &operator=(CompliantClass const &) &; // COMPLIANT
14+
CompliantClass &operator=(CompliantClass &&) & noexcept; // COMPLIANT
1515
};
1616

1717
class CompliantWithAlternatives {
@@ -22,9 +22,9 @@ class CompliantWithAlternatives {
2222
explicit constexpr CompliantWithAlternatives(
2323
CompliantWithAlternatives &&) noexcept; // COMPLIANT
2424
constexpr CompliantWithAlternatives &
25-
operator=(const CompliantWithAlternatives &) &noexcept; // COMPLIANT
25+
operator=(const CompliantWithAlternatives &) & noexcept; // COMPLIANT
2626
constexpr CompliantWithAlternatives &
27-
operator=(CompliantWithAlternatives &&) &noexcept; // COMPLIANT
27+
operator=(CompliantWithAlternatives &&) & noexcept; // COMPLIANT
2828
};
2929

3030
class CompliantVoidReturn {
@@ -35,7 +35,7 @@ class CompliantVoidReturn {
3535
void
3636
operator=(CompliantVoidReturn const &) &; // COMPLIANT - void return allowed
3737
void operator=(
38-
CompliantVoidReturn &&) &noexcept; // COMPLIANT - void return allowed
38+
CompliantVoidReturn &&) & noexcept; // COMPLIANT - void return allowed
3939
};
4040

4141
// Non-compliant examples
@@ -146,15 +146,93 @@ class DeletedOperations {
146146
struct CompliantStruct {
147147
public:
148148
CompliantStruct() = default;
149-
CompliantStruct(CompliantStruct const &); // COMPLIANT
150-
CompliantStruct(CompliantStruct &&) noexcept; // COMPLIANT
151-
CompliantStruct &operator=(CompliantStruct const &) &; // COMPLIANT
152-
CompliantStruct &operator=(CompliantStruct &&) &noexcept; // COMPLIANT
149+
CompliantStruct(CompliantStruct const &); // COMPLIANT
150+
CompliantStruct(CompliantStruct &&) noexcept; // COMPLIANT
151+
CompliantStruct &operator=(CompliantStruct const &) &; // COMPLIANT
152+
CompliantStruct &operator=(CompliantStruct &&) & noexcept; // COMPLIANT
153153
};
154154

155155
struct NonCompliantStruct {
156156
public:
157157
NonCompliantStruct() = default;
158158
NonCompliantStruct(
159159
NonCompliantStruct &); // NON_COMPLIANT - non-const reference
160-
};
160+
};
161+
162+
// Static error case. This would be debatably non-compliant if it were not a
163+
// static error, because by pure specificationrules, it is not a copy or move
164+
// constructor. OTOH, clang's error states that it's a malformed copy
165+
// constructor. Overall, there's a case to be made for compliant and
166+
// non-compliant, but either way we cannot test it here.
167+
// struct NonLvalueRefConstructor {
168+
// public:
169+
// NonLvalueRefConstructor(NonLvalueRefConstructor n) noexcept; // COMPLIANT
170+
//}
171+
172+
struct NonRvalueRefConstructorAndAssignment {
173+
public:
174+
// This is a static error just like `NonLvalueRefConstructor`, for similar
175+
// reasons.
176+
// NonRvalueRefConstructorAndAssignment(NonRvalueRefConstructorAndAssignment
177+
// n) noexcept;
178+
179+
// The following is already tested in `NonCompliantCopyByValue`
180+
// void operator=(NonRvalueRefConstructorAndAssignment n);
181+
};
182+
183+
class AssignmentReturnByValue {
184+
public:
185+
AssignmentReturnByValue operator=(
186+
AssignmentReturnByValue const &) &; // NON_COMPLIANT - wrong return type
187+
AssignmentReturnByValue operator=(AssignmentReturnByValue &&)
188+
& noexcept; // NON_COMPLIANT - wrong return type
189+
};
190+
191+
class AssignmentReturnRvalueRef {
192+
public:
193+
AssignmentReturnRvalueRef &&operator=(
194+
AssignmentReturnRvalueRef const &) &; // NON_COMPLIANT - wrong return type
195+
AssignmentReturnRvalueRef &&operator=(AssignmentReturnRvalueRef &&)
196+
& noexcept; // NON_COMPLIANT - wrong return type
197+
};
198+
199+
class WrongClass;
200+
class WrongClassAssignmentReturn {
201+
public:
202+
WrongClass &operator=(WrongClassAssignmentReturn const &)
203+
&; // NON_COMPLIANT - wrong return type
204+
WrongClass &operator=(WrongClassAssignmentReturn &&)
205+
& noexcept; // NON_COMPLIANT - wrong return type
206+
};
207+
208+
class ScalarReturnType {
209+
public:
210+
int operator=(
211+
ScalarReturnType const &) &; // NON_COMPLIANT - wrong return type
212+
int operator=(
213+
ScalarReturnType &&) & noexcept; // NON_COMPLIANT - wrong return type
214+
};
215+
216+
class PointerReturnType {
217+
public:
218+
PointerReturnType *
219+
operator=(PointerReturnType const &) &; // NON_COMPLIANT - wrong return type
220+
PointerReturnType *operator=(
221+
PointerReturnType &&) & noexcept; // NON_COMPLIANT - wrong return type
222+
};
223+
224+
class RvalueRefQualifiedAssignment {
225+
public:
226+
void operator=(const RvalueRefQualifiedAssignment &)
227+
&&; // NON_COMPLIANT - rvalue ref qualified
228+
void operator=(RvalueRefQualifiedAssignment &&)
229+
&& noexcept; // NON_COMPLIANT - rvalue ref qualified
230+
};
231+
232+
// It is a static error to declare assignment operators as `explicit`.
233+
// class ExplicitAssignmentOperators {
234+
// public:
235+
// explicit void operator=(const ExplicitAssignmentOperators &) &; //
236+
// NON_COMPLIANT explicit void operator=(ExplicitAssignmentOperators &&) &; //
237+
// NON_COMPLIANT
238+
// };

0 commit comments

Comments
 (0)