From bb09ae94f57f5e2a0010d87e6516097d3faf826e Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Wed, 2 Nov 2022 23:45:45 +0000 Subject: [PATCH 1/2] M0-1-4: Exclude constexpr variables whose constant is used in a template argument. --- ...2022-11-02-m0-1-4-single-use-with-templates.md | 2 ++ .../src/rules/M0-1-4/SingleUsePODVariable.qll | 15 ++++++++++++++- .../M0-1-4/SingleUseMemberPODVariable.expected | 1 + cpp/autosar/test/rules/M0-1-4/test.cpp | 12 ++++++++++-- 4 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 change_notes/2022-11-02-m0-1-4-single-use-with-templates.md diff --git a/change_notes/2022-11-02-m0-1-4-single-use-with-templates.md b/change_notes/2022-11-02-m0-1-4-single-use-with-templates.md new file mode 100644 index 0000000000..c6c2c5d99e --- /dev/null +++ b/change_notes/2022-11-02-m0-1-4-single-use-with-templates.md @@ -0,0 +1,2 @@ + - `M0-1-4` - `SingleUseMemberPODVariable.ql` + - Reduce false positives by excluding any constexpr variable whose constant value is used as an argument to a template. \ No newline at end of file diff --git a/cpp/autosar/src/rules/M0-1-4/SingleUsePODVariable.qll b/cpp/autosar/src/rules/M0-1-4/SingleUsePODVariable.qll index c750bb130c..c4e220549a 100644 --- a/cpp/autosar/src/rules/M0-1-4/SingleUsePODVariable.qll +++ b/cpp/autosar/src/rules/M0-1-4/SingleUsePODVariable.qll @@ -4,6 +4,12 @@ import cpp import codingstandards.cpp.TrivialType import codingstandards.cpp.deadcode.UnusedVariables +/** Gets the constant value of a constexpr variable. */ +private string getConstExprValue(Variable v) { + result = v.getInitializer().getExpr().getValue() and + v.isConstexpr() +} + /** Gets a "use" count according to rule M0-1-4. */ int getUseCount(Variable v) { exists(int initializers | @@ -12,7 +18,14 @@ int getUseCount(Variable v) { result = initializers + count(VariableAccess access | access = v.getAnAccess() and not access.isCompilerGenerated()) - + count(UserProvidedConstructorFieldInit cfi | cfi.getTarget() = v) + + count(UserProvidedConstructorFieldInit cfi | cfi.getTarget() = v) + + // For constexpr variables used as template arguments, we don't see accesses (just the + // appropriate literals). We therefore take a conservative approach and count the number of + // template instantiations that use the given constant, and consider each one to be a use + // of the variable + count(ClassTemplateInstantiation cti | + cti.getTemplateArgument(_).(Expr).getValue() = getConstExprValue(v) + ) ) } diff --git a/cpp/autosar/test/rules/M0-1-4/SingleUseMemberPODVariable.expected b/cpp/autosar/test/rules/M0-1-4/SingleUseMemberPODVariable.expected index f4309e7a4d..89d048d67a 100644 --- a/cpp/autosar/test/rules/M0-1-4/SingleUseMemberPODVariable.expected +++ b/cpp/autosar/test/rules/M0-1-4/SingleUseMemberPODVariable.expected @@ -1,3 +1,4 @@ +| test.cpp:36:24:36:29 | unused | Member POD variable unused in C1 is only $@. | test.cpp:36:31:36:31 | initializer for unused | used once | | test_global_or_namespace.cpp:16:7:16:7 | x | Member POD variable x in GA is only $@. | test_global_or_namespace.cpp:38:6:38:6 | x | used once | | test_global_or_namespace.cpp:54:7:54:7 | x | Member POD variable x in N1A is only $@. | test_global_or_namespace.cpp:76:6:76:6 | x | used once | | test_member.cpp:5:7:5:8 | m2 | Member POD variable m2 in A is only $@. | test_member.cpp:9:21:9:25 | constructor init of field m2 | used once | diff --git a/cpp/autosar/test/rules/M0-1-4/test.cpp b/cpp/autosar/test/rules/M0-1-4/test.cpp index 81391e444a..1bd8c09f39 100644 --- a/cpp/autosar/test/rules/M0-1-4/test.cpp +++ b/cpp/autosar/test/rules/M0-1-4/test.cpp @@ -1,5 +1,5 @@ /** Test cases for `SingleUseLocalPODVariable.ql` */ - +#include class A {}; class B { @@ -30,4 +30,12 @@ void test_templates() { f1(); // Triggers a NON_COMPLIANT case in f1(), because B is a POD type f1(); // Does not trigger a NON_COMPLIANT case in f1(), because C is not a // POD type -} \ No newline at end of file +} + +class C1 { + static constexpr int unused{1}; // NON_COMPLIANT + static constexpr int used{2}; // COMPLIANT + int test_use() { return used; } + static constexpr int size{3}; // COMPLIANT[FALSE_POSITIVE] + std::array array{false, false}; // size is used here +}; \ No newline at end of file From dad6bc18769fedad9f877e24150e234e74c7da11 Mon Sep 17 00:00:00 2001 From: Luke Cartey <5377966+lcartey@users.noreply.github.com> Date: Fri, 4 Nov 2022 11:06:06 +0000 Subject: [PATCH 2/2] Update cpp/autosar/test/rules/M0-1-4/test.cpp --- cpp/autosar/test/rules/M0-1-4/test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/autosar/test/rules/M0-1-4/test.cpp b/cpp/autosar/test/rules/M0-1-4/test.cpp index 1bd8c09f39..e6ab55c24a 100644 --- a/cpp/autosar/test/rules/M0-1-4/test.cpp +++ b/cpp/autosar/test/rules/M0-1-4/test.cpp @@ -36,6 +36,6 @@ class C1 { static constexpr int unused{1}; // NON_COMPLIANT static constexpr int used{2}; // COMPLIANT int test_use() { return used; } - static constexpr int size{3}; // COMPLIANT[FALSE_POSITIVE] + static constexpr int size{3}; // COMPLIANT std::array array{false, false}; // size is used here }; \ No newline at end of file