Repository navigation
C++: Fix Expr <-> DataFlow::Node mapping for glvalue qualifiers
#23046
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
base: main
Are you sure you want to change the base?
Changes from all commits
f3b66f8
6f73258
4c4033f
4cc3de2
13a9724
a7eb87a
96a9871
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -244,17 +244,49 @@ private module Cached { | |
| ) | ||
| } | ||
|
|
||
| /** | ||
| * Gets a `glvalue` expression whose unconverted result is the same as the | ||
| * unconverted result of `e`. | ||
| */ | ||
| pragma[inline] | ||
| private Expr getAGLValueCategoryExpr(Expr e) { | ||
| result.isGLValueCategory() and | ||
| result.getUnconverted() = e.getUnconverted() | ||
| } | ||
|
|
||
| /** Holds if `node` should be an `IndirectOperand` that maps `node.asExpr()` to `e`. */ | ||
| private predicate exprNodeShouldBeIndirectOperand(IndirectOperand node, Expr e, int n) { | ||
| exists(ArgumentOperand operand | | ||
| exists(ArgumentOperand operand | isIndirectOperandOfArgument(node, operand, e, n) | | ||
| // If `x` has type `Foo` in a call such `x.f()` the `VariableAddress` | ||
| // instruction (which is of type `glvalue<Foo>`) is the qualifier. | ||
| // So the `DataFlow::Node` we want to represent `x` is the indirection of | ||
| // the qualifier (which will then have type `Foo`). | ||
| // Since the node -> expression mapping is one-to-many we additionally need to | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've a hard time following this, especially since the example you give seems many-to-one (there's only one expression in the example
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, right. I can see how this is a bit confusing. Let me clear up things in the conversation here, and then we can figure out how to improve the comments. The instruction-to-node mapping is many-to-one, but the node-to-expression mapping is one-to-many. This does play a role here:
In the
Does that make it more clear? I'm still trying to figure out how to articulate this in a code comment 😅 |
||
| // check that the specific expression we map to is also a glvalue. For example, | ||
| // in `(*x).f()` the qualifier generates IR like: | ||
| // ``` | ||
| // r1(glval<Foo *>) = VariableAddress[x] : | ||
| // r2(Foo *) = Load[x] : &:r1 | ||
| // r3(glval<Foo>) = CopyValue : r2 | ||
| // ``` | ||
| // The qualifier is associated with both `*x` and the lvalue-to-rvalue | ||
| // conversion of `x`. Only `*x` is a glvalue and should map to the | ||
| // indirect qualifier node; the converted `x` is a pointer prvalue and | ||
| // should map to the direct qualifier node. So we require that the fully | ||
| // converted qualifier (i.e., the expression with `n = 0`) is a glvalue, | ||
| // and then map every expression in the conversion chain with the same | ||
| // unconverted expression to the indirect node. | ||
| operand.isGLValue() and | ||
| operand instanceof ThisArgumentOperand and | ||
| isIndirectOperandOfArgument(node, operand, getAGLValueCategoryExpr(e), 0) | ||
| or | ||
| // When an argument (qualifier or positional) is a prvalue and the | ||
| // parameter (qualifier or positional) is a (const) reference, IR | ||
| // construction introduces a temporary `IRVariable`. The `VariableAddress` | ||
| // instruction has the argument as its `getConvertedResultExpression` | ||
| // result. However, the instruction actually represents the _address_ of | ||
| // the argument. So to fix this mismatch, we have the indirection of the | ||
| // `VariableAddressInstruction` map to the expression. | ||
| isIndirectOperandOfArgument(node, operand, e, n) and | ||
| irTempOperandConversionFlows(operand) | ||
| ) | ||
| } | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.