|
| 1 | +/** |
| 2 | + * @id c/misra/redeclaration-of-object-without-alignment |
| 3 | + * @name RULE-8-15: Alignment should match between all declarations of an object |
| 4 | + * @description An object declared with an explicit alignment shall be explicitly aligned in all |
| 5 | + * declarations. |
| 6 | + * @kind problem |
| 7 | + * @precision very-high |
| 8 | + * @problem.severity error |
| 9 | + * @tags external/misra/id/rule-8-15 |
| 10 | + * external/misra/c/2012/amendment3 |
| 11 | + * readability |
| 12 | + * maintainability |
| 13 | + * external/misra/obligation/required |
| 14 | + */ |
| 15 | + |
| 16 | +import cpp |
| 17 | +import codingstandards.c.misra |
| 18 | + |
| 19 | +/** |
| 20 | + * Performance optimization; start query by joining attributes to declarations |
| 21 | + * rather than locations. |
| 22 | + * |
| 23 | + * Including the entry location also speeds up search. |
| 24 | + */ |
| 25 | +newtype TAttributeDeclLocation = |
| 26 | + TAttributeDeclLocationInfo(Attribute attribute, DeclarationEntry entry, Location entryLocation) { |
| 27 | + entry.getDeclaration().(Variable).getAnAttribute() = attribute and |
| 28 | + entryLocation = entry.getLocation() |
| 29 | + } |
| 30 | + |
| 31 | +/** |
| 32 | + * Get a DeclarationEntry along with its explicitly declared Attributes. |
| 33 | + * |
| 34 | + * DeclarationEntry does not have a method for getting Attributes by default, |
| 35 | + * because an attribute declared on any DeclarationEntry affects all others, |
| 36 | + * and attributes really belong to the declared variable rather than the |
| 37 | + * declaration itself. |
| 38 | + * |
| 39 | + * In order to support this rule, we find for each attribute |
| 40 | + * - A declaration entry which |
| 41 | + * - corresponds to a variable associated with this attribute |
| 42 | + * - is in the same file as this attribute |
| 43 | + * - has identifier location after the attribute declaration |
| 44 | + * - has no other declaration entry between this one and the attribute. |
| 45 | + * |
| 46 | + * This should give us a highly reliable means of finding which attributes are |
| 47 | + * associated with which `DeclarationEntry`s. |
| 48 | + * |
| 49 | + * One note of caution: the location of the associated `Variable` must be |
| 50 | + * treated with caution, as calls to `getLocation()` on a redeclared `Variable` |
| 51 | + * can return multiple results. This class must act on `DeclarationEntry`s to |
| 52 | + * deliver reliable results. |
| 53 | + */ |
| 54 | +class DeclarationEntryAttribute extends Attribute { |
| 55 | + DeclarationEntry declarationEntry; |
| 56 | + Location location; |
| 57 | + Location declLocation; |
| 58 | + File file; |
| 59 | + TAttributeDeclLocation locInfo; |
| 60 | + |
| 61 | + DeclarationEntryAttribute() { |
| 62 | + locInfo = TAttributeDeclLocationInfo(this, declarationEntry, declLocation) and |
| 63 | + file = getFile() and |
| 64 | + location = getLocation() and |
| 65 | + declLocation = declarationEntry.getLocation() and |
| 66 | + declarationEntry.getDeclaration().(Variable).getAnAttribute() = this and |
| 67 | + declarationEntry.getFile() = file and |
| 68 | + location.isBefore(declLocation, _) and |
| 69 | + not exists(TAttributeDeclLocation blocInfo, DeclarationEntry betterFit, Location blocation | |
| 70 | + blocInfo = TAttributeDeclLocationInfo(this, betterFit, blocation) and |
| 71 | + not betterFit = declarationEntry and |
| 72 | + blocation = betterFit.getLocation() and |
| 73 | + betterFit.getFile() = file and |
| 74 | + betterFit.getDeclaration() = declarationEntry.getDeclaration() and |
| 75 | + blocation.isBefore(declLocation, _) and |
| 76 | + location.isBefore(blocation, _) |
| 77 | + ) |
| 78 | + } |
| 79 | + |
| 80 | + DeclarationEntry getDeclarationEntry() { result = declarationEntry } |
| 81 | +} |
| 82 | + |
| 83 | +from DeclarationEntry unaligned, DeclarationEntry aligned, DeclarationEntryAttribute attribute |
| 84 | +where |
| 85 | + not isExcluded(unaligned, AlignmentPackage::redeclarationOfObjectWithoutAlignmentQuery()) and |
| 86 | + attribute.hasName("_Alignas") and |
| 87 | + attribute.getDeclarationEntry() = aligned and |
| 88 | + aligned.getDeclaration() = unaligned.getDeclaration() and |
| 89 | + not exists(DeclarationEntryAttribute matchingAlignment | |
| 90 | + matchingAlignment.hasName("_Alignas") and |
| 91 | + matchingAlignment.getDeclarationEntry() = unaligned |
| 92 | + ) |
| 93 | +select unaligned, |
| 94 | + "Variable " + unaligned.getName() + |
| 95 | + " declared without explicit alignment to match $@ with alignment $@.", aligned, |
| 96 | + "other definition", attribute, attribute.toString() |
0 commit comments