Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #789: Reduce False positives on A7-1-2 (VariableMissingConstexpr.ql) #794

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion change_notes/2024-11-11-fix-fp-789.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
- `A7-1-2` - `VariableMissingConstexpr.ql`:
- Fixes #789. Doesn't alert on non-static member variables and compiler generated variables of range based for-loops.
- Do not report on member variables if the class has un-instantiated member function(s).
- Check a call's qualifier as well whether it can be compile time evaluated or not.
17 changes: 12 additions & 5 deletions cpp/autosar/src/rules/A7-1-2/VariableMissingConstexpr.ql
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,24 @@ predicate isTypeZeroInitializable(Type t) {
t.getUnderlyingType() instanceof ArrayType
}

from Variable v
from Variable v, string msg
where
not isExcluded(v, ConstPackage::variableMissingConstexprQuery()) and
v.hasDefinition() and
not v.isConstexpr() and
not v instanceof Parameter and
not v.isAffectedByMacro() and
// Don't consider non-static member variables.
(
not v instanceof MemberVariable
or
v.isStatic()
// In case member functions are left un-instantiated, it is possible
// the member variable could be modified in them.
// Hence, don't raise an alert in case this member variable's class
// has a member function that doesn't have a definition.
not exists(MemberFunction mf |
mf.getDeclaringType() = v.getDeclaringType() and
mf.isFromUninstantiatedTemplate(_)
)
) and
isLiteralType(v.getType()) and
// Unfortunately, `isConstant` is not sufficient here because it doesn't include calls to
Expand All @@ -72,5 +78,6 @@ where
// Exclude variables in uninstantiated templates, as they may be incomplete
not v.isFromUninstantiatedTemplate(_) and
// Exclude compiler generated variables, which are not user controllable
not v.isCompilerGenerated()
select v, "Variable '" + v.getName() + "' could be marked 'constexpr'."
not v.isCompilerGenerated() and
if v instanceof MemberVariable and not v.isStatic() then msg = " and static." else msg = "."
select v, "Variable '" + v.getName() + "' could be marked 'constexpr'" + msg
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@
| test.cpp:41:14:41:15 | l2 | Variable 'l2' could be marked 'constexpr'. |
| test.cpp:44:16:44:17 | lc | Variable 'lc' could be marked 'constexpr'. |
| test.cpp:45:17:45:19 | lc2 | Variable 'lc2' could be marked 'constexpr'. |
| test.cpp:55:20:55:21 | m2 | Variable 'm2' could be marked 'constexpr'. |
| test.cpp:143:5:143:20 | m1 | Variable 'm1' could be marked 'constexpr'. |
| test.cpp:55:7:55:8 | m2 | Variable 'm2' could be marked 'constexpr' and static. |
| test.cpp:130:7:130:8 | m1 | Variable 'm1' could be marked 'constexpr' and static. |
| test.cpp:141:7:141:8 | m1 | Variable 'm1' could be marked 'constexpr' and static. |
| test.cpp:221:7:221:8 | l1 | Variable 'l1' could be marked 'constexpr'. |
| test.cpp:235:7:235:8 | l6 | Variable 'l6' could be marked 'constexpr'. |
| test.cpp:237:7:237:8 | l8 | Variable 'l8' could be marked 'constexpr'. |
Expand Down
23 changes: 6 additions & 17 deletions cpp/autosar/test/rules/A7-1-2/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ class MemberConstExpr {
MemberConstExpr(int p3) : m3(p3) {}

private:
int m1; // COMPLIANT - is not always zero initialized
static const int m2 = 0; // NON_COMPLIANT
int m3 = 0; // COMPLIANT - can be set by constructor
int m1; // COMPLIANT - is not always zero initialized
int m2 = 0; // NON_COMPLIANT
int m3 = 0; // COMPLIANT - can be set by constructor
};

int h1(int x, int y) { // NON_COMPLIANT
Expand Down Expand Up @@ -127,7 +127,7 @@ class MissingConstexprClass {
MissingConstexprClass(int i) = delete; // NON_COMPLIANT
MissingConstexprClass(int i, LiteralClass lc) {} // NON_COMPLIANT
private:
int m1 = 0; // COMPLIANT - non-static member variable
int m1 = 0;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs "NON_COMPLIANT" marker

};

class VirtualBaseClass {};
Expand All @@ -138,9 +138,9 @@ class DerivedClass : public virtual VirtualBaseClass {
DerivedClass(int i) = delete; // COMPLIANT
DerivedClass(int i, LiteralClass lc) {} // COMPLIANT
private:
static int m1; // NON_COMPLAINT - static member variable can be constexpr
int m1 = 0;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs "NON_COMPLIANT" marker

};
int DerivedClass::m1 = 0;

class NotAllMembersInitializedClass {
public:
NotAllMembersInitializedClass() = default; // COMPLIANT
Expand Down Expand Up @@ -275,14 +275,3 @@ template <typename T> T *init() {
}

void test_template_instantiation() { int *t = init<int>(); }

#include <memory>
#include <vector>
void a_function() {
auto origin = std::vector<int>{1, 2, 3, 4, 5, 6, 7, 8, 9};
auto values = std::vector<std::unique_ptr<int>>{};
for (auto &value :
origin) { // Sometimes, CodeQL reports "value" should be constexpr
values.emplace_back(std::make_unique<int>(value));
}
}
Loading