Skip to content

Conversation

@chrchr-github
Copy link
Collaborator

No description provided.

if (tokvalue->exprId() == tok->exprId() && !(tok->variable() && tok->variable()->isArray()) &&
!astIsContainerView(tok->astParent()))
continue;
if (tokvalue->str() == "=" && Token::simpleMatch(tokvalue->astOperand1(), "."))
Copy link
Owner

Choose a reason for hiding this comment

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

I am not sure exactly what this code does with tokvalue..
should it be checked that the dot is a unary operand? we could have something like ab.a=...

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Or maybe this needs to be fixed in ValueFlow, i.e. the tokvalue should already point at the assigned variable?

Copy link
Owner

Choose a reason for hiding this comment

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

hmm I am actually not very sure about how LifetimeTokens work

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The = is produced here and then goes unchanged through LifetimeStore:

std::vector<const Token*> args = getArguments(tok);

So I guess it's OK to handle the designated initializer later.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yea ValueFlow needs to be updated. It treats the .x = x as an expression to capture the lifetime because it only handles aggregate constructors without the name. It needs to be updated to associate the correct lifetime to the correct variable(it currently assumes its in the order of member variables which is not the case when it skips variables with named aggregates).

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I see, but that seems like a different problem.
At least there is a FN for this:

struct A { int i; int& r; };
A f() {
    int x = 0;
    A a{.r = x};
    return a;
}

Copy link
Contributor

Choose a reason for hiding this comment

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

Its the same problem. The valueflow is wrong, it should be lifetime[SubObject]=(x) and not lifetime[SubObject]=(.r=x). The checker is trying to compensate for incorrect valueflow. The valueflow should be corrected. These extra checks here can cause problems later on, and are harder to debug.

At least there is a FN for this:

Its the same problem. It tries to assign the lifetime to i which is just an integer so it doesnt capture a lifetime.

Since this doesnt fix the valueflow it introduces a new FP for cases like this:

struct A { int& r; int i; };
A f() {
    int x = 0;
    A a{.i= x};
    return a;
}

You are looking in the right place in valueflow where this needs to be corrected. The args vector needs to be adjusted for the desginated initailizers so it puts each element in the same order as the struct by matching the names of the variables. We could set the token to null for when its missing an initializer but we might need to update the LifetimeStore::forEach to handle null token.

if (tokvalue->exprId() == tok->exprId() && !(tok->variable() && tok->variable()->isArray()) &&
!astIsContainerView(tok->astParent()))
continue;
if (tokvalue->str() == "=" && Token::simpleMatch(tokvalue->astOperand1(), ".") && !tokvalue->astOperand1()->astOperand2())
Copy link
Owner

Choose a reason for hiding this comment

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

How about;

Suggested change
if (tokvalue->str() == "=" && Token::simpleMatch(tokvalue->astOperand1(), ".") && !tokvalue->astOperand1()->astOperand2())
if (tokvalue->str() == "=" && tokvalue->astOperand1() && astOperand1()->astOperand2()->isUnaryOp("."))

Copy link
Owner

Choose a reason for hiding this comment

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

it feels a bit like we should create a "isDesignatedInitializer" utility function. but well it doesn't seem to be needed much. in premiumaddon we have a utility function..
I don't have a strong opinion; create a "isDesignatedInitializer" utility function if you want.

@chrchr-github chrchr-github marked this pull request as draft November 3, 2025 07:55
@sonarqubecloud
Copy link

sonarqubecloud bot commented Nov 4, 2025

@chrchr-github chrchr-github marked this pull request as ready for review November 4, 2025 19:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants