Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit07a3b16

Browse files
authored
Merge pull request#188 from github/lcartey/essential-types
Implement `EssentialTypes`
2 parentsdcd22fd +0b984b2 commit07a3b16

File tree

56 files changed

+3370
-11
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+3370
-11
lines changed
Lines changed: 376 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,376 @@
1+
/**
2+
* A module for identifying essential types as defined by MISRA C 2012.
3+
*/
4+
5+
import codingstandards.c.misra
6+
import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils
7+
import MisraExpressions
8+
9+
newtypeTEssentialTypeCategory=
10+
EssentiallyBooleanType()or
11+
EssentiallyCharacterType()or
12+
EssentiallyEnumType()or
13+
EssentiallySignedType()or
14+
EssentiallyUnsignedType()or
15+
EssentiallyFloatingType()
16+
17+
/** An essential type category, as specified by Appendix D.1. */
18+
classEssentialTypeCategoryextendsTEssentialTypeCategory{
19+
stringtoString(){
20+
this=EssentiallyBooleanType()andresult="essentially Boolean type"
21+
or
22+
this=EssentiallyCharacterType()andresult="essentially Character type"
23+
or
24+
this=EssentiallyEnumType()andresult="essentially Enum Type"
25+
or
26+
this=EssentiallySignedType()andresult="essentially Signed type"
27+
or
28+
this=EssentiallyUnsignedType()andresult="essentially Unsigned type"
29+
or
30+
this=EssentiallyFloatingType()andresult="essentially Floating type"
31+
}
32+
}
33+
34+
/**
35+
* Gets the unsigned type of lowest rank that can represent the value of the given expression,
36+
* assuming that the expression is essentially unsigned.
37+
*/
38+
privateIntegralTypeutlr(Exprconst){
39+
getEssentialTypeCategory(const.getType())=EssentiallyUnsignedType()and
40+
getEssentialTypeCategory(result)=EssentiallyUnsignedType()and
41+
exists(floatc|c=const.getValue().toFloat()|
42+
// As with range analysis, we assume two's complement representation
43+
typeLowerBound(result)<=cand
44+
typeUpperBound(result)>=cand
45+
forall(IntegralTypeit|
46+
getEssentialTypeCategory(it)=EssentiallyUnsignedType()and
47+
typeLowerBound(it)<=cand
48+
typeUpperBound(it)>=c
49+
|
50+
result.getSize()<=it.getSize()
51+
)
52+
)
53+
}
54+
55+
/**
56+
* Gets the signed type of lowest rank that can represent the value of the given expression,
57+
* assuming that the expression is essentially signed.
58+
*/
59+
privateIntegralTypestlr(Exprconst){
60+
getEssentialTypeCategory(const.getType())=EssentiallySignedType()and
61+
getEssentialTypeCategory(result)=EssentiallySignedType()and
62+
exists(floatc|c=const.getValue().toFloat()|
63+
// As with range analysis, we assume two's complement representation
64+
typeLowerBound(result)<=cand
65+
typeUpperBound(result)>=cand
66+
forall(IntegralTypeit|
67+
getEssentialTypeCategory(it)=EssentiallySignedType()and
68+
typeLowerBound(it)<=cand
69+
typeUpperBound(it)>=c
70+
|
71+
result.getSize()<=it.getSize()
72+
)
73+
)
74+
}
75+
76+
/**
77+
* Define the essential type category for an essentialType or a typedef of an essentialType.
78+
*/
79+
EssentialTypeCategorygetEssentialTypeCategory(Typetype){
80+
exists(TypeessentialType|
81+
iftypeinstanceofMisraBoolType
82+
thenessentialType=type
83+
else
84+
// If not a bool type, resolve the typedefs to determine the actual type
85+
essentialType=type.getUnspecifiedType()
86+
|
87+
result=EssentiallyBooleanType()andessentialTypeinstanceofMisraBoolType
88+
or
89+
result=EssentiallyCharacterType()andessentialTypeinstanceofPlainCharType
90+
or
91+
result=EssentiallySignedType()and
92+
essentialType.(IntegralType).isSigned()and
93+
notessentialTypeinstanceofPlainCharType
94+
or
95+
result=EssentiallyUnsignedType()and
96+
essentialType.(IntegralType).isUnsigned()and
97+
notessentialTypeinstanceofPlainCharType
98+
or
99+
result=EssentiallyEnumType()and
100+
essentialTypeinstanceofEnumand
101+
notessentialTypeinstanceofMisraBoolType
102+
or
103+
result=EssentiallyFloatingType()and
104+
essentialTypeinstanceofFloatingPointType
105+
)
106+
}
107+
108+
/**
109+
* Gets the essential type of the given expression `e`, considering any explicit conversions.
110+
*/
111+
TypegetEssentialType(Expre){
112+
ife.hasExplicitConversion()
113+
then
114+
ife.getConversion()instanceofParenthesisExpr
115+
then
116+
ife.getConversion().(ParenthesisExpr).hasExplicitConversion()
117+
thenresult=e.getConversion().(ParenthesisExpr).getConversion().getType()
118+
elseresult=e.getConversion().(ParenthesisExpr).getExpr().(EssentialExpr).getEssentialType()
119+
elseresult=e.getConversion().getType()
120+
elseresult=e.(EssentialExpr).getEssentialType()
121+
}
122+
123+
TypegetEssentialTypeBeforeConversions(Expre){result=e.(EssentialExpr).getEssentialType()}
124+
125+
classEssentialExprextendsExpr{
126+
TypegetEssentialType(){result=this.getType()}
127+
128+
TypegetStandardType(){result=this.getType()}
129+
}
130+
131+
classEssentialCommaExprextendsEssentialExpr,CommaExpr{
132+
overrideTypegetEssentialType(){result=getEssentialType(getRightOperand())}
133+
}
134+
135+
classEssentialRelationalOperationExprextendsEssentialExpr,RelationalOperation{
136+
overrideTypegetEssentialType(){resultinstanceofBoolType}
137+
}
138+
139+
classEssentialBinaryLogicalOperationExprextendsEssentialExpr,BinaryLogicalOperation{
140+
overrideTypegetEssentialType(){resultinstanceofBoolType}
141+
}
142+
143+
classEssentialEqualityOperationExprextendsEssentialExpr,EqualityOperation{
144+
overrideTypegetEssentialType(){resultinstanceofBoolType}
145+
}
146+
147+
classEssentialBinaryBitwiseOperationExprextendsEssentialExpr,BinaryBitwiseOperation{
148+
EssentialBinaryBitwiseOperationExpr(){
149+
thisinstanceofLShiftExpror
150+
thisinstanceofRShiftExpr
151+
}
152+
153+
overrideTypegetEssentialType(){
154+
exists(TypeoperandEssentialType,EssentialTypeCategoryoperandEssentialTypeCategory|
155+
operandEssentialType=getEssentialType(getLeftOperand())and
156+
operandEssentialTypeCategory=getEssentialTypeCategory(operandEssentialType)
157+
|
158+
ifoperandEssentialTypeCategoryinstanceofEssentiallyUnsignedType
159+
then
160+
ifexists(this.getValue())
161+
thenresult=utlr(this)// If constant and essentially unsigned us the utlr
162+
elseresult=operandEssentialType
163+
elseresult=this.getStandardType()
164+
)
165+
}
166+
}
167+
168+
classEssentialBitwiseComplementExprextendsEssentialExpr,ComplementExpr{
169+
overrideTypegetEssentialType(){
170+
exists(TypeoperandEssentialType,EssentialTypeCategoryoperandEssentialTypeCategory|
171+
operandEssentialType=getEssentialType(getOperand())and
172+
operandEssentialTypeCategory=getEssentialTypeCategory(operandEssentialType)
173+
|
174+
ifoperandEssentialTypeCategoryinstanceofEssentiallyUnsignedType
175+
then
176+
ifexists(this.getValue())
177+
thenresult=utlr(this)// If constant and essentially unsigned us the utlr
178+
elseresult=operandEssentialType
179+
elseresult=this.getStandardType()
180+
)
181+
}
182+
}
183+
184+
classEssentialUnaryPlusExprextendsEssentialExpr,UnaryPlusExpr{
185+
overrideTypegetEssentialType(){
186+
exists(TypeoperandEssentialType,EssentialTypeCategoryoperandEssentialTypeCategory|
187+
operandEssentialType=getEssentialType(getOperand())and
188+
operandEssentialTypeCategory=getEssentialTypeCategory(operandEssentialType)
189+
|
190+
if
191+
operandEssentialTypeCategory=
192+
[EssentiallyUnsignedType().(TEssentialTypeCategory),EssentiallySignedType()]
193+
thenresult=operandEssentialType
194+
elseresult=getStandardType()
195+
)
196+
}
197+
}
198+
199+
classEssentialUnaryMinusExprextendsEssentialExpr,UnaryMinusExpr{
200+
overrideTypegetEssentialType(){
201+
exists(TypeoperandEssentialType,EssentialTypeCategoryoperandEssentialTypeCategory|
202+
operandEssentialType=getEssentialType(getOperand())and
203+
operandEssentialTypeCategory=getEssentialTypeCategory(operandEssentialType)
204+
|
205+
ifoperandEssentialTypeCategory=EssentiallySignedType()
206+
thenifexists(this.getValue())thenresult=stlr(this)elseresult=operandEssentialType
207+
elseresult=getStandardType()
208+
)
209+
}
210+
}
211+
212+
classEssentialConditionalExprextendsEssentialExpr,ConditionalExpr{
213+
overrideTypegetEssentialType(){
214+
exists(TypethenEssentialType,TypeelseEssentialType|
215+
thenEssentialType=getEssentialType(getThen())and
216+
elseEssentialType=getEssentialType(getElse())
217+
|
218+
ifthenEssentialType=elseEssentialType
219+
thenresult=thenEssentialType
220+
else
221+
if
222+
getEssentialTypeCategory(thenEssentialType)=EssentiallySignedType()and
223+
getEssentialTypeCategory(elseEssentialType)=EssentiallySignedType()
224+
then
225+
ifthenEssentialType.getSize()>elseEssentialType.getSize()
226+
thenresult=thenEssentialType
227+
elseresult=elseEssentialType
228+
else
229+
if
230+
getEssentialTypeCategory(thenEssentialType)=EssentiallyUnsignedType()and
231+
getEssentialTypeCategory(elseEssentialType)=EssentiallyUnsignedType()
232+
then
233+
ifthenEssentialType.getSize()>elseEssentialType.getSize()
234+
thenresult=thenEssentialType
235+
elseresult=elseEssentialType
236+
elseresult=this.getStandardType()
237+
)
238+
}
239+
}
240+
241+
classEssentialBinaryArithmeticExprextendsEssentialExpr,BinaryArithmeticOperation{
242+
EssentialBinaryArithmeticExpr(){
243+
// GNU C extension has min/max which we can ignore
244+
notthisinstanceofMinExprand
245+
notthisinstanceofMaxExpr
246+
}
247+
248+
overrideTypegetEssentialType(){
249+
exists(
250+
TypeleftEssentialType,TyperightEssentialType,
251+
EssentialTypeCategoryleftEssentialTypeCategory,
252+
EssentialTypeCategoryrightEssentialTypeCategory
253+
|
254+
leftEssentialType=getEssentialType(getLeftOperand())and
255+
rightEssentialType=getEssentialType(getRightOperand())and
256+
leftEssentialTypeCategory=getEssentialTypeCategory(leftEssentialType)and
257+
rightEssentialTypeCategory=getEssentialTypeCategory(rightEssentialType)
258+
|
259+
if
260+
leftEssentialTypeCategory=EssentiallySignedType()and
261+
rightEssentialTypeCategory=EssentiallySignedType()
262+
then
263+
ifexists(getValue())
264+
thenresult=stlr(this)
265+
else(
266+
ifleftEssentialType.getSize()>rightEssentialType.getSize()
267+
thenresult=leftEssentialType
268+
elseresult=rightEssentialType
269+
)
270+
else
271+
if
272+
leftEssentialTypeCategory=EssentiallyUnsignedType()and
273+
rightEssentialTypeCategory=EssentiallyUnsignedType()
274+
then
275+
ifexists(getValue())
276+
thenresult=utlr(this)
277+
else(
278+
ifleftEssentialType.getSize()>rightEssentialType.getSize()
279+
thenresult=leftEssentialType
280+
elseresult=rightEssentialType
281+
)
282+
else
283+
if
284+
thisinstanceofAddExprand
285+
(
286+
leftEssentialTypeCategory=EssentiallyCharacterType()
287+
or
288+
rightEssentialTypeCategory=EssentiallyCharacterType()
289+
)and
290+
(
291+
leftEssentialTypeCategory=
292+
[EssentiallySignedType(),EssentiallyUnsignedType().(TEssentialTypeCategory)]
293+
or
294+
rightEssentialTypeCategory=
295+
[EssentiallySignedType(),EssentiallyUnsignedType().(TEssentialTypeCategory)]
296+
)
297+
or
298+
thisinstanceofSubExprand
299+
leftEssentialTypeCategory=EssentiallyCharacterType()and
300+
rightEssentialTypeCategory=
301+
[EssentiallySignedType(),EssentiallyUnsignedType().(TEssentialTypeCategory)]
302+
thenresultinstanceofPlainCharType
303+
elseresult=this.getStandardType()
304+
)
305+
}
306+
}
307+
308+
classEssentialEnumConstantAccessextendsEssentialExpr,EnumConstantAccess{
309+
overrideTypegetEssentialType(){result=getTarget().getDeclaringEnum()}
310+
}
311+
312+
classEssentialLiteralextendsEssentialExpr,Literal{
313+
overrideTypegetEssentialType(){
314+
ifthisinstanceofBooleanLiteral
315+
thenresultinstanceofMisraBoolType
316+
else(
317+
ifthis.(CharLiteral).getCharacter().length()=1
318+
thenresultinstanceofPlainCharType
319+
else(
320+
getStandardType().(IntegralType).isSigned()and
321+
result=stlr(this)
322+
or
323+
notgetStandardType().(IntegralType).isSigned()and
324+
result=utlr(this)
325+
)
326+
)
327+
}
328+
}
329+
330+
/**
331+
* Holds if `rValue` is assigned to an object of type `lValueEssentialType`.
332+
*
333+
* Assignment is according to "Assignment" in Appendix J of MISRA C 2012, with the inclusion of a
334+
* special case for switch statements as specified for Rule 10.3 and Rule 10.6.
335+
*/
336+
predicateisAssignmentToEssentialType(TypelValueEssentialType,ExprrValue){
337+
// Special case for Rule 10.3/ Rule 10.6.
338+
exists(SwitchCasesc|
339+
lValueEssentialType=sc.getSwitchStmt().getControllingExpr().getType()and
340+
rValue=sc.getExpr()
341+
)
342+
or
343+
exists(Assignmenta|
344+
lValueEssentialType=a.getLValue().getType()and
345+
rValue=a.getRValue()
346+
)
347+
or
348+
exists(FunctionCallfc,inti|
349+
lValueEssentialType=fc.getTarget().getParameter(i).getType()and
350+
rValue=fc.getArgument(i)
351+
)
352+
or
353+
exists(Functionf,ReturnStmtrs|
354+
lValueEssentialType=f.getType()and
355+
rs.getEnclosingFunction()=fand
356+
rValue=rs.getExpr()
357+
)
358+
or
359+
// Initializing a non-aggregate type
360+
exists(Initializeri|
361+
lValueEssentialType=i.getDeclaration().(Variable).getType()and
362+
rValue=i.getExpr()
363+
)
364+
or
365+
// Initializing an array
366+
exists(ArrayAggregateLiteralaal|
367+
lValueEssentialType=aal.getElementType()and
368+
rValue=aal.getElementExpr(_)
369+
)
370+
or
371+
// Initializing a struct or union
372+
exists(ClassAggregateLiteralcal,Fieldfield|
373+
lValueEssentialType=field.getType()and
374+
rValue=cal.getFieldExpr(field)
375+
)
376+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp