Skip to content

Commit 3c1615d

Browse files
authored
Merge pull request #703 from github/lcartey/language-extensions-improvements
Rule 1.2: Address false positives for variable length arrays, improve reporting
2 parents 76de855 + 55c9f23 commit 3c1615d

File tree

6 files changed

+196
-75
lines changed

6 files changed

+196
-75
lines changed

c/common/src/codingstandards/c/Extensions.qll

Lines changed: 85 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,28 @@ import codingstandards.cpp.Extensions
44
/**
55
* Common base class for modeling compiler extensions.
66
*/
7-
abstract class CCompilerExtension extends CompilerExtension { }
7+
abstract class CCompilerExtension extends CompilerExtension {
8+
abstract string getMessage();
9+
}
810

911
// Reference: https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html#Other-Builtins
1012
abstract class CConditionalDefineExtension extends CCompilerExtension, PreprocessorIfdef {
13+
string feature;
14+
1115
CConditionalDefineExtension() {
12-
exists(toString().indexOf("__has_builtin")) or
13-
exists(toString().indexOf("__has_constexpr_builtin")) or
14-
exists(toString().indexOf("__has_feature")) or
15-
exists(toString().indexOf("__has_extension")) or
16-
exists(toString().indexOf("__has_attribute")) or
17-
exists(toString().indexOf("__has_declspec_attribute")) or
18-
exists(toString().indexOf("__is_identifier")) or
19-
exists(toString().indexOf("__has_include")) or
20-
exists(toString().indexOf("__has_include_next")) or
21-
exists(toString().indexOf("__has_warning"))
16+
feature =
17+
[
18+
"__has_builtin", "__has_constexpr_builtin", "__has_feature", "__has_extension",
19+
"__has_attribute", "__has_declspec_attribute", "__is_identifier", "__has_include",
20+
"__has_include_next", "__has_warning"
21+
] and
22+
exists(toString().indexOf(feature))
23+
}
24+
25+
override string getMessage() {
26+
result =
27+
"Call to builtin function '" + feature +
28+
"' is a compiler extension and is not portable to other compilers."
2229
}
2330
}
2431

@@ -31,6 +38,12 @@ class CMacroBasedExtension extends CCompilerExtension, Macro {
3138
"__clang_version__", "__clang_literal_encoding__", "__clang_wide_literal_encoding__"
3239
]
3340
}
41+
42+
override string getMessage() {
43+
result =
44+
"Use of builtin macro '" + getBody() +
45+
"' is a compiler extension and is not portable to other compilers."
46+
}
3447
}
3548

3649
// Reference: https://gcc.gnu.org/onlinedocs/gcc/Variable-Attributes.html#Variable-Attributes
@@ -41,6 +54,12 @@ class CAttributeExtension extends CCompilerExtension, Attribute {
4154
"fallthrough", "read_only", "alias"
4255
]
4356
}
57+
58+
override string getMessage() {
59+
result =
60+
"Use of attribute '" + getName() +
61+
"' is a compiler extension and is not portable to other compilers."
62+
}
4463
}
4564

4665
// Reference: https://gcc.gnu.org/onlinedocs/gcc/_005f_005fsync-Builtins.html#g_t_005f_005fsync-Builtins
@@ -61,21 +80,41 @@ class CFunctionExtension extends CCompilerExtension, FunctionCall {
6180
// the built-in extensions
6281
getTarget().getName().indexOf("__builtin_") = 0
6382
}
83+
84+
override string getMessage() {
85+
result =
86+
"Call to builtin function '" + getTarget().getName() +
87+
"' is a compiler extension and is not portable to other compilers."
88+
}
6489
}
6590

6691
// Reference: https://gcc.gnu.org/onlinedocs/gcc/Alignment.html#Alignment
6792
class CFunctionLikeExtension extends CCompilerExtension, AlignofExprOperator {
6893
CFunctionLikeExtension() { exists(getValueText().indexOf("__alignof__")) }
94+
95+
override string getMessage() {
96+
result = "'__alignof__' is a compiler extension and is not portable to other compilers."
97+
}
6998
}
7099

71100
// Reference: https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html#Statement-Exprs
72-
class CStmtExprExtension extends CCompilerExtension, StmtExpr { }
101+
class CStmtExprExtension extends CCompilerExtension, StmtExpr {
102+
override string getMessage() {
103+
result =
104+
"Statement expressions are a compiler extension and are not portable to other compilers."
105+
}
106+
}
73107

74108
// Use of ternary like the following: `int a = 0 ?: 0;` where the
75109
// one of the branches is omitted
76110
// Reference: https://gcc.gnu.org/onlinedocs/gcc/Conditionals.html#Conditionals
77111
class CTerseTernaryExtension extends CCompilerExtension, ConditionalExpr {
78112
CTerseTernaryExtension() { getCondition() = getElse() or getCondition() = getThen() }
113+
114+
override string getMessage() {
115+
result =
116+
"Ternaries with omitted middle operands are a compiler extension and is not portable to other compilers."
117+
}
79118
}
80119

81120
// Reference: https://gcc.gnu.org/onlinedocs/gcc/_005f_005fint128.html#g_t_005f_005fint128
@@ -87,31 +126,63 @@ class CRealTypeExtensionExtension extends CCompilerExtension, DeclarationEntry {
87126
getType() instanceof Decimal64Type or
88127
getType() instanceof Float128Type
89128
}
129+
130+
override string getMessage() {
131+
result = "Decimal floats are a compiler extension and are not portable to other compilers."
132+
}
90133
}
91134

92135
// Reference: https://gcc.gnu.org/onlinedocs/gcc/_005f_005fint128.html#g_t_005f_005fint128
93136
class CIntegerTypeExtension extends CCompilerExtension, DeclarationEntry {
94137
CIntegerTypeExtension() { getType() instanceof Int128Type }
138+
139+
override string getMessage() {
140+
result = "128-bit integers are a compiler extension and are not portable to other compilers."
141+
}
95142
}
96143

97144
// Reference: https://gcc.gnu.org/onlinedocs/gcc/Long-Long.html#Long-Long
98145
class CLongLongType extends CCompilerExtension, DeclarationEntry {
99146
CLongLongType() { getType() instanceof LongLongType }
147+
148+
override string getMessage() {
149+
result =
150+
"Double-Word integers are a compiler extension and are not portable to other compilers."
151+
}
100152
}
101153

102154
class CZeroLengthArraysExtension extends CCompilerExtension, DeclarationEntry {
103155
CZeroLengthArraysExtension() { getType().(ArrayType).getArraySize() = 0 }
156+
157+
override string getMessage() {
158+
result = "Zero length arrays are a compiler extension and are not portable to other compilers."
159+
}
104160
}
105161

106162
// Reference: https://gcc.gnu.org/onlinedocs/gcc/Empty-Structures.html#Empty-Structures
107163
class CEmptyStructExtension extends CCompilerExtension, Struct {
108164
CEmptyStructExtension() { not exists(getAMember(_)) }
165+
166+
override string getMessage() {
167+
result = "Empty structures are a compiler extension and are not portable to other compilers."
168+
}
109169
}
110170

111171
// Reference: https://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html#Variable-Length
112-
class CVariableLengthArraysExtension extends CCompilerExtension, DeclarationEntry {
172+
class CVariableLengthArraysExtension extends CCompilerExtension, Field {
113173
CVariableLengthArraysExtension() {
114174
getType() instanceof ArrayType and
115-
not getType().(ArrayType).hasArraySize()
175+
not getType().(ArrayType).hasArraySize() and
176+
// Not the final member of the struct, which is allowed to be variably sized
177+
not exists(int lastIndex, Class declaringStruct |
178+
declaringStruct = getDeclaringType() and
179+
lastIndex = count(declaringStruct.getACanonicalMember()) - 1 and
180+
this = declaringStruct.getCanonicalMember(lastIndex)
181+
)
182+
}
183+
184+
override string getMessage() {
185+
result =
186+
"Variable length arrays are a compiler extension and are not portable to other compilers."
116187
}
117188
}

c/misra/src/rules/RULE-1-2/LanguageExtensionsShouldNotBeUsed.ql

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@
1313

1414
import cpp
1515
import codingstandards.c.misra
16+
import codingstandards.cpp.AlertReporting
1617
import codingstandards.c.Extensions
1718

1819
from CCompilerExtension e
1920
where not isExcluded(e, Language3Package::languageExtensionsShouldNotBeUsedQuery())
20-
select e, "Is a compiler extension and is not portable to other compilers."
21+
select MacroUnwrapper<CCompilerExtension>::unwrapElement(e), e.getMessage()

0 commit comments

Comments
 (0)