cppcheck-py 2.20.0__py3-none-win32.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cppcheck/__init__.py +55 -0
- cppcheck/cppcheck-2.20.0.tar.gz +0 -0
- cppcheck/data/addons/__init__.py +0 -0
- cppcheck/data/addons/cppcheck.py +41 -0
- cppcheck/data/addons/cppcheckdata.py +1727 -0
- cppcheck/data/addons/findcasts.py +32 -0
- cppcheck/data/addons/misc.py +163 -0
- cppcheck/data/addons/misra.py +5153 -0
- cppcheck/data/addons/misra_9.py +559 -0
- cppcheck/data/addons/naming.py +92 -0
- cppcheck/data/addons/namingng.py +420 -0
- cppcheck/data/addons/runaddon.py +16 -0
- cppcheck/data/addons/threadsafety.py +350 -0
- cppcheck/data/addons/y2038.py +602 -0
- cppcheck/data/cfg/avr.cfg +402 -0
- cppcheck/data/cfg/bento4.cfg +142 -0
- cppcheck/data/cfg/boost.cfg +1284 -0
- cppcheck/data/cfg/bsd.cfg +567 -0
- cppcheck/data/cfg/cairo.cfg +90 -0
- cppcheck/data/cfg/cppcheck-lib.cfg +72 -0
- cppcheck/data/cfg/cppunit.cfg +48 -0
- cppcheck/data/cfg/dpdk.cfg +11 -0
- cppcheck/data/cfg/embedded_sql.cfg +4 -0
- cppcheck/data/cfg/emscripten.cfg +108 -0
- cppcheck/data/cfg/ginac.cfg +12848 -0
- cppcheck/data/cfg/gnu.cfg +1738 -0
- cppcheck/data/cfg/googletest.cfg +62 -0
- cppcheck/data/cfg/gtk.cfg +23086 -0
- cppcheck/data/cfg/icu.cfg +221 -0
- cppcheck/data/cfg/kde.cfg +92 -0
- cppcheck/data/cfg/libcerror.cfg +203 -0
- cppcheck/data/cfg/libcurl.cfg +487 -0
- cppcheck/data/cfg/libsigc++.cfg +36 -0
- cppcheck/data/cfg/lua.cfg +316 -0
- cppcheck/data/cfg/mfc.cfg +271 -0
- cppcheck/data/cfg/microsoft_atl.cfg +40 -0
- cppcheck/data/cfg/microsoft_sal.cfg +490 -0
- cppcheck/data/cfg/microsoft_unittest.cfg +20 -0
- cppcheck/data/cfg/motif.cfg +318 -0
- cppcheck/data/cfg/nspr.cfg +38 -0
- cppcheck/data/cfg/ntl.cfg +6907 -0
- cppcheck/data/cfg/opencv2.cfg +132 -0
- cppcheck/data/cfg/opengl.cfg +581 -0
- cppcheck/data/cfg/openmp.cfg +157 -0
- cppcheck/data/cfg/openssl.cfg +174 -0
- cppcheck/data/cfg/pcre.cfg +165 -0
- cppcheck/data/cfg/posix.cfg +6445 -0
- cppcheck/data/cfg/protobuf.cfg +10 -0
- cppcheck/data/cfg/python.cfg +674 -0
- cppcheck/data/cfg/qt.cfg +5502 -0
- cppcheck/data/cfg/ruby.cfg +142 -0
- cppcheck/data/cfg/sdl.cfg +354 -0
- cppcheck/data/cfg/selinux.cfg +3621 -0
- cppcheck/data/cfg/sfml.cfg +301 -0
- cppcheck/data/cfg/sqlite3.cfg +1571 -0
- cppcheck/data/cfg/std.cfg +9215 -0
- cppcheck/data/cfg/tinyxml2.cfg +37 -0
- cppcheck/data/cfg/vcl.cfg +4 -0
- cppcheck/data/cfg/windows.cfg +17237 -0
- cppcheck/data/cfg/wxsqlite3.cfg +1955 -0
- cppcheck/data/cfg/wxsvg.cfg +16905 -0
- cppcheck/data/cfg/wxwidgets.cfg +17313 -0
- cppcheck/data/cfg/zephyr.cfg +113 -0
- cppcheck/data/cfg/zlib.cfg +1450 -0
- cppcheck/data/cppcheck-htmlreport +1157 -0
- cppcheck/data/cppcheck.exe +0 -0
- cppcheck/data/platforms/aix_ppc64.xml +18 -0
- cppcheck/data/platforms/arm32-wchar_t2.xml +18 -0
- cppcheck/data/platforms/arm32-wchar_t4.xml +18 -0
- cppcheck/data/platforms/arm64-wchar_t2.xml +18 -0
- cppcheck/data/platforms/arm64-wchar_t4.xml +18 -0
- cppcheck/data/platforms/avr8.xml +18 -0
- cppcheck/data/platforms/cray_sv1.xml +18 -0
- cppcheck/data/platforms/elbrus-e1cp.xml +18 -0
- cppcheck/data/platforms/mips32.xml +18 -0
- cppcheck/data/platforms/msp430_eabi_large_datamodel.xml +18 -0
- cppcheck/data/platforms/pic16.xml +18 -0
- cppcheck/data/platforms/pic8-enhanced.xml +18 -0
- cppcheck/data/platforms/pic8.xml +18 -0
- cppcheck_py-2.20.0.dist-info/METADATA +76 -0
- cppcheck_py-2.20.0.dist-info/RECORD +84 -0
- cppcheck_py-2.20.0.dist-info/WHEEL +5 -0
- cppcheck_py-2.20.0.dist-info/entry_points.txt +4 -0
- cppcheck_py-2.20.0.dist-info/licenses/LICENSE.md +191 -0
|
@@ -0,0 +1,559 @@
|
|
|
1
|
+
# Holds information about an array, struct or union's element definition.
|
|
2
|
+
class ElementDef:
|
|
3
|
+
def __init__(self, elementType, name, valueType, dimensions = None):
|
|
4
|
+
self.elementType = elementType # 'array', 'record' or 'value'
|
|
5
|
+
self.name = str(name)
|
|
6
|
+
self.valueType = valueType
|
|
7
|
+
self.children = []
|
|
8
|
+
self.dimensions = dimensions
|
|
9
|
+
self.parent = None
|
|
10
|
+
|
|
11
|
+
self.isDesignated = False
|
|
12
|
+
self.isPositional = False
|
|
13
|
+
self.numInits = 0
|
|
14
|
+
self.childIndex = -1
|
|
15
|
+
|
|
16
|
+
self.flexibleToken = None
|
|
17
|
+
self.isFlexible = False
|
|
18
|
+
self.structureViolationToken = None
|
|
19
|
+
|
|
20
|
+
def __repr__(self):
|
|
21
|
+
inits = ""
|
|
22
|
+
if self.isPositional:
|
|
23
|
+
inits += 'P'
|
|
24
|
+
if self.isDesignated:
|
|
25
|
+
inits += 'D'
|
|
26
|
+
if not (self.isPositional or self.isDesignated) and self.numInits == 0:
|
|
27
|
+
inits += '_'
|
|
28
|
+
if self.numInits > 1:
|
|
29
|
+
inits += str(self.numInits)
|
|
30
|
+
|
|
31
|
+
attrs = ["childIndex", "elementType", "valueType"]
|
|
32
|
+
return "{}({}, {}, {})".format(
|
|
33
|
+
"ElementDef",
|
|
34
|
+
self.getLongName(),
|
|
35
|
+
inits,
|
|
36
|
+
", ".join(("{}={}".format(a, repr(getattr(self, a))) for a in attrs))
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
@property
|
|
40
|
+
def isArray(self):
|
|
41
|
+
return self.elementType == 'array'
|
|
42
|
+
|
|
43
|
+
@property
|
|
44
|
+
def isRecord(self):
|
|
45
|
+
return self.elementType == 'record'
|
|
46
|
+
|
|
47
|
+
@property
|
|
48
|
+
def isValue(self):
|
|
49
|
+
return self.elementType == 'value'
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def getLongName(self):
|
|
53
|
+
return self.parent.getLongName() + "." + self.name if self.parent else self.name
|
|
54
|
+
|
|
55
|
+
def getInitDump(self):
|
|
56
|
+
t = []
|
|
57
|
+
if self.isPositional:
|
|
58
|
+
t.append('P')
|
|
59
|
+
if self.isDesignated:
|
|
60
|
+
t.append('D')
|
|
61
|
+
if self.numInits == 0:
|
|
62
|
+
t.append('_')
|
|
63
|
+
if self.numInits > 1:
|
|
64
|
+
t.append(str(self.numInits))
|
|
65
|
+
|
|
66
|
+
myDump = "".join(t)
|
|
67
|
+
|
|
68
|
+
if len(self.children):
|
|
69
|
+
childDumps = []
|
|
70
|
+
for c in self.children:
|
|
71
|
+
childDumps.append(c.getInitDump())
|
|
72
|
+
if self.structureViolationToken is not None:
|
|
73
|
+
myDump += "!"
|
|
74
|
+
myDump += "{ " + ", ".join(childDumps) + " }"
|
|
75
|
+
|
|
76
|
+
return myDump
|
|
77
|
+
|
|
78
|
+
def addChild(self, child):
|
|
79
|
+
self.children.append(child)
|
|
80
|
+
child.parent = self
|
|
81
|
+
|
|
82
|
+
def getNextChild(self):
|
|
83
|
+
self.childIndex += 1
|
|
84
|
+
return self.getChildByIndex(self.childIndex)
|
|
85
|
+
|
|
86
|
+
def getChildByIndex(self, index):
|
|
87
|
+
if self.isFlexible:
|
|
88
|
+
while len(self.children) <= index:
|
|
89
|
+
createChild(self, self.flexibleToken, len(self.children), None)
|
|
90
|
+
return self.children[index] if 0 <= index < len(self.children) else None
|
|
91
|
+
|
|
92
|
+
def getChildByName(self, name):
|
|
93
|
+
for c in self.children:
|
|
94
|
+
if c.name == name:
|
|
95
|
+
return c
|
|
96
|
+
return None
|
|
97
|
+
|
|
98
|
+
def getNextValueElement(self, root):
|
|
99
|
+
current = self
|
|
100
|
+
while current != root:
|
|
101
|
+
if not current.parent:
|
|
102
|
+
return None
|
|
103
|
+
# Get next index of parent
|
|
104
|
+
i = current.parent.children.index(current) + 1
|
|
105
|
+
# Next index of parent exists
|
|
106
|
+
if i < len(current.parent.children):
|
|
107
|
+
current = current.parent.children[i]
|
|
108
|
+
return current.getFirstValueElement()
|
|
109
|
+
|
|
110
|
+
# Next index of parent doesn't exist. Move up
|
|
111
|
+
current = current.parent
|
|
112
|
+
return None
|
|
113
|
+
|
|
114
|
+
def getFirstValueElement(self):
|
|
115
|
+
current = self
|
|
116
|
+
|
|
117
|
+
# Move to first child as long as children exists
|
|
118
|
+
next_child = current.getChildByIndex(0)
|
|
119
|
+
while next_child:
|
|
120
|
+
current = next_child
|
|
121
|
+
next_child = current.getChildByIndex(0)
|
|
122
|
+
return current
|
|
123
|
+
|
|
124
|
+
def getLastValueElement(self):
|
|
125
|
+
current = self
|
|
126
|
+
# Move to last child as long as children exists
|
|
127
|
+
while len(current.children) > 0:
|
|
128
|
+
current = current.children[-1]
|
|
129
|
+
return current
|
|
130
|
+
|
|
131
|
+
def getChildByValueElement(self, ed):
|
|
132
|
+
potentialChild = ed
|
|
133
|
+
while potentialChild and potentialChild not in self.children:
|
|
134
|
+
potentialChild = potentialChild.parent
|
|
135
|
+
|
|
136
|
+
return self.children[self.children.index(potentialChild)] if potentialChild else None
|
|
137
|
+
|
|
138
|
+
def getEffectiveLevel(self):
|
|
139
|
+
if self.parent and self.parent.elementType == "array":
|
|
140
|
+
return self.parent.getEffectiveLevel() + 1
|
|
141
|
+
return 0
|
|
142
|
+
|
|
143
|
+
def setInitialized(self, designated=False, positional=False):
|
|
144
|
+
if designated:
|
|
145
|
+
self.isDesignated = True
|
|
146
|
+
if positional or not designated:
|
|
147
|
+
self.isPositional = True
|
|
148
|
+
self.numInits += 1
|
|
149
|
+
|
|
150
|
+
def initializeChildren(self):
|
|
151
|
+
for child in self.children:
|
|
152
|
+
child.setInitialized(positional=True)
|
|
153
|
+
child.initializeChildren()
|
|
154
|
+
|
|
155
|
+
def unset(self):
|
|
156
|
+
self.isDesignated = False
|
|
157
|
+
self.isPositional = False
|
|
158
|
+
|
|
159
|
+
# Unset is always recursive
|
|
160
|
+
for child in self.children:
|
|
161
|
+
child.unset()
|
|
162
|
+
|
|
163
|
+
def markStuctureViolation(self, token):
|
|
164
|
+
if self.name == '->':
|
|
165
|
+
self.children[0].markStuctureViolation(token)
|
|
166
|
+
elif not self.structureViolationToken:
|
|
167
|
+
self.structureViolationToken = token
|
|
168
|
+
|
|
169
|
+
def markAsFlexibleArray(self, token):
|
|
170
|
+
self.flexibleToken = token
|
|
171
|
+
self.isFlexible = True
|
|
172
|
+
|
|
173
|
+
def markAsCurrent(self):
|
|
174
|
+
if self.parent:
|
|
175
|
+
if self.name == '<-':
|
|
176
|
+
self.parent.childIndex = self.parent.children.index(self.children[0])
|
|
177
|
+
else:
|
|
178
|
+
self.parent.childIndex = self.parent.children.index(self)
|
|
179
|
+
|
|
180
|
+
self.parent.markAsCurrent()
|
|
181
|
+
|
|
182
|
+
def isAllChildrenSet(self):
|
|
183
|
+
myself = len(self.children) == 0 and (self.isDesignated or self.isPositional)
|
|
184
|
+
mychildren = len(self.children) > 0 and all([child.isAllChildrenSet() for child in self.children])
|
|
185
|
+
return myself or mychildren
|
|
186
|
+
|
|
187
|
+
def isAllSet(self):
|
|
188
|
+
return all([child.isPositional or child.isDesignated for child in self.children])
|
|
189
|
+
|
|
190
|
+
def isOnlyDesignated(self):
|
|
191
|
+
return all([not child.isPositional for child in self.children])
|
|
192
|
+
|
|
193
|
+
def isMisra92Compliant(self):
|
|
194
|
+
return self.structureViolationToken is None and all([child.isMisra92Compliant() for child in self.children])
|
|
195
|
+
|
|
196
|
+
def isMisra93Compliant(self):
|
|
197
|
+
if self.elementType == 'array':
|
|
198
|
+
result = self.isAllChildrenSet() or \
|
|
199
|
+
((self.isAllSet() or
|
|
200
|
+
self.isOnlyDesignated()) and
|
|
201
|
+
all([not (child.isDesignated or child.isPositional) or child.isMisra93Compliant() for child in self.children]))
|
|
202
|
+
return result
|
|
203
|
+
if self.elementType == 'record':
|
|
204
|
+
result = all([child.isMisra93Compliant() for child in self.children])
|
|
205
|
+
return result
|
|
206
|
+
return True
|
|
207
|
+
|
|
208
|
+
def isMisra94Compliant(self):
|
|
209
|
+
return self.numInits <= 1 and all([child.isMisra94Compliant() for child in self.children])
|
|
210
|
+
|
|
211
|
+
def isMisra95Compliant(self):
|
|
212
|
+
return not self.isFlexible or all([not child.isDesignated for child in self.children])
|
|
213
|
+
|
|
214
|
+
# Parses the initializers and update the ElementDefs status accordingly
|
|
215
|
+
class InitializerParser:
|
|
216
|
+
def __init__(self):
|
|
217
|
+
self.token = None
|
|
218
|
+
self.root = None
|
|
219
|
+
self.ed = None
|
|
220
|
+
self.rootStack = []
|
|
221
|
+
|
|
222
|
+
def parseInitializer(self, root, token):
|
|
223
|
+
self.root = root
|
|
224
|
+
self.token = token
|
|
225
|
+
dummyRoot = ElementDef('array', '->', self.root.valueType)
|
|
226
|
+
dummyRoot.children = [self.root]
|
|
227
|
+
|
|
228
|
+
self.rootStack = []
|
|
229
|
+
self.root = dummyRoot
|
|
230
|
+
self.ed = self.root.getFirstValueElement()
|
|
231
|
+
isFirstElement = False
|
|
232
|
+
isDesignated = False
|
|
233
|
+
|
|
234
|
+
while self.token:
|
|
235
|
+
if self.token.str == ',':
|
|
236
|
+
self.token = self.token.astOperand1
|
|
237
|
+
isFirstElement = False
|
|
238
|
+
|
|
239
|
+
# Designated initializer ( [2]=... or .name=... )
|
|
240
|
+
elif self.token.isAssignmentOp and not self.token.valueType:
|
|
241
|
+
self.popFromStackIfExitElement()
|
|
242
|
+
|
|
243
|
+
self.ed = getElementByDesignator(self.root, self.token.astOperand1)
|
|
244
|
+
if self.ed:
|
|
245
|
+
# Update root
|
|
246
|
+
self.pushToRootStackAndMarkAsDesignated()
|
|
247
|
+
# Make sure ed points to valueElement
|
|
248
|
+
self.ed = self.ed.getFirstValueElement()
|
|
249
|
+
|
|
250
|
+
self.token = self.token.astOperand2
|
|
251
|
+
isFirstElement = False
|
|
252
|
+
isDesignated = True
|
|
253
|
+
|
|
254
|
+
elif self.token.isString and self.ed and self.ed.isArray:
|
|
255
|
+
self.ed.setInitialized(isDesignated)
|
|
256
|
+
if self.token == self.token.astParent.astOperand1 and self.token.astParent.astOperand2:
|
|
257
|
+
self.token = self.token.astParent.astOperand2
|
|
258
|
+
self.ed.markAsCurrent()
|
|
259
|
+
self.ed = self.root.getNextChild()
|
|
260
|
+
else:
|
|
261
|
+
self.unwindAndContinue()
|
|
262
|
+
continue
|
|
263
|
+
|
|
264
|
+
elif self.token.str == '{':
|
|
265
|
+
nextChild = self.root.getNextChild() if self.root is not None else None
|
|
266
|
+
|
|
267
|
+
if nextChild:
|
|
268
|
+
if nextChild.isArray or nextChild.isRecord:
|
|
269
|
+
nextChild.unset()
|
|
270
|
+
nextChild.setInitialized(isDesignated)
|
|
271
|
+
self.ed = nextChild.getFirstValueElement()
|
|
272
|
+
isDesignated = False
|
|
273
|
+
elif nextChild.valueType is None:
|
|
274
|
+
# No type information available - unable to check structure - assume correct initialization
|
|
275
|
+
nextChild.setInitialized(isDesignated)
|
|
276
|
+
self.unwindAndContinue()
|
|
277
|
+
continue
|
|
278
|
+
|
|
279
|
+
elif self.token.astOperand1:
|
|
280
|
+
# Create dummy nextChild to represent excess levels in initializer
|
|
281
|
+
dummyRoot = ElementDef('array', '<-', self.root.valueType)
|
|
282
|
+
dummyRoot.parent = self.root
|
|
283
|
+
dummyRoot.childIndex = 0
|
|
284
|
+
dummyRoot.children = [nextChild]
|
|
285
|
+
nextChild.parent = dummyRoot
|
|
286
|
+
|
|
287
|
+
self.root.markStuctureViolation(self.token)
|
|
288
|
+
|
|
289
|
+
# Fake dummy as nextChild (of current root)
|
|
290
|
+
nextChild = dummyRoot
|
|
291
|
+
|
|
292
|
+
if nextChild and self.token.astOperand1:
|
|
293
|
+
self.root = nextChild
|
|
294
|
+
self.token = self.token.astOperand1
|
|
295
|
+
isFirstElement = True
|
|
296
|
+
else:
|
|
297
|
+
if self.root:
|
|
298
|
+
# {}
|
|
299
|
+
if self.root.name == '<-':
|
|
300
|
+
self.root.parent.markStuctureViolation(self.token)
|
|
301
|
+
else:
|
|
302
|
+
self.root.markStuctureViolation(self.token)
|
|
303
|
+
self.ed = None
|
|
304
|
+
self.unwindAndContinue()
|
|
305
|
+
|
|
306
|
+
else:
|
|
307
|
+
if self.ed and self.ed.isValue:
|
|
308
|
+
if not isDesignated and len(self.rootStack) > 0 and self.rootStack[-1][1] == self.root:
|
|
309
|
+
self.rootStack[-1][0].markStuctureViolation(self.token)
|
|
310
|
+
if isFirstElement and self.token.str == '0' and self.token.next.str == '}':
|
|
311
|
+
# Zero initializer causes recursive initialization
|
|
312
|
+
self.root.initializeChildren()
|
|
313
|
+
elif self.token.isString and self.ed.valueType and self.ed.valueType.pointer > 0:
|
|
314
|
+
if self.ed.valueType.pointer - self.ed.getEffectiveLevel() == 1:
|
|
315
|
+
if self.ed.parent != self.root:
|
|
316
|
+
self.root.markStuctureViolation(self.token)
|
|
317
|
+
self.ed.setInitialized(isDesignated)
|
|
318
|
+
elif self.ed.valueType.pointer == self.ed.getEffectiveLevel():
|
|
319
|
+
if(self.root.name != '->' and self.ed.parent.parent != self.root) or (self.root.name == '->' and self.root.children[0] != self.ed.parent):
|
|
320
|
+
self.root.markStuctureViolation(self.token)
|
|
321
|
+
else:
|
|
322
|
+
self.ed.parent.setInitialized(isDesignated)
|
|
323
|
+
self.ed.parent.initializeChildren()
|
|
324
|
+
|
|
325
|
+
else:
|
|
326
|
+
if self.root is not None and self.ed.parent != self.root:
|
|
327
|
+
# Check if token is correct value type for self.root.children[?]
|
|
328
|
+
child = self.root.getChildByValueElement(self.ed)
|
|
329
|
+
if self.token.valueType:
|
|
330
|
+
if child.elementType != 'record' or self.token.valueType.type != 'record' or child.valueType.typeScope != self.token.valueType.typeScope:
|
|
331
|
+
self.root.markStuctureViolation(self.token)
|
|
332
|
+
|
|
333
|
+
self.ed.setInitialized(isDesignated)
|
|
334
|
+
|
|
335
|
+
# Mark all elements up to root with positional or designated
|
|
336
|
+
# (for complex designators, or missing structure)
|
|
337
|
+
parent = self.ed.parent
|
|
338
|
+
while parent and parent != self.root:
|
|
339
|
+
parent.isDesignated = isDesignated if isDesignated and not parent.isPositional else parent.isDesignated
|
|
340
|
+
parent.isPositional = not isDesignated if not isDesignated and not parent.isDesignated else parent.isPositional
|
|
341
|
+
parent = parent.parent
|
|
342
|
+
isDesignated = False
|
|
343
|
+
|
|
344
|
+
if self.token.isString and self.ed.parent.isArray:
|
|
345
|
+
self.ed = self.ed.parent
|
|
346
|
+
self.unwindAndContinue()
|
|
347
|
+
|
|
348
|
+
def pushToRootStackAndMarkAsDesignated(self):
|
|
349
|
+
new = self.ed.parent
|
|
350
|
+
if new != self.root:
|
|
351
|
+
# Mark all elements up to self.root root as designated
|
|
352
|
+
parent = new
|
|
353
|
+
while parent and parent != self.root:
|
|
354
|
+
parent.isDesignated = True
|
|
355
|
+
parent = parent.parent
|
|
356
|
+
self.rootStack.append((self.root, new))
|
|
357
|
+
new.markAsCurrent()
|
|
358
|
+
new.childIndex = new.children.index(self.ed) - 1
|
|
359
|
+
self.root = new
|
|
360
|
+
|
|
361
|
+
def popFromStackIfExitElement(self):
|
|
362
|
+
if len(self.rootStack) > 0 and self.rootStack[-1][1] == self.root:
|
|
363
|
+
old = self.rootStack.pop()[0]
|
|
364
|
+
old.markAsCurrent()
|
|
365
|
+
self.root = old
|
|
366
|
+
|
|
367
|
+
def unwindAndContinue(self):
|
|
368
|
+
while self.token:
|
|
369
|
+
if self.token.astParent.astOperand1 == self.token and self.token.astParent.astOperand2:
|
|
370
|
+
if self.ed:
|
|
371
|
+
if self.token.astParent.astOperand2.str == "{" and self.ed.isDesignated:
|
|
372
|
+
self.popFromStackIfExitElement()
|
|
373
|
+
else:
|
|
374
|
+
self.ed.markAsCurrent()
|
|
375
|
+
self.ed = self.ed.getNextValueElement(self.root)
|
|
376
|
+
|
|
377
|
+
self.token = self.token.astParent.astOperand2
|
|
378
|
+
break
|
|
379
|
+
|
|
380
|
+
self.token = self.token.astParent
|
|
381
|
+
if self.token.str == '{':
|
|
382
|
+
if self.root:
|
|
383
|
+
self.ed = self.root.getLastValueElement()
|
|
384
|
+
self.ed.markAsCurrent()
|
|
385
|
+
|
|
386
|
+
# Cleanup if root is dummy node representing excess levels in initializer
|
|
387
|
+
if self.root.name == '<-':
|
|
388
|
+
self.root.children[0].parent = self.root.parent
|
|
389
|
+
|
|
390
|
+
self.root = self.root.parent
|
|
391
|
+
|
|
392
|
+
if self.token.astParent is None:
|
|
393
|
+
self.token = None
|
|
394
|
+
break
|
|
395
|
+
|
|
396
|
+
def misra_9_x(self, data, rule, rawTokens = None):
|
|
397
|
+
|
|
398
|
+
parser = InitializerParser()
|
|
399
|
+
|
|
400
|
+
for variable in data.variables:
|
|
401
|
+
if variable.nameToken is None:
|
|
402
|
+
continue
|
|
403
|
+
|
|
404
|
+
nameToken = variable.nameToken
|
|
405
|
+
|
|
406
|
+
# Check if declaration and initialization is
|
|
407
|
+
# split into two separate statements in ast.
|
|
408
|
+
if nameToken.next and nameToken.next.isSplittedVarDeclEq:
|
|
409
|
+
nameToken = nameToken.next.next
|
|
410
|
+
|
|
411
|
+
# Find declarations with initializer assignment
|
|
412
|
+
eq = nameToken
|
|
413
|
+
while not eq.isAssignmentOp and eq.astParent:
|
|
414
|
+
eq = eq.astParent
|
|
415
|
+
|
|
416
|
+
# We are only looking for initializers
|
|
417
|
+
if not eq.isAssignmentOp or eq.astOperand2.isName:
|
|
418
|
+
continue
|
|
419
|
+
|
|
420
|
+
if variable.isArray or variable.isClass:
|
|
421
|
+
ed = getElementDef(nameToken, rawTokens)
|
|
422
|
+
# No need to check non-arrays if valueType is missing,
|
|
423
|
+
# since we can't say anything useful about the structure
|
|
424
|
+
# without it.
|
|
425
|
+
if ed.valueType is None and not variable.isArray:
|
|
426
|
+
continue
|
|
427
|
+
parser.parseInitializer(ed, eq.astOperand2)
|
|
428
|
+
# print(rule, nameToken.str + '=', ed.getInitDump())
|
|
429
|
+
if rule == 902 and not ed.isMisra92Compliant():
|
|
430
|
+
self.reportError(nameToken, 9, 2)
|
|
431
|
+
if rule == 903 and not ed.isMisra93Compliant():
|
|
432
|
+
# Do not check when variable is pointer type
|
|
433
|
+
type_token = variable.nameToken
|
|
434
|
+
while type_token and type_token.isName:
|
|
435
|
+
type_token = type_token.previous
|
|
436
|
+
if type_token and type_token.str == '*':
|
|
437
|
+
continue
|
|
438
|
+
|
|
439
|
+
self.reportError(nameToken, 9, 3)
|
|
440
|
+
if rule == 904 and not ed.isMisra94Compliant():
|
|
441
|
+
self.reportError(nameToken, 9, 4)
|
|
442
|
+
if rule == 905 and not ed.isMisra95Compliant():
|
|
443
|
+
self.reportError(nameToken, 9, 5)
|
|
444
|
+
|
|
445
|
+
def getElementDef(nameToken, rawTokens = None):
|
|
446
|
+
if nameToken.variable.isArray:
|
|
447
|
+
ed = ElementDef("array", nameToken.str, nameToken.valueType)
|
|
448
|
+
createArrayChildrenDefs(ed, nameToken.astParent, nameToken.variable, rawTokens)
|
|
449
|
+
elif nameToken.variable.isClass:
|
|
450
|
+
ed = ElementDef("record", nameToken.str, nameToken.valueType)
|
|
451
|
+
createRecordChildrenDefs(ed, nameToken.variable)
|
|
452
|
+
else:
|
|
453
|
+
ed = ElementDef("value", nameToken.str, nameToken.valueType)
|
|
454
|
+
return ed
|
|
455
|
+
|
|
456
|
+
def createArrayChildrenDefs(ed, token, var, rawTokens = None):
|
|
457
|
+
if token and token.str == '[':
|
|
458
|
+
if rawTokens is not None:
|
|
459
|
+
foundToken = next((rawToken for rawToken in rawTokens
|
|
460
|
+
if rawToken.file == token.file
|
|
461
|
+
and rawToken.linenr == token.linenr
|
|
462
|
+
and rawToken.column == token.column
|
|
463
|
+
), None)
|
|
464
|
+
|
|
465
|
+
if foundToken and foundToken.next and foundToken.next.str == ']':
|
|
466
|
+
ed.markAsFlexibleArray(token)
|
|
467
|
+
|
|
468
|
+
if (token.astOperand2 is not None) and (token.astOperand2.getKnownIntValue() is not None):
|
|
469
|
+
for i in range(token.astOperand2.getKnownIntValue()):
|
|
470
|
+
createChild(ed, token, i, var)
|
|
471
|
+
else:
|
|
472
|
+
ed.markAsFlexibleArray(token)
|
|
473
|
+
|
|
474
|
+
|
|
475
|
+
def createChild(ed, token, name, var):
|
|
476
|
+
if token.astParent and token.astParent.str == '[':
|
|
477
|
+
child = ElementDef("array", name, ed.valueType)
|
|
478
|
+
createArrayChildrenDefs(child, token.astParent, var)
|
|
479
|
+
else:
|
|
480
|
+
if ed.valueType and ed.valueType.type == "record":
|
|
481
|
+
child = ElementDef("record", name, ed.valueType)
|
|
482
|
+
createRecordChildrenDefs(child, var)
|
|
483
|
+
else:
|
|
484
|
+
child = ElementDef("value", name, ed.valueType)
|
|
485
|
+
|
|
486
|
+
ed.addChild(child)
|
|
487
|
+
|
|
488
|
+
def createRecordChildrenDefs(ed, var):
|
|
489
|
+
valueType = ed.valueType
|
|
490
|
+
if not valueType or not valueType.typeScope:
|
|
491
|
+
return
|
|
492
|
+
if var is None:
|
|
493
|
+
return
|
|
494
|
+
typeToken = var.typeEndToken
|
|
495
|
+
while typeToken and typeToken.isName:
|
|
496
|
+
typeToken = typeToken.previous
|
|
497
|
+
if typeToken and typeToken.str == '*':
|
|
498
|
+
child = ElementDef("pointer", var.nameToken, var.nameToken.valueType)
|
|
499
|
+
ed.addChild(child)
|
|
500
|
+
return
|
|
501
|
+
child_dict = {}
|
|
502
|
+
for variable in valueType.typeScope.varlist:
|
|
503
|
+
if variable is var:
|
|
504
|
+
continue
|
|
505
|
+
child = getElementDef(variable.nameToken)
|
|
506
|
+
child_dict[variable.nameToken] = child
|
|
507
|
+
for scopes in valueType.typeScope.nestedList:
|
|
508
|
+
varscope = False
|
|
509
|
+
if scopes.nestedIn == valueType.typeScope:
|
|
510
|
+
for variable in valueType.typeScope.varlist:
|
|
511
|
+
if variable.nameToken and variable.nameToken.valueType and variable.nameToken.valueType.typeScope == scopes:
|
|
512
|
+
varscope = True
|
|
513
|
+
break
|
|
514
|
+
if not varscope:
|
|
515
|
+
ed1 = ElementDef("record", scopes.Id, valueType)
|
|
516
|
+
for variable in scopes.varlist:
|
|
517
|
+
child = getElementDef(variable.nameToken)
|
|
518
|
+
ed1.addChild(child)
|
|
519
|
+
child_dict[scopes.bodyStart] = ed1
|
|
520
|
+
sorted_keys = sorted(list(child_dict.keys()), key=lambda k: (k.file, k.linenr, k.column))
|
|
521
|
+
for _key in sorted_keys:
|
|
522
|
+
ed.addChild(child_dict[_key])
|
|
523
|
+
|
|
524
|
+
|
|
525
|
+
def getElementByDesignator(ed, token):
|
|
526
|
+
if not token.str in [ '.', '[' ]:
|
|
527
|
+
return None
|
|
528
|
+
|
|
529
|
+
while token.str in [ '.', '[' ]:
|
|
530
|
+
token = token.astOperand1
|
|
531
|
+
|
|
532
|
+
while ed and not token.isAssignmentOp:
|
|
533
|
+
token = token.astParent
|
|
534
|
+
|
|
535
|
+
if token.str == '[':
|
|
536
|
+
if not ed.isArray:
|
|
537
|
+
ed.markStuctureViolation(token)
|
|
538
|
+
|
|
539
|
+
chIndex = -1
|
|
540
|
+
if token.astOperand2 is not None:
|
|
541
|
+
chIndex = token.astOperand2.getKnownIntValue()
|
|
542
|
+
elif token.astOperand1 is not None:
|
|
543
|
+
chIndex = token.astOperand1.getKnownIntValue()
|
|
544
|
+
|
|
545
|
+
ed = ed.getChildByIndex(chIndex) if chIndex is not None else None
|
|
546
|
+
|
|
547
|
+
elif token.str == '.':
|
|
548
|
+
if not ed.isRecord:
|
|
549
|
+
ed.markStuctureViolation(token)
|
|
550
|
+
|
|
551
|
+
name = ""
|
|
552
|
+
if token.astOperand2 is not None:
|
|
553
|
+
name = token.astOperand2.str
|
|
554
|
+
elif token.astOperand1 is not None:
|
|
555
|
+
name = token.astOperand1.str
|
|
556
|
+
|
|
557
|
+
ed = ed.getChildByName(name)
|
|
558
|
+
|
|
559
|
+
return ed
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
#
|
|
3
|
+
# cppcheck addon for naming conventions
|
|
4
|
+
#
|
|
5
|
+
# Example usage (variable name must start with lowercase, function name must start with uppercase):
|
|
6
|
+
# $ cppcheck --dump path-to-src/
|
|
7
|
+
# $ python addons/naming.py --var='[a-z].*' --function='[A-Z].*' path-to-src/*.dump
|
|
8
|
+
#
|
|
9
|
+
|
|
10
|
+
import cppcheckdata
|
|
11
|
+
import sys
|
|
12
|
+
import re
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def validate_regex(expr):
|
|
16
|
+
try:
|
|
17
|
+
re.compile(expr)
|
|
18
|
+
except re.error:
|
|
19
|
+
print('Error: "{}" is not a valid regular expression.'.format(expr))
|
|
20
|
+
sys.exit(1)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
RE_VARNAME = None
|
|
24
|
+
RE_CONSTNAME = None
|
|
25
|
+
RE_PRIVATE_MEMBER_VARIABLE = None
|
|
26
|
+
RE_FUNCTIONNAME = None
|
|
27
|
+
for arg in sys.argv[1:]:
|
|
28
|
+
if arg[:6] == '--var=':
|
|
29
|
+
RE_VARNAME = arg[6:]
|
|
30
|
+
validate_regex(RE_VARNAME)
|
|
31
|
+
elif arg.startswith('--const='):
|
|
32
|
+
RE_CONSTNAME = arg[arg.find('=')+1:]
|
|
33
|
+
validate_regex(RE_CONSTNAME)
|
|
34
|
+
elif arg.startswith('--private-member-variable='):
|
|
35
|
+
RE_PRIVATE_MEMBER_VARIABLE = arg[arg.find('=')+1:]
|
|
36
|
+
validate_regex(RE_PRIVATE_MEMBER_VARIABLE)
|
|
37
|
+
elif arg[:11] == '--function=':
|
|
38
|
+
RE_FUNCTIONNAME = arg[11:]
|
|
39
|
+
validate_regex(RE_FUNCTIONNAME)
|
|
40
|
+
# TODO: bail out on unknown parameter
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def reportError(token, severity, msg, errorId):
|
|
44
|
+
cppcheckdata.reportError(token, severity, msg, 'naming', errorId)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
for arg in sys.argv[1:]:
|
|
48
|
+
if not arg.endswith('.dump'):
|
|
49
|
+
continue
|
|
50
|
+
print('Checking ' + arg + '...')
|
|
51
|
+
data = cppcheckdata.CppcheckData(arg)
|
|
52
|
+
|
|
53
|
+
for cfg in data.iterconfigurations():
|
|
54
|
+
print('Checking %s, config %s...' % (arg, cfg.name))
|
|
55
|
+
if RE_VARNAME:
|
|
56
|
+
for var in cfg.variables:
|
|
57
|
+
if var.access == 'Private':
|
|
58
|
+
continue
|
|
59
|
+
if var.nameToken and not var.isConst:
|
|
60
|
+
res = re.match(RE_VARNAME, var.nameToken.str)
|
|
61
|
+
if not res:
|
|
62
|
+
reportError(var.typeStartToken, 'style', 'Variable ' +
|
|
63
|
+
var.nameToken.str + ' violates naming convention', 'varname')
|
|
64
|
+
if RE_CONSTNAME:
|
|
65
|
+
for var in cfg.variables:
|
|
66
|
+
if var.access == 'Private':
|
|
67
|
+
continue
|
|
68
|
+
if var.nameToken and var.isConst:
|
|
69
|
+
res = re.match(RE_CONSTNAME, var.nameToken.str)
|
|
70
|
+
if not res:
|
|
71
|
+
reportError(var.typeStartToken, 'style', 'Constant ' +
|
|
72
|
+
var.nameToken.str + ' violates naming convention', 'constname')
|
|
73
|
+
if RE_PRIVATE_MEMBER_VARIABLE:
|
|
74
|
+
for var in cfg.variables:
|
|
75
|
+
if (var.access is None) or var.access != 'Private':
|
|
76
|
+
continue
|
|
77
|
+
res = re.match(RE_PRIVATE_MEMBER_VARIABLE, var.nameToken.str)
|
|
78
|
+
if not res:
|
|
79
|
+
reportError(var.typeStartToken, 'style', 'Private member variable ' +
|
|
80
|
+
var.nameToken.str + ' violates naming convention', 'privateMemberVariable')
|
|
81
|
+
if RE_FUNCTIONNAME:
|
|
82
|
+
for scope in cfg.scopes:
|
|
83
|
+
if scope.type == 'Function':
|
|
84
|
+
function = scope.function
|
|
85
|
+
if function is not None and function.type in ('Constructor', 'Destructor', 'CopyConstructor', 'MoveConstructor'):
|
|
86
|
+
continue
|
|
87
|
+
res = re.match(RE_FUNCTIONNAME, scope.className)
|
|
88
|
+
if not res:
|
|
89
|
+
reportError(
|
|
90
|
+
scope.bodyStart, 'style', 'Function ' + scope.className + ' violates naming convention', 'functionName')
|
|
91
|
+
|
|
92
|
+
sys.exit(cppcheckdata.EXIT_CODE)
|