Skip to content

Commit cbc7d53

Browse files
Merge pull request #979 from github/michaelrfairhurst/preconditions-rule-8-2-9
Implement RULE-8-2-9 - PolymorphicClassTypeExpressionInTypeid
2 parents 33bc0b1 + 0fc649c commit cbc7d53

File tree

8 files changed

+167
-1
lines changed

8 files changed

+167
-1
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/
2+
import cpp
3+
import RuleMetadata
4+
import codingstandards.cpp.exclusions.RuleMetadata
5+
6+
newtype Preconditions1Query = TPolymorphicClassTypeExpressionInTypeidQuery()
7+
8+
predicate isPreconditions1QueryMetadata(Query query, string queryId, string ruleId, string category) {
9+
query =
10+
// `Query` instance for the `polymorphicClassTypeExpressionInTypeid` query
11+
Preconditions1Package::polymorphicClassTypeExpressionInTypeidQuery() and
12+
queryId =
13+
// `@id` for the `polymorphicClassTypeExpressionInTypeid` query
14+
"cpp/misra/polymorphic-class-type-expression-in-typeid" and
15+
ruleId = "RULE-8-2-9" and
16+
category = "required"
17+
}
18+
19+
module Preconditions1Package {
20+
Query polymorphicClassTypeExpressionInTypeidQuery() {
21+
//autogenerate `Query` type
22+
result =
23+
// `Query` type for `polymorphicClassTypeExpressionInTypeid` query
24+
TQueryCPP(TPreconditions1PackageQuery(TPolymorphicClassTypeExpressionInTypeidQuery()))
25+
}
26+
}

cpp/common/src/codingstandards/cpp/exclusions/cpp/RuleMetadata.qll

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ import Operators
4444
import OrderOfEvaluation
4545
import OutOfBounds
4646
import Pointers
47+
import Preconditions1
4748
import Representation
4849
import Scope
4950
import SideEffects1
@@ -103,6 +104,7 @@ newtype TCPPQuery =
103104
TOrderOfEvaluationPackageQuery(OrderOfEvaluationQuery q) or
104105
TOutOfBoundsPackageQuery(OutOfBoundsQuery q) or
105106
TPointersPackageQuery(PointersQuery q) or
107+
TPreconditions1PackageQuery(Preconditions1Query q) or
106108
TRepresentationPackageQuery(RepresentationQuery q) or
107109
TScopePackageQuery(ScopeQuery q) or
108110
TSideEffects1PackageQuery(SideEffects1Query q) or
@@ -162,6 +164,7 @@ predicate isQueryMetadata(Query query, string queryId, string ruleId, string cat
162164
isOrderOfEvaluationQueryMetadata(query, queryId, ruleId, category) or
163165
isOutOfBoundsQueryMetadata(query, queryId, ruleId, category) or
164166
isPointersQueryMetadata(query, queryId, ruleId, category) or
167+
isPreconditions1QueryMetadata(query, queryId, ruleId, category) or
165168
isRepresentationQueryMetadata(query, queryId, ruleId, category) or
166169
isScopeQueryMetadata(query, queryId, ruleId, category) or
167170
isSideEffects1QueryMetadata(query, queryId, ruleId, category) or
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/**
2+
* @id cpp/misra/polymorphic-class-type-expression-in-typeid
3+
* @name RULE-8-2-9: The operand to typeid shall not be an expression of polymorphic class type
4+
* @description It is unclear whether a typeid expression will be evaluated at runtime or compile
5+
* time when its static type is a polymorphic class type.
6+
* @kind problem
7+
* @precision very-high
8+
* @problem.severity error
9+
* @tags external/misra/id/rule-8-2-9
10+
* scope/single-translation-unit
11+
* readability
12+
* correctness
13+
* performance
14+
* external/misra/enforcement/decidable
15+
* external/misra/obligation/required
16+
*/
17+
18+
import cpp
19+
import codingstandards.cpp.misra
20+
21+
from TypeidOperator typeid, Expr operand, Class polymorphicClass
22+
where
23+
not isExcluded(typeid, Preconditions1Package::polymorphicClassTypeExpressionInTypeidQuery()) and
24+
operand = typeid.getExpr().getFullyConverted() and
25+
polymorphicClass = operand.getType().getUnderlyingType() and
26+
polymorphicClass.isPolymorphic()
27+
select typeid, "Use of 'typeid' with $@ of polymorphic class type $@.", operand, "expression",
28+
polymorphicClass, polymorphicClass.getName()
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
| test.cpp:41:30:41:39 | typeid ... | Use of 'typeid' with $@ of polymorphic class type $@. | test.cpp:41:37:41:38 | l1 | expression | test.cpp:7:8:7:24 | PolymorphicStruct | PolymorphicStruct |
2+
| test.cpp:42:30:42:40 | typeid ... | Use of 'typeid' with $@ of polymorphic class type $@. | test.cpp:42:37:42:39 | * ... | expression | test.cpp:7:8:7:24 | PolymorphicStruct | PolymorphicStruct |
3+
| test.cpp:43:30:43:39 | typeid ... | Use of 'typeid' with $@ of polymorphic class type $@. | test.cpp:43:37:43:38 | l3 | expression | test.cpp:11:8:11:25 | DerivedPolymorphic | DerivedPolymorphic |
4+
| test.cpp:44:30:44:39 | typeid ... | Use of 'typeid' with $@ of polymorphic class type $@. | test.cpp:44:37:44:38 | l4 | expression | test.cpp:15:7:15:22 | PolymorphicClass | PolymorphicClass |
5+
| test.cpp:57:30:57:39 | typeid ... | Use of 'typeid' with $@ of polymorphic class type $@. | test.cpp:57:37:57:38 | (reference dereference) | expression | test.cpp:7:8:7:24 | PolymorphicStruct | PolymorphicStruct |
6+
| test.cpp:61:30:61:56 | typeid ... | Use of 'typeid' with $@ of polymorphic class type $@. | test.cpp:61:37:61:55 | temporary object | expression | test.cpp:7:8:7:24 | PolymorphicStruct | PolymorphicStruct |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
rules/RULE-8-2-9/PolymorphicClassTypeExpressionInTypeid.ql
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
#include <typeinfo>
2+
3+
struct NonPolymorphic {
4+
void foo() {}
5+
};
6+
7+
struct PolymorphicStruct {
8+
virtual void foo() {}
9+
};
10+
11+
struct DerivedPolymorphic : public PolymorphicStruct {
12+
void foo() override {}
13+
};
14+
15+
class PolymorphicClass {
16+
public:
17+
virtual ~PolymorphicClass() = default;
18+
virtual void method() {}
19+
};
20+
21+
void test_typeid_with_type_id() {
22+
const std::type_info &l1 = typeid(NonPolymorphic); // COMPLIANT
23+
const std::type_info &l2 = typeid(PolymorphicStruct); // COMPLIANT
24+
const std::type_info &l3 = typeid(PolymorphicClass); // COMPLIANT
25+
}
26+
27+
void test_typeid_with_non_polymorphic_expression() {
28+
NonPolymorphic l1;
29+
NonPolymorphic *l2 = &l1;
30+
31+
const std::type_info &l3 = typeid(l1); // COMPLIANT
32+
const std::type_info &l4 = typeid(*l2); // COMPLIANT
33+
}
34+
35+
void test_typeid_with_polymorphic_expression() {
36+
PolymorphicStruct l1;
37+
PolymorphicStruct *l2 = &l1;
38+
DerivedPolymorphic l3;
39+
PolymorphicClass l4;
40+
41+
const std::type_info &l5 = typeid(l1); // NON_COMPLIANT
42+
const std::type_info &l6 = typeid(*l2); // NON_COMPLIANT
43+
const std::type_info &l7 = typeid(l3); // NON_COMPLIANT
44+
const std::type_info &l8 = typeid(l4); // NON_COMPLIANT
45+
}
46+
47+
void test_typeid_with_polymorphic_function_call() {
48+
PolymorphicStruct l1;
49+
50+
const std::type_info &l2 = typeid(l1.foo()); // COMPLIANT
51+
}
52+
53+
void test_typeid_with_reference_to_polymorphic() {
54+
PolymorphicStruct l1;
55+
PolymorphicStruct &l2 = l1;
56+
57+
const std::type_info &l3 = typeid(l2); // NON_COMPLIANT
58+
}
59+
60+
void test_typeid_with_polymorphic_temporary() {
61+
const std::type_info &l1 = typeid(PolymorphicStruct{}); // NON_COMPLIANT
62+
}
63+
64+
void test_typeid_with_polymorphic_pointer() {
65+
NonPolymorphic *l1 = new NonPolymorphic();
66+
PolymorphicStruct *l2 = new PolymorphicStruct();
67+
DerivedPolymorphic *l3 = new DerivedPolymorphic();
68+
PolymorphicClass *l4 = new PolymorphicClass();
69+
70+
// Pointer types are not polymorphic themselves
71+
const std::type_info &l5 = typeid(l1); // COMPLIANT
72+
const std::type_info &l6 = typeid(l2); // COMPLIANT
73+
const std::type_info &l7 = typeid(l3); // COMPLIANT
74+
const std::type_info &l8 = typeid(l4); // COMPLIANT
75+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"MISRA-C++-2023": {
3+
"RULE-8-2-9": {
4+
"properties": {
5+
"enforcement": "decidable",
6+
"obligation": "required"
7+
},
8+
"queries": [
9+
{
10+
"description": "It is unclear whether a typeid expression will be evaluated at runtime or compile time when its static type is a polymorphic class type.",
11+
"kind": "problem",
12+
"name": "The operand to typeid shall not be an expression of polymorphic class type",
13+
"precision": "very-high",
14+
"severity": "error",
15+
"short_name": "PolymorphicClassTypeExpressionInTypeid",
16+
"tags": [
17+
"scope/single-translation-unit",
18+
"readability",
19+
"correctness",
20+
"performance"
21+
]
22+
}
23+
],
24+
"title": "The operand to typeid shall not be an expression of polymorphic class type"
25+
}
26+
}
27+
}

rules.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -890,7 +890,7 @@ cpp,MISRA-C++-2023,RULE-8-2-5,Yes,Required,Decidable,Single Translation Unit,rei
890890
cpp,MISRA-C++-2023,RULE-8-2-6,Yes,Required,Decidable,Single Translation Unit,"An object with integral, enumerated, or pointer to void type shall not be cast to a pointer type","RULE-11-6, INT36-C",Conversions2,Easy,
891891
cpp,MISRA-C++-2023,RULE-8-2-7,Yes,Advisory,Decidable,Single Translation Unit,A cast should not convert a pointer type to an integral type,"RULE-11-6, INT36-C",Conversions2,Easy,
892892
cpp,MISRA-C++-2023,RULE-8-2-8,Yes,Required,Decidable,Single Translation Unit,An object pointer type shall not be cast to an integral type other than std::uintptr_t or std::intptr_t,"RULE-11-6, INT36-C",Conversions2,Easy,
893-
cpp,MISRA-C++-2023,RULE-8-2-9,Yes,Required,Decidable,Single Translation Unit,The operand to typeid shall not be an expression of polymorphic class type,,Preconditions,Easy,
893+
cpp,MISRA-C++-2023,RULE-8-2-9,Yes,Required,Decidable,Single Translation Unit,The operand to typeid shall not be an expression of polymorphic class type,,Preconditions1,Easy,
894894
cpp,MISRA-C++-2023,RULE-8-2-10,Yes,Required,Undecidable,System,"Functions shall not call themselves, either directly or indirectly",A7-5-2,ImportMisra23,Import,
895895
cpp,MISRA-C++-2023,RULE-8-2-11,Yes,Required,Decidable,Single Translation Unit,An argument passed via ellipsis shall have an appropriate type,,Preconditions,Easy,
896896
cpp,MISRA-C++-2023,RULE-8-3-1,Yes,Advisory,Decidable,Single Translation Unit,The built-in unary - operator should not be applied to an expression of unsigned type,M5-3-2,ImportMisra23,Import,

0 commit comments

Comments
 (0)