@specs-feup/clava-misra 1.0.2 → 1.0.4

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 (322) hide show
  1. package/.gitignore +8 -0
  2. package/README.md +53 -19
  3. package/dist/MISRA.d.ts +28 -10
  4. package/dist/MISRA.d.ts.map +1 -1
  5. package/dist/MISRA.js +30 -10
  6. package/dist/MISRA.js.map +1 -1
  7. package/dist/MISRAContext.d.ts +65 -11
  8. package/dist/MISRAContext.d.ts.map +1 -1
  9. package/dist/MISRAContext.js +131 -35
  10. package/dist/MISRAContext.js.map +1 -1
  11. package/dist/MISRARule.d.ts +38 -25
  12. package/dist/MISRARule.d.ts.map +1 -1
  13. package/dist/MISRARule.js +40 -18
  14. package/dist/MISRARule.js.map +1 -1
  15. package/dist/MISRATool.d.ts +46 -5
  16. package/dist/MISRATool.d.ts.map +1 -1
  17. package/dist/MISRATool.js +118 -45
  18. package/dist/MISRATool.js.map +1 -1
  19. package/dist/StandardGuideline.d.ts +22 -0
  20. package/dist/StandardGuideline.d.ts.map +1 -0
  21. package/dist/StandardGuideline.js +12 -0
  22. package/dist/StandardGuideline.js.map +1 -0
  23. package/dist/ast-visitor/Context.d.ts +11 -0
  24. package/dist/ast-visitor/Context.d.ts.map +1 -0
  25. package/dist/ast-visitor/Context.js +15 -0
  26. package/dist/ast-visitor/Context.js.map +1 -0
  27. package/dist/ast-visitor/Visit.d.ts +23 -0
  28. package/dist/ast-visitor/Visit.d.ts.map +1 -0
  29. package/dist/ast-visitor/Visit.js +18 -0
  30. package/dist/ast-visitor/Visit.js.map +1 -0
  31. package/dist/ast-visitor/VisitWithContext.d.ts +32 -0
  32. package/dist/ast-visitor/VisitWithContext.d.ts.map +1 -0
  33. package/dist/ast-visitor/VisitWithContext.js +26 -0
  34. package/dist/ast-visitor/VisitWithContext.js.map +1 -0
  35. package/dist/main.js +1 -2
  36. package/dist/main.js.map +1 -1
  37. package/dist/rules/Section13_SideEffects/Rule_13_6_SafeSizeOfOperand.d.ts +27 -0
  38. package/dist/rules/Section13_SideEffects/Rule_13_6_SafeSizeOfOperand.d.ts.map +1 -0
  39. package/dist/rules/Section13_SideEffects/Rule_13_6_SafeSizeOfOperand.js +98 -0
  40. package/dist/rules/Section13_SideEffects/Rule_13_6_SafeSizeOfOperand.js.map +1 -0
  41. package/dist/rules/Section16_SwitchStatements/Rule_16_2_TopLevelSwitch.d.ts +45 -6
  42. package/dist/rules/Section16_SwitchStatements/Rule_16_2_TopLevelSwitch.d.ts.map +1 -1
  43. package/dist/rules/Section16_SwitchStatements/Rule_16_2_TopLevelSwitch.js +91 -8
  44. package/dist/rules/Section16_SwitchStatements/Rule_16_2_TopLevelSwitch.js.map +1 -1
  45. package/dist/rules/Section16_SwitchStatements/Rule_16_3_UnconditionalBreak.d.ts +15 -5
  46. package/dist/rules/Section16_SwitchStatements/Rule_16_3_UnconditionalBreak.d.ts.map +1 -1
  47. package/dist/rules/Section16_SwitchStatements/Rule_16_3_UnconditionalBreak.js +20 -6
  48. package/dist/rules/Section16_SwitchStatements/Rule_16_3_UnconditionalBreak.js.map +1 -1
  49. package/dist/rules/Section16_SwitchStatements/Rule_16_4_SwitchHasDefault.d.ts +11 -5
  50. package/dist/rules/Section16_SwitchStatements/Rule_16_4_SwitchHasDefault.d.ts.map +1 -1
  51. package/dist/rules/Section16_SwitchStatements/Rule_16_4_SwitchHasDefault.js +13 -10
  52. package/dist/rules/Section16_SwitchStatements/Rule_16_4_SwitchHasDefault.js.map +1 -1
  53. package/dist/rules/Section16_SwitchStatements/Rule_16_5_DefaultFirstOrLast.d.ts +11 -6
  54. package/dist/rules/Section16_SwitchStatements/Rule_16_5_DefaultFirstOrLast.d.ts.map +1 -1
  55. package/dist/rules/Section16_SwitchStatements/Rule_16_5_DefaultFirstOrLast.js +19 -11
  56. package/dist/rules/Section16_SwitchStatements/Rule_16_5_DefaultFirstOrLast.js.map +1 -1
  57. package/dist/rules/Section16_SwitchStatements/Rule_16_6_SwitchMinTwoClauses.d.ts +15 -5
  58. package/dist/rules/Section16_SwitchStatements/Rule_16_6_SwitchMinTwoClauses.d.ts.map +1 -1
  59. package/dist/rules/Section16_SwitchStatements/Rule_16_6_SwitchMinTwoClauses.js +24 -10
  60. package/dist/rules/Section16_SwitchStatements/Rule_16_6_SwitchMinTwoClauses.js.map +1 -1
  61. package/dist/rules/Section16_SwitchStatements/Rule_16_7_NonBooleanSwitchCondition.d.ts +22 -6
  62. package/dist/rules/Section16_SwitchStatements/Rule_16_7_NonBooleanSwitchCondition.d.ts.map +1 -1
  63. package/dist/rules/Section16_SwitchStatements/Rule_16_7_NonBooleanSwitchCondition.js +37 -10
  64. package/dist/rules/Section16_SwitchStatements/Rule_16_7_NonBooleanSwitchCondition.js.map +1 -1
  65. package/dist/rules/Section17_Functions/Rule_17_3_ImplicitFunction.d.ts +66 -0
  66. package/dist/rules/Section17_Functions/Rule_17_3_ImplicitFunction.d.ts.map +1 -0
  67. package/dist/rules/Section17_Functions/Rule_17_3_ImplicitFunction.js +209 -0
  68. package/dist/rules/Section17_Functions/Rule_17_3_ImplicitFunction.js.map +1 -0
  69. package/dist/rules/Section17_Functions/Rule_17_4_NonVoidReturn.d.ts +37 -12
  70. package/dist/rules/Section17_Functions/Rule_17_4_NonVoidReturn.d.ts.map +1 -1
  71. package/dist/rules/Section17_Functions/Rule_17_4_NonVoidReturn.js +112 -39
  72. package/dist/rules/Section17_Functions/Rule_17_4_NonVoidReturn.js.map +1 -1
  73. package/dist/rules/Section17_Functions/Rule_17_6_StaticArraySizeParam.d.ts +15 -5
  74. package/dist/rules/Section17_Functions/Rule_17_6_StaticArraySizeParam.d.ts.map +1 -1
  75. package/dist/rules/Section17_Functions/Rule_17_6_StaticArraySizeParam.js +21 -7
  76. package/dist/rules/Section17_Functions/Rule_17_6_StaticArraySizeParam.js.map +1 -1
  77. package/dist/rules/Section17_Functions/Rule_17_7_UnusedReturnValue.d.ts +11 -6
  78. package/dist/rules/Section17_Functions/Rule_17_7_UnusedReturnValue.d.ts.map +1 -1
  79. package/dist/rules/Section17_Functions/Rule_17_7_UnusedReturnValue.js +17 -8
  80. package/dist/rules/Section17_Functions/Rule_17_7_UnusedReturnValue.js.map +1 -1
  81. package/dist/rules/Section21-StandardLibraries/DisallowedStdLibFunctionRule.d.ts +105 -0
  82. package/dist/rules/Section21-StandardLibraries/DisallowedStdLibFunctionRule.d.ts.map +1 -0
  83. package/dist/rules/Section21-StandardLibraries/DisallowedStdLibFunctionRule.js +258 -0
  84. package/dist/rules/Section21-StandardLibraries/DisallowedStdLibFunctionRule.js.map +1 -0
  85. package/dist/rules/Section21-StandardLibraries/Rule_21_10_NoTimeDateFunctions.d.ts +25 -0
  86. package/dist/rules/Section21-StandardLibraries/Rule_21_10_NoTimeDateFunctions.d.ts.map +1 -0
  87. package/dist/rules/Section21-StandardLibraries/Rule_21_10_NoTimeDateFunctions.js +27 -0
  88. package/dist/rules/Section21-StandardLibraries/Rule_21_10_NoTimeDateFunctions.js.map +1 -0
  89. package/dist/rules/Section21-StandardLibraries/Rule_21_11_NoTgmathFunctions.d.ts +29 -0
  90. package/dist/rules/Section21-StandardLibraries/Rule_21_11_NoTgmathFunctions.d.ts.map +1 -0
  91. package/dist/rules/Section21-StandardLibraries/Rule_21_11_NoTgmathFunctions.js +31 -0
  92. package/dist/rules/Section21-StandardLibraries/Rule_21_11_NoTgmathFunctions.js.map +1 -0
  93. package/dist/rules/Section21-StandardLibraries/Rule_21_3_NoDynamicMemory.d.ts +25 -0
  94. package/dist/rules/Section21-StandardLibraries/Rule_21_3_NoDynamicMemory.d.ts.map +1 -0
  95. package/dist/rules/Section21-StandardLibraries/Rule_21_3_NoDynamicMemory.js +27 -0
  96. package/dist/rules/Section21-StandardLibraries/Rule_21_3_NoDynamicMemory.js.map +1 -0
  97. package/dist/rules/Section21-StandardLibraries/Rule_21_6_NoStdIOFunctions.d.ts +25 -0
  98. package/dist/rules/Section21-StandardLibraries/Rule_21_6_NoStdIOFunctions.d.ts.map +1 -0
  99. package/dist/rules/Section21-StandardLibraries/Rule_21_6_NoStdIOFunctions.js +27 -0
  100. package/dist/rules/Section21-StandardLibraries/Rule_21_6_NoStdIOFunctions.js.map +1 -0
  101. package/dist/rules/Section21-StandardLibraries/Rule_21_7_NoNumericStringConversions.d.ts +25 -0
  102. package/dist/rules/Section21-StandardLibraries/Rule_21_7_NoNumericStringConversions.d.ts.map +1 -0
  103. package/dist/rules/Section21-StandardLibraries/Rule_21_7_NoNumericStringConversions.js +27 -0
  104. package/dist/rules/Section21-StandardLibraries/Rule_21_7_NoNumericStringConversions.js.map +1 -0
  105. package/dist/rules/Section21-StandardLibraries/Rule_21_8_NoProcessControlFunctions.d.ts +30 -0
  106. package/dist/rules/Section21-StandardLibraries/Rule_21_8_NoProcessControlFunctions.d.ts.map +1 -0
  107. package/dist/rules/Section21-StandardLibraries/Rule_21_8_NoProcessControlFunctions.js +32 -0
  108. package/dist/rules/Section21-StandardLibraries/Rule_21_8_NoProcessControlFunctions.js.map +1 -0
  109. package/dist/rules/Section21-StandardLibraries/Rule_21_9_NoGenericSearchOrSort.d.ts +25 -0
  110. package/dist/rules/Section21-StandardLibraries/Rule_21_9_NoGenericSearchOrSort.d.ts.map +1 -0
  111. package/dist/rules/Section21-StandardLibraries/Rule_21_9_NoGenericSearchOrSort.js +27 -0
  112. package/dist/rules/Section21-StandardLibraries/Rule_21_9_NoGenericSearchOrSort.js.map +1 -0
  113. package/dist/rules/Section2_UnusedCode/Rule_2_3_UnusedTypeDecl.d.ts +6 -14
  114. package/dist/rules/Section2_UnusedCode/Rule_2_3_UnusedTypeDecl.d.ts.map +1 -1
  115. package/dist/rules/Section2_UnusedCode/Rule_2_3_UnusedTypeDecl.js +17 -27
  116. package/dist/rules/Section2_UnusedCode/Rule_2_3_UnusedTypeDecl.js.map +1 -1
  117. package/dist/rules/Section2_UnusedCode/Rule_2_4_UnusedTagDecl.d.ts +13 -7
  118. package/dist/rules/Section2_UnusedCode/Rule_2_4_UnusedTagDecl.d.ts.map +1 -1
  119. package/dist/rules/Section2_UnusedCode/Rule_2_4_UnusedTagDecl.js +31 -17
  120. package/dist/rules/Section2_UnusedCode/Rule_2_4_UnusedTagDecl.js.map +1 -1
  121. package/dist/rules/Section2_UnusedCode/Rule_2_6_UnusedLabels.d.ts +26 -7
  122. package/dist/rules/Section2_UnusedCode/Rule_2_6_UnusedLabels.d.ts.map +1 -1
  123. package/dist/rules/Section2_UnusedCode/Rule_2_6_UnusedLabels.js +32 -14
  124. package/dist/rules/Section2_UnusedCode/Rule_2_6_UnusedLabels.js.map +1 -1
  125. package/dist/rules/Section2_UnusedCode/Rule_2_7_UnusedParameters.d.ts +48 -6
  126. package/dist/rules/Section2_UnusedCode/Rule_2_7_UnusedParameters.d.ts.map +1 -1
  127. package/dist/rules/Section2_UnusedCode/Rule_2_7_UnusedParameters.js +84 -34
  128. package/dist/rules/Section2_UnusedCode/Rule_2_7_UnusedParameters.js.map +1 -1
  129. package/dist/rules/Section3_Comments/Rule_3_1_CommentSequences.d.ts +24 -5
  130. package/dist/rules/Section3_Comments/Rule_3_1_CommentSequences.d.ts.map +1 -1
  131. package/dist/rules/Section3_Comments/Rule_3_1_CommentSequences.js +27 -7
  132. package/dist/rules/Section3_Comments/Rule_3_1_CommentSequences.js.map +1 -1
  133. package/dist/rules/Section5_Identifiers/IdentifierRenameRule.d.ts +46 -0
  134. package/dist/rules/Section5_Identifiers/IdentifierRenameRule.d.ts.map +1 -0
  135. package/dist/rules/Section5_Identifiers/IdentifierRenameRule.js +40 -0
  136. package/dist/rules/Section5_Identifiers/IdentifierRenameRule.js.map +1 -0
  137. package/dist/rules/Section5_Identifiers/Rule_5_1_DistinctExternalIdentifiers.d.ts +25 -0
  138. package/dist/rules/Section5_Identifiers/Rule_5_1_DistinctExternalIdentifiers.d.ts.map +1 -0
  139. package/dist/rules/Section5_Identifiers/Rule_5_1_DistinctExternalIdentifiers.js +46 -0
  140. package/dist/rules/Section5_Identifiers/Rule_5_1_DistinctExternalIdentifiers.js.map +1 -0
  141. package/dist/rules/Section5_Identifiers/Rule_5_6_UniqueTypedefNames.d.ts +26 -0
  142. package/dist/rules/Section5_Identifiers/Rule_5_6_UniqueTypedefNames.d.ts.map +1 -0
  143. package/dist/rules/Section5_Identifiers/Rule_5_6_UniqueTypedefNames.js +54 -0
  144. package/dist/rules/Section5_Identifiers/Rule_5_6_UniqueTypedefNames.js.map +1 -0
  145. package/dist/rules/Section5_Identifiers/Rule_5_7_UniqueTagNames.d.ts +27 -0
  146. package/dist/rules/Section5_Identifiers/Rule_5_7_UniqueTagNames.d.ts.map +1 -0
  147. package/dist/rules/Section5_Identifiers/Rule_5_7_UniqueTagNames.js +55 -0
  148. package/dist/rules/Section5_Identifiers/Rule_5_7_UniqueTagNames.js.map +1 -0
  149. package/dist/rules/Section5_Identifiers/Rule_5_8_UniqueExternalLinkIdentifiers.d.ts +24 -0
  150. package/dist/rules/Section5_Identifiers/Rule_5_8_UniqueExternalLinkIdentifiers.d.ts.map +1 -0
  151. package/dist/rules/Section5_Identifiers/Rule_5_8_UniqueExternalLinkIdentifiers.js +42 -0
  152. package/dist/rules/Section5_Identifiers/Rule_5_8_UniqueExternalLinkIdentifiers.js.map +1 -0
  153. package/dist/rules/Section5_Identifiers/Rule_5_9_UniqueInternalLinkIdentifiers.d.ts +24 -0
  154. package/dist/rules/Section5_Identifiers/Rule_5_9_UniqueInternalLinkIdentifiers.d.ts.map +1 -0
  155. package/dist/rules/Section5_Identifiers/Rule_5_9_UniqueInternalLinkIdentifiers.js +42 -0
  156. package/dist/rules/Section5_Identifiers/Rule_5_9_UniqueInternalLinkIdentifiers.js.map +1 -0
  157. package/dist/rules/Section8_DeclarationsAndDefinitions/Rule_8_6_SingleExternalDefinition.d.ts +35 -0
  158. package/dist/rules/Section8_DeclarationsAndDefinitions/Rule_8_6_SingleExternalDefinition.d.ts.map +1 -0
  159. package/dist/rules/Section8_DeclarationsAndDefinitions/Rule_8_6_SingleExternalDefinition.js +98 -0
  160. package/dist/rules/Section8_DeclarationsAndDefinitions/Rule_8_6_SingleExternalDefinition.js.map +1 -0
  161. package/dist/rules/Section8_DeclarationsAndDefinitions/Rule_8_7_RestrictExternalLinkage.d.ts +35 -0
  162. package/dist/rules/Section8_DeclarationsAndDefinitions/Rule_8_7_RestrictExternalLinkage.d.ts.map +1 -0
  163. package/dist/rules/Section8_DeclarationsAndDefinitions/Rule_8_7_RestrictExternalLinkage.js +76 -0
  164. package/dist/rules/Section8_DeclarationsAndDefinitions/Rule_8_7_RestrictExternalLinkage.js.map +1 -0
  165. package/dist/rules/Section8_DeclarationsAndDefinitions/Rule_8_9_BlockScopeDefinition.d.ts +32 -0
  166. package/dist/rules/Section8_DeclarationsAndDefinitions/Rule_8_9_BlockScopeDefinition.d.ts.map +1 -0
  167. package/dist/rules/Section8_DeclarationsAndDefinitions/Rule_8_9_BlockScopeDefinition.js +57 -0
  168. package/dist/rules/Section8_DeclarationsAndDefinitions/Rule_8_9_BlockScopeDefinition.js.map +1 -0
  169. package/dist/rules/UserConfigurableRule.d.ts +55 -0
  170. package/dist/rules/UserConfigurableRule.d.ts.map +1 -0
  171. package/dist/rules/UserConfigurableRule.js +16 -0
  172. package/dist/rules/UserConfigurableRule.js.map +1 -0
  173. package/dist/rules/index.d.ts +11 -18
  174. package/dist/rules/index.d.ts.map +1 -1
  175. package/dist/rules/index.js +47 -7
  176. package/dist/rules/index.js.map +1 -1
  177. package/dist/tests/Section17_Functions/misra_config.json +10 -0
  178. package/dist/tests/Section21-StandardLibraries/misra_config.json +88 -0
  179. package/dist/tests/Section21-StandardLibraries/problematic_misra_config.json +19 -0
  180. package/dist/tests/utils.d.ts +6 -3
  181. package/dist/tests/utils.d.ts.map +1 -1
  182. package/dist/tests/utils.js +33 -7
  183. package/dist/tests/utils.js.map +1 -1
  184. package/dist/utils/CallUtils.d.ts +15 -0
  185. package/dist/utils/CallUtils.d.ts.map +1 -0
  186. package/dist/utils/CallUtils.js +34 -0
  187. package/dist/utils/CallUtils.js.map +1 -0
  188. package/dist/utils/CommentUtils.d.ts +21 -0
  189. package/dist/utils/CommentUtils.d.ts.map +1 -0
  190. package/dist/utils/CommentUtils.js +27 -0
  191. package/dist/utils/CommentUtils.js.map +1 -0
  192. package/dist/utils/FileUtils.d.ts +67 -0
  193. package/dist/utils/FileUtils.d.ts.map +1 -0
  194. package/dist/utils/FileUtils.js +144 -0
  195. package/dist/utils/FileUtils.js.map +1 -0
  196. package/dist/utils/FunctionUtils.d.ts +47 -0
  197. package/dist/utils/FunctionUtils.d.ts.map +1 -0
  198. package/dist/utils/FunctionUtils.js +87 -0
  199. package/dist/utils/FunctionUtils.js.map +1 -0
  200. package/dist/utils/IdentifierUtils.d.ts +63 -0
  201. package/dist/utils/IdentifierUtils.d.ts.map +1 -0
  202. package/dist/utils/IdentifierUtils.js +133 -0
  203. package/dist/utils/IdentifierUtils.js.map +1 -0
  204. package/dist/utils/JoinpointUtils.d.ts +36 -0
  205. package/dist/utils/JoinpointUtils.d.ts.map +1 -0
  206. package/dist/utils/JoinpointUtils.js +63 -0
  207. package/dist/utils/JoinpointUtils.js.map +1 -0
  208. package/dist/utils/ProgramUtils.d.ts +39 -0
  209. package/dist/utils/ProgramUtils.d.ts.map +1 -0
  210. package/dist/utils/ProgramUtils.js +97 -0
  211. package/dist/utils/ProgramUtils.js.map +1 -0
  212. package/dist/utils/SwitchUtils.d.ts +21 -0
  213. package/dist/utils/SwitchUtils.d.ts.map +1 -0
  214. package/dist/utils/SwitchUtils.js +47 -0
  215. package/dist/utils/SwitchUtils.js.map +1 -0
  216. package/dist/utils/TypeDeclUtils.d.ts +35 -0
  217. package/dist/utils/TypeDeclUtils.d.ts.map +1 -0
  218. package/dist/utils/TypeDeclUtils.js +78 -0
  219. package/dist/utils/TypeDeclUtils.js.map +1 -0
  220. package/dist/utils/VarUtils.d.ts +51 -0
  221. package/dist/utils/VarUtils.d.ts.map +1 -0
  222. package/dist/utils/VarUtils.js +91 -0
  223. package/dist/utils/VarUtils.js.map +1 -0
  224. package/package.json +16 -7
  225. package/src/MISRA.ts +33 -17
  226. package/src/MISRAContext.ts +128 -30
  227. package/src/MISRARule.ts +61 -29
  228. package/src/MISRATool.ts +126 -42
  229. package/src/StandardGuideline.ts +23 -0
  230. package/src/ast-visitor/Context.ts +16 -0
  231. package/src/ast-visitor/Visit.ts +26 -0
  232. package/src/ast-visitor/VisitWithContext.ts +42 -0
  233. package/src/main.ts +1 -4
  234. package/src/rules/Section13_SideEffects/Rule_13_6_SafeSizeOfOperand.ts +114 -0
  235. package/src/rules/Section16_SwitchStatements/Rule_16_2_TopLevelSwitch.ts +103 -13
  236. package/src/rules/Section16_SwitchStatements/Rule_16_3_UnconditionalBreak.ts +24 -10
  237. package/src/rules/Section16_SwitchStatements/Rule_16_4_SwitchHasDefault.ts +17 -8
  238. package/src/rules/Section16_SwitchStatements/Rule_16_5_DefaultFirstOrLast.ts +20 -12
  239. package/src/rules/Section16_SwitchStatements/Rule_16_6_SwitchMinTwoClauses.ts +23 -12
  240. package/src/rules/Section16_SwitchStatements/Rule_16_7_NonBooleanSwitchCondition.ts +44 -13
  241. package/src/rules/Section17_Functions/Rule_17_3_ImplicitFunction.ts +153 -104
  242. package/src/rules/Section17_Functions/Rule_17_4_NonVoidReturn.ts +114 -44
  243. package/src/rules/Section17_Functions/Rule_17_6_StaticArraySizeParam.ts +27 -10
  244. package/src/rules/Section17_Functions/Rule_17_7_UnusedReturnValue.ts +20 -12
  245. package/src/rules/Section21-StandardLibraries/DisallowedStdLibFunctionRule.ts +317 -0
  246. package/src/rules/Section21-StandardLibraries/Rule_21_10_NoTimeDateFunctions.ts +30 -0
  247. package/src/rules/Section21-StandardLibraries/Rule_21_11_NoTgmathFunctions.ts +35 -0
  248. package/src/rules/Section21-StandardLibraries/Rule_21_3_NoDynamicMemory.ts +30 -0
  249. package/src/rules/Section21-StandardLibraries/Rule_21_6_NoStdIOFunctions.ts +30 -0
  250. package/src/rules/Section21-StandardLibraries/Rule_21_7_NoNumericStringConversions.ts +29 -0
  251. package/src/rules/Section21-StandardLibraries/Rule_21_8_NoProcessControlFunctions.ts +36 -0
  252. package/src/rules/Section21-StandardLibraries/Rule_21_9_NoGenericSearchOrSort.ts +30 -0
  253. package/src/rules/Section2_UnusedCode/Rule_2_3_UnusedTypeDecl.ts +14 -29
  254. package/src/rules/Section2_UnusedCode/Rule_2_4_UnusedTagDecl.ts +33 -19
  255. package/src/rules/Section2_UnusedCode/Rule_2_6_UnusedLabels.ts +33 -20
  256. package/src/rules/Section2_UnusedCode/Rule_2_7_UnusedParameters.ts +90 -45
  257. package/src/rules/Section3_Comments/Rule_3_1_CommentSequences.ts +27 -8
  258. package/src/rules/Section5_Identifiers/IdentifierRenameRule.ts +63 -0
  259. package/src/rules/Section5_Identifiers/Rule_5_1_DistinctExternalIdentifiers.ts +52 -0
  260. package/src/rules/Section5_Identifiers/Rule_5_6_UniqueTypedefNames.ts +62 -0
  261. package/src/rules/Section5_Identifiers/Rule_5_7_UniqueTagNames.ts +61 -0
  262. package/src/rules/Section5_Identifiers/Rule_5_8_UniqueExternalLinkIdentifiers.ts +47 -0
  263. package/src/rules/Section5_Identifiers/Rule_5_9_UniqueInternalLinkIdentifiers.ts +47 -0
  264. package/src/rules/Section8_DeclarationsAndDefinitions/Rule_8_6_SingleExternalDefinition.ts +118 -0
  265. package/src/rules/Section8_DeclarationsAndDefinitions/Rule_8_7_RestrictExternalLinkage.ts +89 -0
  266. package/src/rules/Section8_DeclarationsAndDefinitions/Rule_8_9_BlockScopeDefinition.ts +65 -0
  267. package/src/rules/UserConfigurableRule.ts +60 -0
  268. package/src/rules/index.ts +45 -7
  269. package/src/tests/Section13_SideEffects/Rule_13_6_SafeSizeOfOperand.test.ts +114 -0
  270. package/src/tests/Section16_SwitchStatements/Rule_16_2_TopLevelSwitch.test.ts +7 -5
  271. package/src/tests/Section16_SwitchStatements/Rule_16_3_UnconditionalBreak.test.ts +40 -13
  272. package/src/tests/Section16_SwitchStatements/Rule_16_4_SwitchHasDefault.test.ts +10 -12
  273. package/src/tests/Section16_SwitchStatements/Rule_16_5_DefaultFirstOrLast.test.ts +5 -5
  274. package/src/tests/Section16_SwitchStatements/Rule_16_6_SwitchMinTwoClauses.test.ts +5 -5
  275. package/src/tests/Section16_SwitchStatements/Rule_16_7_NonBooleanSwitchCondition.test.ts +5 -5
  276. package/src/tests/Section17_Functions/Rule_17_3_ImplicitFunctions.test.ts +68 -40
  277. package/src/tests/Section17_Functions/Rule_17_3_ImplicitFunctions_MissingConfig.test.ts +98 -0
  278. package/src/tests/Section17_Functions/Rule_17_3_ImplicitFunctions_ProblematicConfig.test.ts +71 -0
  279. package/src/tests/Section17_Functions/Rule_17_4_NonVoidReturn.test.ts +103 -49
  280. package/src/tests/Section17_Functions/Rule_17_4_NonVoidReturn_MissingConfig.test.ts +7 -7
  281. package/src/tests/Section17_Functions/Rule_17_6_StaticArraySizeParam.test.ts +36 -7
  282. package/src/tests/Section17_Functions/Rule_17_7_UnusedReturnValue.test.ts +25 -21
  283. package/src/tests/Section17_Functions/misra_config.json +4 -3
  284. package/src/tests/Section21-StandardLibraries/Rule_21_10_NoTimeDateFunctions.test.ts +62 -0
  285. package/src/tests/Section21-StandardLibraries/Rule_21_11_NoTgmathFunctions.test.ts +67 -0
  286. package/src/tests/Section21-StandardLibraries/Rule_21_3_NoDynamicMemory.test.ts +84 -0
  287. package/src/tests/Section21-StandardLibraries/Rule_21_3_NoDynamicMemory_MissingConfig.test.ts +33 -0
  288. package/src/tests/Section21-StandardLibraries/Rule_21_3_NoDynamicMemory_ProblematicConfig.test.ts +71 -0
  289. package/src/tests/Section21-StandardLibraries/Rule_21_6_NoStdIOFunctions.test.ts +63 -0
  290. package/src/tests/Section21-StandardLibraries/Rule_21_7_NoNumericStringConversions.test.ts +91 -0
  291. package/src/tests/Section21-StandardLibraries/Rule_21_8_NoProcessControlFunctions.test.ts +65 -0
  292. package/src/tests/Section21-StandardLibraries/Rule_21_9_NoGenericSearchOrSort.test.ts +89 -0
  293. package/src/tests/Section21-StandardLibraries/misra_config.json +88 -0
  294. package/src/tests/Section21-StandardLibraries/problematic_misra_config.json +19 -0
  295. package/src/tests/Section2_UnusedCode/Rule_2_3_UnusedTypeDecl.test.ts +148 -113
  296. package/src/tests/Section2_UnusedCode/Rule_2_4_UnusedTagDecl.test.ts +243 -163
  297. package/src/tests/Section2_UnusedCode/Rule_2_6_UnusedLabels.test.ts +32 -20
  298. package/src/tests/Section2_UnusedCode/Rule_2_7_UnusedParameters.test.ts +36 -30
  299. package/src/tests/Section3_Comments/Rule_3_1_CommentSequences.test.ts +37 -8
  300. package/src/tests/Section5_Identifiers/Rule_5_1_DistinctExternalIdentifiers.test.ts +78 -0
  301. package/src/tests/Section5_Identifiers/Rule_5_6_UniqueTypedefNames.test.ts +120 -0
  302. package/src/tests/Section5_Identifiers/Rule_5_7_UniqueTagNames.test.ts +51 -0
  303. package/src/tests/Section5_Identifiers/Rule_5_8_UniqueExternalLinkIdentifiers.test.ts +73 -0
  304. package/src/tests/Section5_Identifiers/Rule_5_9_UniqueInternalLinkIdentifiers.test.ts +97 -0
  305. package/src/tests/Section8_DeclarationsAndDefinitions/Rule_8_6_SingleExternalDefinition.test.ts +160 -0
  306. package/src/tests/Section8_DeclarationsAndDefinitions/Rule_8_7_RestrictExternalLinkage.test.ts +46 -0
  307. package/src/tests/Section8_DeclarationsAndDefinitions/Rule_8_9_BlockScopeDefinition.test.ts +69 -0
  308. package/src/tests/utils.ts +32 -7
  309. package/src/utils/CallUtils.ts +37 -0
  310. package/src/utils/CommentUtils.ts +29 -0
  311. package/src/utils/FileUtils.ts +169 -0
  312. package/src/utils/FunctionUtils.ts +97 -0
  313. package/src/utils/IdentifierUtils.ts +142 -0
  314. package/src/utils/JoinpointUtils.ts +70 -0
  315. package/src/utils/ProgramUtils.ts +107 -0
  316. package/src/utils/SwitchUtils.ts +52 -0
  317. package/src/utils/TypeDeclUtils.ts +88 -0
  318. package/src/utils/VarUtils.ts +102 -0
  319. package/tsconfig.json +2 -1
  320. package/src/rules/Section20-PreprocessingDirectives/Rule_20_2_InvalidHeaderFileName.ts +0 -120
  321. package/src/rules/Section3_Comments/Rule_3_2_LineSplicing.ts +0 -36
  322. package/src/utils/utils.ts +0 -280
@@ -1,67 +1,45 @@
1
1
  import { Call, FileJp, Joinpoint, Program } from "@specs-feup/clava/api/Joinpoints.js";
2
- import MISRARule from "../../MISRARule.js";
3
- import MISRAContext from "../../MISRAContext.js";
4
- import { MISRATransformationReport, MISRATransformationType } from "../../MISRA.js";
5
- import { getFilesWithCallToImplicitFunction, getIncludesOfFile, isCallToImplicitFunction, isValidFile, removeIncludeFromFile } from "../../utils/utils.js";
2
+ import { AnalysisType, MISRATransformationReport, MISRATransformationType } from "../../MISRA.js";
3
+ import { findFunctionDef } from "../../utils/FunctionUtils.js";
4
+ import { getCallIndex, isCallToImplicitFunction } from "../../utils/CallUtils.js";
6
5
  import Query from "@specs-feup/lara/api/weaver/Query.js";
7
- import ClavaJoinPoints from "@specs-feup/clava/api/clava/ClavaJoinPoints.js";
6
+ import { addExternFunctionDecl, getFilesWithCallToImplicitFunction, getIncludesOfFile, isValidFileWithExplicitCall, removeIncludeFromFile } from "../../utils/FileUtils.js";
7
+ import UserConfigurableRule from "../UserConfigurableRule.js";
8
8
 
9
9
  /**
10
- * MISRA Rule 17.3: A function shall not be declared implicitly
10
+ * MISRA-C Rule 17.3: A function shall not be declared implicitly
11
11
  */
12
- export default class Rule_17_3_ImplicitFunction extends MISRARule {
13
- priority = 1;
12
+ export default class Rule_17_3_ImplicitFunction extends UserConfigurableRule {
13
+ /**
14
+ * A positive integer starting from 1 that indicates the rule's priority, determining the order in which rules are applied.
15
+ */
16
+ readonly priority = 1;
14
17
 
15
- constructor(context: MISRAContext) {
16
- super("17.3", context);
17
- }
18
+ /**
19
+ * Scope of analysis
20
+ */
21
+ readonly analysisType = AnalysisType.SINGLE_TRANSLATION_UNIT;
18
22
 
19
23
  /**
20
- * Checks if the given joinpoint represents a call to an implicit function.
21
- *
22
- * @param $jp - Joinpoint to analyze
23
- * @param logErrors - [logErrors=false] - Whether to log errors if a violation is detected
24
- * @returns Returns true if the joinpoint violates the rule, false otherwise
24
+ * Standards to which this rule applies to
25
25
  */
26
- match($jp: Joinpoint, logErrors: boolean = false): boolean {
27
- if (!($jp instanceof Program)) return false;
28
-
29
- const implicitCalls = Query.searchFrom($jp, Call, (callJp) => isCallToImplicitFunction(callJp)). get();
30
- for (const callJp of implicitCalls) {
31
- if (logErrors) {
32
- this.logMISRAError(callJp, `Function '${callJp.name}' is declared implicitly.`);
33
- }
34
- }
35
- return implicitCalls.length > 0;
26
+ protected override readonly appliesTo = new Set(["c90"]);
27
+
28
+ /**
29
+ * @returns Rule identifier according to MISRA-C:2012
30
+ */
31
+ override get name(): string {
32
+ return "17.3";
36
33
  }
37
34
 
38
35
  /**
39
- * Transforms every implicit call by adding a missing include directive or extern statement specified on the config file.
40
- *
41
- * - If the configuration is missing or the specified fix is invalid (i.e., not a '.h' or '.c'), no transformation is performed and the call is left unchanged.
42
- * - The fix is applied only if it successfully resolves the issue (i.e., makes the call explicit and the file compiles with no error).
43
- * - Otherwise, the fix is removed.
36
+ * Returns the prefix to be used for error messages related to the given joinpoint
44
37
  *
45
- * @param $jp - Joinpoint to transform
46
- * @returns Report detailing the transformation result
38
+ * @param $jp - Joinpoint where the violation was detected
39
+ * @returns Returns a prefix to prepend to error messages if no configuration is specified or if the configuration does not contain a fix for this violation
47
40
  */
48
- transform($jp: Joinpoint): MISRATransformationReport {
49
- if (!this.match($jp)) return new MISRATransformationReport(MISRATransformationType.NoChange);
50
-
51
- const programJp = $jp as Program;
52
- const filesWithImplicitCall = getFilesWithCallToImplicitFunction(programJp);
53
- let changedDescendant = false;
54
-
55
- for (const fileJp of filesWithImplicitCall) {
56
- changedDescendant = changedDescendant || this.solveImplicitCalls(fileJp);
57
- }
58
-
59
- if (changedDescendant) {
60
- programJp.rebuild();
61
- return new MISRATransformationReport(MISRATransformationType.Replacement, Query.root() as Program);
62
- } else {
63
- return new MISRATransformationReport(MISRATransformationType.NoChange);
64
- }
41
+ getErrorMsgPrefix(callJp: Call): string {
42
+ return `Function '${callJp.name}' is declared implicitly.`;
65
43
  }
66
44
 
67
45
  /**
@@ -70,7 +48,9 @@ export default class Rule_17_3_ImplicitFunction extends MISRARule {
70
48
  * @param errorMsgPrefix
71
49
  * @returns
72
50
  */
73
- private getImplicitFixFromConfig(callJp: Call, errorMsgPrefix: string): string | undefined {
51
+ getFixFromConfig(callJp: Call): string | undefined {
52
+ const errorMsgPrefix = this.getErrorMsgPrefix(callJp);
53
+
74
54
  if (!this.context.config) {
75
55
  this.logMISRAError(callJp, `${errorMsgPrefix} Include or extern not added due to missing config file.`);
76
56
  return undefined;
@@ -96,6 +76,57 @@ export default class Rule_17_3_ImplicitFunction extends MISRARule {
96
76
  return configFix;
97
77
  }
98
78
 
79
+ /**
80
+ * Checks if the given joinpoint represents a call to an implicit function.
81
+ *
82
+ * @param $jp - Joinpoint to analyze
83
+ * @param logErrors - [logErrors=false] - Whether to log errors if a violation is detected
84
+ * @returns Returns true if the joinpoint violates the rule, false otherwise
85
+ */
86
+ match($jp: Joinpoint, logErrors: boolean = false): boolean {
87
+ if (!($jp instanceof Program && this.appliesToCurrentStandard())) return false;
88
+
89
+ const implicitCalls = Query.searchFrom($jp, Call, (callJp) => isCallToImplicitFunction(callJp)). get();
90
+ if (logErrors) {
91
+ for (const callJp of implicitCalls) {
92
+ this.logMISRAError(callJp, this.getErrorMsgPrefix(callJp));
93
+ }
94
+ }
95
+
96
+ return implicitCalls.length > 0;
97
+ }
98
+
99
+ /**
100
+ * Transforms every implicit call by adding a missing include directive or extern statement specified on the config file.
101
+ *
102
+ * - If the configuration is missing or the specified fix is invalid (i.e., not a '.h' or '.c' file), no transformation is performed and the call is left unchanged.
103
+ * - The fix is applied only if it successfully resolves the issue (i.e., makes the call explicit and the file compiles with no error).
104
+ * - Otherwise, the fix is removed.
105
+ *
106
+ * @param $jp - Joinpoint to transform
107
+ * @returns Report detailing the transformation result
108
+ */
109
+ apply($jp: Joinpoint): MISRATransformationReport {
110
+ if (!this.match($jp))
111
+ return new MISRATransformationReport(MISRATransformationType.NoChange);
112
+
113
+ const filesWithImplicitCall = getFilesWithCallToImplicitFunction($jp as Program);
114
+ let changedDescendant = false;
115
+
116
+ for (const fileJp of filesWithImplicitCall) {
117
+ if (this.solveImplicitCalls(fileJp)) {
118
+ changedDescendant = true;
119
+ }
120
+ }
121
+
122
+ if (changedDescendant) {
123
+ this.rebuildProgram();
124
+ return new MISRATransformationReport(MISRATransformationType.Replacement, Query.root() as Program);
125
+ } else {
126
+ return new MISRATransformationReport(MISRATransformationType.NoChange);
127
+ }
128
+ }
129
+
99
130
  /**
100
131
  * Attempts to resolve implicit function calls in a file by adding missing includes or extern statements based on the configuration file.
101
132
  * @param fileJp The file to analyze
@@ -105,76 +136,94 @@ export default class Rule_17_3_ImplicitFunction extends MISRARule {
105
136
  const implicitCalls = Query.searchFrom(fileJp, Call, (callJp) => (isCallToImplicitFunction(callJp))).get();
106
137
  const originalIncludes = getIncludesOfFile(fileJp);
107
138
  let solvedCalls = new Set<string>();
108
- let addedIncludes: string[] = [];
139
+ let addedIncludes = new Set<string>();
109
140
  let changedFile = false;
110
141
 
111
- for (const callJp of implicitCalls) {
112
- const errorMsgPrefix = `Function '${callJp.name}' is declared implicitly.`;
142
+ for (const callJp of implicitCalls) {
143
+ if (this.context.getRuleResult(this.ruleID, callJp) === MISRATransformationType.NoChange) {
144
+ continue;
145
+ }
113
146
 
114
147
  if (solvedCalls.has(callJp.name)) {
115
148
  continue;
116
149
  }
117
-
118
- const configFix = this.getImplicitFixFromConfig(callJp, errorMsgPrefix);
119
- if (!configFix) {
150
+
151
+ const configFix = this.getFixFromConfig(callJp);
152
+ if (configFix === undefined) {
153
+ this.context.addRuleResult(this.ruleID, callJp, MISRATransformationType.NoChange);
120
154
  continue;
121
155
  }
122
156
 
123
- const callIndex = Query.searchFrom(fileJp, Call, { name: callJp.name }).get().findIndex(c => c.equals(callJp));
157
+ const callIndex = getCallIndex(fileJp, callJp);
124
158
  const isInclude = configFix.endsWith(".h");
125
- if (isInclude) {
126
- if (originalIncludes.includes(configFix)) {
127
- this.logMISRAError(callJp, `${errorMsgPrefix} Provided include \'${configFix}\' does not fix the violation.`);
128
- }
129
- else if (addedIncludes.includes(configFix)) {
130
-
131
- if (this.isValidFileWithExplicitCall(fileJp, callJp.name, callIndex)) {
132
- solvedCalls.add(callJp.name);
133
- } else {
134
- this.logMISRAError(callJp, `${errorMsgPrefix} Provided include \'${configFix}\' does not fix the violation.`);
135
- }
136
- }
137
- else {
138
- fileJp.addInclude(configFix);
139
- const fileCompiles = this.isValidFileWithExplicitCall(fileJp, callJp.name, callIndex);
140
-
141
- if (fileCompiles) {
142
- solvedCalls.add(callJp.name);
143
- addedIncludes.push(configFix);
144
- changedFile = true;
145
- } else {
146
- removeIncludeFromFile(configFix, fileJp);
147
- this.logMISRAError(callJp, `${errorMsgPrefix} Provided include \'${configFix}\' does not fix the violation.`);
148
- }
159
+ const success = isInclude ?
160
+ this.solveWithInclude(fileJp, callJp, configFix, originalIncludes, addedIncludes, callIndex) :
161
+ this.solveWithExtern(fileJp, callJp, configFix, callIndex);
162
+
163
+ if (success) {
164
+ solvedCalls.add(callJp.name);
165
+ changedFile = true;
166
+ if (isInclude) {
167
+ addedIncludes.add(configFix);
149
168
  }
169
+ } else {
170
+ this.context.addRuleResult(this.ruleID, callJp, MISRATransformationType.NoChange);
150
171
  }
151
172
  }
152
173
  return changedFile;
153
174
  }
154
175
 
155
- /**
156
- * Checks if the rebuilt version of the file compiles and if the provided call is no longer implicit
157
- * @param fileJp The file to analyze
158
- * @param funcName The function name to search the call
159
- * @param callIndex The index of the call
160
- */
161
- private isValidFileWithExplicitCall(fileJp: FileJp, funcName: string, callIndex: number) {
162
- const programJp = fileJp.parent as Program;
163
- let copyFile = ClavaJoinPoints.fileWithSource(`temp_misra_${fileJp.name}`, fileJp.code, fileJp.relativeFolderpath);
164
-
165
- copyFile = programJp.addFile(copyFile) as FileJp;
166
- try {
167
- const rebuiltFile = copyFile.rebuild();
168
- const fileToRemove = Query.searchFrom(programJp, FileJp, {filepath: rebuiltFile.filepath}).first() as FileJp;
169
- const callJp = Query.searchFrom(fileToRemove, Call, {name: funcName}).get().at(callIndex);
170
- const isExplicitCall = callJp !== undefined && !isCallToImplicitFunction(callJp);
176
+ private solveWithInclude(fileJp: FileJp, callJp: Call, includePath: string, originalIncludes: Set<string>, addedIncludes: Set<string>, callIndex: number): boolean {
177
+ const errorMsgPrefix = this.getErrorMsgPrefix(callJp);
178
+ let success = false;
179
+
180
+ if (originalIncludes.has(includePath)) {
181
+ this.logMISRAError(callJp, `${errorMsgPrefix} Provided include \'${includePath}\' does not fix the violation.`);
182
+ }
183
+ else if (addedIncludes.has(includePath)) {
184
+
185
+ if (isValidFileWithExplicitCall(fileJp, callJp.name, callIndex)) {
186
+ success = true;
187
+ } else {
188
+ this.logMISRAError(callJp, `${errorMsgPrefix} Provided include \'${includePath}\' does not fix the violation.`);
189
+ }
190
+ }
191
+ else {
192
+ fileJp.addInclude(includePath);
193
+ const fileCompiles = isValidFileWithExplicitCall(fileJp, callJp.name, callIndex);
194
+
195
+ if (fileCompiles) {
196
+ success = true;
197
+ } else {
198
+ removeIncludeFromFile(includePath, fileJp);
199
+ this.logMISRAError(callJp, `${errorMsgPrefix} Provided include \'${includePath}\' does not fix the violation.`);
200
+ }
201
+ }
202
+ return success;
203
+ }
204
+
205
+ private solveWithExtern(fileJp: FileJp, callJp: Call, functionLocation: string, callIndex: number): boolean {
206
+ const errorMsgPrefix = this.getErrorMsgPrefix(callJp);
207
+ const functionDef = findFunctionDef(callJp.name, functionLocation);
208
+ let success = false;
171
209
 
172
- fileToRemove?.detach();
173
- return isExplicitCall;
210
+ if (!functionDef) {
211
+ this.logMISRAError(callJp, `${errorMsgPrefix} Provided file \'${functionLocation}\' does not have function definition.`);
212
+ } else {
213
+ const externDecl = addExternFunctionDecl(fileJp, functionDef);
174
214
 
175
- } catch(error) {
176
- copyFile.detach();
177
- return false;
215
+ if (!externDecl) {
216
+ this.logMISRAError(callJp, `${errorMsgPrefix} Provided definition at \'${functionLocation}\' does not have external linkage.`);
217
+ } else {
218
+ const fileCompiles = isValidFileWithExplicitCall(fileJp, callJp.name, callIndex, true);
219
+ if (fileCompiles) {
220
+ success = true;
221
+ } else {
222
+ externDecl.detach();
223
+ this.logMISRAError(callJp, `${errorMsgPrefix} Provided definition at \'${functionLocation}\' does not fix the violation.`);
224
+ }
225
+ }
178
226
  }
227
+ return success;
179
228
  }
180
- }
229
+ }
@@ -1,20 +1,31 @@
1
- import { BuiltinType, FileJp, FunctionJp, Joinpoint, ReturnStmt } from "@specs-feup/clava/api/Joinpoints.js";
2
- import MISRARule from "../../MISRARule.js";
3
- import MISRAContext from "../../MISRAContext.js";
1
+ import { Body, BuiltinType, FileJp, FunctionJp, Joinpoint, ReturnStmt } from "@specs-feup/clava/api/Joinpoints.js";
4
2
  import ClavaJoinPoints from "@specs-feup/clava/api/clava/ClavaJoinPoints.js";
5
- import { MISRATransformationReport, MISRATransformationType } from "../../MISRA.js";
6
- import Query from "@specs-feup/lara/api/weaver/Query.js";
7
- import { isValidFile } from "../../utils/utils.js";
3
+ import { AnalysisType, MISRATransformationReport, MISRATransformationType } from "../../MISRA.js";
4
+ import { isValidFile } from "../../utils/FileUtils.js";
5
+ import UserConfigurableRule from "../UserConfigurableRule.js";
6
+ import ClavaNode from "@specs-feup/clava-flow/ClavaNode";
7
+ import ReturnNode from "@specs-feup/clava-flow/cfg/node/ReturnNode";
8
+ import ClavaCfgGenerator from "@specs-feup/clava-flow/transformation/ClavaCfgGenerator";
9
+ import BaseNode from "@specs-feup/flow/graph/BaseNode";
10
+ import Graph from "@specs-feup/flow/graph/Graph";
11
+ import ControlFlowEdge from "@specs-feup/flow/flow/ControlFlowEdge";
8
12
 
9
13
  /**
10
- * MISRA Rule 17.4: All exit paths from a function with non-void return type shall have an
11
- explicit return statement with an expression. In a non-void function:
12
- - Every return statement has an expression, and
13
- - Control cannot reach the end of the function without encountering a return statement
14
+ * MISRA-C Rule 17.4: All exit paths from a function with non-void return type shall have an explicit return statement with an expression. In a non-void function:
15
+ * - Every return statement has an expression, and
16
+ * - Control cannot reach the end of the function without encountering a return statement
14
17
  */
15
- export default class Rule_17_4_NonVoidReturn extends MISRARule {
16
- constructor(context: MISRAContext) {
17
- super("17.4", context);
18
+ export default class Rule_17_4_NonVoidReturn extends UserConfigurableRule {
19
+ /**
20
+ * Scope of analysis
21
+ */
22
+ readonly analysisType = AnalysisType.SINGLE_TRANSLATION_UNIT;
23
+
24
+ /**
25
+ * @returns Rule identifier according to MISRA-C:2012
26
+ */
27
+ override get name(): string {
28
+ return "17.4";
18
29
  }
19
30
 
20
31
  /**
@@ -26,20 +37,48 @@ export default class Rule_17_4_NonVoidReturn extends MISRARule {
26
37
  */
27
38
  match($jp: Joinpoint, logErrors: boolean = false): boolean {
28
39
  if (!($jp instanceof FunctionJp && $jp.isImplementation)) return false;
29
-
30
40
  if ($jp.returnType instanceof BuiltinType && $jp.returnType.isVoid) return false;
41
+ if ($jp.body.children.some(childJp => childJp instanceof ReturnStmt)) return false;
42
+
43
+ const nonCompliant = !this.allControlPathsReturn($jp);
31
44
 
32
- const emptyReturnStms = Query.searchFrom($jp, ReturnStmt, {returnExpr: undefined}).get();
33
- const exitReturn = $jp.body.children.filter(child => child instanceof ReturnStmt && !emptyReturnStms.includes(child))[0];
34
- if (logErrors) {
35
- emptyReturnStms?.forEach(emptyReturn =>
36
- this.logMISRAError(emptyReturn, "Every return statement in a non-void function must include an expression.")
37
- )
38
- if (exitReturn === undefined) {
39
- this.logMISRAError($jp, `Function '${$jp.name}' reaches the end without a return statement.`)
40
- }
45
+ if (logErrors && nonCompliant) {
46
+ this.logMISRAError($jp, `Function '${$jp.name}' reaches the end without a return statement.`)
41
47
  }
42
- return emptyReturnStms.length > 0 || exitReturn === undefined;
48
+ return nonCompliant;
49
+ }
50
+
51
+ /**
52
+ * Performs a depth.first search on the function's control flow graph (CFG) to check if all exit paths in the function have a return statement
53
+ *
54
+ * @param functionJp The function to analyze
55
+ * @returns Returns true if all exit paths in the function have an explicit return statement, otherwise returns false.
56
+ */
57
+ private allControlPathsReturn(functionJp: FunctionJp) {
58
+ // Generate control flow graph
59
+ const cfg = Graph.create().apply(new ClavaCfgGenerator(functionJp));
60
+ const startNode: BaseNode.Class = cfg.nodes.filterIs(ClavaNode).filter(node => node.jp instanceof Body)[0];
61
+ cfg.edges.filter(edge => edge.is(ControlFlowEdge) && edge.as(ControlFlowEdge).isFake).forEach((edge) => {
62
+ edge.remove();
63
+ })
64
+
65
+ const stack = [startNode];
66
+ const visited = new Set();
67
+
68
+ while (stack.length > 0) {
69
+ const node = stack.pop()!;
70
+
71
+ if (visited.has(node) || node?.is(ReturnNode))
72
+ continue;
73
+
74
+ let children = Array.from(node.outgoers).map(edge => edge.target);
75
+ if (!children || children.length === 0)
76
+ return false; // Reached the end of the graph without finding a single return statement
77
+
78
+ children = children.filter(child => !visited.has(child));
79
+ children.forEach(child => stack.push(child.as(BaseNode)));
80
+ }
81
+ return true;
43
82
  }
44
83
 
45
84
  /**
@@ -50,29 +89,19 @@ export default class Rule_17_4_NonVoidReturn extends MISRARule {
50
89
  * @param $jp - Joinpoint to transform
51
90
  * @returns Report detailing the transformation result
52
91
  */
53
- transform($jp: Joinpoint): MISRATransformationReport {
54
- if (!this.match($jp)) return new MISRATransformationReport(MISRATransformationType.NoChange);
55
-
56
- const functionJp = $jp as FunctionJp;
57
- const fileJp = functionJp.getAncestor("file") as FileJp;
58
- const returnType = functionJp.type.code;
59
- const errorMsgPrefix = `Function '${functionJp.name}' reaches the end without a return statement.`;
60
-
61
- if (!this.context.config) {
62
- this.logMISRAError($jp, `${errorMsgPrefix} Default value return not added due to missing config file.`)
63
- return new MISRATransformationReport(MISRATransformationType.NoChange);
92
+ apply($jp: Joinpoint): MISRATransformationReport {
93
+ const previousResult = $jp instanceof FunctionJp ? this.context.getRuleResult(this.ruleID, $jp) : undefined;
94
+ if (previousResult === MISRATransformationType.NoChange || !this.match($jp)) {
95
+ return new MISRATransformationReport(MISRATransformationType.NoChange);
64
96
  }
65
97
 
66
- let defaultValueReturn;
67
- try {
68
- defaultValueReturn = this.context.config.get("defaultValues")[returnType];
69
- } catch (error) {
70
- this.logMISRAError($jp, `${errorMsgPrefix} Default value return was not added as \'defaultValues\' is not defined in the configuration file.`);
71
- return new MISRATransformationReport(MISRATransformationType.NoChange);
72
- }
98
+ const functionJp = $jp as FunctionJp;
99
+ const fileJp = functionJp.getAncestor("file") as FileJp;
100
+ const errorMsgPrefix = this.getErrorMsgPrefix(functionJp);
73
101
 
102
+ const defaultValueReturn = this.getFixFromConfig(functionJp);
74
103
  if (defaultValueReturn === undefined) {
75
- this.logMISRAError($jp, `${errorMsgPrefix} Default value return not added due to missing default value configuration for type '${returnType}'.`);
104
+ this.context.addRuleResult(this.ruleID, $jp, MISRATransformationType.NoChange);
76
105
  return new MISRATransformationReport(MISRATransformationType.NoChange);
77
106
  }
78
107
 
@@ -80,12 +109,53 @@ export default class Rule_17_4_NonVoidReturn extends MISRARule {
80
109
  const returnStmt = ClavaJoinPoints.returnStmt(ClavaJoinPoints.exprLiteral(String(defaultValueReturn), functionJp.returnType)) as ReturnStmt;
81
110
  functionJp.body.lastChild ? functionJp.body.lastChild.insertAfter(returnStmt) : functionJp.body.setFirstChild(returnStmt);
82
111
 
83
- // Validate the provided default value. If it is invalid, the return stmt is removed
112
+ // Validate the provided default value
84
113
  if (isValidFile(fileJp)) {
85
114
  return new MISRATransformationReport(MISRATransformationType.DescendantChange);
86
115
  }
116
+
117
+ // If the default value is invalid, the return stmt is removed
87
118
  returnStmt.detach();
88
119
  this.logMISRAError($jp, `${errorMsgPrefix} Provided default value for type '${functionJp.type.code}' is invalid and was therefore not inserted.`);
120
+ this.context.addRuleResult(this.ruleID, $jp, MISRATransformationType.NoChange);
89
121
  return new MISRATransformationReport(MISRATransformationType.NoChange);
90
122
  }
123
+
124
+ /**
125
+ * Returns the prefix to be used for error messages related to the given joinpoint
126
+ *
127
+ * @param $jp - Joinpoint where the violation was detected
128
+ * @returns Returns a prefix to prepend to error messages if no configuration is specified or if the configuration does not contain a fix for this violation
129
+ */
130
+ getErrorMsgPrefix(functionJp: FunctionJp): string {
131
+ return `Function '${functionJp.name}' reaches the end without a return statement.`;
132
+ }
133
+
134
+ /**
135
+ * Retrieves a fix for the given joinpoint using the provided configuration file
136
+ * @param $jp - Joinpoint where the violation was detected
137
+ * @return The fix retrieved from the configuration for the violation, or `undefined` if no applicable fix is found.
138
+ */
139
+ getFixFromConfig(functionJp: FunctionJp): string | undefined {
140
+ const errorMsgPrefix = this.getErrorMsgPrefix(functionJp);
141
+
142
+ if (!this.context.config) {
143
+ this.logMISRAError(functionJp, `${errorMsgPrefix} Default value return not added due to missing config file.`)
144
+ return undefined;
145
+ }
146
+
147
+ let defaultValueReturn: string | undefined = undefined;
148
+ const returnType = functionJp.type.code;
149
+ try {
150
+ defaultValueReturn = this.context.config.get("defaultValues")[returnType];
151
+ } catch (error) {
152
+ this.logMISRAError(functionJp, `${errorMsgPrefix} Default value return was not added as \'defaultValues\' is not defined in the configuration file.`);
153
+ return undefined;
154
+ }
155
+
156
+ if (defaultValueReturn === undefined) {
157
+ this.logMISRAError(functionJp, `${errorMsgPrefix} Default value return not added due to missing default value configuration for type '${returnType}'.`);
158
+ }
159
+ return defaultValueReturn;
160
+ }
91
161
  }
@@ -1,17 +1,33 @@
1
1
  import { AdjustedType, ArrayType, FunctionJp, Joinpoint, Param } from "@specs-feup/clava/api/Joinpoints.js";
2
2
  import MISRARule from "../../MISRARule.js";
3
- import MISRAContext from "../../MISRAContext.js";
4
3
  import ClavaJoinPoints from "@specs-feup/clava/api/clava/ClavaJoinPoints.js";
5
- import { MISRATransformationReport, MISRATransformationType } from "../../MISRA.js";
6
- import { getParamReferences } from "../../utils/utils.js";
4
+ import { AnalysisType, MISRATransformationReport, MISRATransformationType } from "../../MISRA.js";
5
+ import { getParamReferences } from "../../utils/FunctionUtils.js";
7
6
 
8
7
  /**
9
- * MISRA Rule 17.6: The declaration of an array parameter shall not contain the static keyword between the [ ]
8
+ * MISRA-C Rule 17.6: The declaration of an array parameter shall not contain the static keyword between the [ ]
10
9
  */
11
10
  export default class Rule_17_6_StaticArraySizeParam extends MISRARule {
11
+ /**
12
+ * Scope of analysis
13
+ */
14
+ readonly analysisType = AnalysisType.SINGLE_TRANSLATION_UNIT;
15
+
16
+ /**
17
+ * Standards to which this rule applies to
18
+ */
19
+ protected override readonly appliesTo = new Set(["c99", "c11"]);
20
+
21
+ /**
22
+ * List of static array size params
23
+ */
12
24
  #invalidParams: Param[] = [];
13
- constructor(context: MISRAContext) {
14
- super("17.6", context);
25
+
26
+ /**
27
+ * @returns Rule identifier according to MISRA-C:2012
28
+ */
29
+ override get name(): string {
30
+ return "17.6";
15
31
  }
16
32
 
17
33
  /**
@@ -22,7 +38,7 @@ export default class Rule_17_6_StaticArraySizeParam extends MISRARule {
22
38
  * @returns Returns true if the joinpoint violates the rule, false otherwise
23
39
  */
24
40
  match($jp: Joinpoint, logErrors: boolean = false): boolean {
25
- if (!($jp instanceof FunctionJp) || $jp.root.standard === "c90") return false;
41
+ if (!($jp instanceof FunctionJp && this.appliesToCurrentStandard())) return false;
26
42
 
27
43
  this.#invalidParams = $jp.params.filter(paramJp => paramJp.type instanceof AdjustedType &&
28
44
  paramJp.type.originalType instanceof ArrayType &&
@@ -44,11 +60,12 @@ export default class Rule_17_6_StaticArraySizeParam extends MISRARule {
44
60
  * @param $jp - Joinpoint to transform
45
61
  * @returns Report detailing the transformation result
46
62
  */
47
- transform($jp: Joinpoint): MISRATransformationReport {
48
- if (!this.match($jp)) return new MISRATransformationReport(MISRATransformationType.NoChange);
63
+ apply($jp: Joinpoint): MISRATransformationReport {
64
+ if (!this.match($jp))
65
+ return new MISRATransformationReport(MISRATransformationType.NoChange);
49
66
 
50
67
  for (const invalidParam of this.#invalidParams) {
51
- const paramRefs = getParamReferences(invalidParam, $jp);
68
+ const paramRefs = getParamReferences(invalidParam, $jp as FunctionJp);
52
69
 
53
70
  // Replace the parameter with a new array parameter whose size is variant
54
71
  const originalType = (invalidParam.type as AdjustedType).originalType;
@@ -1,17 +1,22 @@
1
- import { BuiltinType, Call, ExprStmt, Joinpoint } from "@specs-feup/clava/api/Joinpoints.js";
1
+ import { BuiltinType, Call, Cast, ExprStmt, Joinpoint } from "@specs-feup/clava/api/Joinpoints.js";
2
2
  import MISRARule from "../../MISRARule.js";
3
- import MISRAContext from "../../MISRAContext.js";
4
3
  import ClavaJoinPoints from "@specs-feup/clava/api/clava/ClavaJoinPoints.js";
5
- import { MISRATransformationReport, MISRATransformationType } from "../../MISRA.js";
6
- import { isCallToImplicitFunction } from "../../utils/utils.js";
4
+ import { AnalysisType, MISRATransformationReport, MISRATransformationType } from "../../MISRA.js";
7
5
 
8
6
  /**
9
- * MISRA Rule 17.7: The value returned by a function having non-void return type shall be
10
- used
7
+ * MISRA-C Rule 17.7: The value returned by a function having non-void return type shall be used
11
8
  */
12
9
  export default class Rule_17_7_UnusedReturnValue extends MISRARule {
13
- constructor(context: MISRAContext) {
14
- super("17.7", context);
10
+ /**
11
+ * Scope of analysis
12
+ */
13
+ readonly analysisType = AnalysisType.SINGLE_TRANSLATION_UNIT;
14
+
15
+ /**
16
+ * @returns Rule identifier according to MISRA-C:2012
17
+ */
18
+ override get name(): string {
19
+ return "17.7";
15
20
  }
16
21
 
17
22
  /**
@@ -39,11 +44,14 @@ export default class Rule_17_7_UnusedReturnValue extends MISRARule {
39
44
  * @param $jp - Joinpoint to transform
40
45
  * @returns Report detailing the transformation result
41
46
  */
42
- transform($jp: Joinpoint): MISRATransformationReport {
43
- if (!this.match($jp)) return new MISRATransformationReport(MISRATransformationType.NoChange);
47
+ apply($jp: Joinpoint): MISRATransformationReport {
48
+ if (!this.match($jp))
49
+ return new MISRATransformationReport(MISRATransformationType.NoChange);
44
50
 
45
51
  const callJp = $jp as Call;
46
- const newJp = ClavaJoinPoints.cStyleCast(ClavaJoinPoints.type("void"), callJp);
47
- return new MISRATransformationReport(MISRATransformationType.Replacement, $jp.replaceWith(newJp));
52
+ const castJp = ClavaJoinPoints.cStyleCast(ClavaJoinPoints.type("void"), callJp);
53
+ const newJp = $jp.replaceWith(castJp) as Cast;
54
+ newJp.subExpr.replaceWith($jp);
55
+ return new MISRATransformationReport(MISRATransformationType.Replacement, newJp);
48
56
  }
49
57
  }