From 618dac594729eb4e26f6427440636ff988a366cb Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Tue, 24 Oct 2023 22:26:38 +0100 Subject: [PATCH 1/4] A7-1-5: Ignore inits of a non-fundamental type --- ...pecifierNotUsedAppropriatelyInVariableDefinition.ql | 10 ++++++++-- cpp/autosar/test/rules/A7-1-5/test.cpp | 8 +++++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/cpp/autosar/src/rules/A7-1-5/AutoSpecifierNotUsedAppropriatelyInVariableDefinition.ql b/cpp/autosar/src/rules/A7-1-5/AutoSpecifierNotUsedAppropriatelyInVariableDefinition.ql index 54b62720a9..7c91ade133 100644 --- a/cpp/autosar/src/rules/A7-1-5/AutoSpecifierNotUsedAppropriatelyInVariableDefinition.ql +++ b/cpp/autosar/src/rules/A7-1-5/AutoSpecifierNotUsedAppropriatelyInVariableDefinition.ql @@ -19,6 +19,10 @@ import cpp import codingstandards.cpp.autosar +class FundamentalType extends BuiltInType { + FundamentalType() { not this instanceof ErroneousType and not this instanceof UnknownType } +} + from Variable v where not isExcluded(v, @@ -28,12 +32,14 @@ where // exclude uninstantiated templates and rely on the instantiated templates, because an uninstantiated template may not contain the information required to determine if the usage is allowed. not v.isFromUninstantiatedTemplate(_) and not ( - // find ones where + // Initialized by function call v.getInitializer().getExpr() instanceof FunctionCall or + // Initialized by lambda expression v.getInitializer().getExpr() instanceof LambdaExpression or - v.getInitializer().getExpr() instanceof ClassAggregateLiteral + // Initialized by non-fundamental type + not v.getInitializer().getExpr().getType() instanceof FundamentalType ) and // Exclude compiler generated variables not v.isCompilerGenerated() diff --git a/cpp/autosar/test/rules/A7-1-5/test.cpp b/cpp/autosar/test/rules/A7-1-5/test.cpp index 34be754905..1358682f78 100644 --- a/cpp/autosar/test/rules/A7-1-5/test.cpp +++ b/cpp/autosar/test/rules/A7-1-5/test.cpp @@ -108,7 +108,13 @@ void instantiate() { } void test_loop() { - for (const auto a : {8, 9, 10}) { + for (const auto a : {8, 9, 10}) { // NON_COMPLIANT - a is initialized with a + // non-constant initializer + a; + } + + std::vector v = {1, 2, 3}; + for (const auto a : v) { // COMPLIANT - a is intialized with a function call a; } } \ No newline at end of file From 6336fd2a3dd2ca955f5e112cfe7e10928d71603c Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Tue, 24 Oct 2023 23:14:21 +0100 Subject: [PATCH 2/4] A7-1-5: Expand test cases Add extra test cases which highlight issues with range based for loops. --- ...AppropriatelyInVariableDefinition.expected | 2 +- cpp/autosar/test/rules/A7-1-5/test.cpp | 25 +++++++++++++++---- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/cpp/autosar/test/rules/A7-1-5/AutoSpecifierNotUsedAppropriatelyInVariableDefinition.expected b/cpp/autosar/test/rules/A7-1-5/AutoSpecifierNotUsedAppropriatelyInVariableDefinition.expected index 03e53068f4..7a5da3abac 100644 --- a/cpp/autosar/test/rules/A7-1-5/AutoSpecifierNotUsedAppropriatelyInVariableDefinition.expected +++ b/cpp/autosar/test/rules/A7-1-5/AutoSpecifierNotUsedAppropriatelyInVariableDefinition.expected @@ -4,4 +4,4 @@ | test.cpp:27:8:27:8 | a | Use of auto in variable definition is not the result of a function call, lambda expression, or non-fundamental type initializer. | | test.cpp:28:8:28:8 | b | Use of auto in variable definition is not the result of a function call, lambda expression, or non-fundamental type initializer. | | test.cpp:81:10:81:10 | a | Use of auto in variable definition is not the result of a function call, lambda expression, or non-fundamental type initializer. | -| test.cpp:111:19:111:19 | a | Use of auto in variable definition is not the result of a function call, lambda expression, or non-fundamental type initializer. | +| test.cpp:111:13:111:13 | a | Use of auto in variable definition is not the result of a function call, lambda expression, or non-fundamental type initializer. | diff --git a/cpp/autosar/test/rules/A7-1-5/test.cpp b/cpp/autosar/test/rules/A7-1-5/test.cpp index 1358682f78..ba2ce2be81 100644 --- a/cpp/autosar/test/rules/A7-1-5/test.cpp +++ b/cpp/autosar/test/rules/A7-1-5/test.cpp @@ -106,15 +106,30 @@ void instantiate() { t381.test_381_1(); t381.test_381_2(); } - +class Foo {}; void test_loop() { - for (const auto a : {8, 9, 10}) { // NON_COMPLIANT - a is initialized with a - // non-constant initializer + for (auto a : {8, 9, 10}) { // NON_COMPLIANT - a is initialized with a + // non-constant initializer a; } std::vector v = {1, 2, 3}; - for (const auto a : v) { // COMPLIANT - a is intialized with a function call + for (auto &a : v) { // COMPLIANT - a is intialized with a function call + a; + } + + Foo f1; + Foo f2; + for (auto &a : {f1, f2}) { // COMPLIANT - initialized with a non-fundamental + // type + a; + } +} + +template void test_template(std::vector v2) { + for (auto &a : v2) { // COMPLIANT - a is intialized with a function call a; } -} \ No newline at end of file +} + +void test_template_instantiation() { test_template({1, 2, 3}); } \ No newline at end of file From 18fc071d80e1151656a1a535f6f16dc6f6cd963d Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Tue, 24 Oct 2023 23:19:00 +0100 Subject: [PATCH 3/4] A7-1-5: Add changenote for non-fundamental types --- change_notes/2023-10-24-a7-1-5-non-fundamental.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 change_notes/2023-10-24-a7-1-5-non-fundamental.md diff --git a/change_notes/2023-10-24-a7-1-5-non-fundamental.md b/change_notes/2023-10-24-a7-1-5-non-fundamental.md new file mode 100644 index 0000000000..f0c9802f5c --- /dev/null +++ b/change_notes/2023-10-24-a7-1-5-non-fundamental.md @@ -0,0 +1,8 @@ + * `A7-1-5` - exclude auto variables initialized with an expression of non-fundamental type. Typically this occurs when using range based for loops with arrays of non-fundamental types. For example: + ``` + void iterate(Foo values[]) { + for (auto value : values) { // COMPLIANT (previously false positive) + // ... + } + } + ``` \ No newline at end of file From d2d804322940a3952206714321edfd1f98f8f287 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Thu, 26 Oct 2023 11:39:31 +0100 Subject: [PATCH 4/4] A15-4-4: Ignore results on uninstantiated templates --- change_notes/2023-10-26-a15-4-4-noexcept.md | 1 + cpp/autosar/src/rules/A15-4-4/MissingNoExcept.ql | 6 ++++-- cpp/autosar/test/rules/A15-4-4/test.cpp | 13 +++++++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 change_notes/2023-10-26-a15-4-4-noexcept.md diff --git a/change_notes/2023-10-26-a15-4-4-noexcept.md b/change_notes/2023-10-26-a15-4-4-noexcept.md new file mode 100644 index 0000000000..e778264cc3 --- /dev/null +++ b/change_notes/2023-10-26-a15-4-4-noexcept.md @@ -0,0 +1 @@ + * `A15-4-4`: remove false positives reported on uninsantiated templates. \ No newline at end of file diff --git a/cpp/autosar/src/rules/A15-4-4/MissingNoExcept.ql b/cpp/autosar/src/rules/A15-4-4/MissingNoExcept.ql index 0226c20d30..7701a8a1ea 100644 --- a/cpp/autosar/src/rules/A15-4-4/MissingNoExcept.ql +++ b/cpp/autosar/src/rules/A15-4-4/MissingNoExcept.ql @@ -33,5 +33,7 @@ where // The function is defined in this database f.hasDefinition() and // This function is not an overriden call operator of a lambda expression - not exists(LambdaExpression lambda | lambda.getLambdaFunction() = f) -select f, "Function " + f.getName() + " could be declared noexcept(true)." + not exists(LambdaExpression lambda | lambda.getLambdaFunction() = f) and + // Exclude results from uinstantiated templates + not f.isFromUninstantiatedTemplate(_) +select f, "Function " + f.getQualifiedName() + " could be declared noexcept(true)." diff --git a/cpp/autosar/test/rules/A15-4-4/test.cpp b/cpp/autosar/test/rules/A15-4-4/test.cpp index f0b676373e..7d8597a75f 100644 --- a/cpp/autosar/test/rules/A15-4-4/test.cpp +++ b/cpp/autosar/test/rules/A15-4-4/test.cpp @@ -30,4 +30,17 @@ class A { void lambda_example() noexcept { auto with_capture = [=]() {}; auto empty_capture = []() {}; +} + +#include +template +void swap_wrapper(TypeA lhs, + TypeB rhs) noexcept(noexcept(std::swap(*lhs, *rhs))) { + std::swap(*lhs, *rhs); +} + +void test_swap_wrapper() noexcept { + int a = 0; + int b = 1; + swap_wrapper(&a, &b); } \ No newline at end of file