cppcheck-py 2.19.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.
Files changed (84) hide show
  1. cppcheck/__init__.py +55 -0
  2. cppcheck/cppcheck-2.19.0.tar.gz +0 -0
  3. cppcheck/data/addons/__init__.py +0 -0
  4. cppcheck/data/addons/cppcheck.py +41 -0
  5. cppcheck/data/addons/cppcheckdata.py +1727 -0
  6. cppcheck/data/addons/findcasts.py +32 -0
  7. cppcheck/data/addons/misc.py +163 -0
  8. cppcheck/data/addons/misra.py +5153 -0
  9. cppcheck/data/addons/misra_9.py +559 -0
  10. cppcheck/data/addons/naming.py +92 -0
  11. cppcheck/data/addons/namingng.py +420 -0
  12. cppcheck/data/addons/runaddon.py +16 -0
  13. cppcheck/data/addons/threadsafety.py +350 -0
  14. cppcheck/data/addons/y2038.py +602 -0
  15. cppcheck/data/cfg/avr.cfg +402 -0
  16. cppcheck/data/cfg/bento4.cfg +142 -0
  17. cppcheck/data/cfg/boost.cfg +1284 -0
  18. cppcheck/data/cfg/bsd.cfg +567 -0
  19. cppcheck/data/cfg/cairo.cfg +89 -0
  20. cppcheck/data/cfg/cppcheck-lib.cfg +72 -0
  21. cppcheck/data/cfg/cppunit.cfg +48 -0
  22. cppcheck/data/cfg/dpdk.cfg +11 -0
  23. cppcheck/data/cfg/embedded_sql.cfg +4 -0
  24. cppcheck/data/cfg/emscripten.cfg +108 -0
  25. cppcheck/data/cfg/ginac.cfg +12848 -0
  26. cppcheck/data/cfg/gnu.cfg +1738 -0
  27. cppcheck/data/cfg/googletest.cfg +62 -0
  28. cppcheck/data/cfg/gtk.cfg +23082 -0
  29. cppcheck/data/cfg/icu.cfg +221 -0
  30. cppcheck/data/cfg/kde.cfg +92 -0
  31. cppcheck/data/cfg/libcerror.cfg +203 -0
  32. cppcheck/data/cfg/libcurl.cfg +487 -0
  33. cppcheck/data/cfg/libsigc++.cfg +36 -0
  34. cppcheck/data/cfg/lua.cfg +316 -0
  35. cppcheck/data/cfg/mfc.cfg +271 -0
  36. cppcheck/data/cfg/microsoft_atl.cfg +40 -0
  37. cppcheck/data/cfg/microsoft_sal.cfg +490 -0
  38. cppcheck/data/cfg/microsoft_unittest.cfg +20 -0
  39. cppcheck/data/cfg/motif.cfg +318 -0
  40. cppcheck/data/cfg/nspr.cfg +38 -0
  41. cppcheck/data/cfg/ntl.cfg +6907 -0
  42. cppcheck/data/cfg/opencv2.cfg +132 -0
  43. cppcheck/data/cfg/opengl.cfg +581 -0
  44. cppcheck/data/cfg/openmp.cfg +157 -0
  45. cppcheck/data/cfg/openssl.cfg +174 -0
  46. cppcheck/data/cfg/pcre.cfg +165 -0
  47. cppcheck/data/cfg/posix.cfg +6445 -0
  48. cppcheck/data/cfg/protobuf.cfg +10 -0
  49. cppcheck/data/cfg/python.cfg +674 -0
  50. cppcheck/data/cfg/qt.cfg +5502 -0
  51. cppcheck/data/cfg/ruby.cfg +142 -0
  52. cppcheck/data/cfg/sdl.cfg +354 -0
  53. cppcheck/data/cfg/selinux.cfg +3621 -0
  54. cppcheck/data/cfg/sfml.cfg +301 -0
  55. cppcheck/data/cfg/sqlite3.cfg +1571 -0
  56. cppcheck/data/cfg/std.cfg +9205 -0
  57. cppcheck/data/cfg/tinyxml2.cfg +37 -0
  58. cppcheck/data/cfg/vcl.cfg +4 -0
  59. cppcheck/data/cfg/windows.cfg +17237 -0
  60. cppcheck/data/cfg/wxsqlite3.cfg +1955 -0
  61. cppcheck/data/cfg/wxsvg.cfg +16905 -0
  62. cppcheck/data/cfg/wxwidgets.cfg +17245 -0
  63. cppcheck/data/cfg/zephyr.cfg +113 -0
  64. cppcheck/data/cfg/zlib.cfg +1450 -0
  65. cppcheck/data/cppcheck-htmlreport +1157 -0
  66. cppcheck/data/cppcheck.exe +0 -0
  67. cppcheck/data/platforms/aix_ppc64.xml +18 -0
  68. cppcheck/data/platforms/arm32-wchar_t2.xml +18 -0
  69. cppcheck/data/platforms/arm32-wchar_t4.xml +18 -0
  70. cppcheck/data/platforms/arm64-wchar_t2.xml +18 -0
  71. cppcheck/data/platforms/arm64-wchar_t4.xml +18 -0
  72. cppcheck/data/platforms/avr8.xml +18 -0
  73. cppcheck/data/platforms/cray_sv1.xml +18 -0
  74. cppcheck/data/platforms/elbrus-e1cp.xml +18 -0
  75. cppcheck/data/platforms/mips32.xml +18 -0
  76. cppcheck/data/platforms/msp430_eabi_large_datamodel.xml +18 -0
  77. cppcheck/data/platforms/pic16.xml +18 -0
  78. cppcheck/data/platforms/pic8-enhanced.xml +18 -0
  79. cppcheck/data/platforms/pic8.xml +18 -0
  80. cppcheck_py-2.19.0.dist-info/METADATA +76 -0
  81. cppcheck_py-2.19.0.dist-info/RECORD +84 -0
  82. cppcheck_py-2.19.0.dist-info/WHEEL +5 -0
  83. cppcheck_py-2.19.0.dist-info/entry_points.txt +4 -0
  84. cppcheck_py-2.19.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)