Skip to content

Commit b18a89e

Browse files
Merge pull request github#174 from github/jeongsoolee09/misra6-1_and_misra6-2
Initiate Types Rule Package and Implement MISRA RULE-6-1 and RULE-6-2
2 parents 3d39c53 + 3e96c5f commit b18a89e

13 files changed

+716
-2
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/**
2+
* @id c/misra/bit-fields-shall-only-be-declared-with-an-appropriate-type
3+
* @name RULE-6-1: Bit-fields shall only be declared with an appropriate type
4+
* @description Declaring bit-fields on types other than appropriate ones causes
5+
* implementation-specific or undefined behavior.
6+
* @kind problem
7+
* @precision very-high
8+
* @problem.severity error
9+
* @tags external/misra/id/rule-6-1
10+
* external/misra/obligation/required
11+
*/
12+
13+
import cpp
14+
import codingstandards.c.misra
15+
16+
predicate isAppropriatePrimitive(Type type) {
17+
/* An appropriate primitive types to which a bit-field can be declared. */
18+
type instanceof IntType and
19+
(
20+
type.(IntegralType).isExplicitlySigned() or
21+
type.(IntegralType).isExplicitlyUnsigned()
22+
)
23+
or
24+
type instanceof BoolType
25+
}
26+
27+
from BitField bitField
28+
where
29+
not isExcluded(bitField,
30+
BitfieldTypesPackage::bitFieldsShallOnlyBeDeclaredWithAnAppropriateTypeQuery()) and
31+
/* A violation would neither be an appropriate primitive type nor an appropriate typedef. */
32+
not isAppropriatePrimitive(bitField.getType().resolveTypedefs())
33+
select bitField, "Bit-field " + bitField + " is declared on type " + bitField.getType() + "."
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/**
2+
* @id c/misra/single-bit-named-bit-fields-of-a-signed-type
3+
* @name RULE-6-2: Single-bit named bit fields shall not be of a signed type
4+
* @description Single-bit named bit fields carry no useful information and therefore should not be
5+
* declared or used.
6+
* @kind problem
7+
* @precision very-high
8+
* @problem.severity error
9+
* @tags external/misra/id/rule-6-2
10+
* external/misra/obligation/required
11+
*/
12+
13+
import cpp
14+
import codingstandards.c.misra
15+
16+
/*
17+
* Check if the DECLARED bit-fields is a single bit, because Rule 6.2 also intends to catch confusion on the programmers' part. Consider:
18+
*
19+
* struct S {
20+
* int32_t x: 1;
21+
* }
22+
*
23+
* In this case, field x is essentially of 32 bits, but is declared as 1 bit and its type int32_t is signed. Therefore, it indicates confusion by the programmer, which is exactly what this rule intends to find.
24+
*/
25+
26+
from BitField bitField
27+
where
28+
not isExcluded(bitField, BitfieldTypesPackage::singleBitNamedBitFieldsOfASignedTypeQuery()) and
29+
bitField.getDeclaredNumBits() = 1 and // Single-bit,
30+
not bitField.isAnonymous() and // named,
31+
bitField.getType().(IntegralType).isSigned() // but its type is signed.
32+
select bitField,
33+
"Single-bit bit-field named " + bitField.toString() + " has a signed type " + bitField.getType() +
34+
"."
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
| test.c:6:7:6:8 | x1 | Bit-field x1 is declared on type int. |
2+
| test.c:10:15:10:16 | x5 | Bit-field x5 is declared on type signed long. |
3+
| test.c:12:15:12:16 | x6 | Bit-field x6 is declared on type signed char. |
4+
| test.c:14:14:14:15 | x7 | Bit-field x7 is declared on type Color. |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
rules/RULE-6-1/BitFieldsShallOnlyBeDeclaredWithAnAppropriateType.ql

c/misra/test/rules/RULE-6-1/test.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
typedef unsigned int UINT16;
2+
3+
enum Color { R, G, B };
4+
5+
struct SampleStruct {
6+
int x1 : 2; // NON_COMPLIANT - not explicitly signed or unsigned
7+
unsigned int x2 : 2; // COMPILANT - explicitly unsigned
8+
signed int x3 : 2; // COMPILANT - explicitly signed
9+
UINT16 x4 : 2; // COMPLIANT - type alias resolves to a compliant type
10+
signed long x5 : 2; // NON_COMPLIANT - cannot declare bit field for long, even
11+
// if it's signed
12+
signed char x6 : 2; // NON_COMPILANT - cannot declare bit field for char, even
13+
// if it's signed
14+
enum Color x7 : 3; // NON_COMPILANT - cannot declare bit field for enum
15+
} sample_struct;
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
| test.c:4:7:4:8 | x1 | Single-bit bit-field named x1 has a signed type int. |
2+
| test.c:7:14:7:15 | x2 | Single-bit bit-field named x2 has a signed type signed int. |
3+
| test.c:9:7:9:8 | x3 | Single-bit bit-field named x3 has a signed type signed char. |
4+
| test.c:11:7:11:8 | x4 | Single-bit bit-field named x4 has a signed type signed short. |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
rules/RULE-6-2/SingleBitNamedBitFieldsOfASignedType.ql

c/misra/test/rules/RULE-6-2/test.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#include <stdint.h>
2+
3+
struct SampleStruct {
4+
int x1 : 1; // NON_COMPILANT: very likely be signed, but if it's not, the
5+
// query will automatically handle it since we use signed(), not
6+
// isExplicitlySigned().
7+
signed int x2 : 1; // NON_COMPILANT: single-bit named field with a signed type
8+
signed char
9+
x3 : 1; // NON_COMPILANT: single-bit named field with a signed type
10+
signed short
11+
x4 : 1; // NON_COMPILANT: single-bit named field with a signed type
12+
unsigned int
13+
x5 : 1; // COMPILANT: single-bit named field but with an unsigned type
14+
signed int x6 : 2; // COMPILANT: named field with a signed type but declared
15+
// to carry more than 1 bit
16+
signed char : 1; // COMPILANT: single-bit bit-field but unnamed
17+
} sample_struct;
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/
2+
import cpp
3+
import RuleMetadata
4+
import codingstandards.cpp.exclusions.RuleMetadata
5+
6+
newtype BitfieldTypesQuery =
7+
TBitFieldsShallOnlyBeDeclaredWithAnAppropriateTypeQuery() or
8+
TSingleBitNamedBitFieldsOfASignedTypeQuery()
9+
10+
predicate isBitfieldTypesQueryMetadata(Query query, string queryId, string ruleId, string category) {
11+
query =
12+
// `Query` instance for the `bitFieldsShallOnlyBeDeclaredWithAnAppropriateType` query
13+
BitfieldTypesPackage::bitFieldsShallOnlyBeDeclaredWithAnAppropriateTypeQuery() and
14+
queryId =
15+
// `@id` for the `bitFieldsShallOnlyBeDeclaredWithAnAppropriateType` query
16+
"c/misra/bit-fields-shall-only-be-declared-with-an-appropriate-type" and
17+
ruleId = "RULE-6-1" and
18+
category = "required"
19+
or
20+
query =
21+
// `Query` instance for the `singleBitNamedBitFieldsOfASignedType` query
22+
BitfieldTypesPackage::singleBitNamedBitFieldsOfASignedTypeQuery() and
23+
queryId =
24+
// `@id` for the `singleBitNamedBitFieldsOfASignedType` query
25+
"c/misra/single-bit-named-bit-fields-of-a-signed-type" and
26+
ruleId = "RULE-6-2" and
27+
category = "required"
28+
}
29+
30+
module BitfieldTypesPackage {
31+
Query bitFieldsShallOnlyBeDeclaredWithAnAppropriateTypeQuery() {
32+
//autogenerate `Query` type
33+
result =
34+
// `Query` type for `bitFieldsShallOnlyBeDeclaredWithAnAppropriateType` query
35+
TQueryC(TBitfieldTypesPackageQuery(TBitFieldsShallOnlyBeDeclaredWithAnAppropriateTypeQuery()))
36+
}
37+
38+
Query singleBitNamedBitFieldsOfASignedTypeQuery() {
39+
//autogenerate `Query` type
40+
result =
41+
// `Query` type for `singleBitNamedBitFieldsOfASignedType` query
42+
TQueryC(TBitfieldTypesPackageQuery(TSingleBitNamedBitFieldsOfASignedTypeQuery()))
43+
}
44+
}

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import cpp
33
import codingstandards.cpp.exclusions.RuleMetadata
44
//** Import packages for this language **/
55
import Banned
6+
import BitfieldTypes
67
import Concurrency1
78
import Concurrency2
89
import Concurrency3
@@ -47,6 +48,7 @@ import Syntax
4748
/** The TQuery type representing this language * */
4849
newtype TCQuery =
4950
TBannedPackageQuery(BannedQuery q) or
51+
TBitfieldTypesPackageQuery(BitfieldTypesQuery q) or
5052
TConcurrency1PackageQuery(Concurrency1Query q) or
5153
TConcurrency2PackageQuery(Concurrency2Query q) or
5254
TConcurrency3PackageQuery(Concurrency3Query q) or
@@ -91,6 +93,7 @@ newtype TCQuery =
9193
/** The metadata predicate * */
9294
predicate isQueryMetadata(Query query, string queryId, string ruleId, string category) {
9395
isBannedQueryMetadata(query, queryId, ruleId, category) or
96+
isBitfieldTypesQueryMetadata(query, queryId, ruleId, category) or
9497
isConcurrency1QueryMetadata(query, queryId, ruleId, category) or
9598
isConcurrency2QueryMetadata(query, queryId, ruleId, category) or
9699
isConcurrency3QueryMetadata(query, queryId, ruleId, category) or

0 commit comments

Comments
 (0)