From 77a17c2fd6bed578a37c24d0840444367828d7b8 Mon Sep 17 00:00:00 2001 From: Kristen Newbury Date: Mon, 26 Jan 2026 14:28:55 -0500 Subject: [PATCH 1/9] Add RULE-6-5-2 linkage2 --- .../cpp/exclusions/cpp/Linkage2.qll | 44 ++++++++++++++++ .../cpp/exclusions/cpp/RuleMetadata.qll | 3 ++ .../InternalLinkageSpecifiedAppropriately.ql | 46 +++++++++++++++++ ...rnalLinkageSpecifiedAppropriately.expected | 4 ++ ...nternalLinkageSpecifiedAppropriately.qlref | 1 + cpp/misra/test/rules/RULE-6-5-2/test.cpp | 14 ++++++ rule_packages/cpp/Linkage2.json | 50 +++++++++++++++++++ rules.csv | 4 +- 8 files changed, 164 insertions(+), 2 deletions(-) create mode 100644 cpp/common/src/codingstandards/cpp/exclusions/cpp/Linkage2.qll create mode 100644 cpp/misra/src/rules/RULE-6-5-2/InternalLinkageSpecifiedAppropriately.ql create mode 100644 cpp/misra/test/rules/RULE-6-5-2/InternalLinkageSpecifiedAppropriately.expected create mode 100644 cpp/misra/test/rules/RULE-6-5-2/InternalLinkageSpecifiedAppropriately.qlref create mode 100644 cpp/misra/test/rules/RULE-6-5-2/test.cpp create mode 100644 rule_packages/cpp/Linkage2.json diff --git a/cpp/common/src/codingstandards/cpp/exclusions/cpp/Linkage2.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Linkage2.qll new file mode 100644 index 000000000..0d804e1cc --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Linkage2.qll @@ -0,0 +1,44 @@ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ +import cpp +import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata + +newtype Linkage2Query = + THeaderDefinitionsExternalLinkageQuery() or + TInternalLinkageSpecifiedAppropriatelyQuery() + +predicate isLinkage2QueryMetadata(Query query, string queryId, string ruleId, string category) { + query = + // `Query` instance for the `headerDefinitionsExternalLinkage` query + Linkage2Package::headerDefinitionsExternalLinkageQuery() and + queryId = + // `@id` for the `headerDefinitionsExternalLinkage` query + "cpp/misra/header-definitions-external-linkage" and + ruleId = "RULE-6-2-4" and + category = "required" + or + query = + // `Query` instance for the `internalLinkageSpecifiedAppropriately` query + Linkage2Package::internalLinkageSpecifiedAppropriatelyQuery() and + queryId = + // `@id` for the `internalLinkageSpecifiedAppropriately` query + "cpp/misra/internal-linkage-specified-appropriately" and + ruleId = "RULE-6-5-2" and + category = "advisory" +} + +module Linkage2Package { + Query headerDefinitionsExternalLinkageQuery() { + //autogenerate `Query` type + result = + // `Query` type for `headerDefinitionsExternalLinkage` query + TQueryCPP(TLinkage2PackageQuery(THeaderDefinitionsExternalLinkageQuery())) + } + + Query internalLinkageSpecifiedAppropriatelyQuery() { + //autogenerate `Query` type + result = + // `Query` type for `internalLinkageSpecifiedAppropriately` query + TQueryCPP(TLinkage2PackageQuery(TInternalLinkageSpecifiedAppropriatelyQuery())) + } +} diff --git a/cpp/common/src/codingstandards/cpp/exclusions/cpp/RuleMetadata.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/RuleMetadata.qll index 0c3cbcc28..16e53c95b 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/cpp/RuleMetadata.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/RuleMetadata.qll @@ -34,6 +34,7 @@ import IntegerConversion import Invariants import Iterators import Lambdas +import Linkage2 import Literals import Loops import Macros @@ -96,6 +97,7 @@ newtype TCPPQuery = TInvariantsPackageQuery(InvariantsQuery q) or TIteratorsPackageQuery(IteratorsQuery q) or TLambdasPackageQuery(LambdasQuery q) or + TLinkage2PackageQuery(Linkage2Query q) or TLiteralsPackageQuery(LiteralsQuery q) or TLoopsPackageQuery(LoopsQuery q) or TMacrosPackageQuery(MacrosQuery q) or @@ -158,6 +160,7 @@ predicate isQueryMetadata(Query query, string queryId, string ruleId, string cat isInvariantsQueryMetadata(query, queryId, ruleId, category) or isIteratorsQueryMetadata(query, queryId, ruleId, category) or isLambdasQueryMetadata(query, queryId, ruleId, category) or + isLinkage2QueryMetadata(query, queryId, ruleId, category) or isLiteralsQueryMetadata(query, queryId, ruleId, category) or isLoopsQueryMetadata(query, queryId, ruleId, category) or isMacrosQueryMetadata(query, queryId, ruleId, category) or diff --git a/cpp/misra/src/rules/RULE-6-5-2/InternalLinkageSpecifiedAppropriately.ql b/cpp/misra/src/rules/RULE-6-5-2/InternalLinkageSpecifiedAppropriately.ql new file mode 100644 index 000000000..fe8dafc38 --- /dev/null +++ b/cpp/misra/src/rules/RULE-6-5-2/InternalLinkageSpecifiedAppropriately.ql @@ -0,0 +1,46 @@ +/** + * @id cpp/misra/internal-linkage-specified-appropriately + * @name RULE-6-5-2: Internal linkage should be specified appropriately + * @description Using certain specifiers or declaring entities with internal linkage in certain + * namespaces can lead to confusion as to the linkage of the entity and can cause code + * to be more difficult to read. + * @kind problem + * @precision very-high + * @problem.severity error + * @tags external/misra/id/rule-6-5-2 + * correctness + * maintainability + * readability + * scope/single-translation-unit + * external/misra/enforcement/decidable + * external/misra/obligation/advisory + */ + +import cpp +import codingstandards.cpp.misra +import codingstandards.cpp.Linkage +import codingstandards.cpp.types.Pointers + +from DeclarationEntry decl, string message +where + not isExcluded(decl, Linkage2Package::internalLinkageSpecifiedAppropriatelyQuery()) and + hasInternalLinkage(decl.getDeclaration()) and + //exclusions as per rule for const and constexpr Variables + not decl.getDeclaration().(Variable).getUnderlyingType().isConst() and + not decl.getDeclaration().(Variable).getType().(PointerOrArrayType).isDeeplyConstBelow() and + not decl.getDeclaration().(Variable).isConstexpr() and + ( + decl.hasSpecifier("static") and + ( + decl.getDeclaration().getNamespace().isAnonymous() and + message = "Static specifier used in anonymous namespace." + or + not decl.getDeclaration().getNamespace().isAnonymous() and + message = "Static specifier used in non-anonymous namespace." + ) + or + decl.hasSpecifier("extern") and + decl.getDeclaration().getNamespace().isAnonymous() and + message = "Extern specifier used in anonymous namespace." + ) +select decl, message diff --git a/cpp/misra/test/rules/RULE-6-5-2/InternalLinkageSpecifiedAppropriately.expected b/cpp/misra/test/rules/RULE-6-5-2/InternalLinkageSpecifiedAppropriately.expected new file mode 100644 index 000000000..e805ed275 --- /dev/null +++ b/cpp/misra/test/rules/RULE-6-5-2/InternalLinkageSpecifiedAppropriately.expected @@ -0,0 +1,4 @@ +| test.cpp:1:13:1:13 | declaration of f | Static specifier used in non-anonymous namespace. | +| test.cpp:5:13:5:14 | declaration of f2 | Extern specifier used in anonymous namespace. | +| test.cpp:8:12:8:13 | declaration of i1 | Extern specifier used in anonymous namespace. | +| test.cpp:9:12:9:13 | definition of i2 | Static specifier used in anonymous namespace. | diff --git a/cpp/misra/test/rules/RULE-6-5-2/InternalLinkageSpecifiedAppropriately.qlref b/cpp/misra/test/rules/RULE-6-5-2/InternalLinkageSpecifiedAppropriately.qlref new file mode 100644 index 000000000..e2905c717 --- /dev/null +++ b/cpp/misra/test/rules/RULE-6-5-2/InternalLinkageSpecifiedAppropriately.qlref @@ -0,0 +1 @@ +rules/RULE-6-5-2/InternalLinkageSpecifiedAppropriately.ql \ No newline at end of file diff --git a/cpp/misra/test/rules/RULE-6-5-2/test.cpp b/cpp/misra/test/rules/RULE-6-5-2/test.cpp new file mode 100644 index 000000000..6107309db --- /dev/null +++ b/cpp/misra/test/rules/RULE-6-5-2/test.cpp @@ -0,0 +1,14 @@ +static void f(); // NON_COMPILANT - prefer to use an anonymous namespace + +namespace { +void f1(); // COMPILANT +extern void f2(); // NON_COMPILANT + +int i; // COMPILANT +extern int i1; // NON_COMPILANT +static int i2; // NON_COMPILANT - prefer to not use static as it is redundant +} // namespace + +namespace named { +static const int i[] = {1}; // COMPILANT - exception +} \ No newline at end of file diff --git a/rule_packages/cpp/Linkage2.json b/rule_packages/cpp/Linkage2.json new file mode 100644 index 000000000..fd57834de --- /dev/null +++ b/rule_packages/cpp/Linkage2.json @@ -0,0 +1,50 @@ +{ + "MISRA-C++-2023": { + "RULE-6-2-4": { + "properties": { + "enforcement": "decidable", + "obligation": "required" + }, + "queries": [ + { + "description": "Placing the definitions of functions or objects that are non-inline and have external linkage can lead to violations of the ODR and can lead to undefined behaviour.", + "kind": "problem", + "name": "A header file shall not contain definitions of functions or objects that are non-inline and have external linkage", + "precision": "very-high", + "severity": "error", + "short_name": "HeaderDefinitionsExternalLinkage", + "tags": [ + "correctness", + "maintainability", + "readability", + "scope/single-translation-unit" + ] + } + ], + "title": "A header file shall not contain definitions of functions or objects that are non-inline and have external linkage" + }, + "RULE-6-5-2": { + "properties": { + "enforcement": "decidable", + "obligation": "advisory" + }, + "queries": [ + { + "description": "Using certain specifiers or declaring entities with internal linkage in certain namespaces can lead to confusion as to the linkage of the entity and can cause code to be more difficult to read.", + "kind": "problem", + "name": "Internal linkage should be specified appropriately", + "precision": "very-high", + "severity": "error", + "short_name": "InternalLinkageSpecifiedAppropriately", + "tags": [ + "correctness", + "maintainability", + "readability", + "scope/single-translation-unit" + ] + } + ], + "title": "Internal linkage should be specified appropriately" + } + } +} \ No newline at end of file diff --git a/rules.csv b/rules.csv index a2eb7eddd..0fbadfe1b 100644 --- a/rules.csv +++ b/rules.csv @@ -856,12 +856,12 @@ cpp,MISRA-C++-2023,RULE-6-0-4,Yes,Required,Decidable,Single Translation Unit,The cpp,MISRA-C++-2023,RULE-6-2-1,Yes,Required,Decidable,System,The one-definition rule shall not be violated,M3-2-2,ImportMisra23,Import, cpp,MISRA-C++-2023,RULE-6-2-2,Yes,Required,Decidable,System,All declarations of a variable or function shall have the same type,"M3-9-1,DCL40-C",Declarations2,Easy, cpp,MISRA-C++-2023,RULE-6-2-3,Yes,Required,Decidable,System,The source code used to implement an entity shall appear only once,,Declarations2,Medium, -cpp,MISRA-C++-2023,RULE-6-2-4,Yes,Required,Decidable,Single Translation Unit,A header file shall not contain definitions of functions or objects that are non-inline and have external linkage,,Linkage,Easy, +cpp,MISRA-C++-2023,RULE-6-2-4,Yes,Required,Decidable,Single Translation Unit,A header file shall not contain definitions of functions or objects that are non-inline and have external linkage,M3-2-4,Linkage2,Easy, cpp,MISRA-C++-2023,RULE-6-4-1,Yes,Required,Decidable,Single Translation Unit,A variable declared in an inner scope shall not hide a variable declared in an outer scope,A2-10-1,ImportMisra23,Import, cpp,MISRA-C++-2023,RULE-6-4-2,Yes,Required,Decidable,Single Translation Unit,Derived classes shall not conceal functions that are inherited from their bases,A7-3-1,ImportMisra23,Import, cpp,MISRA-C++-2023,RULE-6-4-3,Yes,Required,Decidable,Single Translation Unit,A name that is present in a dependent base shall not be resolved by unqualified lookup,M14-6-1,ImportMisra23,Import, cpp,MISRA-C++-2023,RULE-6-5-1,Yes,Advisory,Decidable,Single Translation Unit,A function or object with external linkage should be introduced in a header file,,Linkage,Medium, -cpp,MISRA-C++-2023,RULE-6-5-2,Yes,Advisory,Decidable,Single Translation Unit,Internal linkage should be specified appropriately,,Linkage,Medium, +cpp,MISRA-C++-2023,RULE-6-5-2,Yes,Advisory,Decidable,Single Translation Unit,Internal linkage should be specified appropriately,,Linkage2,Medium, cpp,MISRA-C++-2023,RULE-6-7-1,Yes,Required,Decidable,Single Translation Unit,Local variables shall not have static storage duration,,Declarations2,Easy, cpp,MISRA-C++-2023,RULE-6-7-2,Yes,Required,Decidable,Single Translation Unit,Global variables shall not be used,,Banned,Easy, cpp,MISRA-C++-2023,RULE-6-8-1,Yes,Required,Undecidable,System,An object shall not be accessed outside of its lifetime,A3-8-1,ImportMisra23,Import, From 9f48c75ac9c44130f48ebf2c55a5aeb6eff56fc7 Mon Sep 17 00:00:00 2001 From: Kristen Newbury Date: Mon, 26 Jan 2026 16:57:32 -0500 Subject: [PATCH 2/9] Add shared rule A3-1-1 for RULE-6-2-4 linkage2 and improve A3-1-1 --- .vscode/tasks.json | 2 + .../2026-01-26-a3-1-1-extern-to-full.md | 2 + .../A3-1-1/ViolationsOfOneDefinitionRule.ql | 67 ++--------------- .../ViolationsOfOneDefinitionRule.expected | 3 - .../ViolationsOfOneDefinitionRule.qlref | 1 - .../ViolationsOfOneDefinitionRule.testref | 1 + cpp/autosar/test/rules/A3-1-1/test.hpp | 26 ------- .../cpp/exclusions/cpp/Linkage2.qll | 16 ++-- .../ViolationsOfOneDefinitionRule.qll | 74 +++++++++++++++++++ .../ViolationsOfOneDefinitionRule.expected | 3 + .../ViolationsOfOneDefinitionRule.ql | 4 + .../violationsofonedefinitionrule}/test.cpp | 0 .../violationsofonedefinitionrule/test.hpp | 26 +++++++ .../ViolationsOfOneDefinitionRuleMisra.ql | 27 +++++++ ...ViolationsOfOneDefinitionRuleMisra.testref | 1 + rule_packages/cpp/Includes.json | 1 + rule_packages/cpp/Linkage2.json | 3 +- rules.csv | 2 +- 18 files changed, 157 insertions(+), 102 deletions(-) create mode 100644 change_notes/2026-01-26-a3-1-1-extern-to-full.md delete mode 100644 cpp/autosar/test/rules/A3-1-1/ViolationsOfOneDefinitionRule.expected delete mode 100644 cpp/autosar/test/rules/A3-1-1/ViolationsOfOneDefinitionRule.qlref create mode 100644 cpp/autosar/test/rules/A3-1-1/ViolationsOfOneDefinitionRule.testref delete mode 100644 cpp/autosar/test/rules/A3-1-1/test.hpp create mode 100644 cpp/common/src/codingstandards/cpp/rules/violationsofonedefinitionrule/ViolationsOfOneDefinitionRule.qll create mode 100644 cpp/common/test/rules/violationsofonedefinitionrule/ViolationsOfOneDefinitionRule.expected create mode 100644 cpp/common/test/rules/violationsofonedefinitionrule/ViolationsOfOneDefinitionRule.ql rename cpp/{autosar/test/rules/A3-1-1 => common/test/rules/violationsofonedefinitionrule}/test.cpp (100%) create mode 100644 cpp/common/test/rules/violationsofonedefinitionrule/test.hpp create mode 100644 cpp/misra/src/rules/RULE-6-2-4/ViolationsOfOneDefinitionRuleMisra.ql create mode 100644 cpp/misra/test/rules/RULE-6-2-4/ViolationsOfOneDefinitionRuleMisra.testref diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 74f065ac3..c5b2bbd1b 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -259,6 +259,8 @@ "Language1", "Language2", "Language3", + "Linkage1", + "Linkage2", "Literals", "Loops", "Macros", diff --git a/change_notes/2026-01-26-a3-1-1-extern-to-full.md b/change_notes/2026-01-26-a3-1-1-extern-to-full.md new file mode 100644 index 000000000..0b073d168 --- /dev/null +++ b/change_notes/2026-01-26-a3-1-1-extern-to-full.md @@ -0,0 +1,2 @@ +- `A3-1-1` - `ViolationsOfOneDefinitionRule.ql`: + - The query previously would incorrectly allow cases where something was defined with `extern` and did not use the defined external linkage library to find external linkage. This change may result in the query finding more results. \ No newline at end of file diff --git a/cpp/autosar/src/rules/A3-1-1/ViolationsOfOneDefinitionRule.ql b/cpp/autosar/src/rules/A3-1-1/ViolationsOfOneDefinitionRule.ql index 4beb91e8f..c07e7c7b7 100644 --- a/cpp/autosar/src/rules/A3-1-1/ViolationsOfOneDefinitionRule.ql +++ b/cpp/autosar/src/rules/A3-1-1/ViolationsOfOneDefinitionRule.ql @@ -20,67 +20,10 @@ import cpp import codingstandards.cpp.autosar -import codingstandards.cpp.AcceptableHeader +import codingstandards.cpp.rules.violationsofonedefinitionrule.ViolationsOfOneDefinitionRule -predicate isInline(Function decl) { - exists(Specifier spec | - spec = decl.getASpecifier() and - ( - spec.hasName("inline") or - spec.hasName("constexpr") - ) - ) +class ViolationsOfOneDefinitionRuleQuery extends ViolationsOfOneDefinitionRuleSharedQuery { + ViolationsOfOneDefinitionRuleQuery() { + this = IncludesPackage::violationsOfOneDefinitionRuleQuery() + } } - -predicate isExtern(FunctionDeclarationEntry decl) { - exists(string spec | - spec = decl.getASpecifier() and - spec = "extern" - ) -} - -from DeclarationEntry decl, string case, string name -where - ( - //a non-inline/non-extern function defined in a header - exists(FunctionDeclarationEntry fn | - fn.isDefinition() and - not ( - isInline(fn.getDeclaration()) - or - isExtern(fn) - or - //any (defined) templates do not violate the ODR - fn.isFromUninstantiatedTemplate(_) - or - fn.isFromTemplateInstantiation(_) and - //except for specializations, those do violate ODR - not fn.isSpecialization() - or - fn.getDeclaration().isStatic() - ) and - decl = fn and - case = "function" - ) - or - //an non-const object defined in a header - exists(GlobalOrNamespaceVariable object | - object.hasDefinition() and - not ( - object.isConstexpr() - or - object.isConst() - or - object.isStatic() - ) and - decl = object.getDefinition() and - case = "object" - ) - ) and - not decl.getDeclaration().getNamespace().isAnonymous() and - decl.getFile() instanceof AcceptableHeader and - not isExcluded(decl, IncludesPackage::violationsOfOneDefinitionRuleQuery()) and - name = decl.getName() -select decl, - "Header file $@ contains " + case + " " + name + " that lead to One Defintion Rule violation.", - decl.getFile(), decl.getFile().getBaseName() diff --git a/cpp/autosar/test/rules/A3-1-1/ViolationsOfOneDefinitionRule.expected b/cpp/autosar/test/rules/A3-1-1/ViolationsOfOneDefinitionRule.expected deleted file mode 100644 index 12437f55a..000000000 --- a/cpp/autosar/test/rules/A3-1-1/ViolationsOfOneDefinitionRule.expected +++ /dev/null @@ -1,3 +0,0 @@ -| test.hpp:9:18:9:24 | definition of f5 | Header file $@ contains function f5 that lead to One Defintion Rule violation. | test.hpp:0:0:0:0 | test.hpp | test.hpp | -| test.hpp:11:6:11:7 | definition of f4 | Header file $@ contains function f4 that lead to One Defintion Rule violation. | test.hpp:0:0:0:0 | test.hpp | test.hpp | -| test.hpp:13:5:13:5 | definition of g | Header file $@ contains object g that lead to One Defintion Rule violation. | test.hpp:0:0:0:0 | test.hpp | test.hpp | diff --git a/cpp/autosar/test/rules/A3-1-1/ViolationsOfOneDefinitionRule.qlref b/cpp/autosar/test/rules/A3-1-1/ViolationsOfOneDefinitionRule.qlref deleted file mode 100644 index b15e7a57e..000000000 --- a/cpp/autosar/test/rules/A3-1-1/ViolationsOfOneDefinitionRule.qlref +++ /dev/null @@ -1 +0,0 @@ -rules/A3-1-1/ViolationsOfOneDefinitionRule.ql \ No newline at end of file diff --git a/cpp/autosar/test/rules/A3-1-1/ViolationsOfOneDefinitionRule.testref b/cpp/autosar/test/rules/A3-1-1/ViolationsOfOneDefinitionRule.testref new file mode 100644 index 000000000..d15ec80aa --- /dev/null +++ b/cpp/autosar/test/rules/A3-1-1/ViolationsOfOneDefinitionRule.testref @@ -0,0 +1 @@ +cpp/common/test/rules/violationsofonedefinitionrule/ViolationsOfOneDefinitionRule.ql \ No newline at end of file diff --git a/cpp/autosar/test/rules/A3-1-1/test.hpp b/cpp/autosar/test/rules/A3-1-1/test.hpp deleted file mode 100644 index 552d398df..000000000 --- a/cpp/autosar/test/rules/A3-1-1/test.hpp +++ /dev/null @@ -1,26 +0,0 @@ -void f(); // COMPLIANT -extern void f1() {} // COMPLIANT -static inline void f2() {} // COMPLIANT - -template void f3(T) { int i; } // COMPLIANT - -template void f5(T) { int i; } // COMPLIANT - -template <> void f5(int t) { int i; } // NON_COMPLIANT - -void f4() {} // NON_COMPLIANT - -int g; // NON_COMPLIANT -extern int g1; // COMPLIANT -constexpr static int g2 = 1; // COMPLIANT - -namespace n1 { -constexpr static int l = 1; // COMPLIANT -const static int l1 = 1; // COMPLIANT -static int l2; // COMPLIANT -static void f5() {} // COMPLIANT -} // namespace n1 - -class A {}; - -static void f6(int a, A a1) { f3(a1); } // COMPLIANT \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/exclusions/cpp/Linkage2.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Linkage2.qll index 0d804e1cc..a2d0481f6 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/cpp/Linkage2.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Linkage2.qll @@ -4,16 +4,16 @@ import RuleMetadata import codingstandards.cpp.exclusions.RuleMetadata newtype Linkage2Query = - THeaderDefinitionsExternalLinkageQuery() or + TViolationsOfOneDefinitionRuleMisraQuery() or TInternalLinkageSpecifiedAppropriatelyQuery() predicate isLinkage2QueryMetadata(Query query, string queryId, string ruleId, string category) { query = - // `Query` instance for the `headerDefinitionsExternalLinkage` query - Linkage2Package::headerDefinitionsExternalLinkageQuery() and + // `Query` instance for the `violationsOfOneDefinitionRuleMisra` query + Linkage2Package::violationsOfOneDefinitionRuleMisraQuery() and queryId = - // `@id` for the `headerDefinitionsExternalLinkage` query - "cpp/misra/header-definitions-external-linkage" and + // `@id` for the `violationsOfOneDefinitionRuleMisra` query + "cpp/misra/violations-of-one-definition-rule-misra" and ruleId = "RULE-6-2-4" and category = "required" or @@ -28,11 +28,11 @@ predicate isLinkage2QueryMetadata(Query query, string queryId, string ruleId, st } module Linkage2Package { - Query headerDefinitionsExternalLinkageQuery() { + Query violationsOfOneDefinitionRuleMisraQuery() { //autogenerate `Query` type result = - // `Query` type for `headerDefinitionsExternalLinkage` query - TQueryCPP(TLinkage2PackageQuery(THeaderDefinitionsExternalLinkageQuery())) + // `Query` type for `violationsOfOneDefinitionRuleMisra` query + TQueryCPP(TLinkage2PackageQuery(TViolationsOfOneDefinitionRuleMisraQuery())) } Query internalLinkageSpecifiedAppropriatelyQuery() { diff --git a/cpp/common/src/codingstandards/cpp/rules/violationsofonedefinitionrule/ViolationsOfOneDefinitionRule.qll b/cpp/common/src/codingstandards/cpp/rules/violationsofonedefinitionrule/ViolationsOfOneDefinitionRule.qll new file mode 100644 index 000000000..1e7f3095a --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/rules/violationsofonedefinitionrule/ViolationsOfOneDefinitionRule.qll @@ -0,0 +1,74 @@ +/** + * Provides a library with a `problems` predicate for the following issue: + * Placing the definitions of functions or objects that are non-inline and have + * external linkage can lead to violations of the ODR and can lead to undefined + * behaviour. + */ + +import cpp +import codingstandards.cpp.Customizations +import codingstandards.cpp.Exclusions +import codingstandards.cpp.AcceptableHeader +import codingstandards.cpp.Linkage + +predicate isInline(Function decl) { + exists(Specifier spec | + spec = decl.getASpecifier() and + ( + spec.hasName("inline") or + spec.hasName("constexpr") + ) + ) +} + +abstract class ViolationsOfOneDefinitionRuleSharedQuery extends Query { } + +Query getQuery() { result instanceof ViolationsOfOneDefinitionRuleSharedQuery } + +query predicate problems(DeclarationEntry decl, string message, File declFile, string secondmessage) { + exists(string case | + not isExcluded(decl, getQuery()) and + declFile = decl.getFile() and + secondmessage = decl.getFile().getBaseName() and + message = + "Header file $@ contains " + case + " " + decl.getName() + + " that lead to One Defintion Rule violation." and + hasExternalLinkage(decl.getDeclaration()) and + ( + //a non-inline/non-extern function defined in a header + exists(FunctionDeclarationEntry fn | + fn.isDefinition() and + not ( + isInline(fn.getDeclaration()) + or + //any (defined) templates do not violate the ODR + fn.isFromUninstantiatedTemplate(_) + or + fn.isFromTemplateInstantiation(_) and + //except for specializations, those do violate ODR + not fn.isSpecialization() + or + //static/nonstatic member functions should still not be defined (so do not exclude here) + fn.getDeclaration().isStatic() and not fn.getFunction() instanceof MemberFunction + ) and + decl = fn and + case = "function" + ) + or + //an non-const object defined in a header + exists(Variable object | + not ( + object.isConstexpr() + or + object.isConst() + or + object.isStatic() + ) and + decl = object.getDefinition() and + case = "object" + ) + ) and + not decl.getDeclaration().getNamespace().isAnonymous() and + decl.getFile() instanceof AcceptableHeader + ) +} diff --git a/cpp/common/test/rules/violationsofonedefinitionrule/ViolationsOfOneDefinitionRule.expected b/cpp/common/test/rules/violationsofonedefinitionrule/ViolationsOfOneDefinitionRule.expected new file mode 100644 index 000000000..537cfd758 --- /dev/null +++ b/cpp/common/test/rules/violationsofonedefinitionrule/ViolationsOfOneDefinitionRule.expected @@ -0,0 +1,3 @@ +| test.hpp:3:6:3:7 | definition of f1 | Header file $@ contains function f1 that lead to One Defintion Rule violation. | test.hpp:0:0:0:0 | test.hpp | test.hpp | +| test.hpp:8:5:8:5 | definition of i | Header file $@ contains object i that lead to One Defintion Rule violation. | test.hpp:0:0:0:0 | test.hpp | test.hpp | +| test.hpp:9:12:9:13 | definition of i1 | Header file $@ contains object i1 that lead to One Defintion Rule violation. | test.hpp:0:0:0:0 | test.hpp | test.hpp | diff --git a/cpp/common/test/rules/violationsofonedefinitionrule/ViolationsOfOneDefinitionRule.ql b/cpp/common/test/rules/violationsofonedefinitionrule/ViolationsOfOneDefinitionRule.ql new file mode 100644 index 000000000..737a42db9 --- /dev/null +++ b/cpp/common/test/rules/violationsofonedefinitionrule/ViolationsOfOneDefinitionRule.ql @@ -0,0 +1,4 @@ +// GENERATED FILE - DO NOT MODIFY +import codingstandards.cpp.rules.violationsofonedefinitionrule.ViolationsOfOneDefinitionRule + +class TestFileQuery extends ViolationsOfOneDefinitionRuleSharedQuery, TestQuery { } diff --git a/cpp/autosar/test/rules/A3-1-1/test.cpp b/cpp/common/test/rules/violationsofonedefinitionrule/test.cpp similarity index 100% rename from cpp/autosar/test/rules/A3-1-1/test.cpp rename to cpp/common/test/rules/violationsofonedefinitionrule/test.cpp diff --git a/cpp/common/test/rules/violationsofonedefinitionrule/test.hpp b/cpp/common/test/rules/violationsofonedefinitionrule/test.hpp new file mode 100644 index 000000000..3d8aaab1f --- /dev/null +++ b/cpp/common/test/rules/violationsofonedefinitionrule/test.hpp @@ -0,0 +1,26 @@ +void f(); // COMPLIANT + +void f1() {} // NON_COMPLIANT +inline void f2() {} // COMPLIANT + +template void f3(T){}; // COMPLIANT - implicitly inline + +int i; // NON_COMPLIANT +extern int i1 = 1; // NON_COMPLIANT + +constexpr auto i2{1}; // COMPLIANT - not external linkage + +struct S { + int i; // COMPLIANT - no linkage + inline static const int i1{1}; // COMPLIANT - inline +}; + +class C { + static int m(); // COMPLIANT + int m1(); // COMPLIANT +}; + +int C::m() {} // NON_COMPLIANT[FALSE_NEGATIVE] - external linkage library + // issue/namespace of class not found +int C::m1() {} // NON_COMPLIANT[FALSE_NEGATIVE] - external linkage library + // issue/namespace of class not found \ No newline at end of file diff --git a/cpp/misra/src/rules/RULE-6-2-4/ViolationsOfOneDefinitionRuleMisra.ql b/cpp/misra/src/rules/RULE-6-2-4/ViolationsOfOneDefinitionRuleMisra.ql new file mode 100644 index 000000000..71b61197d --- /dev/null +++ b/cpp/misra/src/rules/RULE-6-2-4/ViolationsOfOneDefinitionRuleMisra.ql @@ -0,0 +1,27 @@ +/** + * @id cpp/misra/violations-of-one-definition-rule-misra + * @name RULE-6-2-4: A header file shall not contain definitions of functions or objects that are non-inline and have external linkage + * @description Placing the definitions of functions or objects that are non-inline and have + * external linkage can lead to violations of the ODR and can lead to undefined + * behaviour. + * @kind problem + * @precision very-high + * @problem.severity error + * @tags external/misra/id/rule-6-2-4 + * correctness + * maintainability + * readability + * scope/single-translation-unit + * external/misra/enforcement/decidable + * external/misra/obligation/required + */ + +import cpp +import codingstandards.cpp.misra +import codingstandards.cpp.rules.violationsofonedefinitionrule.ViolationsOfOneDefinitionRule + +class ViolationsOfOneDefinitionRuleMisraQuery extends ViolationsOfOneDefinitionRuleSharedQuery { + ViolationsOfOneDefinitionRuleMisraQuery() { + this = Linkage2Package::violationsOfOneDefinitionRuleMisraQuery() + } +} diff --git a/cpp/misra/test/rules/RULE-6-2-4/ViolationsOfOneDefinitionRuleMisra.testref b/cpp/misra/test/rules/RULE-6-2-4/ViolationsOfOneDefinitionRuleMisra.testref new file mode 100644 index 000000000..d15ec80aa --- /dev/null +++ b/cpp/misra/test/rules/RULE-6-2-4/ViolationsOfOneDefinitionRuleMisra.testref @@ -0,0 +1 @@ +cpp/common/test/rules/violationsofonedefinitionrule/ViolationsOfOneDefinitionRule.ql \ No newline at end of file diff --git a/rule_packages/cpp/Includes.json b/rule_packages/cpp/Includes.json index 1d7f97ed0..9f58ee88f 100644 --- a/rule_packages/cpp/Includes.json +++ b/rule_packages/cpp/Includes.json @@ -42,6 +42,7 @@ "precision": "very-high", "severity": "warning", "short_name": "ViolationsOfOneDefinitionRule", + "shared_implementation_short_name": "ViolationsOfOneDefinitionRule", "tags": [ "correctness", "maintainability", diff --git a/rule_packages/cpp/Linkage2.json b/rule_packages/cpp/Linkage2.json index fd57834de..67d5e4b56 100644 --- a/rule_packages/cpp/Linkage2.json +++ b/rule_packages/cpp/Linkage2.json @@ -12,7 +12,8 @@ "name": "A header file shall not contain definitions of functions or objects that are non-inline and have external linkage", "precision": "very-high", "severity": "error", - "short_name": "HeaderDefinitionsExternalLinkage", + "short_name": "ViolationsOfOneDefinitionRuleMisra", + "shared_implementation_short_name": "ViolationsOfOneDefinitionRule", "tags": [ "correctness", "maintainability", diff --git a/rules.csv b/rules.csv index 0fbadfe1b..c9ed10b48 100644 --- a/rules.csv +++ b/rules.csv @@ -856,7 +856,7 @@ cpp,MISRA-C++-2023,RULE-6-0-4,Yes,Required,Decidable,Single Translation Unit,The cpp,MISRA-C++-2023,RULE-6-2-1,Yes,Required,Decidable,System,The one-definition rule shall not be violated,M3-2-2,ImportMisra23,Import, cpp,MISRA-C++-2023,RULE-6-2-2,Yes,Required,Decidable,System,All declarations of a variable or function shall have the same type,"M3-9-1,DCL40-C",Declarations2,Easy, cpp,MISRA-C++-2023,RULE-6-2-3,Yes,Required,Decidable,System,The source code used to implement an entity shall appear only once,,Declarations2,Medium, -cpp,MISRA-C++-2023,RULE-6-2-4,Yes,Required,Decidable,Single Translation Unit,A header file shall not contain definitions of functions or objects that are non-inline and have external linkage,M3-2-4,Linkage2,Easy, +cpp,MISRA-C++-2023,RULE-6-2-4,Yes,Required,Decidable,Single Translation Unit,A header file shall not contain definitions of functions or objects that are non-inline and have external linkage,A3-1-1,Linkage2,Import, cpp,MISRA-C++-2023,RULE-6-4-1,Yes,Required,Decidable,Single Translation Unit,A variable declared in an inner scope shall not hide a variable declared in an outer scope,A2-10-1,ImportMisra23,Import, cpp,MISRA-C++-2023,RULE-6-4-2,Yes,Required,Decidable,Single Translation Unit,Derived classes shall not conceal functions that are inherited from their bases,A7-3-1,ImportMisra23,Import, cpp,MISRA-C++-2023,RULE-6-4-3,Yes,Required,Decidable,Single Translation Unit,A name that is present in a dependent base shall not be resolved by unqualified lookup,M14-6-1,ImportMisra23,Import, From 14939e5633e724b2efb969d1ff1951f9bf0be09b Mon Sep 17 00:00:00 2001 From: Mauro Baluda Date: Tue, 27 Jan 2026 11:00:08 +0100 Subject: [PATCH 3/9] Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- cpp/misra/test/rules/RULE-6-5-2/test.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/cpp/misra/test/rules/RULE-6-5-2/test.cpp b/cpp/misra/test/rules/RULE-6-5-2/test.cpp index 6107309db..5127f1bfa 100644 --- a/cpp/misra/test/rules/RULE-6-5-2/test.cpp +++ b/cpp/misra/test/rules/RULE-6-5-2/test.cpp @@ -1,14 +1,14 @@ -static void f(); // NON_COMPILANT - prefer to use an anonymous namespace +static void f(); // NON_COMPLIANT - prefer to use an anonymous namespace namespace { -void f1(); // COMPILANT -extern void f2(); // NON_COMPILANT +void f1(); // COMPLIANT +extern void f2(); // NON_COMPLIANT -int i; // COMPILANT -extern int i1; // NON_COMPILANT -static int i2; // NON_COMPILANT - prefer to not use static as it is redundant +int i; // COMPLIANT +extern int i1; // NON_COMPLIANT +static int i2; // NON_COMPLIANT - prefer to not use static as it is redundant } // namespace namespace named { -static const int i[] = {1}; // COMPILANT - exception +static const int i[] = {1}; // COMPLIANT - exception } \ No newline at end of file From 9c3cd89ac615c900ac9d036275cfd62216237e34 Mon Sep 17 00:00:00 2001 From: Mauro Baluda Date: Tue, 27 Jan 2026 14:46:51 +0100 Subject: [PATCH 4/9] Update RuleMetadata.qll --- .../src/codingstandards/cpp/exclusions/cpp/RuleMetadata.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/common/src/codingstandards/cpp/exclusions/cpp/RuleMetadata.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/RuleMetadata.qll index 22dea0233..19d0caf5e 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/cpp/RuleMetadata.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/RuleMetadata.qll @@ -98,8 +98,8 @@ newtype TCPPQuery = TInvariantsPackageQuery(InvariantsQuery q) or TIteratorsPackageQuery(IteratorsQuery q) or TLambdasPackageQuery(LambdasQuery q) or - TLinkage2PackageQuery(Linkage2Query q) or TLinkage1PackageQuery(Linkage1Query q) or + TLinkage2PackageQuery(Linkage2Query q) or TLiteralsPackageQuery(LiteralsQuery q) or TLoopsPackageQuery(LoopsQuery q) or TMacrosPackageQuery(MacrosQuery q) or From f327e11001a23788516b8e6468417cf0370589dd Mon Sep 17 00:00:00 2001 From: Mauro Baluda Date: Tue, 27 Jan 2026 15:54:32 +0100 Subject: [PATCH 5/9] Update cpp/common/src/codingstandards/cpp/rules/violationsofonedefinitionrule/ViolationsOfOneDefinitionRule.qll Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../ViolationsOfOneDefinitionRule.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/common/src/codingstandards/cpp/rules/violationsofonedefinitionrule/ViolationsOfOneDefinitionRule.qll b/cpp/common/src/codingstandards/cpp/rules/violationsofonedefinitionrule/ViolationsOfOneDefinitionRule.qll index 1e7f3095a..89f35aadf 100644 --- a/cpp/common/src/codingstandards/cpp/rules/violationsofonedefinitionrule/ViolationsOfOneDefinitionRule.qll +++ b/cpp/common/src/codingstandards/cpp/rules/violationsofonedefinitionrule/ViolationsOfOneDefinitionRule.qll @@ -32,7 +32,7 @@ query predicate problems(DeclarationEntry decl, string message, File declFile, s secondmessage = decl.getFile().getBaseName() and message = "Header file $@ contains " + case + " " + decl.getName() + - " that lead to One Defintion Rule violation." and + " that lead to One Definition Rule violation." and hasExternalLinkage(decl.getDeclaration()) and ( //a non-inline/non-extern function defined in a header From 4d6052c70b02e9726c8312703b6d824257136b02 Mon Sep 17 00:00:00 2001 From: Kristen Newbury Date: Tue, 27 Jan 2026 10:15:34 -0500 Subject: [PATCH 6/9] Add missing expected file update --- .../ViolationsOfOneDefinitionRule.expected | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/common/test/rules/violationsofonedefinitionrule/ViolationsOfOneDefinitionRule.expected b/cpp/common/test/rules/violationsofonedefinitionrule/ViolationsOfOneDefinitionRule.expected index 537cfd758..e3cd553c6 100644 --- a/cpp/common/test/rules/violationsofonedefinitionrule/ViolationsOfOneDefinitionRule.expected +++ b/cpp/common/test/rules/violationsofonedefinitionrule/ViolationsOfOneDefinitionRule.expected @@ -1,3 +1,3 @@ -| test.hpp:3:6:3:7 | definition of f1 | Header file $@ contains function f1 that lead to One Defintion Rule violation. | test.hpp:0:0:0:0 | test.hpp | test.hpp | -| test.hpp:8:5:8:5 | definition of i | Header file $@ contains object i that lead to One Defintion Rule violation. | test.hpp:0:0:0:0 | test.hpp | test.hpp | -| test.hpp:9:12:9:13 | definition of i1 | Header file $@ contains object i1 that lead to One Defintion Rule violation. | test.hpp:0:0:0:0 | test.hpp | test.hpp | +| test.hpp:3:6:3:7 | definition of f1 | Header file $@ contains function f1 that lead to One Definition Rule violation. | test.hpp:0:0:0:0 | test.hpp | test.hpp | +| test.hpp:8:5:8:5 | definition of i | Header file $@ contains object i that lead to One Definition Rule violation. | test.hpp:0:0:0:0 | test.hpp | test.hpp | +| test.hpp:9:12:9:13 | definition of i1 | Header file $@ contains object i1 that lead to One Definition Rule violation. | test.hpp:0:0:0:0 | test.hpp | test.hpp | From e5da8c9e9ac596164803dbad0aa631669d2c4181 Mon Sep 17 00:00:00 2001 From: Kristen Newbury Date: Tue, 27 Jan 2026 10:16:49 -0500 Subject: [PATCH 7/9] Add missing change notes file update --- change_notes/2026-01-26-a3-1-1-extern-to-full.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/change_notes/2026-01-26-a3-1-1-extern-to-full.md b/change_notes/2026-01-26-a3-1-1-extern-to-full.md index 0b073d168..cd5ee74a4 100644 --- a/change_notes/2026-01-26-a3-1-1-extern-to-full.md +++ b/change_notes/2026-01-26-a3-1-1-extern-to-full.md @@ -1,2 +1,2 @@ - `A3-1-1` - `ViolationsOfOneDefinitionRule.ql`: - - The query previously would incorrectly allow cases where something was defined with `extern` and did not use the defined external linkage library to find external linkage. This change may result in the query finding more results. \ No newline at end of file + - The query previously would incorrectly allow cases where something was defined with `extern` and did not use the defined external linkage library to find external linkage. This change may result in the query finding more results. Additionally a typo has been fixed in the alert message which will cause the old alerts for this query to now show up as new ones. \ No newline at end of file From de0eb9ee5692dcd9c325902948f3246928c32d0c Mon Sep 17 00:00:00 2001 From: Kristen Newbury Date: Wed, 28 Jan 2026 13:00:23 -0500 Subject: [PATCH 8/9] Improve scope.qll library to handle global classes and align severity tag on RULE-6-2-4 with A3-1-1 --- cpp/common/src/codingstandards/cpp/Scope.qll | 3 +++ .../ViolationsOfOneDefinitionRule.expected | 2 ++ .../test/rules/violationsofonedefinitionrule/test.hpp | 6 ++---- .../rules/RULE-6-2-4/ViolationsOfOneDefinitionRuleMisra.ql | 2 +- rule_packages/cpp/Linkage2.json | 2 +- 5 files changed, 9 insertions(+), 6 deletions(-) diff --git a/cpp/common/src/codingstandards/cpp/Scope.qll b/cpp/common/src/codingstandards/cpp/Scope.qll index 5438c1713..53234f562 100644 --- a/cpp/common/src/codingstandards/cpp/Scope.qll +++ b/cpp/common/src/codingstandards/cpp/Scope.qll @@ -369,6 +369,9 @@ predicate hidesStrict(UserVariable v1, UserVariable v2) { predicate hasNamespaceScope(Declaration decl) { // getNamespace always returns a namespace (e.g. the global namespace). exists(Namespace n | namespacembrs(unresolveElement(n), underlyingElement(decl))) + or + decl.isTopLevel() and + not namespacembrs(_, decl) } /** Holds if `decl` has class scope. */ diff --git a/cpp/common/test/rules/violationsofonedefinitionrule/ViolationsOfOneDefinitionRule.expected b/cpp/common/test/rules/violationsofonedefinitionrule/ViolationsOfOneDefinitionRule.expected index e3cd553c6..ec43e0a4d 100644 --- a/cpp/common/test/rules/violationsofonedefinitionrule/ViolationsOfOneDefinitionRule.expected +++ b/cpp/common/test/rules/violationsofonedefinitionrule/ViolationsOfOneDefinitionRule.expected @@ -1,3 +1,5 @@ | test.hpp:3:6:3:7 | definition of f1 | Header file $@ contains function f1 that lead to One Definition Rule violation. | test.hpp:0:0:0:0 | test.hpp | test.hpp | | test.hpp:8:5:8:5 | definition of i | Header file $@ contains object i that lead to One Definition Rule violation. | test.hpp:0:0:0:0 | test.hpp | test.hpp | | test.hpp:9:12:9:13 | definition of i1 | Header file $@ contains object i1 that lead to One Definition Rule violation. | test.hpp:0:0:0:0 | test.hpp | test.hpp | +| test.hpp:23:5:23:8 | definition of m | Header file $@ contains function m that lead to One Definition Rule violation. | test.hpp:0:0:0:0 | test.hpp | test.hpp | +| test.hpp:25:5:25:9 | definition of m1 | Header file $@ contains function m1 that lead to One Definition Rule violation. | test.hpp:0:0:0:0 | test.hpp | test.hpp | diff --git a/cpp/common/test/rules/violationsofonedefinitionrule/test.hpp b/cpp/common/test/rules/violationsofonedefinitionrule/test.hpp index 3d8aaab1f..84af9176a 100644 --- a/cpp/common/test/rules/violationsofonedefinitionrule/test.hpp +++ b/cpp/common/test/rules/violationsofonedefinitionrule/test.hpp @@ -20,7 +20,5 @@ class C { int m1(); // COMPLIANT }; -int C::m() {} // NON_COMPLIANT[FALSE_NEGATIVE] - external linkage library - // issue/namespace of class not found -int C::m1() {} // NON_COMPLIANT[FALSE_NEGATIVE] - external linkage library - // issue/namespace of class not found \ No newline at end of file +int C::m() {} // NON_COMPLIANT +int C::m1() {} // NON_COMPLIANT \ No newline at end of file diff --git a/cpp/misra/src/rules/RULE-6-2-4/ViolationsOfOneDefinitionRuleMisra.ql b/cpp/misra/src/rules/RULE-6-2-4/ViolationsOfOneDefinitionRuleMisra.ql index 71b61197d..4c91b3206 100644 --- a/cpp/misra/src/rules/RULE-6-2-4/ViolationsOfOneDefinitionRuleMisra.ql +++ b/cpp/misra/src/rules/RULE-6-2-4/ViolationsOfOneDefinitionRuleMisra.ql @@ -6,7 +6,7 @@ * behaviour. * @kind problem * @precision very-high - * @problem.severity error + * @problem.severity warning * @tags external/misra/id/rule-6-2-4 * correctness * maintainability diff --git a/rule_packages/cpp/Linkage2.json b/rule_packages/cpp/Linkage2.json index 67d5e4b56..15a75a8a9 100644 --- a/rule_packages/cpp/Linkage2.json +++ b/rule_packages/cpp/Linkage2.json @@ -11,7 +11,7 @@ "kind": "problem", "name": "A header file shall not contain definitions of functions or objects that are non-inline and have external linkage", "precision": "very-high", - "severity": "error", + "severity": "warning", "short_name": "ViolationsOfOneDefinitionRuleMisra", "shared_implementation_short_name": "ViolationsOfOneDefinitionRule", "tags": [ From fe20f7e7f1efd5d766b037b1d458ac3ada5c1cc5 Mon Sep 17 00:00:00 2001 From: Kristen Newbury Date: Wed, 28 Jan 2026 16:42:16 -0500 Subject: [PATCH 9/9] Improve testcase for externallinkagearraywithoutexplicitsize and change note to match --- ...-1-extern-to-full.md => 2026-01-26-improve-queries.md} | 4 +++- .../ExternalLinkageArrayWithoutExplicitSize.expected | 2 ++ .../externallinkagearraywithoutexplicitsize/test.cpp | 8 +++----- 3 files changed, 8 insertions(+), 6 deletions(-) rename change_notes/{2026-01-26-a3-1-1-extern-to-full.md => 2026-01-26-improve-queries.md} (56%) diff --git a/change_notes/2026-01-26-a3-1-1-extern-to-full.md b/change_notes/2026-01-26-improve-queries.md similarity index 56% rename from change_notes/2026-01-26-a3-1-1-extern-to-full.md rename to change_notes/2026-01-26-improve-queries.md index cd5ee74a4..856f4949e 100644 --- a/change_notes/2026-01-26-a3-1-1-extern-to-full.md +++ b/change_notes/2026-01-26-improve-queries.md @@ -1,2 +1,4 @@ - `A3-1-1` - `ViolationsOfOneDefinitionRule.ql`: - - The query previously would incorrectly allow cases where something was defined with `extern` and did not use the defined external linkage library to find external linkage. This change may result in the query finding more results. Additionally a typo has been fixed in the alert message which will cause the old alerts for this query to now show up as new ones. \ No newline at end of file + - The query previously would incorrectly allow cases where something was defined with `extern` and did not use the defined external linkage library to find external linkage. This change may result in the query finding more results. Additionally a typo has been fixed in the alert message which will cause the old alerts for this query to now show up as new ones. + - `RULE-6-0-2`, `A3-1-4` - `ExternalLinkageArrayWithoutExplicitSizeMisra.ql`, `ExternalLinkageArrayWithoutExplicitSizeAutosar.ql`: + - The queries listed now find flexible member arrays in structs, as those do not have an explicit size. \ No newline at end of file diff --git a/cpp/common/test/rules/externallinkagearraywithoutexplicitsize/ExternalLinkageArrayWithoutExplicitSize.expected b/cpp/common/test/rules/externallinkagearraywithoutexplicitsize/ExternalLinkageArrayWithoutExplicitSize.expected index 89dab3d48..ffb8222c3 100644 --- a/cpp/common/test/rules/externallinkagearraywithoutexplicitsize/ExternalLinkageArrayWithoutExplicitSize.expected +++ b/cpp/common/test/rules/externallinkagearraywithoutexplicitsize/ExternalLinkageArrayWithoutExplicitSize.expected @@ -1,2 +1,4 @@ | test.cpp:19:14:19:15 | declaration of e1 | The declared array 'e1' with external linkage doesn't specify the size explicitly. | +| test.cpp:27:20:27:38 | declaration of flexibleArrayMember | The declared array 'flexibleArrayMember' with external linkage doesn't specify the size explicitly. | +| test.cpp:28:14:28:33 | declaration of flexibleArrayMember2 | The declared array 'flexibleArrayMember2' with external linkage doesn't specify the size explicitly. | | test.hpp:2:13:2:26 | declaration of header_and_cpp | The declared array 'header_and_cpp' with external linkage doesn't specify the size explicitly. | diff --git a/cpp/common/test/rules/externallinkagearraywithoutexplicitsize/test.cpp b/cpp/common/test/rules/externallinkagearraywithoutexplicitsize/test.cpp index 6bacd9b48..d0cb2bee6 100644 --- a/cpp/common/test/rules/externallinkagearraywithoutexplicitsize/test.cpp +++ b/cpp/common/test/rules/externallinkagearraywithoutexplicitsize/test.cpp @@ -23,11 +23,9 @@ struct s { // Structs must have at least one non-flexible array member. int foo; - // static data members have external linkage - but not currently detected in - // our external linkage lib - also FAMs are expected to be detected - // specifically in RULE-18-7 - static const int flexibleArrayMember[]; // NON_COMPLIANT[FALSE_NEGATIVE] - static int flexibleArrayMember2[]; // NON_COMPLIANT[FALSE_NEGATIVE] + // FAMs are expected to be detected specifically in RULE-18-7 + static const int flexibleArrayMember[]; // NON_COMPLIANT + static int flexibleArrayMember2[]; // NON_COMPLIANT }; // test.cpp