Skip to content

Commit 917c62e

Browse files
committed
Rule 5.8: Improve performance
This rule was highlighted as performing poorly as it created an effective cross product on declarations with the same name, which is expensive on some databases. The performance fix is to: (a) Create a predicate which represents all the conflicting identifiers by simply counting the number of declarations and confirming at least on such declaration is external. (b) Use this to create a result table of Declarations that conflict with those identifiers. (c) Implement a "non unique" external identifier class that provides a member predicate to get all the conflicting declarations. The key point here is to prevent the optimiser from doing a join between Declaration.getName() and Declaration.getName(). Instead, the join is between the names of the non-unique external identifiers and the much smaller table of declarations that conflict with at least one such entry.
1 parent 5a13000 commit 917c62e

File tree

1 file changed

+32
-3
lines changed

1 file changed

+32
-3
lines changed

c/misra/src/rules/RULE-5-8/IdentifiersWithExternalLinkageNotUnique.ql

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,39 @@ import cpp
1515
import codingstandards.c.misra
1616
import codingstandards.cpp.Identifiers
1717

18-
from Declaration de, ExternalIdentifiers e
18+
/**
19+
* Holds if the `identifierName` has conflicting declarations.
20+
*/
21+
predicate isExternalIdentifierNotUnique(string identifierName) {
22+
// More than one declaration with this name
23+
count(Declaration d | d.getName() = identifierName) > 1 and
24+
// At least one declaration is an external identifier
25+
exists(ExternalIdentifiers e | e.getName() = identifierName)
26+
}
27+
28+
/**
29+
* Holds if the `Declaration` `d` is conflicting with an external identifier.
30+
*/
31+
predicate isConflictingDeclaration(Declaration d, string name) {
32+
isExternalIdentifierNotUnique(name) and
33+
d.getName() = name
34+
}
35+
36+
/**
37+
* An external identifier which is not uniquely defined in the source code.
38+
*/
39+
class NotUniqueExternalIdentifier extends ExternalIdentifiers {
40+
NotUniqueExternalIdentifier() { isExternalIdentifierNotUnique(getName()) }
41+
42+
Declaration getAConflictingDeclaration() {
43+
not result = this and
44+
isConflictingDeclaration(result, getName())
45+
}
46+
}
47+
48+
from NotUniqueExternalIdentifier e, Declaration de
1949
where
2050
not isExcluded(de, Declarations6Package::identifiersWithExternalLinkageNotUniqueQuery()) and
2151
not isExcluded(e, Declarations6Package::identifiersWithExternalLinkageNotUniqueQuery()) and
22-
not de = e and
23-
de.getName() = e.getName()
52+
de = e.getAConflictingDeclaration()
2453
select de, "Identifier conflicts with external identifier $@", e, e.getName()

0 commit comments

Comments
 (0)