From f1417b07ba14aff45af15e64ba0c42616a5a47e4 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Wed, 18 Feb 2026 12:35:22 -0800 Subject: [PATCH 1/2] Implement Rule 0.2.4, unused functions with limited visibility. --- ...-member-functions-with-internal-linkage.md | 2 + .../src/rules/A0-1-3/UnusedLocalFunction.ql | 93 +------------- .../rules/A0-1-3/UnusedLocalFunctionOld.ql | 110 +++++++++++++++++ .../rules/A0-1-3/UnusedLocalFunction.testref | 1 + .../cpp/exclusions/cpp/DeadCode10.qll | 26 ++++ .../cpp/exclusions/cpp/RuleMetadata.qll | 3 + .../UnusedLocalFunction.qll | 115 ++++++++++++++++++ .../UnusedLocalFunction.expected | 2 + .../UnusedLocalFunction.ql | 8 ++ .../test/rules/unusedlocalfunction}/test.cpp | 21 ++++ .../UnusedLimitedVisibilityFunction.ql | 26 ++++ .../UnusedLimitedVisibilityFunction.testref | 1 + rule_packages/cpp/DeadCode.json | 1 + rule_packages/cpp/DeadCode10.json | 30 +++++ rules.csv | 2 +- 15 files changed, 351 insertions(+), 90 deletions(-) create mode 100644 change_notes/2026-02-18-unused-member-functions-with-internal-linkage.md create mode 100644 cpp/autosar/src/rules/A0-1-3/UnusedLocalFunctionOld.ql create mode 100644 cpp/autosar/test/rules/A0-1-3/UnusedLocalFunction.testref create mode 100644 cpp/common/src/codingstandards/cpp/exclusions/cpp/DeadCode10.qll create mode 100644 cpp/common/src/codingstandards/cpp/rules/unusedlocalfunction/UnusedLocalFunction.qll rename cpp/{autosar/test/rules/A0-1-3 => common/test/rules/unusedlocalfunction}/UnusedLocalFunction.expected (70%) create mode 100644 cpp/common/test/rules/unusedlocalfunction/UnusedLocalFunction.ql rename cpp/{autosar/test/rules/A0-1-3 => common/test/rules/unusedlocalfunction}/test.cpp (89%) create mode 100644 cpp/misra/src/rules/RULE-0-2-4/UnusedLimitedVisibilityFunction.ql create mode 100644 cpp/misra/test/rules/RULE-0-2-4/UnusedLimitedVisibilityFunction.testref create mode 100644 rule_packages/cpp/DeadCode10.json diff --git a/change_notes/2026-02-18-unused-member-functions-with-internal-linkage.md b/change_notes/2026-02-18-unused-member-functions-with-internal-linkage.md new file mode 100644 index 0000000000..b1ace10380 --- /dev/null +++ b/change_notes/2026-02-18-unused-member-functions-with-internal-linkage.md @@ -0,0 +1,2 @@ + - `A0-1-3` - `UnusedLocalFunction.ql`: + - Query now reports unused public members of classes in anonymous namespaces, which have internal linkage. \ No newline at end of file diff --git a/cpp/autosar/src/rules/A0-1-3/UnusedLocalFunction.ql b/cpp/autosar/src/rules/A0-1-3/UnusedLocalFunction.ql index 3d5869123a..d6ce2985a6 100644 --- a/cpp/autosar/src/rules/A0-1-3/UnusedLocalFunction.ql +++ b/cpp/autosar/src/rules/A0-1-3/UnusedLocalFunction.ql @@ -16,95 +16,10 @@ import cpp import codingstandards.cpp.autosar -import codingstandards.cpp.DynamicCallGraph -import codingstandards.cpp.deadcode.UnusedFunctions +import codingstandards.cpp.rules.unusedlocalfunction.UnusedLocalFunction -/** - * Checks if an overloaded function of - * the function passed in the arguments, is called. - */ -predicate overloadedFunctionIsCalled(Function unusedFunction) { - exists(Function f | f = unusedFunction.getAnOverload() and f = getTarget(_)) -} - -/** Checks if a Function's address was taken. */ -predicate addressBeenTaken(Function unusedFunction) { - exists(FunctionAccess fa | fa.getTarget() = unusedFunction) -} - -/** A `Function` nested in an anonymous namespace. */ -class AnonymousNamespaceFunction extends Function { - AnonymousNamespaceFunction() { getNamespace().getParentNamespace*().isAnonymous() } -} - -/** - * A function which is "local" to a particular scope or translation unit. - */ -class LocalFunction extends UnusedFunctions::UsableFunction { - string localFunctionType; - - LocalFunction() { - this.(MemberFunction).isPrivate() and - localFunctionType = "Private member" - or - // A function in an anonymous namespace (which is deduced to have internal linkage) - this instanceof AnonymousNamespaceFunction and - // Not member functions, which don't have internal linkage - not this instanceof MemberFunction and - localFunctionType = "Anonymous namespace" - or - // Static functions with internal linkage - this.isStatic() and - // Member functions never have internal linkage - not this instanceof MemberFunction and - // Functions in anonymous namespaces automatically have the "static" specifier added by the - // extractor. We therefore excluded them from this case, and instead report them in the - // anonymous namespace, as we don't know whether the "static" specifier was explicitly - // provided by the user. - not this instanceof AnonymousNamespaceFunction and - localFunctionType = "Static" - } - - /** Gets the type of local function. */ - string getLocalFunctionType() { result = localFunctionType } +module UnusedLocalFunctionConfig implements UnusedLocalFunctionConfigSig { + Query getQuery() { result = DeadCodePackage::unusedLocalFunctionQuery() } } -from LocalFunction unusedLocalFunction, string name -where - not isExcluded(unusedLocalFunction, DeadCodePackage::unusedLocalFunctionQuery()) and - // No static or dynamic call target for this function - not unusedLocalFunction = getTarget(_) and - // If this is a TemplateFunction or an instantiation of a template, then only report it as unused - // if all other instantiations of the template are unused - not exists( - Function functionFromUninstantiatedTemplate, Function functionFromInstantiatedTemplate - | - // `unusedLocalFunction` is a template instantiation from `functionFromUninstantiatedTemplate` - unusedLocalFunction.isConstructedFrom(functionFromUninstantiatedTemplate) - or - // `unusedLocalFunction` is from an uninstantiated template - unusedLocalFunction = functionFromUninstantiatedTemplate - | - // There exists an instantiation which is called - functionFromInstantiatedTemplate.isConstructedFrom(functionFromUninstantiatedTemplate) and - functionFromInstantiatedTemplate = getTarget(_) - ) and - // A function is defined as "used" if any one of the following holds true: - // - It's an explicitly deleted functions e.g. =delete - // - It's annotated as "[[maybe_unused]]" - // - It's part of an overloaded set and any one of the overloaded instance - // is called. - // - It's an operand of an expression in an unevaluated context. - not unusedLocalFunction.isDeleted() and - not unusedLocalFunction.getAnAttribute().getName() = "maybe_unused" and - not overloadedFunctionIsCalled(unusedLocalFunction) and - not addressBeenTaken(unusedLocalFunction) and - // Get a printable name - ( - if exists(unusedLocalFunction.getQualifiedName()) - then name = unusedLocalFunction.getQualifiedName() - else name = unusedLocalFunction.getName() - ) -select unusedLocalFunction, - unusedLocalFunction.getLocalFunctionType() + " function " + name + - " is not statically called, or is in an unused template." +import UnusedLocalFunction diff --git a/cpp/autosar/src/rules/A0-1-3/UnusedLocalFunctionOld.ql b/cpp/autosar/src/rules/A0-1-3/UnusedLocalFunctionOld.ql new file mode 100644 index 0000000000..3d5869123a --- /dev/null +++ b/cpp/autosar/src/rules/A0-1-3/UnusedLocalFunctionOld.ql @@ -0,0 +1,110 @@ +/** + * @id cpp/autosar/unused-local-function + * @name A0-1-3: Unused local function + * @description Every function defined in an anonymous namespace, or static function with internal + * linkage, or private member function shall be used. + * @kind problem + * @precision very-high + * @problem.severity warning + * @tags external/autosar/id/a0-1-3 + * readability + * maintainability + * external/autosar/allocated-target/implementation + * external/autosar/enforcement/automated + * external/autosar/obligation/required + */ + +import cpp +import codingstandards.cpp.autosar +import codingstandards.cpp.DynamicCallGraph +import codingstandards.cpp.deadcode.UnusedFunctions + +/** + * Checks if an overloaded function of + * the function passed in the arguments, is called. + */ +predicate overloadedFunctionIsCalled(Function unusedFunction) { + exists(Function f | f = unusedFunction.getAnOverload() and f = getTarget(_)) +} + +/** Checks if a Function's address was taken. */ +predicate addressBeenTaken(Function unusedFunction) { + exists(FunctionAccess fa | fa.getTarget() = unusedFunction) +} + +/** A `Function` nested in an anonymous namespace. */ +class AnonymousNamespaceFunction extends Function { + AnonymousNamespaceFunction() { getNamespace().getParentNamespace*().isAnonymous() } +} + +/** + * A function which is "local" to a particular scope or translation unit. + */ +class LocalFunction extends UnusedFunctions::UsableFunction { + string localFunctionType; + + LocalFunction() { + this.(MemberFunction).isPrivate() and + localFunctionType = "Private member" + or + // A function in an anonymous namespace (which is deduced to have internal linkage) + this instanceof AnonymousNamespaceFunction and + // Not member functions, which don't have internal linkage + not this instanceof MemberFunction and + localFunctionType = "Anonymous namespace" + or + // Static functions with internal linkage + this.isStatic() and + // Member functions never have internal linkage + not this instanceof MemberFunction and + // Functions in anonymous namespaces automatically have the "static" specifier added by the + // extractor. We therefore excluded them from this case, and instead report them in the + // anonymous namespace, as we don't know whether the "static" specifier was explicitly + // provided by the user. + not this instanceof AnonymousNamespaceFunction and + localFunctionType = "Static" + } + + /** Gets the type of local function. */ + string getLocalFunctionType() { result = localFunctionType } +} + +from LocalFunction unusedLocalFunction, string name +where + not isExcluded(unusedLocalFunction, DeadCodePackage::unusedLocalFunctionQuery()) and + // No static or dynamic call target for this function + not unusedLocalFunction = getTarget(_) and + // If this is a TemplateFunction or an instantiation of a template, then only report it as unused + // if all other instantiations of the template are unused + not exists( + Function functionFromUninstantiatedTemplate, Function functionFromInstantiatedTemplate + | + // `unusedLocalFunction` is a template instantiation from `functionFromUninstantiatedTemplate` + unusedLocalFunction.isConstructedFrom(functionFromUninstantiatedTemplate) + or + // `unusedLocalFunction` is from an uninstantiated template + unusedLocalFunction = functionFromUninstantiatedTemplate + | + // There exists an instantiation which is called + functionFromInstantiatedTemplate.isConstructedFrom(functionFromUninstantiatedTemplate) and + functionFromInstantiatedTemplate = getTarget(_) + ) and + // A function is defined as "used" if any one of the following holds true: + // - It's an explicitly deleted functions e.g. =delete + // - It's annotated as "[[maybe_unused]]" + // - It's part of an overloaded set and any one of the overloaded instance + // is called. + // - It's an operand of an expression in an unevaluated context. + not unusedLocalFunction.isDeleted() and + not unusedLocalFunction.getAnAttribute().getName() = "maybe_unused" and + not overloadedFunctionIsCalled(unusedLocalFunction) and + not addressBeenTaken(unusedLocalFunction) and + // Get a printable name + ( + if exists(unusedLocalFunction.getQualifiedName()) + then name = unusedLocalFunction.getQualifiedName() + else name = unusedLocalFunction.getName() + ) +select unusedLocalFunction, + unusedLocalFunction.getLocalFunctionType() + " function " + name + + " is not statically called, or is in an unused template." diff --git a/cpp/autosar/test/rules/A0-1-3/UnusedLocalFunction.testref b/cpp/autosar/test/rules/A0-1-3/UnusedLocalFunction.testref new file mode 100644 index 0000000000..5bfa8d6867 --- /dev/null +++ b/cpp/autosar/test/rules/A0-1-3/UnusedLocalFunction.testref @@ -0,0 +1 @@ +cpp/common/test/rules/unusedlocalfunction/UnusedLocalFunction.ql \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/exclusions/cpp/DeadCode10.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/DeadCode10.qll new file mode 100644 index 0000000000..7f6bb1ea8f --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/DeadCode10.qll @@ -0,0 +1,26 @@ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ +import cpp +import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata + +newtype DeadCode10Query = TUnusedLimitedVisibilityFunctionQuery() + +predicate isDeadCode10QueryMetadata(Query query, string queryId, string ruleId, string category) { + query = + // `Query` instance for the `unusedLimitedVisibilityFunction` query + DeadCode10Package::unusedLimitedVisibilityFunctionQuery() and + queryId = + // `@id` for the `unusedLimitedVisibilityFunction` query + "cpp/misra/unused-limited-visibility-function" and + ruleId = "RULE-0-2-4" and + category = "advisory" +} + +module DeadCode10Package { + Query unusedLimitedVisibilityFunctionQuery() { + //autogenerate `Query` type + result = + // `Query` type for `unusedLimitedVisibilityFunction` query + TQueryCPP(TDeadCode10PackageQuery(TUnusedLimitedVisibilityFunctionQuery())) + } +} diff --git a/cpp/common/src/codingstandards/cpp/exclusions/cpp/RuleMetadata.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/RuleMetadata.qll index cad86d2285..b595e2daa4 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/cpp/RuleMetadata.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/RuleMetadata.qll @@ -17,6 +17,7 @@ import Const import Conversions import Conversions2 import DeadCode +import DeadCode10 import DeadCode3 import DeadCode4 import Declarations @@ -89,6 +90,7 @@ newtype TCPPQuery = TConversionsPackageQuery(ConversionsQuery q) or TConversions2PackageQuery(Conversions2Query q) or TDeadCodePackageQuery(DeadCodeQuery q) or + TDeadCode10PackageQuery(DeadCode10Query q) or TDeadCode3PackageQuery(DeadCode3Query q) or TDeadCode4PackageQuery(DeadCode4Query q) or TDeclarationsPackageQuery(DeclarationsQuery q) or @@ -161,6 +163,7 @@ predicate isQueryMetadata(Query query, string queryId, string ruleId, string cat isConversionsQueryMetadata(query, queryId, ruleId, category) or isConversions2QueryMetadata(query, queryId, ruleId, category) or isDeadCodeQueryMetadata(query, queryId, ruleId, category) or + isDeadCode10QueryMetadata(query, queryId, ruleId, category) or isDeadCode3QueryMetadata(query, queryId, ruleId, category) or isDeadCode4QueryMetadata(query, queryId, ruleId, category) or isDeclarationsQueryMetadata(query, queryId, ruleId, category) or diff --git a/cpp/common/src/codingstandards/cpp/rules/unusedlocalfunction/UnusedLocalFunction.qll b/cpp/common/src/codingstandards/cpp/rules/unusedlocalfunction/UnusedLocalFunction.qll new file mode 100644 index 0000000000..956352bae3 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/rules/unusedlocalfunction/UnusedLocalFunction.qll @@ -0,0 +1,115 @@ +/** + * Provides a configurable module UnusedLocalFunction with a `problems` predicate + * for the following issue: + * Unused functions may indicate a coding error or require maintenance; functions that + * are unused with certain visibility have no effect on the program and should be + * removed. + */ + +import cpp +import codingstandards.cpp.Customizations +import codingstandards.cpp.Exclusions +import codingstandards.cpp.DynamicCallGraph +import codingstandards.cpp.deadcode.UnusedFunctions + +/** + * Checks if an overloaded function of + * the function passed in the arguments, is called. + */ +predicate overloadedFunctionIsCalled(Function unusedFunction) { + exists(Function f | f = unusedFunction.getAnOverload() and f = getTarget(_)) +} + +/** Checks if a Function's address was taken. */ +predicate addressBeenTaken(Function unusedFunction) { + exists(FunctionAccess fa | fa.getTarget() = unusedFunction) +} + +/** A `Function` nested in an anonymous namespace. */ +class AnonymousNamespaceFunction extends Function { + AnonymousNamespaceFunction() { getNamespace().getParentNamespace*().isAnonymous() } +} + +/** + * A function which is "local" to a particular scope or translation unit. + */ +class LocalFunction extends UnusedFunctions::UsableFunction { + string localFunctionType; + + LocalFunction() { + this.(MemberFunction).isPrivate() and + localFunctionType = "Private member" + or + // A function in an anonymous namespace (which is deduced to have internal linkage) + this instanceof AnonymousNamespaceFunction and + not this instanceof MemberFunction and + localFunctionType = "Anonymous namespace" + or + // Class members in anonymous namespaces also have internal linkage. + this instanceof AnonymousNamespaceFunction and + this instanceof MemberFunction and + localFunctionType = "Anonymous namespace class member" + or + // Static functions with internal linkage + this.isStatic() and + // Member functions never have internal linkage + not this instanceof MemberFunction and + // Functions in anonymous namespaces automatically have the "static" specifier added by the + // extractor. We therefore excluded them from this case, and instead report them in the + // anonymous namespace, as we don't know whether the "static" specifier was explicitly + // provided by the user. + not this instanceof AnonymousNamespaceFunction and + localFunctionType = "Static" + } + + /** Gets the type of local function. */ + string getLocalFunctionType() { result = localFunctionType } +} + +signature module UnusedLocalFunctionConfigSig { + Query getQuery(); +} + +module UnusedLocalFunction { + query predicate problems(LocalFunction unusedLocalFunction, string message) { + exists(string name | + not isExcluded(unusedLocalFunction, Config::getQuery()) and + // No static or dynamic call target for this function + not unusedLocalFunction = getTarget(_) and + // If this is a TemplateFunction or an instantiation of a template, then only report it as unused + // if all other instantiations of the template are unused + not exists( + Function functionFromUninstantiatedTemplate, Function functionFromInstantiatedTemplate + | + // `unusedLocalFunction` is a template instantiation from `functionFromUninstantiatedTemplate` + unusedLocalFunction.isConstructedFrom(functionFromUninstantiatedTemplate) + or + // `unusedLocalFunction` is from an uninstantiated template + unusedLocalFunction = functionFromUninstantiatedTemplate + | + // There exists an instantiation which is called + functionFromInstantiatedTemplate.isConstructedFrom(functionFromUninstantiatedTemplate) and + functionFromInstantiatedTemplate = getTarget(_) + ) and + // A function is defined as "used" if any one of the following holds true: + // - It's an explicitly deleted functions e.g. =delete + // - It's annotated as "[[maybe_unused]]" + // - It's part of an overloaded set and any one of the overloaded instance + // is called. + // - It's an operand of an expression in an unevaluated context. + not unusedLocalFunction.isDeleted() and + not unusedLocalFunction.getAnAttribute().getName() = "maybe_unused" and + not overloadedFunctionIsCalled(unusedLocalFunction) and + not addressBeenTaken(unusedLocalFunction) and + // Get a printable name + ( + if exists(unusedLocalFunction.getQualifiedName()) + then name = unusedLocalFunction.getQualifiedName() + else name = unusedLocalFunction.getName() + ) and + message = + unusedLocalFunction.getLocalFunctionType() + " function " + name + + " is not statically called, or is in an unused template." + ) + } +} diff --git a/cpp/autosar/test/rules/A0-1-3/UnusedLocalFunction.expected b/cpp/common/test/rules/unusedlocalfunction/UnusedLocalFunction.expected similarity index 70% rename from cpp/autosar/test/rules/A0-1-3/UnusedLocalFunction.expected rename to cpp/common/test/rules/unusedlocalfunction/UnusedLocalFunction.expected index 8be80b683d..e2599d5b53 100644 --- a/cpp/autosar/test/rules/A0-1-3/UnusedLocalFunction.expected +++ b/cpp/common/test/rules/unusedlocalfunction/UnusedLocalFunction.expected @@ -4,3 +4,5 @@ | test.cpp:60:5:60:9 | getAT | Private member function C::getAT is not statically called, or is in an unused template. | | test.cpp:81:6:81:7 | h2 | Anonymous namespace function (unnamed namespace)::h2 is not statically called, or is in an unused template. | | test.cpp:85:6:85:7 | h3 | Anonymous namespace function (unnamed namespace)::foo::bar::h3 is not statically called, or is in an unused template. | +| test.cpp:144:8:144:8 | f | Anonymous namespace class member function (unnamed namespace)::C1::f is not statically called, or is in an unused template. | +| test.cpp:150:8:150:8 | f | Anonymous namespace class member function (unnamed namespace)::named::C2::f is not statically called, or is in an unused template. | diff --git a/cpp/common/test/rules/unusedlocalfunction/UnusedLocalFunction.ql b/cpp/common/test/rules/unusedlocalfunction/UnusedLocalFunction.ql new file mode 100644 index 0000000000..f22020d77d --- /dev/null +++ b/cpp/common/test/rules/unusedlocalfunction/UnusedLocalFunction.ql @@ -0,0 +1,8 @@ +// GENERATED FILE - DO NOT MODIFY +import codingstandards.cpp.rules.unusedlocalfunction.UnusedLocalFunction + +module TestFileConfig implements UnusedLocalFunctionConfigSig { + Query getQuery() { result instanceof TestQuery } +} + +import UnusedLocalFunction diff --git a/cpp/autosar/test/rules/A0-1-3/test.cpp b/cpp/common/test/rules/unusedlocalfunction/test.cpp similarity index 89% rename from cpp/autosar/test/rules/A0-1-3/test.cpp rename to cpp/common/test/rules/unusedlocalfunction/test.cpp index 4ec8af884a..9ce37dcaae 100644 --- a/cpp/autosar/test/rules/A0-1-3/test.cpp +++ b/cpp/common/test/rules/unusedlocalfunction/test.cpp @@ -137,3 +137,24 @@ class classWithOverloads { return c + d; } }; + +namespace { +class C1 { +public: + void f() {} // NON_COMPLIANT - never used, internal linkage +}; + +namespace named { +class C2 { +public: + void f() {} // NON_COMPLIANT - never used, internal linkage +}; +} // namespace named +} // namespace + +namespace N1 { +class C3 { +public: + void f() {} // COMPLIANT - public external linkage +}; +} // namespace N1 \ No newline at end of file diff --git a/cpp/misra/src/rules/RULE-0-2-4/UnusedLimitedVisibilityFunction.ql b/cpp/misra/src/rules/RULE-0-2-4/UnusedLimitedVisibilityFunction.ql new file mode 100644 index 0000000000..638c864196 --- /dev/null +++ b/cpp/misra/src/rules/RULE-0-2-4/UnusedLimitedVisibilityFunction.ql @@ -0,0 +1,26 @@ +/** + * @id cpp/misra/unused-limited-visibility-function + * @name RULE-0-2-4: Functions with limited visibility should be used at least once + * @description Unused functions may indicate a coding error or require maintenance; functions that + * are unused with certain visibility have no effect on the program and should be + * removed. + * @kind problem + * @precision very-high + * @problem.severity error + * @tags external/misra/id/rule-0-2-4 + * scope/system + * maintainability + * correctness + * external/misra/enforcement/decidable + * external/misra/obligation/advisory + */ + +import cpp +import codingstandards.cpp.misra +import codingstandards.cpp.rules.unusedlocalfunction.UnusedLocalFunction + +module UnusedLimitedVisibilityFunctionConfig implements UnusedLocalFunctionConfigSig { + Query getQuery() { result = DeadCode10Package::unusedLimitedVisibilityFunctionQuery() } +} + +import UnusedLocalFunction diff --git a/cpp/misra/test/rules/RULE-0-2-4/UnusedLimitedVisibilityFunction.testref b/cpp/misra/test/rules/RULE-0-2-4/UnusedLimitedVisibilityFunction.testref new file mode 100644 index 0000000000..5bfa8d6867 --- /dev/null +++ b/cpp/misra/test/rules/RULE-0-2-4/UnusedLimitedVisibilityFunction.testref @@ -0,0 +1 @@ +cpp/common/test/rules/unusedlocalfunction/UnusedLocalFunction.ql \ No newline at end of file diff --git a/rule_packages/cpp/DeadCode.json b/rule_packages/cpp/DeadCode.json index 4746f86dee..7c38f2b3db 100644 --- a/rule_packages/cpp/DeadCode.json +++ b/rule_packages/cpp/DeadCode.json @@ -64,6 +64,7 @@ "precision": "very-high", "severity": "warning", "short_name": "UnusedLocalFunction", + "shared_implementation_short_name": "UnusedLocalFunction", "tags": [ "readability", "maintainability" diff --git a/rule_packages/cpp/DeadCode10.json b/rule_packages/cpp/DeadCode10.json new file mode 100644 index 0000000000..2626c0c78e --- /dev/null +++ b/rule_packages/cpp/DeadCode10.json @@ -0,0 +1,30 @@ +{ + "MISRA-C++-2023": { + "RULE-0-2-4": { + "properties": { + "enforcement": "decidable", + "obligation": "advisory" + }, + "queries": [ + { + "description": "Unused functions may indicate a coding error or require maintenance; functions that are unused with certain visibility have no effect on the program and should be removed.", + "kind": "problem", + "name": "Functions with limited visibility should be used at least once", + "precision": "very-high", + "severity": "error", + "short_name": "UnusedLimitedVisibilityFunction", + "shared_implementation_short_name": "UnusedLocalFunction", + "tags": [ + "scope/system", + "maintainability", + "correctness" + ], + "implementation_scope": { + "description": "Use of any overload of a function in an overload set constitute a use of all members of the set. An overload set is a set of functions with the same name that differ in the number, type and/or qualifiers of their parameters, and, for the purpose of this query, are limited to functions which are declared in the same scope (namespace or class). Functions defined in anonymous (unnamed) namespaces and global namespaces are therefore not currently considered to be part of the same overload set." + } + } + ], + "title": "Functions with limited visibility should be used at least once" + } + } +} \ No newline at end of file diff --git a/rules.csv b/rules.csv index dcc5ee5c5f..4beb15db97 100644 --- a/rules.csv +++ b/rules.csv @@ -830,7 +830,7 @@ cpp,MISRA-C++-2023,RULE-0-1-2,Yes,Required,Decidable,Single Translation Unit,The cpp,MISRA-C++-2023,RULE-0-2-1,Yes,Advisory,Decidable,Single Translation Unit,Variables with limited visibility should be used at least once,M0-1-3,DeadCode2,Easy, cpp,MISRA-C++-2023,RULE-0-2-2,Yes,Required,Decidable,Single Translation Unit,A named function parameter shall be used at least once,"A0-1-4, A0-1-5",DeadCode2,Easy, cpp,MISRA-C++-2023,RULE-0-2-3,Yes,Advisory,Decidable,Single Translation Unit,Types with limited visibility should be used at least once,A0-1-6,DeadCode2,Easy, -cpp,MISRA-C++-2023,RULE-0-2-4,Yes,Advisory,Decidable,System,Functions with limited visibility should be used at least once,A0-1-3,DeadCode2,Easy, +cpp,MISRA-C++-2023,RULE-0-2-4,Yes,Advisory,Decidable,System,Functions with limited visibility should be used at least once,A0-1-3,DeadCode10,Easy, cpp,MISRA-C++-2023,DIR-0-3-1,Yes,Advisory,,,Floating-point arithmetic should be used appropriately,,FloatingPoint,Hard, cpp,MISRA-C++-2023,DIR-0-3-2,Yes,Required,,,A function call shall not violate the function’s preconditions,,Preconditions,Hard, cpp,MISRA-C++-2023,RULE-4-1-1,Yes,Required,Undecidable,System,A program shall conform to ISO/IEC 14882:2017 (C++17),,Toolchain2,Hard, From b8d858a4279839f65b4daca37c88ca57b5f95d1f Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Wed, 18 Feb 2026 14:58:24 -0800 Subject: [PATCH 2/2] Remove qlref from 10-1-3 now that its shared. --- cpp/autosar/test/rules/A0-1-3/UnusedLocalFunction.qlref | 1 - 1 file changed, 1 deletion(-) delete mode 100644 cpp/autosar/test/rules/A0-1-3/UnusedLocalFunction.qlref diff --git a/cpp/autosar/test/rules/A0-1-3/UnusedLocalFunction.qlref b/cpp/autosar/test/rules/A0-1-3/UnusedLocalFunction.qlref deleted file mode 100644 index 7a0ff6ecba..0000000000 --- a/cpp/autosar/test/rules/A0-1-3/UnusedLocalFunction.qlref +++ /dev/null @@ -1 +0,0 @@ -rules/A0-1-3/UnusedLocalFunction.ql \ No newline at end of file