Skip to content

Commit 603244e

Browse files
committed
Add RULE-6-8-4
1 parent b4af299 commit 603244e

File tree

4 files changed

+172
-0
lines changed

4 files changed

+172
-0
lines changed
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/**
2+
* @id cpp/misra/member-functions-refqualified
3+
* @name RULE-6-8-4: Member functions returning references to their object should be refqualified appropriately
4+
* @description Member functions that return references to temporary objects (or subobjects) can
5+
* lead to dangling pointers.
6+
* @kind problem
7+
* @precision very-high
8+
* @problem.severity error
9+
* @tags external/misra/id/rule-6-8-4
10+
* correctness
11+
* scope/single-translation-unit
12+
* external/misra/enforcement/decidable
13+
* external/misra/obligation/advisory
14+
*/
15+
16+
import cpp
17+
import codingstandards.cpp.misra
18+
import codingstandards.cpp.types.Compatible
19+
import codingstandards.cpp.Operator
20+
21+
abstract class MembersReturningObjectOrSubobject extends MemberFunction {
22+
string toString() { result = "Members returning object or subobject" }
23+
}
24+
25+
class MembersReturningObject extends MembersReturningObjectOrSubobject {
26+
MembersReturningObject() {
27+
exists(ReturnStmt r, ThisExpr t |
28+
r.getEnclosingFunction() = this and
29+
(
30+
r.getAChild*() = t
31+
or
32+
exists(PointerDereferenceExpr p |
33+
p.getAChild*() = t and
34+
r.getAChild*() = p
35+
)
36+
) and
37+
t.getActualType().stripType() = this.getDeclaringType()
38+
)
39+
}
40+
}
41+
42+
class MembersReturningSubObject extends MembersReturningObjectOrSubobject {
43+
MembersReturningSubObject() {
44+
exists(ReturnStmt r, FieldSubObjectDeclaration field |
45+
r.getEnclosingFunction() = this and
46+
(
47+
r.getAChild*() = field.(Field).getAnAccess()
48+
or
49+
exists(PointerDereferenceExpr p |
50+
p.getAChild*() = field.(Field).getAnAccess() and
51+
r.getAChild*() = p
52+
)
53+
) and
54+
field.(Field).getDeclaringType() = this.getDeclaringType()
55+
)
56+
}
57+
}
58+
59+
predicate relevantTypes(Type a, Type b) {
60+
exists(MembersReturningObject f, MemberFunction overload |
61+
f.getAnOverload() = overload and
62+
exists(int i |
63+
f.getParameter(i).getType() = a and
64+
overload.getParameter(i).getType() = b
65+
)
66+
)
67+
}
68+
69+
class AppropriatelyQualified extends MembersReturningObjectOrSubobject {
70+
AppropriatelyQualified() {
71+
//non-const-lvalue-ref-qualified
72+
this.isLValueRefQualified() and
73+
not this.hasSpecifier("const")
74+
or
75+
//const-lvalue-ref-qualified
76+
this.isLValueRefQualified() and
77+
this.hasSpecifier("const") and
78+
//and overload exists that is rvalue-ref-qualified
79+
exists(MemberFunction overload |
80+
this.getAnOverload() = overload and
81+
overload.isRValueRefQualified() and
82+
//and has same param list
83+
forall(int i | exists([this, overload].getParameter(i)) |
84+
TypeEquivalence<TypesCompatibleConfig, relevantTypes/2>::equalTypes(this.getParameter(i)
85+
.getType(), overload.getParameter(i).getType())
86+
)
87+
)
88+
}
89+
}
90+
91+
/**
92+
* Fields that are not reference type can be subobjects
93+
*/
94+
class FieldSubObjectDeclaration extends Declaration {
95+
FieldSubObjectDeclaration() {
96+
not this.getADeclarationEntry().getType() instanceof ReferenceType and
97+
this instanceof Field
98+
}
99+
}
100+
101+
class DefaultedAssignmentOperator extends AssignmentOperator {
102+
DefaultedAssignmentOperator() { this.isDefaulted() }
103+
}
104+
105+
from MembersReturningObjectOrSubobject f
106+
where
107+
not isExcluded(f, Declarations5Package::memberFunctionsRefqualifiedQuery()) and
108+
not f instanceof AppropriatelyQualified and
109+
not f instanceof DefaultedAssignmentOperator
110+
select f, "Member function is not properly ref qualified."
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
| test.cpp:10:7:10:11 | Members returning object or subobject | Member function is not properly ref qualified. |
2+
| test.cpp:12:14:12:20 | Members returning object or subobject | Member function is not properly ref qualified. |
3+
| test.cpp:24:12:24:23 | Members returning object or subobject | Member function is not properly ref qualified. |
4+
| test.cpp:28:6:28:18 | Members returning object or subobject | Member function is not properly ref qualified. |
5+
| test.cpp:42:16:42:16 | Members returning object or subobject | Member function is not properly ref qualified. |
6+
| test.cpp:42:16:42:16 | Members returning object or subobject | Member function is not properly ref qualified. |
7+
| test.cpp:42:16:42:16 | Members returning object or subobject | Member function is not properly ref qualified. |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
rules/RULE-6-8-4/MemberFunctionsRefqualified.ql
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
struct A {
2+
int a;
3+
int &b;
4+
5+
int &geta() & { return a; } // COMPLIANT
6+
7+
int const &geta2() const & { // COMPLIANT -- due to overload below
8+
return a;
9+
}
10+
int geta2() && { return a; } // NON_COMPLIANT
11+
12+
int const &getabad() const & { // NON_COMPLIANT -- no overload provided
13+
return a;
14+
}
15+
16+
int getb() && { return b; } // COMPLIANT -- b is not a subobject
17+
18+
A const *getstruct() const & { // COMPLIANT -- due to overload below
19+
return this;
20+
}
21+
22+
A getstruct() const && = delete;
23+
24+
A const *getstructbad() const & { // NON_COMPLIANT -- no overload provided
25+
return this;
26+
}
27+
28+
A &getstructbad2() { return *this; } // NON_COMPLIANT
29+
};
30+
31+
class C {
32+
C *f() { // COMPLIANT -- this is not explicitly designated therefore this is
33+
// not
34+
// relevant for this rule
35+
C *thisclass = this;
36+
return thisclass;
37+
}
38+
};
39+
40+
struct Templ {
41+
template <typename T>
42+
Templ const *f(T) const & { // NON_COMPLIANT -- for an instantiation below
43+
return this;
44+
}
45+
46+
void f(int) const && = delete;
47+
};
48+
49+
void f(int p, float p1) {
50+
Templ t;
51+
t.f(p);
52+
t.f(p1); // instantiation that causes issue due to parameter list type meaning
53+
// there is no overload
54+
}

0 commit comments

Comments
 (0)