diff --git a/c/common/test/rules/unusedtypedeclarations/UnusedTypeDeclarations.expected b/c/common/test/rules/unusedtypedeclarations/UnusedTypeDeclarations.expected index cbcad4dc1c..fb4869d64a 100644 --- a/c/common/test/rules/unusedtypedeclarations/UnusedTypeDeclarations.expected +++ b/c/common/test/rules/unusedtypedeclarations/UnusedTypeDeclarations.expected @@ -2,3 +2,4 @@ | test.c:7:18:7:18 | D | Type declaration D is not used. | | test.c:28:11:28:11 | R | Type declaration R is not used. | | test.c:41:12:41:12 | (unnamed class/struct/union) | Type declaration (unnamed class/struct/union) is not used. | +| test.c:56:3:56:4 | T2 | Type declaration T2 is not used. | diff --git a/c/common/test/rules/unusedtypedeclarations/test.c b/c/common/test/rules/unusedtypedeclarations/test.c index aedd16338e..0e7038d937 100644 --- a/c/common/test/rules/unusedtypedeclarations/test.c +++ b/c/common/test/rules/unusedtypedeclarations/test.c @@ -49,4 +49,13 @@ void test_nested_struct() { s.f1; s.f3; s.f5; -} \ No newline at end of file +} + +typedef struct { + int m1; +} T2; // NON_COMPLIANT +typedef struct { + int m1; +} T1; // COMPLIANT - used in function below + +void test_typedef() { T1 t1; } \ No newline at end of file diff --git a/change_notes/2026-02-18-unused-type-improvements.md b/change_notes/2026-02-18-unused-type-improvements.md new file mode 100644 index 0000000000..4d41ffd8bb --- /dev/null +++ b/change_notes/2026-02-18-unused-type-improvements.md @@ -0,0 +1,6 @@ + - `RULE-2-3`, `A0-1-6` - `UnusedTypeDeclarations.ql`: + - Type usage analysis has been improved to find more possible type usages, including: + - Previous behavior considered anonymous types in variable declarations to be considered used by the variable definition itself. This has been improved to require that a field of the anonymous type is accessed for the type to be considered used. + - Usages of a template type inside a specialization of that template are no longer considered usages of the template type. + - Hidden friend declarations are no longer considered usages of the class they are declaring friendship for. + - Improved exclusions generally, for cases such as nested types and functions within functions. These previously were a source of incorrectly identified type uses. \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/ast/Class.qll b/cpp/common/src/codingstandards/cpp/ast/Class.qll new file mode 100644 index 0000000000..fa9a7967ae --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/ast/Class.qll @@ -0,0 +1,21 @@ +import cpp + +/** + * The last declaration in a class by location order. + * + * This may fail to capture certain cases such as hidden friends (see HiddenFriend.qll). + */ +class LastClassDeclaration extends Declaration { + Class cls; + + pragma[nomagic] + LastClassDeclaration() { + this = + max(Declaration decl, Location l | + decl = cls.getADeclaration() and + l = decl.getLocation() + | + decl order by l.getEndLine(), l.getEndColumn() + ) + } +} diff --git a/cpp/common/src/codingstandards/cpp/ast/HiddenFriend.qll b/cpp/common/src/codingstandards/cpp/ast/HiddenFriend.qll new file mode 100644 index 0000000000..fa301ad13a --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/ast/HiddenFriend.qll @@ -0,0 +1,124 @@ +/** + * The C++ extractor does not support hidden friends, which are friend functions defined within a + * class, rather than declared: + * + * ```cpp + * struct A { + * friend void hidden_friend(A) {} // Definition: this is a hidden friend + * friend void not_hidden_friend(A); // Declaration: this is not a hidden friend + * }; + * ``` + * + * In the database, a `FriendDecl` is not created for the hidden friend. The hidden friend function + * is created as a `TopLevel` function with no enclosing element. However, we can identify it as a + * hidden friend by its location. + */ + +import cpp +import codingstandards.cpp.ast.Class + +class PossibleHiddenFriend extends HiddenFriendCandidate { + ClassCandidate cls; + + PossibleHiddenFriend() { hidesFriend(cls, this) } + + Class getFriendClass() { result = cls } +} + +/** + * Begin by limiting the number of candidate functions to consider. + * + * Only inline top level functions can be hidden friends. + */ +private class HiddenFriendCandidate extends TopLevelFunction { + HiddenFriendCandidate() { this.isInline() } +} + +/** + * Only consider files which contain hidden friend candidates. + */ +private class FileCandidate extends File { + FileCandidate() { exists(HiddenFriendCandidate c | c.getFile() = this) } +} + +/** + * Only consider classes in candidate files, that include hidden friend candidates. + */ +private class ClassCandidate extends Class { + ClassCandidate() { getFile() instanceof FileCandidate } + + Declaration getNextSiblingDeclaration() { + exists(LastClassDeclaration last | + last.getDeclaringType() = this and + result = + min(Declaration decl | + decl.getEnclosingElement() = this.getEnclosingElement() and + pragma[only_bind_out](decl.getFile()) = pragma[only_bind_out](this.getFile()) and + decl.getLocation().getStartLine() > last.getLocation().getEndLine() + | + decl order by decl.getLocation().getStartLine(), decl.getLocation().getStartColumn() + ) + ) + } + + Declaration getNextOrphanedDeclaration() { + exists(LastClassDeclaration last | + last.getDeclaringType() = this and + result = + min(OrphanedDeclaration decl, Location locLast, Location locDecl | + orphanHasFile(decl, this.getFile()) and + locDecl = decl.getLocation() and + locLast = last.getLocation() and + locLast.getStartLine() < locDecl.getEndLine() + | + decl order by locDecl.getStartLine(), locDecl.getStartColumn() + ) + ) + } + + Declaration getFirstNonClassDeclaration() { + exists(LastClassDeclaration last | + last.getDeclaringType() = this and + result = + min(Declaration decl | + decl = getNextSiblingDeclaration() or decl = getNextOrphanedDeclaration() + | + decl order by decl.getLocation().getStartLine(), decl.getLocation().getStartColumn() + ) + ) + } +} + +pragma[nomagic] +private predicate orphanHasFile(OrphanedDeclaration orphan, FileCandidate file) { + orphan.getFile() = file +} + +private class OrphanedDeclaration extends Declaration { + OrphanedDeclaration() { + not exists(getEnclosingElement()) and + not this instanceof HiddenFriendCandidate and + getFile() instanceof FileCandidate and + not isFromTemplateInstantiation(_) + } +} + +pragma[nomagic] +private predicate classCandidateHasFile(ClassCandidate c, FileCandidate f) { c.getFile() = f } + +pragma[nomagic] +private predicate hiddenFriendCandidateHasFile(HiddenFriendCandidate h, FileCandidate f) { + h.getFile() = f +} + +pragma[nomagic] +private predicate hidesFriend(ClassCandidate c, HiddenFriendCandidate f) { + exists(FileCandidate file, Location cloc, Location floc | + classCandidateHasFile(c, file) and + hiddenFriendCandidateHasFile(f, file) and + cloc = c.getLocation() and + floc = f.getLocation() and + cloc.getEndLine() < floc.getStartLine() and + floc.getEndLine() < c.getFirstNonClassDeclaration().getLocation().getStartLine() + ) +} diff --git a/cpp/common/src/codingstandards/cpp/exclusions/cpp/DeadCode9.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/DeadCode9.qll new file mode 100644 index 0000000000..9b00e7ebdd --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/DeadCode9.qll @@ -0,0 +1,26 @@ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ +import cpp +import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata + +newtype DeadCode9Query = TUnusedTypeWithLimitedVisibilityQuery() + +predicate isDeadCode9QueryMetadata(Query query, string queryId, string ruleId, string category) { + query = + // `Query` instance for the `unusedTypeWithLimitedVisibility` query + DeadCode9Package::unusedTypeWithLimitedVisibilityQuery() and + queryId = + // `@id` for the `unusedTypeWithLimitedVisibility` query + "cpp/misra/unused-type-with-limited-visibility" and + ruleId = "RULE-0-2-3" and + category = "advisory" +} + +module DeadCode9Package { + Query unusedTypeWithLimitedVisibilityQuery() { + //autogenerate `Query` type + result = + // `Query` type for `unusedTypeWithLimitedVisibility` query + TQueryCPP(TDeadCode9PackageQuery(TUnusedTypeWithLimitedVisibilityQuery())) + } +} diff --git a/cpp/common/src/codingstandards/cpp/exclusions/cpp/RuleMetadata.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/RuleMetadata.qll index cad86d2285..9ed1fa0b5c 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/cpp/RuleMetadata.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/RuleMetadata.qll @@ -19,6 +19,7 @@ import Conversions2 import DeadCode import DeadCode3 import DeadCode4 +import DeadCode9 import Declarations import ExceptionSafety import Exceptions1 @@ -91,6 +92,7 @@ newtype TCPPQuery = TDeadCodePackageQuery(DeadCodeQuery q) or TDeadCode3PackageQuery(DeadCode3Query q) or TDeadCode4PackageQuery(DeadCode4Query q) or + TDeadCode9PackageQuery(DeadCode9Query q) or TDeclarationsPackageQuery(DeclarationsQuery q) or TExceptionSafetyPackageQuery(ExceptionSafetyQuery q) or TExceptions1PackageQuery(Exceptions1Query q) or @@ -163,6 +165,7 @@ predicate isQueryMetadata(Query query, string queryId, string ruleId, string cat isDeadCodeQueryMetadata(query, queryId, ruleId, category) or isDeadCode3QueryMetadata(query, queryId, ruleId, category) or isDeadCode4QueryMetadata(query, queryId, ruleId, category) or + isDeadCode9QueryMetadata(query, queryId, ruleId, category) or isDeclarationsQueryMetadata(query, queryId, ruleId, category) or isExceptionSafetyQueryMetadata(query, queryId, ruleId, category) or isExceptions1QueryMetadata(query, queryId, ruleId, category) or diff --git a/cpp/common/src/codingstandards/cpp/types/Uses.qll b/cpp/common/src/codingstandards/cpp/types/Uses.qll index 7cbe8cc97c..4be327f7fd 100644 --- a/cpp/common/src/codingstandards/cpp/types/Uses.qll +++ b/cpp/common/src/codingstandards/cpp/types/Uses.qll @@ -12,6 +12,7 @@ */ import cpp +import codingstandards.cpp.ast.HiddenFriend /** * Gets a typedef with the same qualified name and declared at the same location. @@ -35,7 +36,8 @@ private TypedefType getAnEquivalentTypeDef(TypedefType type) { * is from within the function signature or field declaration of the type itself. */ Locatable getATypeUse(Type type) { - result = getATypeUse_i(type, _) + result = getATypeUse_i(type, _) and + not isWithinTypeDefinition(result, type) or // Identify `TypeMention`s of typedef types, where the underlying type is used. // @@ -65,6 +67,39 @@ Locatable getATypeUse(Type type) { ) } +predicate isWithinTypeDefinition(Locatable loc, Type type) { + loc = type + or + loc.getEnclosingElement*() = type + or + isWithinTypeDefinition(loc.(Function).getDeclaringType(), type) + or + isWithinTypeDefinition(loc.(MemberVariable).getDeclaringType(), type) + or + isWithinTypeDefinition(loc.(PossibleHiddenFriend).getFriendClass(), type) + or + isWithinTypeDefinition(loc.(Parameter).getFunction(), type) + or + isWithinTypeDefinition(loc.(Expr).getEnclosingFunction(), type) + or + isWithinTypeDefinition(loc.(LocalVariable).getFunction(), type) + or + exists(TemplateClass tpl, ClassTemplateSpecialization spec | + tpl = type and + tpl = spec.getPrimaryTemplate() and + isWithinTypeDefinition(loc, spec) + ) + //exists(TemplateClass tpl, ClassTemplateSpecialization spec | + // tpl.getAnInstantiation() = type and + // tpl = spec.getPrimaryTemplate() and + // isWithinTypeDefinition(loc, spec) + //) + //exists(ClassTemplateSpecialization spec | + // specializationSharesType(type, spec) and + // isWithinTypeDefinition(loc, spec) + //) +} + private Locatable getATypeUse_i(Type type, string reason) { ( // Restrict to uses within the source checkout root @@ -81,6 +116,7 @@ private Locatable getATypeUse_i(Type type, string reason) { type = v.getType() and // Ignore self referential variables and parameters not v.getDeclaringType().refersTo(type) and + not type.(UserType).isAnonymous() and not type = v.(Parameter).getFunction().getDeclaringType() ) and reason = "used as a variable type" diff --git a/cpp/common/test/rules/unusedtypedeclarations/UnusedTypeDeclarations.expected b/cpp/common/test/rules/unusedtypedeclarations/UnusedTypeDeclarations.expected index 6ae78462b7..a4538f01c5 100644 --- a/cpp/common/test/rules/unusedtypedeclarations/UnusedTypeDeclarations.expected +++ b/cpp/common/test/rules/unusedtypedeclarations/UnusedTypeDeclarations.expected @@ -4,3 +4,7 @@ | test.cpp:77:11:77:11 | R | Type declaration R is not used. | | test.cpp:90:12:90:12 | (unnamed class/struct/union) | Type declaration (unnamed class/struct/union) is not used. | | test.cpp:111:29:111:30 | AA | Type declaration AA is not used. | +| test.cpp:126:7:126:12 | Nested | Type declaration Nested is not used. | +| test.cpp:135:9:135:20 | UnusedNested | Type declaration UnusedNested is not used. | +| test.cpp:138:7:138:22 | NestedBlockScope | Type declaration NestedBlockScope is not used. | +| test.cpp:149:11:149:16 | Unused | Type declaration Unused is not used. | diff --git a/cpp/common/test/rules/unusedtypedeclarations/test.cpp b/cpp/common/test/rules/unusedtypedeclarations/test.cpp index 6eb673c1c7..2c2699af04 100644 --- a/cpp/common/test/rules/unusedtypedeclarations/test.cpp +++ b/cpp/common/test/rules/unusedtypedeclarations/test.cpp @@ -121,4 +121,31 @@ void test_temporary_object_creation() { return C1{p1}; }; -} \ No newline at end of file +} + +class Nested { // NON_COMPLIANT - only used within itself +public: + class NestedNested { // COMPLIANT - used by class `Nested` + public: + Nested f(); + }; + + NestedNested g(); + + class UnusedNested {}; // NON_COMPLIANT - never used by class `Nested` +}; + +class NestedBlockScope { // NON_COMPLIANT - only used within itself +public: + void f() { + class NestedFunction { // COMPLIANT - used in function below + void g() { + NestedBlockScope l1; // Doesn't count as use of `NestedBlockScope`. + } + }; + + NestedFunction l1; + + class Unused {}; // NON_COMPLIANT - never used by function `f` + } +}; \ No newline at end of file diff --git a/cpp/misra/src/rules/RULE-0-2-3/UnusedTypeWithLimitedVisibility.ql b/cpp/misra/src/rules/RULE-0-2-3/UnusedTypeWithLimitedVisibility.ql new file mode 100644 index 0000000000..f1b0789e42 --- /dev/null +++ b/cpp/misra/src/rules/RULE-0-2-3/UnusedTypeWithLimitedVisibility.ql @@ -0,0 +1,38 @@ +/** + * @id cpp/misra/unused-type-with-limited-visibility + * @name RULE-0-2-3: Types with limited visibility should be used at least once + * @description Types that are unused with limited visibility are unnecessary and should either be + * removed or may indicate a developer mistake. + * @kind problem + * @precision very-high + * @problem.severity error + * @tags external/misra/id/rule-0-2-3 + * scope/single-translation-unit + * maintainability + * correctness + * external/misra/enforcement/decidable + * external/misra/obligation/advisory + */ + +import cpp +import codingstandards.cpp.misra +import codingstandards.cpp.types.Uses + +predicate hasLimitedVisibility(UserType type) { + type.isLocal() or + type.getNamespace().isAnonymous() +} + +predicate hasMaybeUnusedAttribute(UserType type) { + exists(Attribute a | a = type.getAnAttribute() and a.getName() = "maybe_unused") +} + +from UserType type +where + not isExcluded(type, DeadCode9Package::unusedTypeWithLimitedVisibilityQuery()) and + hasLimitedVisibility(type) and + not exists(getATypeUse(type)) and + not hasMaybeUnusedAttribute(type) and + not type instanceof TypeTemplateParameter and + not type instanceof ClassTemplateSpecialization +select type, "Type '" + type.getName() + "' with limited visibility is not used." diff --git a/cpp/misra/test/rules/RULE-0-2-3/UnusedTypeWithLimitedVisibility.expected b/cpp/misra/test/rules/RULE-0-2-3/UnusedTypeWithLimitedVisibility.expected new file mode 100644 index 0000000000..00ad42c733 --- /dev/null +++ b/cpp/misra/test/rules/RULE-0-2-3/UnusedTypeWithLimitedVisibility.expected @@ -0,0 +1,11 @@ +| test.cpp:5:9:5:10 | T1 | Type 'T1' with limited visibility is not used. | +| test.cpp:22:8:22:9 | A1 | Type 'A1' with limited visibility is not used. | +| test.cpp:26:8:26:9 | A2 | Type 'A2' with limited visibility is not used. | +| test.cpp:62:28:62:29 | C1<> | Type 'C1<>' with limited visibility is not used. | +| test.cpp:79:14:79:14 | (unnamed class/struct/union) | Type '(unnamed class/struct/union)' with limited visibility is not used. | +| test.cpp:105:12:105:13 | E2 | Type 'E2' with limited visibility is not used. | +| test.cpp:115:9:115:10 | T2 | Type 'T2' with limited visibility is not used. | +| test.cpp:126:10:126:11 | S2 | Type 'S2' with limited visibility is not used. | +| test.cpp:133:8:133:9 | A3 | Type 'A3' with limited visibility is not used. | +| test.cpp:145:8:145:9 | A6 | Type 'A6' with limited visibility is not used. | +| test.cpp:152:29:152:42 | AliasTemplate1 | Type 'AliasTemplate1' with limited visibility is not used. | diff --git a/cpp/misra/test/rules/RULE-0-2-3/UnusedTypeWithLimitedVisibility.qlref b/cpp/misra/test/rules/RULE-0-2-3/UnusedTypeWithLimitedVisibility.qlref new file mode 100644 index 0000000000..710e5e7c68 --- /dev/null +++ b/cpp/misra/test/rules/RULE-0-2-3/UnusedTypeWithLimitedVisibility.qlref @@ -0,0 +1 @@ +rules/RULE-0-2-3/UnusedTypeWithLimitedVisibility.ql \ No newline at end of file diff --git a/cpp/misra/test/rules/RULE-0-2-3/test.cpp b/cpp/misra/test/rules/RULE-0-2-3/test.cpp new file mode 100644 index 0000000000..a9048f1041 --- /dev/null +++ b/cpp/misra/test/rules/RULE-0-2-3/test.cpp @@ -0,0 +1,193 @@ +#include + +// Test case 1: Type aliases in block scope +std::int16_t test_type_alias_unused() { + using T1 = std::int16_t; // NON_COMPLIANT - T1 declared but not used + return 67; +} + +std::int16_t test_type_alias_used() { + using T1 = std::int16_t; // COMPLIANT - T1 is used below + T1 l1 = 42; + return l1; +} + +std::int16_t test_type_alias_maybe_unused() { + using T1 [[maybe_unused]] = std::int32_t; // COMPLIANT - Exception #1 + return 67; +} + +// Test case 2: Types in unnamed namespace +namespace { +struct A1 { + A1 f(); +}; // COMPLIANT - A1 is used below + +struct A2 { + A2 f(); +}; // NON_COMPLIANT - A2 is not used (only in its own definition) + +struct A2; // Not a use of A2 + +A2 A2::f() { return *this; } // Not a use of A2 + +template // COMPLIANT - Exception #2 (template parameter) +void foo() { + A1 l1; // Use of A1 + l1.f(); +} +} // namespace + +// Test case 3: Struct in constexpr if +template inline auto test_constexpr_if() { + struct res { + std::int32_t i; + }; // COMPLIANT - res is used in else branch + if constexpr (cond) { + return 42; + } else { + return res{42}; // res is utilized + } +} + +// Test case 4: Type used as template argument +template std::int32_t bar() { return 42; } + +std::int32_t test_template_argument() { + return bar(); // COMPLIANT - P is used +} + +// Test case 5: Class template specialization +namespace { +template struct C1 {}; // NON_COMPLIANT - only used in its definition + +template <> struct C1 { // COMPLIANT - Exception #3 + void mbr() { C1 l1; } +}; +} // namespace + +namespace { +template struct C2 {}; // COMPLIANT - C2 is used below + +template <> struct C2; // COMPLIANT - Exception #3 + +C2 g1; // Use of C2 +} // namespace + +// Test case 6: Anonymous unions +namespace { +static union { + std::int32_t i1; + std::int32_t j1; +}; // NON_COMPLIANT - anonymous union not used + +static union { + std::int32_t i2; + std::int32_t j2; +}; // COMPLIANT - i2 is used in f3 +} // namespace + +void test_anonymous_union() { + ++i2; // Uses the anonymous union holding i2 +} + +// Test case 7: Lambda closure type +namespace { +void test_lambda_closure() { + [](auto) {}; // COMPLIANT - closure type is always used +} +} // namespace + +// Test case 8: Enumeration type usage +namespace { +enum class E1 { A, B, C }; // COMPLIANT - E1 is used via its enumerators + +enum class E2 { D, E, F }; // NON_COMPLIANT - E2 is not used +} // namespace + +void test_enum_usage() { + auto l1 = E1::A; // Use of E1 +} + +// Test case 9: Multiple type aliases +void test_multiple_aliases() { + using T1 = std::int32_t; // COMPLIANT - T1 is used + using T2 = std::int64_t; // NON_COMPLIANT - T2 is not used + T1 l1 = 0; +} + +// Test case 10: Nested struct in block scope +void test_nested_struct() { + struct S1 { + std::int32_t m1; + }; // COMPLIANT - S1 is used below + S1 l1{42}; + + struct S2 { + std::int32_t m2; + }; // NON_COMPLIANT - S2 is not used +} + +// Test case 11: Class with hidden friend +namespace { +struct A3 { + friend void hidden_friend(A3) {} // Part of A3's definition +}; // NON_COMPLIANT - A3 is not used outside its definition + +// non-hidden friend +struct A4 { // COMPLIANT - A4 is used outside its definition + friend void non_hidden_friend(A4 a); +}; + +void non_hidden_friend(A4 a) {} + +struct A5 {}; // COMPLIANT -- used in A6 hidden friend +struct A6 { // NON_COMPLIANT -- not used in hidden friend + friend void wrong_hidden_friend(A5) {} +}; +} // namespace + +// Test case 12: Alias templates +namespace { +template using AliasTemplate1 = T *; // NON_COMPLIANT + +template using AliasTemplate2 = T *; // COMPLIANT + +void test_alias_template() { AliasTemplate2 l1; } +} // namespace + +// Test case 13: Primary class template usage +namespace { +template struct D1 { T m1; }; // COMPLIANT - D1 is used + +void test_class_template_usage() { D1 l1{42}; } +} // namespace + +// Test case 14: Type in return type +namespace { +struct R1 { + std::int32_t m1; +}; // COMPLIANT - R1 is used in return type + +R1 test_return_type() { return R1{42}; } +} // namespace + +// Test case 15: Type in parameter +namespace { +struct P1 { + std::int32_t m1; +}; // COMPLIANT - P1 is used in parameter + +void test_parameter_type(P1 l1) {} +} // namespace + +// Test case 16: Forward declaration followed by use +namespace { +struct F1; // Not a use + +struct F1 { + std::int32_t m1; +}; // COMPLIANT - F1 is used below + +void test_forward_declaration() { F1 l1{0}; } +} // namespace \ No newline at end of file diff --git a/rule_packages/cpp/DeadCode9.json b/rule_packages/cpp/DeadCode9.json new file mode 100644 index 0000000000..fd5384ed34 --- /dev/null +++ b/rule_packages/cpp/DeadCode9.json @@ -0,0 +1,29 @@ +{ + "MISRA-C++-2023": { + "RULE-0-2-3": { + "properties": { + "enforcement": "decidable", + "obligation": "advisory" + }, + "queries": [ + { + "description": "Types that are unused with limited visibility are unnecessary and should either be removed or may indicate a developer mistake.", + "kind": "problem", + "name": "Types with limited visibility should be used at least once", + "precision": "very-high", + "severity": "error", + "short_name": "UnusedTypeWithLimitedVisibility", + "tags": [ + "scope/single-translation-unit", + "maintainability", + "correctness" + ], + "implementation_scope": { + "description": "CodeQL extractor information for hidden friends is limited, and the number of hidden friends may be overestimated, resulting in false positives." + } + } + ], + "title": "Types 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..3ca3b81b9b 100644 --- a/rules.csv +++ b/rules.csv @@ -829,7 +829,7 @@ cpp,MISRA-C++-2023,RULE-0-1-1,Yes,Advisory,Undecidable,System,A value should not cpp,MISRA-C++-2023,RULE-0-1-2,Yes,Required,Decidable,Single Translation Unit,The value returned by a function shall be used,A0-1-2,DeadCode2,Easy, 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-3,Yes,Advisory,Decidable,Single Translation Unit,Types with limited visibility should be used at least once,A0-1-6,DeadCode9,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,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,