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 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/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/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 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 34be754905..ba2ce2be81 100644 --- a/cpp/autosar/test/rules/A7-1-5/test.cpp +++ b/cpp/autosar/test/rules/A7-1-5/test.cpp @@ -106,9 +106,30 @@ void instantiate() { t381.test_381_1(); t381.test_381_2(); } - +class Foo {}; void test_loop() { - for (const auto a : {8, 9, 10}) { + for (auto a : {8, 9, 10}) { // NON_COMPLIANT - a is initialized with a + // non-constant initializer + a; + } + + std::vector v = {1, 2, 3}; + 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; } -} \ No newline at end of file +} + +template void test_template(std::vector v2) { + for (auto &a : v2) { // COMPLIANT - a is intialized with a function call + a; + } +} + +void test_template_instantiation() { test_template({1, 2, 3}); } \ No newline at end of file