Skip to content

A7-1-2: Query proposes to add constexpr to non-static data members (and other problems) #789

Closed
@rak3-sh

Description

@rak3-sh

Affected rules

  • A7-1-2

Description

1. constexpr on non-static data members

This query should exclude variables that are non-static data members. This is because the compiler raises an error in case a non-static data member is marked as constexpr.

Example

class a_class
{
  int y;
  public:
  // CodeQL says to make 'x' as constexpr. 
  // But when we do so, there is a compiler error: "error: non-static data member ‘x’ declared ‘constexpr’"
  int x = 10; 
  a_class():y(x)
  {
  }
  int getY()
  {
    return y;
  } 
};

int main()
{
  a_class o;
  return o.getY();
}

Fixing as per the alerts raised by CodeQL in the test case of this query (e.g. here or here) also raises the error.

test.cpp:55:3: error: non-static data member ‘m2’ declared ‘constexpr’
   55 |   constexpr int m2 = 0; // NON_COMPLIANT

test.cpp:130:3: error: non-static data member ‘m1’ declared ‘constexpr’
  130 |   constexpr int m1 = 0;

2. constexpr on member variables updated in un-instantiated templates

This query alerts to add constexpr to member variables which are only used in uninstantiated template functions. At first glance, it seems to be correct because since the template function is not instantiated, the member variable isn't getting accessed anywhere and hence becomes a candidate for adding constexpr. However, when the user attempts to fix it, the compiler raises an error and points to the modification in the uninstantiated template function. So should we avoid member variables of templates?

Example

#include <vector>
#include <memory>

template <typename T>
class a_class
{
  // CodeQL says to make "size_" as constexpr because the "add()" function below isn't instantiated and hence, 
  // there is no access of "size_", but if we do this, the compiler complains that "size_" is updated in add.
  // "test.cpp:12:7: error: increment of read-only variable ‘a_class<T>::size_’"
  std::size_t size_ = 0;   
  std::vector<T> values_{};
  public:
  void add(T arg) {
    values_[size_] = arg;
    ++size_;
  }
};

int main()
{
  a_class<int> o;
  return 0;
}

Note: The error about size_ being a non-static data member and constexpr also exists but even if we make it static, we cant fix the error because compiler complains about the update on size_ in the uninstantiated template function add().

3. constexpr for range-based for loop variables

I'm not able to provide a reproducible case but this query alerts on variables used in range-based for loop.

Example

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) { // value can be constexpr
    values.emplace_back(std::make_unique<int>(value));
  }
}

The reason is that when the range based for loop is de-sugared there is an assignment like the following:

for (..)
auto &value = *(__begin) // operator call to * with __begin variable generated by the compiler front end.
...

We have an operator* as an initializer expression and it has a variable access to the __begin variable. The line; “any(Call call | isCompileTimeEvaluatedCall(call))...” here is True for this case because the operator * is marked as constexpr by CodeQL and the getAnArgument() here for this call doesn’t return any arguments. Please note that, the qualifier for this call expression is the __begin variable which is compiler generated. So should we avoid such calls which has a qualifier that has VariableAccess to variables that are compiler generated?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Difficulty-MediumA false positive or false negative report which is expected to take 1-5 days effort to addressImpact-MediumStandard-AUTOSARfalse positive/false negativeAn issue related to observed false positives or false negatives.

    Type

    No type

    Projects

    Status

    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions