diff --git a/change_notes/2022-08-01-a0-1-6-alias-templates.md b/change_notes/2022-08-01-a0-1-6-alias-templates.md new file mode 100644 index 0000000000..1ab2446873 --- /dev/null +++ b/change_notes/2022-08-01-a0-1-6-alias-templates.md @@ -0,0 +1 @@ +- `A0-1-6`: alias templates are now appropriately handled, with alias templates considered used if there exists an instantiation that is used. \ No newline at end of file diff --git a/cpp/autosar/test/rules/A0-1-6/UnusedTypeDeclarations.expected b/cpp/autosar/test/rules/A0-1-6/UnusedTypeDeclarations.expected index ac5fe411e3..4141698a95 100644 --- a/cpp/autosar/test/rules/A0-1-6/UnusedTypeDeclarations.expected +++ b/cpp/autosar/test/rules/A0-1-6/UnusedTypeDeclarations.expected @@ -3,3 +3,4 @@ | test.cpp:10:11:10:11 | D | Type declaration D is not used. | | test.cpp:74:11:74:11 | R | Type declaration R is not used. | | test.cpp:87:12:87:12 | struct | Type declaration struct is not used. | +| test.cpp:108:29:108:30 | AA | Type declaration AA is not used. | diff --git a/cpp/autosar/test/rules/A0-1-6/test.cpp b/cpp/autosar/test/rules/A0-1-6/test.cpp index de6dca9696..c14c0359d8 100644 --- a/cpp/autosar/test/rules/A0-1-6/test.cpp +++ b/cpp/autosar/test/rules/A0-1-6/test.cpp @@ -99,4 +99,12 @@ void test_nested_struct() { template class X { // COMPLIANT - template class never instantiated using custom_type = E; // COMPLIANT - template class never instantiated -}; \ No newline at end of file +}; + +template class Y {}; // COMPLIANT - used in the test case below + +// Alias templates +template using Z = Y; // COMPLIANT - used below +template using AA = Y; // NON_COMPLIANT - never instantiated + +void test_alias_template() { Z v; } diff --git a/cpp/common/src/codingstandards/cpp/TypeUses.qll b/cpp/common/src/codingstandards/cpp/TypeUses.qll index ff1d4c9037..0033401098 100644 --- a/cpp/common/src/codingstandards/cpp/TypeUses.qll +++ b/cpp/common/src/codingstandards/cpp/TypeUses.qll @@ -66,8 +66,15 @@ Locatable getATypeUse(Type type) { } private Locatable getATypeUse_i(Type type) { - // Restrict to uses within the source checkout root - exists(result.getFile().getRelativePath()) and + ( + // Restrict to uses within the source checkout root + exists(result.getFile().getRelativePath()) + or + // Unless it's an alias template instantiation, as they do not have correct locations (last + // verified in CodeQL CLI 2.7.6) + result instanceof UsingAliasTypedefType and + not exists(result.getLocation()) + ) and ( // Used as a variable type exists(Variable v | result = v | @@ -143,5 +150,20 @@ private Locatable getATypeUse_i(Type type) { or // This is a TemplateClass where one of the specializations is used type = used.(ClassTemplateSpecialization).getPrimaryTemplate() + or + // Alias templates - alias templates and instantiations are not properly captured by the + // extractor (last verified in CodeQL CLI 2.7.6). The only distinguishing factor is that + // instantiations of alias templates do not have a location. + exists(UsingAliasTypedefType template, UsingAliasTypedefType instantiation | + // Instantiation is a "use" of the template + used = instantiation and + type = template and + // The template has a location + exists(template.getLocation()) and + // The instantiation does not + not exists(instantiation.getLocation()) and + // Template and instantiation both have the same qualified name + template.getQualifiedName() = instantiation.getQualifiedName() + ) ) }