diff --git a/c/misra/src/rules/RULE-8-7/ShouldNotBeDefinedWithExternalLinkage.ql b/c/misra/src/rules/RULE-8-7/ShouldNotBeDefinedWithExternalLinkage.ql index faa915fdd5..9cdd6532a9 100644 --- a/c/misra/src/rules/RULE-8-7/ShouldNotBeDefinedWithExternalLinkage.ql +++ b/c/misra/src/rules/RULE-8-7/ShouldNotBeDefinedWithExternalLinkage.ql @@ -40,17 +40,22 @@ predicate isReferencedInTranslationUnit( ExternalIdentifiers e, ExternalIdentifierReference r, TranslationUnit t ) { r.getExternalIdentifierTarget() = e and - r.getFile() = t + // Used within the translation unit or an included header + r.getFile() = t.getAUserFile() } from ExternalIdentifiers e, ExternalIdentifierReference a1, TranslationUnit t1 where not isExcluded(e, Declarations6Package::shouldNotBeDefinedWithExternalLinkageQuery()) and + // Only report external identifiers where we see the definition + e.hasDefinition() and isReferencedInTranslationUnit(e, a1, t1) and // Not referenced in any other translation unit not exists(TranslationUnit t2 | isReferencedInTranslationUnit(e, _, t2) and not t1 = t2 - ) + ) and + // Definition is also in the same translation unit + e.getDefinition().getFile() = t1.getAUserFile() select e, "Declaration with external linkage is accessed in only one translation unit $@.", a1, a1.toString() diff --git a/c/misra/test/rules/RULE-8-7/ShouldNotBeDefinedWithExternalLinkage.expected b/c/misra/test/rules/RULE-8-7/ShouldNotBeDefinedWithExternalLinkage.expected index b6a53071d9..6610bf236e 100644 --- a/c/misra/test/rules/RULE-8-7/ShouldNotBeDefinedWithExternalLinkage.expected +++ b/c/misra/test/rules/RULE-8-7/ShouldNotBeDefinedWithExternalLinkage.expected @@ -1,3 +1,4 @@ -| test.h:2:12:2:13 | i1 | Declaration with external linkage is accessed in only one translation unit $@. | test.c:4:3:4:4 | i1 | i1 | -| test.h:3:5:3:6 | i2 | Declaration with external linkage is accessed in only one translation unit $@. | test.c:5:3:5:4 | i2 | i2 | -| test.h:5:13:5:14 | f2 | Declaration with external linkage is accessed in only one translation unit $@. | test.c:7:3:7:4 | call to f2 | call to f2 | +| test2.h:2:13:2:14 | f6 | Declaration with external linkage is accessed in only one translation unit $@. | test2.h:3:22:3:23 | call to f6 | call to f6 | +| test.c:3:5:3:6 | i1 | Declaration with external linkage is accessed in only one translation unit $@. | test.c:11:3:11:4 | i1 | i1 | +| test.c:4:5:4:6 | i2 | Declaration with external linkage is accessed in only one translation unit $@. | test.c:12:3:12:4 | i2 | i2 | +| test.c:6:6:6:7 | f2 | Declaration with external linkage is accessed in only one translation unit $@. | test.c:14:3:14:4 | call to f2 | call to f2 | diff --git a/c/misra/test/rules/RULE-8-7/test.c b/c/misra/test/rules/RULE-8-7/test.c index b2cc2a0684..3789a1d269 100644 --- a/c/misra/test/rules/RULE-8-7/test.c +++ b/c/misra/test/rules/RULE-8-7/test.c @@ -1,4 +1,11 @@ #include "test.h" +int i = 0; +int i1 = 0; +int i2; // NON_COMPLIANT - accessed one translation unit +void f1() {} // Definition +void f2() {} // Definition +static void f3(){}; // COMPLIANT - internal linkage +void f4() {} // Definition void f() { i = 0; i1 = 0; diff --git a/c/misra/test/rules/RULE-8-7/test.h b/c/misra/test/rules/RULE-8-7/test.h index 692bb8e3db..782099de02 100644 --- a/c/misra/test/rules/RULE-8-7/test.h +++ b/c/misra/test/rules/RULE-8-7/test.h @@ -1,7 +1,6 @@ extern int i; // COMPLIANT - accessed multiple translation units extern int i1; // NON_COMPLIANT - accessed one translation unit -int i2; // NON_COMPLIANT - accessed one translation unit extern void f1(); // COMPLIANT - accessed multiple translation units extern void f2(); // NON_COMPLIANT - accessed one translation unit -static void f3(); // COMPLIANT - internal linkage -extern void f3(); // COMPLIANT - internal linkage \ No newline at end of file +extern void f4(); // COMPLIANT - accessed across translation units +extern void f5(); // COMPLIANT - no definition \ No newline at end of file diff --git a/c/misra/test/rules/RULE-8-7/test1.c b/c/misra/test/rules/RULE-8-7/test1.c index 77377e78df..5c3b3759c9 100644 --- a/c/misra/test/rules/RULE-8-7/test1.c +++ b/c/misra/test/rules/RULE-8-7/test1.c @@ -1,5 +1,7 @@ -#include "test.h" +#include "test2.h" void f() { i = 0; f1(); + f4(); + f5(); } \ No newline at end of file diff --git a/c/misra/test/rules/RULE-8-7/test2.h b/c/misra/test/rules/RULE-8-7/test2.h new file mode 100644 index 0000000000..d203c3259a --- /dev/null +++ b/c/misra/test/rules/RULE-8-7/test2.h @@ -0,0 +1,3 @@ +#include "test.h" +extern void f6() {} // NON_COMPLIANT +static void test() { f6(); } \ No newline at end of file diff --git a/change_notes/2025-03-09-rule-8-7.md b/change_notes/2025-03-09-rule-8-7.md new file mode 100644 index 0000000000..3c3678ca6d --- /dev/null +++ b/change_notes/2025-03-09-rule-8-7.md @@ -0,0 +1,4 @@ + - `RULE-8-7` - `ShouldNotBeDefinedWithExternalLinkage.ql`: + - Remove false positives where the declaration is not defined in the database. + - Remove false positives where the definition and reference are in different translation units. + - Remove false positives where the reference occurs in a header file. \ No newline at end of file