diff --git a/c/misra/src/rules/RULE-5-8/IdentifiersWithExternalLinkageNotUnique.ql b/c/misra/src/rules/RULE-5-8/IdentifiersWithExternalLinkageNotUnique.ql index ff20ceed18..7406f05f14 100644 --- a/c/misra/src/rules/RULE-5-8/IdentifiersWithExternalLinkageNotUnique.ql +++ b/c/misra/src/rules/RULE-5-8/IdentifiersWithExternalLinkageNotUnique.ql @@ -15,10 +15,39 @@ import cpp import codingstandards.c.misra import codingstandards.cpp.Identifiers -from Declaration de, ExternalIdentifiers e +/** + * Holds if the `identifierName` has conflicting declarations. + */ +predicate isExternalIdentifierNotUnique(string identifierName) { + // More than one declaration with this name + count(Declaration d | d.getName() = identifierName) > 1 and + // At least one declaration is an external identifier + exists(ExternalIdentifiers e | e.getName() = identifierName) +} + +/** + * Holds if the `Declaration` `d` is conflicting with an external identifier. + */ +predicate isConflictingDeclaration(Declaration d, string name) { + isExternalIdentifierNotUnique(name) and + d.getName() = name +} + +/** + * An external identifier which is not uniquely defined in the source code. + */ +class NotUniqueExternalIdentifier extends ExternalIdentifiers { + NotUniqueExternalIdentifier() { isExternalIdentifierNotUnique(getName()) } + + Declaration getAConflictingDeclaration() { + not result = this and + isConflictingDeclaration(result, getName()) + } +} + +from NotUniqueExternalIdentifier e, Declaration de where not isExcluded(de, Declarations6Package::identifiersWithExternalLinkageNotUniqueQuery()) and not isExcluded(e, Declarations6Package::identifiersWithExternalLinkageNotUniqueQuery()) and - not de = e and - de.getName() = e.getName() + de = e.getAConflictingDeclaration() select de, "Identifier conflicts with external identifier $@", e, e.getName() diff --git a/c/misra/src/rules/RULE-8-7/ShouldNotBeDefinedWithExternalLinkage.ql b/c/misra/src/rules/RULE-8-7/ShouldNotBeDefinedWithExternalLinkage.ql index e5649400c8..824a4cf1cf 100644 --- a/c/misra/src/rules/RULE-8-7/ShouldNotBeDefinedWithExternalLinkage.ql +++ b/c/misra/src/rules/RULE-8-7/ShouldNotBeDefinedWithExternalLinkage.ql @@ -20,27 +20,36 @@ import codingstandards.c.misra import codingstandards.cpp.Identifiers import codingstandards.cpp.Scope +ExternalIdentifiers getExternalIdentifierTarget(NameQualifiableElement nqe) { + result = nqe.(Access).getTarget() + or + result = nqe.(FunctionCall).getTarget() +} + /** - * Re-introduce function calls into access description as - * "any reference" + * A reference to an external identifier, either as an `Access` or a `FunctionCall`. */ -class Reference extends NameQualifiableElement { - Reference() { - this instanceof Access or - this instanceof FunctionCall - } +class ExternalIdentifierReference extends NameQualifiableElement { + ExternalIdentifierReference() { exists(getExternalIdentifierTarget(this)) } + + ExternalIdentifiers getExternalIdentifierTarget() { result = getExternalIdentifierTarget(this) } +} + +predicate isReferencedInTranslationUnit( + ExternalIdentifiers e, ExternalIdentifierReference r, TranslationUnit t +) { + r.getExternalIdentifierTarget() = e and + r.getFile() = t } -from ExternalIdentifiers e, Reference a1, TranslationUnit t1 +from ExternalIdentifiers e, ExternalIdentifierReference a1, TranslationUnit t1 where not isExcluded(e, Declarations6Package::shouldNotBeDefinedWithExternalLinkageQuery()) and - (a1.(Access).getTarget() = e or a1.(FunctionCall).getTarget() = e) and - a1.getFile() = t1 and - //not accessed in any other translation unit - not exists(TranslationUnit t2, Reference a2 | - not t1 = t2 and - (a2.(Access).getTarget() = e or a2.(FunctionCall).getTarget() = e) and - a2.getFile() = t2 + isReferencedInTranslationUnit(e, a1, t1) and + // Not referenced in any other translation unit + not exists(TranslationUnit t2 | + isReferencedInTranslationUnit(e, _, t2) and + not t1 = t2 ) select e, "Declaration with external linkage is accessed in only one translation unit $@.", a1, a1.toString() diff --git a/change_notes/2023-03-08-identifier-performance.md b/change_notes/2023-03-08-identifier-performance.md new file mode 100644 index 0000000000..39c2d26bbf --- /dev/null +++ b/change_notes/2023-03-08-identifier-performance.md @@ -0,0 +1,3 @@ + * The performance of the following identifier related rules has been improved: + * MISRA C 2012 `Rule 5.8` + * MISRA C 2012 `Rule 8.7` \ No newline at end of file