Skip to content

C++: Barrier guards API for indirect expressions#12970

Merged
MathiasVP merged 6 commits intogithub:mainfrom
MathiasVP:barrier-guards-for-indirect-expressions
May 3, 2023
Merged

C++: Barrier guards API for indirect expressions#12970
MathiasVP merged 6 commits intogithub:mainfrom
MathiasVP:barrier-guards-for-indirect-expressions

Conversation

@MathiasVP
Copy link
Copy Markdown
Contributor

Background

In the rewrite to use-use flow for C/C++ we added a concept of an indirect node which represents "the value you'd get by dereferencing the value of the expression represented by this node". These are the nodes accessible using the Node::asIndirectExpr() predicate which returns an IndirectExprNode (instead of an ExprNode).

The problem

These new IndirectExprNodes couldn't be marked as barriers with a barrier guard because the predicate offered by the BarrierGuard parameterized module had the signature:

ExprNode getABarrierNode();

which meant that an IndirectExprNodes was never the result of this predicate.

This PR

To resolve the above issue, I've added a new predicate to the BarrierGuard parameterized module with the signature:

IndirectExprNode getAnIndirectBarrierNode();

the implementation is syntactically identical: the only change is the return type.

Commit-by-commit review recommended.

  • The first commit changes our dataflow tests to use the expression-based BarrierGuard API (instead of the Instruction-based one). I don't think we want users to use the Instruction-based one anyway, and we should test the APIs we tell people to use.
  • The second commit adds a test that needs indirect expressions to be marked by a barrier guard.
  • The final commit adds the new API and accepts the test changes 🎉

@MathiasVP MathiasVP requested a review from a team as a code owner April 28, 2023 13:12
@github-actions github-actions Bot added the C++ label Apr 28, 2023
@aschackmull
Copy link
Copy Markdown
Contributor

Why not just change ExprNode getABarrierNode(); to Node getABarrierNode();?

@MathiasVP
Copy link
Copy Markdown
Contributor Author

Why not just change ExprNode getABarrierNode(); to Node getABarrierNode();?

That would also be fine, but then users would have to add an additional check in their isBarrier predicate if they want to restrict the barrier to one of the two cases.

I could imagine both situations, really. Most of the time users probably don't care which one they sanitize because they just want to remove some FP they're seeing. But I personally like to be able to distinguish the two cases, and still keep the pretty one-liner that you get from writing

barrier = DataFlow::BarrierGuard<testBarrierGuard/3>::getAnIndirectBarrierNode()

(😍)

@aschackmull
Copy link
Copy Markdown
Contributor

But I personally like to be able to distinguish the two cases

Right, if you imagine use-cases where you'll want to only have one or the other then it makes sense, but I just thought that you'd always want both.

@aschackmull
Copy link
Copy Markdown
Contributor

If indeed there are such use-cases that merit a split like this, then the qldoc probably needs some elaboration, because it's not at all clear that such use-cases exist, so that'll probably make it hard for users to figure out when to use one or the other or both.

@MathiasVP
Copy link
Copy Markdown
Contributor Author

If indeed there are such use-cases that merit a split like this, then the qldoc probably needs some elaboration, because it's not at all clear that such use-cases exist, so that'll probably make it hard for users to figure out when to use one or the other or both.

Good point. I'll add some QLDoc. The concept of "indirect expression" is explained in some other QLDoc, but it can't hurt to add a more specific explanation within the context of barrier guards 👍.

@aschackmull
Copy link
Copy Markdown
Contributor

Good point. I'll add some QLDoc

👍 Nicely elaborate.

jketema
jketema previously approved these changes May 3, 2023
Copy link
Copy Markdown
Contributor

@jketema jketema left a comment

Choose a reason for hiding this comment

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

LGTM, one small comment. I assume we can skip any DCA experiment, because the new predicate is not used in any query?

}

/** Gets an indirect expression node that is safely guarded by the given guard check. */
IndirectExprNode getAnIndirectBarrierNode() {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Do we want to expose the indirection index here as an argument of getAnIndirectBarrierNode?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

We could do that, yeah. And then implement a getAnIndirectBarrierNode with no parameters as getAnIndirectBarrierNode(_)?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Yup.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 2d98fb7.

@MathiasVP
Copy link
Copy Markdown
Contributor Author

LGTM, one small comment. I assume we can skip any DCA experiment, because the new predicate is not used in any query?

Yeah, I don't see any reason to run DCA here 👍.

Copy link
Copy Markdown
Contributor

@jketema jketema left a comment

Choose a reason for hiding this comment

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

LGTM

@MathiasVP MathiasVP merged commit 2af48e2 into github:main May 3, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants