Skip to content

Commit 177293e

Browse files
authored
Merge pull request #564 from rvermeulen/rvermeulen/fix-rule-6-1
Add support for implementation specific bitfield types
2 parents b31377d + 570dd80 commit 177293e

13 files changed

+99
-12
lines changed

c/misra/src/rules/RULE-6-1/BitFieldsShallOnlyBeDeclaredWithAnAppropriateType.ql

+19-8
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,33 @@
1212

1313
import cpp
1414
import codingstandards.c.misra
15+
import codingstandards.cpp.Compiler
1516

16-
predicate isAppropriatePrimitive(Type type) {
17-
/* An appropriate primitive types to which a bit-field can be declared. */
18-
type instanceof IntType and
17+
Type getSupportedBitFieldType(Compiler compiler) {
18+
compiler instanceof UnsupportedCompiler and
1919
(
20-
type.(IntegralType).isExplicitlySigned() or
21-
type.(IntegralType).isExplicitlyUnsigned()
20+
result instanceof IntType and
21+
(
22+
result.(IntegralType).isExplicitlySigned() or
23+
result.(IntegralType).isExplicitlyUnsigned()
24+
)
25+
or
26+
result instanceof BoolType
2227
)
2328
or
24-
type instanceof BoolType
29+
(compiler instanceof Gcc or compiler instanceof Clang) and
30+
(
31+
result instanceof IntegralOrEnumType
32+
or
33+
result instanceof BoolType
34+
)
2535
}
2636

2737
from BitField bitField
2838
where
2939
not isExcluded(bitField,
3040
BitfieldTypesPackage::bitFieldsShallOnlyBeDeclaredWithAnAppropriateTypeQuery()) and
3141
/* 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() + "."
42+
not getSupportedBitFieldType(getCompiler(bitField.getFile())) =
43+
bitField.getType().resolveTypedefs()
44+
select bitField, "Bit-field '" + bitField + "' is declared on type '" + bitField.getType() + "'."
Original file line numberDiff line numberDiff line change
@@ -1,4 +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. |
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'. |

c/misra/test/rules/RULE-6-1/clang/BitFieldsShallOnlyBeDeclaredWithAnAppropriateType.expected

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
rules/RULE-6-1/BitFieldsShallOnlyBeDeclaredWithAnAppropriateType.ql
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
semmle-extractor-options:--mimic clang --std=c11 --edg --diag_error=implicit_func_decl -nostdinc -I../../../../common/test/includes/standard-library
+15
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; // COMPLIANT
7+
unsigned int x2 : 2; // COMPLIANT - explicitly unsigned
8+
signed int x3 : 2; // COMPLIANT - explicitly signed
9+
UINT16 x4 : 2; // COMPLIANT - type alias resolves to a compliant type
10+
signed long x5 : 2; // COMPLIANT
11+
signed char x6 : 2; // COMPLIANT
12+
enum Color x7 : 3; // COMPLIANT
13+
//_Atomic(int) x8 : 2; // NON_COMPLIANT[COMPILER_CHECKED] - atomic types are
14+
// not permitted for bit-fields.
15+
} sample_struct;

c/misra/test/rules/RULE-6-1/gcc/BitFieldsShallOnlyBeDeclaredWithAnAppropriateType.expected

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
rules/RULE-6-1/BitFieldsShallOnlyBeDeclaredWithAnAppropriateType.ql
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
semmle-extractor-options:--mimic gcc --std=c11 --edg --diag_error=implicit_func_decl -nostdinc -I../../../../common/test/includes/standard-library
+15
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; // COMPLIANT
7+
unsigned int x2 : 2; // COMPLIANT - explicitly unsigned
8+
signed int x3 : 2; // COMPLIANT - explicitly signed
9+
UINT16 x4 : 2; // COMPLIANT - type alias resolves to a compliant type
10+
signed long x5 : 2; // COMPLIANT
11+
signed char x6 : 2; // COMPLIANT
12+
enum Color x7 : 3; // COMPLIANT
13+
//_Atomic(int) x8 : 2; // NON_COMPLIANT[COMPILER_CHECKED] - atomic types are
14+
// not permitted for bit-fields.
15+
} sample_struct;

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

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
semmle-extractor-options:--no-clang --std=c11 --edg --diag_error=implicit_func_decl -nostdinc -I../../../../common/test/includes/standard-library
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
- `RULE-6-1` - `BitFieldsShallOnlyBeDeclaredWithAnAppropriateType.ql`:
2+
- Address FP reported in #318. Add support for implementation specific bitfield types for Clang and Gcc.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/** A module to reason about the compiler used to compile translation units. */
2+
3+
import cpp
4+
import codingstandards.cpp.Scope
5+
6+
newtype Compiler =
7+
Gcc() or
8+
Clang() or
9+
UnsupportedCompiler()
10+
11+
/** Get the match pattern to detect the compiler being mimicked by the extractor to determine the compiler used to compile a file. */
12+
string getMimicMatch(Compiler compiler) {
13+
result = ["%gcc", "%g++"] and compiler instanceof Gcc
14+
or
15+
result = ["%clang", "%clang++"] and compiler instanceof Clang
16+
}
17+
18+
/** Get the compiler used to compile the translation unit the file `f` is part of. */
19+
Compiler getCompiler(File f) {
20+
exists(Compilation compilation, TranslationUnit translationUnit |
21+
compilation.getAFileCompiled() = translationUnit and
22+
(f = translationUnit or f = translationUnit.getAUserFile())
23+
|
24+
if exists(int mimicIndex | compilation.getArgument(mimicIndex) = "--mimic")
25+
then
26+
exists(int mimicIndex |
27+
compilation.getArgument(mimicIndex) = "--mimic" and
28+
(
29+
compilation.getArgument(mimicIndex + 1).matches(getMimicMatch(result))
30+
or
31+
forall(string match | match = getMimicMatch(_) |
32+
not compilation.getArgument(mimicIndex + 1).matches(match)
33+
) and
34+
result = UnsupportedCompiler()
35+
)
36+
)
37+
else result = UnsupportedCompiler()
38+
)
39+
}

0 commit comments

Comments
 (0)