|
|
|
/* @generated */
|
|
|
|
digraph cfg {
|
[clang] fix bad interaction between ConditionalOperator and initializers
Summary:
This is several inter-connected changes together to keep the tests
happy.
The ConditionalOperator `b?t:e` is translated by first creating a
placeholder variable to temporarily store the result of the evaluation
in each branch, then the real thing we want to assign to reads that
variable. But, there are situations where that changes the semantics of
the expression, namely when the value created is a struct on the stack
(eg, a C++ temporary). This is because in SIL we cannot assign the
*address* of a program variable, only its contents, so by the time we're
out of the conditional operator we cannot set the struct value
correctly anymore: we can only set its content, which we did, but that
results in a "shifted" struct value that is one dereference away from
where it should be.
So a batch of changes concern `conditionalOperator_trans`:
- instead of systematically creating a temporary for the conditional,
use the `trans_state.var_exp_typ` provided from above if available
when translating `ConditionalOperator`
- don't even set anything if that variable was already initialized by
merely translating the branch expression, eg when it's a constructor
- fix long-standing TODO to propagate these initialization facts
accurately for ConditionalOperator (used by `init_expr_trans` to also
figure out if it should insert a store to the variable being
initialised or not)
The rest of the changes adapt some relevant other constructs to deal
with conditionalOperator properly now that it can set the current
variable itself, instead of storing stuff inside a temp variable. This
change was a problem because some constructs, eg a variable declaration,
will insert nodes that set up the variable before calling its
initialization, and now the initialization happens *before* that setup,
in the translation of the inner conditional operator, which naturally
creates nodes above the current one.
- add a generic helper to force a sequential order between two
translation results, forcing node creation if necessary
- use that in `init_expr_trans` and `cxxNewExpr_trans`
- adjust many places where `var_exp_typ` was incorrectly not reset when translating sub-expressions
The sequentiality business creates more nodes when used, and the
conditionalOperator business uses fewer temporary variables, so the
frontend results change quite a bit.
Note that biabduction tests were invaluable in debugging this. There
could be other constructs to adjust similarly to cxxNewExpr that were
not covered by the tests though.
Added tests in pulse that exercises the previous bug.
Reviewed By: da319
Differential Revision: D24796282
fbshipit-source-id: 0790c8d17
4 years ago
|
|
|
"operator!=#4715710375716659667.eb4126b3edd381f3092a9e38275754d4_1" [label="1: Start operator!=\nFormals: i1:iterator& i2:iterator&\nLocals: \n " color=yellow style=filled]
|
|
|
|
|
|
|
|
|
|
|
|
"operator!=#4715710375716659667.eb4126b3edd381f3092a9e38275754d4_1" -> "operator!=#4715710375716659667.eb4126b3edd381f3092a9e38275754d4_4" ;
|
|
|
|
"operator!=#4715710375716659667.eb4126b3edd381f3092a9e38275754d4_2" [label="2: Exit operator!= \n " color=yellow style=filled]
|
|
|
|
|
|
|
|
|
|
|
|
"operator!=#4715710375716659667.eb4126b3edd381f3092a9e38275754d4_3" [label="3: + \n " ]
|
|
|
|
|
|
|
|
|
|
|
|
"operator!=#4715710375716659667.eb4126b3edd381f3092a9e38275754d4_3" -> "operator!=#4715710375716659667.eb4126b3edd381f3092a9e38275754d4_9" ;
|
[clang] fix bad interaction between ConditionalOperator and initializers
Summary:
This is several inter-connected changes together to keep the tests
happy.
The ConditionalOperator `b?t:e` is translated by first creating a
placeholder variable to temporarily store the result of the evaluation
in each branch, then the real thing we want to assign to reads that
variable. But, there are situations where that changes the semantics of
the expression, namely when the value created is a struct on the stack
(eg, a C++ temporary). This is because in SIL we cannot assign the
*address* of a program variable, only its contents, so by the time we're
out of the conditional operator we cannot set the struct value
correctly anymore: we can only set its content, which we did, but that
results in a "shifted" struct value that is one dereference away from
where it should be.
So a batch of changes concern `conditionalOperator_trans`:
- instead of systematically creating a temporary for the conditional,
use the `trans_state.var_exp_typ` provided from above if available
when translating `ConditionalOperator`
- don't even set anything if that variable was already initialized by
merely translating the branch expression, eg when it's a constructor
- fix long-standing TODO to propagate these initialization facts
accurately for ConditionalOperator (used by `init_expr_trans` to also
figure out if it should insert a store to the variable being
initialised or not)
The rest of the changes adapt some relevant other constructs to deal
with conditionalOperator properly now that it can set the current
variable itself, instead of storing stuff inside a temp variable. This
change was a problem because some constructs, eg a variable declaration,
will insert nodes that set up the variable before calling its
initialization, and now the initialization happens *before* that setup,
in the translation of the inner conditional operator, which naturally
creates nodes above the current one.
- add a generic helper to force a sequential order between two
translation results, forcing node creation if necessary
- use that in `init_expr_trans` and `cxxNewExpr_trans`
- adjust many places where `var_exp_typ` was incorrectly not reset when translating sub-expressions
The sequentiality business creates more nodes when used, and the
conditionalOperator business uses fewer temporary variables, so the
frontend results change quite a bit.
Note that biabduction tests were invaluable in debugging this. There
could be other constructs to adjust similarly to cxxNewExpr that were
not covered by the tests though.
Added tests in pulse that exercises the previous bug.
Reviewed By: da319
Differential Revision: D24796282
fbshipit-source-id: 0790c8d17
4 years ago
|
|
|
"operator!=#4715710375716659667.eb4126b3edd381f3092a9e38275754d4_4" [label="4: BinaryOperatorStmt: NE \n n$0=*&i1:iterator& [line 19, column 52]\n n$1=*n$0.val:int [line 19, column 52]\n n$2=*&i2:iterator& [line 19, column 62]\n n$3=*n$2.val:int [line 19, column 62]\n " shape="box"]
|
|
|
|
|
|
|
|
|
|
|
|
"operator!=#4715710375716659667.eb4126b3edd381f3092a9e38275754d4_4" -> "operator!=#4715710375716659667.eb4126b3edd381f3092a9e38275754d4_5" ;
|
|
|
|
"operator!=#4715710375716659667.eb4126b3edd381f3092a9e38275754d4_4" -> "operator!=#4715710375716659667.eb4126b3edd381f3092a9e38275754d4_6" ;
|
[clang] fix bad interaction between ConditionalOperator and initializers
Summary:
This is several inter-connected changes together to keep the tests
happy.
The ConditionalOperator `b?t:e` is translated by first creating a
placeholder variable to temporarily store the result of the evaluation
in each branch, then the real thing we want to assign to reads that
variable. But, there are situations where that changes the semantics of
the expression, namely when the value created is a struct on the stack
(eg, a C++ temporary). This is because in SIL we cannot assign the
*address* of a program variable, only its contents, so by the time we're
out of the conditional operator we cannot set the struct value
correctly anymore: we can only set its content, which we did, but that
results in a "shifted" struct value that is one dereference away from
where it should be.
So a batch of changes concern `conditionalOperator_trans`:
- instead of systematically creating a temporary for the conditional,
use the `trans_state.var_exp_typ` provided from above if available
when translating `ConditionalOperator`
- don't even set anything if that variable was already initialized by
merely translating the branch expression, eg when it's a constructor
- fix long-standing TODO to propagate these initialization facts
accurately for ConditionalOperator (used by `init_expr_trans` to also
figure out if it should insert a store to the variable being
initialised or not)
The rest of the changes adapt some relevant other constructs to deal
with conditionalOperator properly now that it can set the current
variable itself, instead of storing stuff inside a temp variable. This
change was a problem because some constructs, eg a variable declaration,
will insert nodes that set up the variable before calling its
initialization, and now the initialization happens *before* that setup,
in the translation of the inner conditional operator, which naturally
creates nodes above the current one.
- add a generic helper to force a sequential order between two
translation results, forcing node creation if necessary
- use that in `init_expr_trans` and `cxxNewExpr_trans`
- adjust many places where `var_exp_typ` was incorrectly not reset when translating sub-expressions
The sequentiality business creates more nodes when used, and the
conditionalOperator business uses fewer temporary variables, so the
frontend results change quite a bit.
Note that biabduction tests were invaluable in debugging this. There
could be other constructs to adjust similarly to cxxNewExpr that were
not covered by the tests though.
Added tests in pulse that exercises the previous bug.
Reviewed By: da319
Differential Revision: D24796282
fbshipit-source-id: 0790c8d17
4 years ago
|
|
|
"operator!=#4715710375716659667.eb4126b3edd381f3092a9e38275754d4_5" [label="5: Prune (true branch, boolean exp) \n PRUNE((n$1 != n$3), true); [line 19, column 52]\n " shape="invhouse"]
|
|
|
|
|
|
|
|
|
|
|
|
"operator!=#4715710375716659667.eb4126b3edd381f3092a9e38275754d4_5" -> "operator!=#4715710375716659667.eb4126b3edd381f3092a9e38275754d4_7" ;
|
[clang] fix bad interaction between ConditionalOperator and initializers
Summary:
This is several inter-connected changes together to keep the tests
happy.
The ConditionalOperator `b?t:e` is translated by first creating a
placeholder variable to temporarily store the result of the evaluation
in each branch, then the real thing we want to assign to reads that
variable. But, there are situations where that changes the semantics of
the expression, namely when the value created is a struct on the stack
(eg, a C++ temporary). This is because in SIL we cannot assign the
*address* of a program variable, only its contents, so by the time we're
out of the conditional operator we cannot set the struct value
correctly anymore: we can only set its content, which we did, but that
results in a "shifted" struct value that is one dereference away from
where it should be.
So a batch of changes concern `conditionalOperator_trans`:
- instead of systematically creating a temporary for the conditional,
use the `trans_state.var_exp_typ` provided from above if available
when translating `ConditionalOperator`
- don't even set anything if that variable was already initialized by
merely translating the branch expression, eg when it's a constructor
- fix long-standing TODO to propagate these initialization facts
accurately for ConditionalOperator (used by `init_expr_trans` to also
figure out if it should insert a store to the variable being
initialised or not)
The rest of the changes adapt some relevant other constructs to deal
with conditionalOperator properly now that it can set the current
variable itself, instead of storing stuff inside a temp variable. This
change was a problem because some constructs, eg a variable declaration,
will insert nodes that set up the variable before calling its
initialization, and now the initialization happens *before* that setup,
in the translation of the inner conditional operator, which naturally
creates nodes above the current one.
- add a generic helper to force a sequential order between two
translation results, forcing node creation if necessary
- use that in `init_expr_trans` and `cxxNewExpr_trans`
- adjust many places where `var_exp_typ` was incorrectly not reset when translating sub-expressions
The sequentiality business creates more nodes when used, and the
conditionalOperator business uses fewer temporary variables, so the
frontend results change quite a bit.
Note that biabduction tests were invaluable in debugging this. There
could be other constructs to adjust similarly to cxxNewExpr that were
not covered by the tests though.
Added tests in pulse that exercises the previous bug.
Reviewed By: da319
Differential Revision: D24796282
fbshipit-source-id: 0790c8d17
4 years ago
|
|
|
"operator!=#4715710375716659667.eb4126b3edd381f3092a9e38275754d4_6" [label="6: Prune (false branch, boolean exp) \n PRUNE(!(n$1 != n$3), false); [line 19, column 52]\n " shape="invhouse"]
|
|
|
|
|
|
|
|
|
|
|
|
"operator!=#4715710375716659667.eb4126b3edd381f3092a9e38275754d4_6" -> "operator!=#4715710375716659667.eb4126b3edd381f3092a9e38275754d4_8" ;
|
[clang] fix bad interaction between ConditionalOperator and initializers
Summary:
This is several inter-connected changes together to keep the tests
happy.
The ConditionalOperator `b?t:e` is translated by first creating a
placeholder variable to temporarily store the result of the evaluation
in each branch, then the real thing we want to assign to reads that
variable. But, there are situations where that changes the semantics of
the expression, namely when the value created is a struct on the stack
(eg, a C++ temporary). This is because in SIL we cannot assign the
*address* of a program variable, only its contents, so by the time we're
out of the conditional operator we cannot set the struct value
correctly anymore: we can only set its content, which we did, but that
results in a "shifted" struct value that is one dereference away from
where it should be.
So a batch of changes concern `conditionalOperator_trans`:
- instead of systematically creating a temporary for the conditional,
use the `trans_state.var_exp_typ` provided from above if available
when translating `ConditionalOperator`
- don't even set anything if that variable was already initialized by
merely translating the branch expression, eg when it's a constructor
- fix long-standing TODO to propagate these initialization facts
accurately for ConditionalOperator (used by `init_expr_trans` to also
figure out if it should insert a store to the variable being
initialised or not)
The rest of the changes adapt some relevant other constructs to deal
with conditionalOperator properly now that it can set the current
variable itself, instead of storing stuff inside a temp variable. This
change was a problem because some constructs, eg a variable declaration,
will insert nodes that set up the variable before calling its
initialization, and now the initialization happens *before* that setup,
in the translation of the inner conditional operator, which naturally
creates nodes above the current one.
- add a generic helper to force a sequential order between two
translation results, forcing node creation if necessary
- use that in `init_expr_trans` and `cxxNewExpr_trans`
- adjust many places where `var_exp_typ` was incorrectly not reset when translating sub-expressions
The sequentiality business creates more nodes when used, and the
conditionalOperator business uses fewer temporary variables, so the
frontend results change quite a bit.
Note that biabduction tests were invaluable in debugging this. There
could be other constructs to adjust similarly to cxxNewExpr that were
not covered by the tests though.
Added tests in pulse that exercises the previous bug.
Reviewed By: da319
Differential Revision: D24796282
fbshipit-source-id: 0790c8d17
4 years ago
|
|
|
"operator!=#4715710375716659667.eb4126b3edd381f3092a9e38275754d4_7" [label="7: ConditionalStmt Branch \n *&return:_Bool=1 [line 19, column 52]\n " shape="box"]
|
|
|
|
|
|
|
|
|
|
|
|
"operator!=#4715710375716659667.eb4126b3edd381f3092a9e38275754d4_7" -> "operator!=#4715710375716659667.eb4126b3edd381f3092a9e38275754d4_3" ;
|
[clang] fix bad interaction between ConditionalOperator and initializers
Summary:
This is several inter-connected changes together to keep the tests
happy.
The ConditionalOperator `b?t:e` is translated by first creating a
placeholder variable to temporarily store the result of the evaluation
in each branch, then the real thing we want to assign to reads that
variable. But, there are situations where that changes the semantics of
the expression, namely when the value created is a struct on the stack
(eg, a C++ temporary). This is because in SIL we cannot assign the
*address* of a program variable, only its contents, so by the time we're
out of the conditional operator we cannot set the struct value
correctly anymore: we can only set its content, which we did, but that
results in a "shifted" struct value that is one dereference away from
where it should be.
So a batch of changes concern `conditionalOperator_trans`:
- instead of systematically creating a temporary for the conditional,
use the `trans_state.var_exp_typ` provided from above if available
when translating `ConditionalOperator`
- don't even set anything if that variable was already initialized by
merely translating the branch expression, eg when it's a constructor
- fix long-standing TODO to propagate these initialization facts
accurately for ConditionalOperator (used by `init_expr_trans` to also
figure out if it should insert a store to the variable being
initialised or not)
The rest of the changes adapt some relevant other constructs to deal
with conditionalOperator properly now that it can set the current
variable itself, instead of storing stuff inside a temp variable. This
change was a problem because some constructs, eg a variable declaration,
will insert nodes that set up the variable before calling its
initialization, and now the initialization happens *before* that setup,
in the translation of the inner conditional operator, which naturally
creates nodes above the current one.
- add a generic helper to force a sequential order between two
translation results, forcing node creation if necessary
- use that in `init_expr_trans` and `cxxNewExpr_trans`
- adjust many places where `var_exp_typ` was incorrectly not reset when translating sub-expressions
The sequentiality business creates more nodes when used, and the
conditionalOperator business uses fewer temporary variables, so the
frontend results change quite a bit.
Note that biabduction tests were invaluable in debugging this. There
could be other constructs to adjust similarly to cxxNewExpr that were
not covered by the tests though.
Added tests in pulse that exercises the previous bug.
Reviewed By: da319
Differential Revision: D24796282
fbshipit-source-id: 0790c8d17
4 years ago
|
|
|
"operator!=#4715710375716659667.eb4126b3edd381f3092a9e38275754d4_8" [label="8: ConditionalStmt Branch \n *&return:_Bool=0 [line 19, column 52]\n " shape="box"]
|
|
|
|
|
|
|
|
|
|
|
|
"operator!=#4715710375716659667.eb4126b3edd381f3092a9e38275754d4_8" -> "operator!=#4715710375716659667.eb4126b3edd381f3092a9e38275754d4_3" ;
|
[clang] fix bad interaction between ConditionalOperator and initializers
Summary:
This is several inter-connected changes together to keep the tests
happy.
The ConditionalOperator `b?t:e` is translated by first creating a
placeholder variable to temporarily store the result of the evaluation
in each branch, then the real thing we want to assign to reads that
variable. But, there are situations where that changes the semantics of
the expression, namely when the value created is a struct on the stack
(eg, a C++ temporary). This is because in SIL we cannot assign the
*address* of a program variable, only its contents, so by the time we're
out of the conditional operator we cannot set the struct value
correctly anymore: we can only set its content, which we did, but that
results in a "shifted" struct value that is one dereference away from
where it should be.
So a batch of changes concern `conditionalOperator_trans`:
- instead of systematically creating a temporary for the conditional,
use the `trans_state.var_exp_typ` provided from above if available
when translating `ConditionalOperator`
- don't even set anything if that variable was already initialized by
merely translating the branch expression, eg when it's a constructor
- fix long-standing TODO to propagate these initialization facts
accurately for ConditionalOperator (used by `init_expr_trans` to also
figure out if it should insert a store to the variable being
initialised or not)
The rest of the changes adapt some relevant other constructs to deal
with conditionalOperator properly now that it can set the current
variable itself, instead of storing stuff inside a temp variable. This
change was a problem because some constructs, eg a variable declaration,
will insert nodes that set up the variable before calling its
initialization, and now the initialization happens *before* that setup,
in the translation of the inner conditional operator, which naturally
creates nodes above the current one.
- add a generic helper to force a sequential order between two
translation results, forcing node creation if necessary
- use that in `init_expr_trans` and `cxxNewExpr_trans`
- adjust many places where `var_exp_typ` was incorrectly not reset when translating sub-expressions
The sequentiality business creates more nodes when used, and the
conditionalOperator business uses fewer temporary variables, so the
frontend results change quite a bit.
Note that biabduction tests were invaluable in debugging this. There
could be other constructs to adjust similarly to cxxNewExpr that were
not covered by the tests though.
Added tests in pulse that exercises the previous bug.
Reviewed By: da319
Differential Revision: D24796282
fbshipit-source-id: 0790c8d17
4 years ago
|
|
|
"operator!=#4715710375716659667.eb4126b3edd381f3092a9e38275754d4_9" [label="9: Return Stmt \n " shape="box"]
|
|
|
|
|
|
|
|
|
|
|
|
"operator!=#4715710375716659667.eb4126b3edd381f3092a9e38275754d4_9" -> "operator!=#4715710375716659667.eb4126b3edd381f3092a9e38275754d4_2" ;
|
|
|
|
"test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_1" [label="1: Start test\nFormals: \nLocals: __end1:iterator 0$?%__sil_tmpSIL_materialize_temp__n$5:iterator __begin1:iterator 0$?%__sil_tmpSIL_materialize_temp__n$14:iterator 0$?%__sil_tmp__temp_return_n$25:iterator 0$?%__sil_tmp__temp_construct_n$27:iterator 0$?%__sil_tmp__temp_construct_n$29:iterator temp:int value:int __range1:vec& vector:vec \n " color=yellow style=filled]
|
|
|
|
|
|
|
|
|
[clang] fix bad interaction between ConditionalOperator and initializers
Summary:
This is several inter-connected changes together to keep the tests
happy.
The ConditionalOperator `b?t:e` is translated by first creating a
placeholder variable to temporarily store the result of the evaluation
in each branch, then the real thing we want to assign to reads that
variable. But, there are situations where that changes the semantics of
the expression, namely when the value created is a struct on the stack
(eg, a C++ temporary). This is because in SIL we cannot assign the
*address* of a program variable, only its contents, so by the time we're
out of the conditional operator we cannot set the struct value
correctly anymore: we can only set its content, which we did, but that
results in a "shifted" struct value that is one dereference away from
where it should be.
So a batch of changes concern `conditionalOperator_trans`:
- instead of systematically creating a temporary for the conditional,
use the `trans_state.var_exp_typ` provided from above if available
when translating `ConditionalOperator`
- don't even set anything if that variable was already initialized by
merely translating the branch expression, eg when it's a constructor
- fix long-standing TODO to propagate these initialization facts
accurately for ConditionalOperator (used by `init_expr_trans` to also
figure out if it should insert a store to the variable being
initialised or not)
The rest of the changes adapt some relevant other constructs to deal
with conditionalOperator properly now that it can set the current
variable itself, instead of storing stuff inside a temp variable. This
change was a problem because some constructs, eg a variable declaration,
will insert nodes that set up the variable before calling its
initialization, and now the initialization happens *before* that setup,
in the translation of the inner conditional operator, which naturally
creates nodes above the current one.
- add a generic helper to force a sequential order between two
translation results, forcing node creation if necessary
- use that in `init_expr_trans` and `cxxNewExpr_trans`
- adjust many places where `var_exp_typ` was incorrectly not reset when translating sub-expressions
The sequentiality business creates more nodes when used, and the
conditionalOperator business uses fewer temporary variables, so the
frontend results change quite a bit.
Note that biabduction tests were invaluable in debugging this. There
could be other constructs to adjust similarly to cxxNewExpr that were
not covered by the tests though.
Added tests in pulse that exercises the previous bug.
Reviewed By: da319
Differential Revision: D24796282
fbshipit-source-id: 0790c8d17
4 years ago
|
|
|
"test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_1" -> "test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_18" ;
|
|
|
|
"test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_2" [label="2: Exit test \n " color=yellow style=filled]
|
|
|
|
|
|
|
|
|
|
|
|
"test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_3" [label="3: Destruction(Scope) \n _=*&__end1:iterator [line 37, column 3]\n n$1=_fun_iterator::~iterator(&__end1:iterator*) injected [line 37, column 3]\n _=*&__begin1:iterator [line 37, column 3]\n n$3=_fun_iterator::~iterator(&__begin1:iterator*) injected [line 37, column 3]\n " shape="box"]
|
|
|
|
|
|
|
|
|
|
|
|
"test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_3" -> "test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_2" ;
|
|
|
|
"test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_4" [label="4: + \n " ]
|
|
|
|
|
|
|
|
|
[clang] fix bad interaction between ConditionalOperator and initializers
Summary:
This is several inter-connected changes together to keep the tests
happy.
The ConditionalOperator `b?t:e` is translated by first creating a
placeholder variable to temporarily store the result of the evaluation
in each branch, then the real thing we want to assign to reads that
variable. But, there are situations where that changes the semantics of
the expression, namely when the value created is a struct on the stack
(eg, a C++ temporary). This is because in SIL we cannot assign the
*address* of a program variable, only its contents, so by the time we're
out of the conditional operator we cannot set the struct value
correctly anymore: we can only set its content, which we did, but that
results in a "shifted" struct value that is one dereference away from
where it should be.
So a batch of changes concern `conditionalOperator_trans`:
- instead of systematically creating a temporary for the conditional,
use the `trans_state.var_exp_typ` provided from above if available
when translating `ConditionalOperator`
- don't even set anything if that variable was already initialized by
merely translating the branch expression, eg when it's a constructor
- fix long-standing TODO to propagate these initialization facts
accurately for ConditionalOperator (used by `init_expr_trans` to also
figure out if it should insert a store to the variable being
initialised or not)
The rest of the changes adapt some relevant other constructs to deal
with conditionalOperator properly now that it can set the current
variable itself, instead of storing stuff inside a temp variable. This
change was a problem because some constructs, eg a variable declaration,
will insert nodes that set up the variable before calling its
initialization, and now the initialization happens *before* that setup,
in the translation of the inner conditional operator, which naturally
creates nodes above the current one.
- add a generic helper to force a sequential order between two
translation results, forcing node creation if necessary
- use that in `init_expr_trans` and `cxxNewExpr_trans`
- adjust many places where `var_exp_typ` was incorrectly not reset when translating sub-expressions
The sequentiality business creates more nodes when used, and the
conditionalOperator business uses fewer temporary variables, so the
frontend results change quite a bit.
Note that biabduction tests were invaluable in debugging this. There
could be other constructs to adjust similarly to cxxNewExpr that were
not covered by the tests though.
Added tests in pulse that exercises the previous bug.
Reviewed By: da319
Differential Revision: D24796282
fbshipit-source-id: 0790c8d17
4 years ago
|
|
|
"test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_4" -> "test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_12" ;
|
|
|
|
"test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_5" [label="5: DeclStmt \n VARIABLE_DECLARED(0$?%__sil_tmpSIL_materialize_temp__n$5:iterator); [line 35, column 18]\n n$9=*&__range1:vec& [line 35, column 18]\n _=*n$9:vec [line 35, column 18]\n n$12=_fun_vec::end(n$9:vec&,&0$?%__sil_tmpSIL_materialize_temp__n$5:iterator*) assign_last [line 35, column 18]\n " shape="box"]
|
|
|
|
|
|
|
|
|
[clang] fix bad interaction between ConditionalOperator and initializers
Summary:
This is several inter-connected changes together to keep the tests
happy.
The ConditionalOperator `b?t:e` is translated by first creating a
placeholder variable to temporarily store the result of the evaluation
in each branch, then the real thing we want to assign to reads that
variable. But, there are situations where that changes the semantics of
the expression, namely when the value created is a struct on the stack
(eg, a C++ temporary). This is because in SIL we cannot assign the
*address* of a program variable, only its contents, so by the time we're
out of the conditional operator we cannot set the struct value
correctly anymore: we can only set its content, which we did, but that
results in a "shifted" struct value that is one dereference away from
where it should be.
So a batch of changes concern `conditionalOperator_trans`:
- instead of systematically creating a temporary for the conditional,
use the `trans_state.var_exp_typ` provided from above if available
when translating `ConditionalOperator`
- don't even set anything if that variable was already initialized by
merely translating the branch expression, eg when it's a constructor
- fix long-standing TODO to propagate these initialization facts
accurately for ConditionalOperator (used by `init_expr_trans` to also
figure out if it should insert a store to the variable being
initialised or not)
The rest of the changes adapt some relevant other constructs to deal
with conditionalOperator properly now that it can set the current
variable itself, instead of storing stuff inside a temp variable. This
change was a problem because some constructs, eg a variable declaration,
will insert nodes that set up the variable before calling its
initialization, and now the initialization happens *before* that setup,
in the translation of the inner conditional operator, which naturally
creates nodes above the current one.
- add a generic helper to force a sequential order between two
translation results, forcing node creation if necessary
- use that in `init_expr_trans` and `cxxNewExpr_trans`
- adjust many places where `var_exp_typ` was incorrectly not reset when translating sub-expressions
The sequentiality business creates more nodes when used, and the
conditionalOperator business uses fewer temporary variables, so the
frontend results change quite a bit.
Note that biabduction tests were invaluable in debugging this. There
could be other constructs to adjust similarly to cxxNewExpr that were
not covered by the tests though.
Added tests in pulse that exercises the previous bug.
Reviewed By: da319
Differential Revision: D24796282
fbshipit-source-id: 0790c8d17
4 years ago
|
|
|
"test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_5" -> "test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_7" ;
|
|
|
|
"test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_6" [label="6: DeclStmt \n VARIABLE_DECLARED(__end1:iterator); [line 35, column 18]\n " shape="box"]
|
|
|
|
|
|
|
|
|
|
|
|
"test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_6" -> "test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_5" ;
|
[clang] fix bad interaction between ConditionalOperator and initializers
Summary:
This is several inter-connected changes together to keep the tests
happy.
The ConditionalOperator `b?t:e` is translated by first creating a
placeholder variable to temporarily store the result of the evaluation
in each branch, then the real thing we want to assign to reads that
variable. But, there are situations where that changes the semantics of
the expression, namely when the value created is a struct on the stack
(eg, a C++ temporary). This is because in SIL we cannot assign the
*address* of a program variable, only its contents, so by the time we're
out of the conditional operator we cannot set the struct value
correctly anymore: we can only set its content, which we did, but that
results in a "shifted" struct value that is one dereference away from
where it should be.
So a batch of changes concern `conditionalOperator_trans`:
- instead of systematically creating a temporary for the conditional,
use the `trans_state.var_exp_typ` provided from above if available
when translating `ConditionalOperator`
- don't even set anything if that variable was already initialized by
merely translating the branch expression, eg when it's a constructor
- fix long-standing TODO to propagate these initialization facts
accurately for ConditionalOperator (used by `init_expr_trans` to also
figure out if it should insert a store to the variable being
initialised or not)
The rest of the changes adapt some relevant other constructs to deal
with conditionalOperator properly now that it can set the current
variable itself, instead of storing stuff inside a temp variable. This
change was a problem because some constructs, eg a variable declaration,
will insert nodes that set up the variable before calling its
initialization, and now the initialization happens *before* that setup,
in the translation of the inner conditional operator, which naturally
creates nodes above the current one.
- add a generic helper to force a sequential order between two
translation results, forcing node creation if necessary
- use that in `init_expr_trans` and `cxxNewExpr_trans`
- adjust many places where `var_exp_typ` was incorrectly not reset when translating sub-expressions
The sequentiality business creates more nodes when used, and the
conditionalOperator business uses fewer temporary variables, so the
frontend results change quite a bit.
Note that biabduction tests were invaluable in debugging this. There
could be other constructs to adjust similarly to cxxNewExpr that were
not covered by the tests though.
Added tests in pulse that exercises the previous bug.
Reviewed By: da319
Differential Revision: D24796282
fbshipit-source-id: 0790c8d17
4 years ago
|
|
|
"test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_7" [label="7: DeclStmt \n n$13=_fun_iterator::iterator(&__end1:iterator*,&0$?%__sil_tmpSIL_materialize_temp__n$5:iterator&) [line 35, column 18]\n _=*&0$?%__sil_tmpSIL_materialize_temp__n$5:iterator [line 35, column 18]\n n$7=_fun_iterator::~iterator(&0$?%__sil_tmpSIL_materialize_temp__n$5:iterator*) injected [line 35, column 18]\n " shape="box"]
|
|
|
|
|
|
|
|
|
|
|
|
"test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_7" -> "test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_4" ;
|
[clang] fix bad interaction between ConditionalOperator and initializers
Summary:
This is several inter-connected changes together to keep the tests
happy.
The ConditionalOperator `b?t:e` is translated by first creating a
placeholder variable to temporarily store the result of the evaluation
in each branch, then the real thing we want to assign to reads that
variable. But, there are situations where that changes the semantics of
the expression, namely when the value created is a struct on the stack
(eg, a C++ temporary). This is because in SIL we cannot assign the
*address* of a program variable, only its contents, so by the time we're
out of the conditional operator we cannot set the struct value
correctly anymore: we can only set its content, which we did, but that
results in a "shifted" struct value that is one dereference away from
where it should be.
So a batch of changes concern `conditionalOperator_trans`:
- instead of systematically creating a temporary for the conditional,
use the `trans_state.var_exp_typ` provided from above if available
when translating `ConditionalOperator`
- don't even set anything if that variable was already initialized by
merely translating the branch expression, eg when it's a constructor
- fix long-standing TODO to propagate these initialization facts
accurately for ConditionalOperator (used by `init_expr_trans` to also
figure out if it should insert a store to the variable being
initialised or not)
The rest of the changes adapt some relevant other constructs to deal
with conditionalOperator properly now that it can set the current
variable itself, instead of storing stuff inside a temp variable. This
change was a problem because some constructs, eg a variable declaration,
will insert nodes that set up the variable before calling its
initialization, and now the initialization happens *before* that setup,
in the translation of the inner conditional operator, which naturally
creates nodes above the current one.
- add a generic helper to force a sequential order between two
translation results, forcing node creation if necessary
- use that in `init_expr_trans` and `cxxNewExpr_trans`
- adjust many places where `var_exp_typ` was incorrectly not reset when translating sub-expressions
The sequentiality business creates more nodes when used, and the
conditionalOperator business uses fewer temporary variables, so the
frontend results change quite a bit.
Note that biabduction tests were invaluable in debugging this. There
could be other constructs to adjust similarly to cxxNewExpr that were
not covered by the tests though.
Added tests in pulse that exercises the previous bug.
Reviewed By: da319
Differential Revision: D24796282
fbshipit-source-id: 0790c8d17
4 years ago
|
|
|
"test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_8" [label="8: DeclStmt \n VARIABLE_DECLARED(0$?%__sil_tmpSIL_materialize_temp__n$14:iterator); [line 35, column 18]\n n$18=*&__range1:vec& [line 35, column 18]\n _=*n$18:vec [line 35, column 18]\n n$21=_fun_vec::begin(n$18:vec&,&0$?%__sil_tmpSIL_materialize_temp__n$14:iterator*) assign_last [line 35, column 18]\n " shape="box"]
|
|
|
|
|
|
|
|
|
|
|
|
"test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_8" -> "test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_10" ;
|
[clang] fix bad interaction between ConditionalOperator and initializers
Summary:
This is several inter-connected changes together to keep the tests
happy.
The ConditionalOperator `b?t:e` is translated by first creating a
placeholder variable to temporarily store the result of the evaluation
in each branch, then the real thing we want to assign to reads that
variable. But, there are situations where that changes the semantics of
the expression, namely when the value created is a struct on the stack
(eg, a C++ temporary). This is because in SIL we cannot assign the
*address* of a program variable, only its contents, so by the time we're
out of the conditional operator we cannot set the struct value
correctly anymore: we can only set its content, which we did, but that
results in a "shifted" struct value that is one dereference away from
where it should be.
So a batch of changes concern `conditionalOperator_trans`:
- instead of systematically creating a temporary for the conditional,
use the `trans_state.var_exp_typ` provided from above if available
when translating `ConditionalOperator`
- don't even set anything if that variable was already initialized by
merely translating the branch expression, eg when it's a constructor
- fix long-standing TODO to propagate these initialization facts
accurately for ConditionalOperator (used by `init_expr_trans` to also
figure out if it should insert a store to the variable being
initialised or not)
The rest of the changes adapt some relevant other constructs to deal
with conditionalOperator properly now that it can set the current
variable itself, instead of storing stuff inside a temp variable. This
change was a problem because some constructs, eg a variable declaration,
will insert nodes that set up the variable before calling its
initialization, and now the initialization happens *before* that setup,
in the translation of the inner conditional operator, which naturally
creates nodes above the current one.
- add a generic helper to force a sequential order between two
translation results, forcing node creation if necessary
- use that in `init_expr_trans` and `cxxNewExpr_trans`
- adjust many places where `var_exp_typ` was incorrectly not reset when translating sub-expressions
The sequentiality business creates more nodes when used, and the
conditionalOperator business uses fewer temporary variables, so the
frontend results change quite a bit.
Note that biabduction tests were invaluable in debugging this. There
could be other constructs to adjust similarly to cxxNewExpr that were
not covered by the tests though.
Added tests in pulse that exercises the previous bug.
Reviewed By: da319
Differential Revision: D24796282
fbshipit-source-id: 0790c8d17
4 years ago
|
|
|
"test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_9" [label="9: DeclStmt \n VARIABLE_DECLARED(__begin1:iterator); [line 35, column 18]\n " shape="box"]
|
|
|
|
|
|
|
|
|
[clang] fix bad interaction between ConditionalOperator and initializers
Summary:
This is several inter-connected changes together to keep the tests
happy.
The ConditionalOperator `b?t:e` is translated by first creating a
placeholder variable to temporarily store the result of the evaluation
in each branch, then the real thing we want to assign to reads that
variable. But, there are situations where that changes the semantics of
the expression, namely when the value created is a struct on the stack
(eg, a C++ temporary). This is because in SIL we cannot assign the
*address* of a program variable, only its contents, so by the time we're
out of the conditional operator we cannot set the struct value
correctly anymore: we can only set its content, which we did, but that
results in a "shifted" struct value that is one dereference away from
where it should be.
So a batch of changes concern `conditionalOperator_trans`:
- instead of systematically creating a temporary for the conditional,
use the `trans_state.var_exp_typ` provided from above if available
when translating `ConditionalOperator`
- don't even set anything if that variable was already initialized by
merely translating the branch expression, eg when it's a constructor
- fix long-standing TODO to propagate these initialization facts
accurately for ConditionalOperator (used by `init_expr_trans` to also
figure out if it should insert a store to the variable being
initialised or not)
The rest of the changes adapt some relevant other constructs to deal
with conditionalOperator properly now that it can set the current
variable itself, instead of storing stuff inside a temp variable. This
change was a problem because some constructs, eg a variable declaration,
will insert nodes that set up the variable before calling its
initialization, and now the initialization happens *before* that setup,
in the translation of the inner conditional operator, which naturally
creates nodes above the current one.
- add a generic helper to force a sequential order between two
translation results, forcing node creation if necessary
- use that in `init_expr_trans` and `cxxNewExpr_trans`
- adjust many places where `var_exp_typ` was incorrectly not reset when translating sub-expressions
The sequentiality business creates more nodes when used, and the
conditionalOperator business uses fewer temporary variables, so the
frontend results change quite a bit.
Note that biabduction tests were invaluable in debugging this. There
could be other constructs to adjust similarly to cxxNewExpr that were
not covered by the tests though.
Added tests in pulse that exercises the previous bug.
Reviewed By: da319
Differential Revision: D24796282
fbshipit-source-id: 0790c8d17
4 years ago
|
|
|
"test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_9" -> "test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_8" ;
|
|
|
|
"test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_10" [label="10: DeclStmt \n n$22=_fun_iterator::iterator(&__begin1:iterator*,&0$?%__sil_tmpSIL_materialize_temp__n$14:iterator&) [line 35, column 18]\n _=*&0$?%__sil_tmpSIL_materialize_temp__n$14:iterator [line 35, column 18]\n n$16=_fun_iterator::~iterator(&0$?%__sil_tmpSIL_materialize_temp__n$14:iterator*) injected [line 35, column 18]\n " shape="box"]
|
|
|
|
|
|
|
|
|
[clang] fix bad interaction between ConditionalOperator and initializers
Summary:
This is several inter-connected changes together to keep the tests
happy.
The ConditionalOperator `b?t:e` is translated by first creating a
placeholder variable to temporarily store the result of the evaluation
in each branch, then the real thing we want to assign to reads that
variable. But, there are situations where that changes the semantics of
the expression, namely when the value created is a struct on the stack
(eg, a C++ temporary). This is because in SIL we cannot assign the
*address* of a program variable, only its contents, so by the time we're
out of the conditional operator we cannot set the struct value
correctly anymore: we can only set its content, which we did, but that
results in a "shifted" struct value that is one dereference away from
where it should be.
So a batch of changes concern `conditionalOperator_trans`:
- instead of systematically creating a temporary for the conditional,
use the `trans_state.var_exp_typ` provided from above if available
when translating `ConditionalOperator`
- don't even set anything if that variable was already initialized by
merely translating the branch expression, eg when it's a constructor
- fix long-standing TODO to propagate these initialization facts
accurately for ConditionalOperator (used by `init_expr_trans` to also
figure out if it should insert a store to the variable being
initialised or not)
The rest of the changes adapt some relevant other constructs to deal
with conditionalOperator properly now that it can set the current
variable itself, instead of storing stuff inside a temp variable. This
change was a problem because some constructs, eg a variable declaration,
will insert nodes that set up the variable before calling its
initialization, and now the initialization happens *before* that setup,
in the translation of the inner conditional operator, which naturally
creates nodes above the current one.
- add a generic helper to force a sequential order between two
translation results, forcing node creation if necessary
- use that in `init_expr_trans` and `cxxNewExpr_trans`
- adjust many places where `var_exp_typ` was incorrectly not reset when translating sub-expressions
The sequentiality business creates more nodes when used, and the
conditionalOperator business uses fewer temporary variables, so the
frontend results change quite a bit.
Note that biabduction tests were invaluable in debugging this. There
could be other constructs to adjust similarly to cxxNewExpr that were
not covered by the tests though.
Added tests in pulse that exercises the previous bug.
Reviewed By: da319
Differential Revision: D24796282
fbshipit-source-id: 0790c8d17
4 years ago
|
|
|
"test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_10" -> "test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_6" ;
|
|
|
|
"test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_11" [label="11: Call _fun_iterator::operator++ \n n$26=_fun_iterator::operator++(&__begin1:iterator&,&0$?%__sil_tmp__temp_return_n$25:iterator*) assign_last [line 35, column 18]\n " shape="box"]
|
|
|
|
|
|
|
|
|
[clang] fix bad interaction between ConditionalOperator and initializers
Summary:
This is several inter-connected changes together to keep the tests
happy.
The ConditionalOperator `b?t:e` is translated by first creating a
placeholder variable to temporarily store the result of the evaluation
in each branch, then the real thing we want to assign to reads that
variable. But, there are situations where that changes the semantics of
the expression, namely when the value created is a struct on the stack
(eg, a C++ temporary). This is because in SIL we cannot assign the
*address* of a program variable, only its contents, so by the time we're
out of the conditional operator we cannot set the struct value
correctly anymore: we can only set its content, which we did, but that
results in a "shifted" struct value that is one dereference away from
where it should be.
So a batch of changes concern `conditionalOperator_trans`:
- instead of systematically creating a temporary for the conditional,
use the `trans_state.var_exp_typ` provided from above if available
when translating `ConditionalOperator`
- don't even set anything if that variable was already initialized by
merely translating the branch expression, eg when it's a constructor
- fix long-standing TODO to propagate these initialization facts
accurately for ConditionalOperator (used by `init_expr_trans` to also
figure out if it should insert a store to the variable being
initialised or not)
The rest of the changes adapt some relevant other constructs to deal
with conditionalOperator properly now that it can set the current
variable itself, instead of storing stuff inside a temp variable. This
change was a problem because some constructs, eg a variable declaration,
will insert nodes that set up the variable before calling its
initialization, and now the initialization happens *before* that setup,
in the translation of the inner conditional operator, which naturally
creates nodes above the current one.
- add a generic helper to force a sequential order between two
translation results, forcing node creation if necessary
- use that in `init_expr_trans` and `cxxNewExpr_trans`
- adjust many places where `var_exp_typ` was incorrectly not reset when translating sub-expressions
The sequentiality business creates more nodes when used, and the
conditionalOperator business uses fewer temporary variables, so the
frontend results change quite a bit.
Note that biabduction tests were invaluable in debugging this. There
could be other constructs to adjust similarly to cxxNewExpr that were
not covered by the tests though.
Added tests in pulse that exercises the previous bug.
Reviewed By: da319
Differential Revision: D24796282
fbshipit-source-id: 0790c8d17
4 years ago
|
|
|
"test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_11" -> "test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_4" ;
|
|
|
|
"test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_12" [label="12: Call _fun_operator!= \n n$28=_fun_iterator::iterator(&0$?%__sil_tmp__temp_construct_n$27:iterator*,&__begin1:iterator&) [line 35, column 18]\n n$30=_fun_iterator::iterator(&0$?%__sil_tmp__temp_construct_n$29:iterator*,&__end1:iterator&) [line 35, column 18]\n n$31=_fun_operator!=(&0$?%__sil_tmp__temp_construct_n$27:iterator,&0$?%__sil_tmp__temp_construct_n$29:iterator) [line 35, column 18]\n " shape="box"]
|
|
|
|
|
|
|
|
|
[clang] fix bad interaction between ConditionalOperator and initializers
Summary:
This is several inter-connected changes together to keep the tests
happy.
The ConditionalOperator `b?t:e` is translated by first creating a
placeholder variable to temporarily store the result of the evaluation
in each branch, then the real thing we want to assign to reads that
variable. But, there are situations where that changes the semantics of
the expression, namely when the value created is a struct on the stack
(eg, a C++ temporary). This is because in SIL we cannot assign the
*address* of a program variable, only its contents, so by the time we're
out of the conditional operator we cannot set the struct value
correctly anymore: we can only set its content, which we did, but that
results in a "shifted" struct value that is one dereference away from
where it should be.
So a batch of changes concern `conditionalOperator_trans`:
- instead of systematically creating a temporary for the conditional,
use the `trans_state.var_exp_typ` provided from above if available
when translating `ConditionalOperator`
- don't even set anything if that variable was already initialized by
merely translating the branch expression, eg when it's a constructor
- fix long-standing TODO to propagate these initialization facts
accurately for ConditionalOperator (used by `init_expr_trans` to also
figure out if it should insert a store to the variable being
initialised or not)
The rest of the changes adapt some relevant other constructs to deal
with conditionalOperator properly now that it can set the current
variable itself, instead of storing stuff inside a temp variable. This
change was a problem because some constructs, eg a variable declaration,
will insert nodes that set up the variable before calling its
initialization, and now the initialization happens *before* that setup,
in the translation of the inner conditional operator, which naturally
creates nodes above the current one.
- add a generic helper to force a sequential order between two
translation results, forcing node creation if necessary
- use that in `init_expr_trans` and `cxxNewExpr_trans`
- adjust many places where `var_exp_typ` was incorrectly not reset when translating sub-expressions
The sequentiality business creates more nodes when used, and the
conditionalOperator business uses fewer temporary variables, so the
frontend results change quite a bit.
Note that biabduction tests were invaluable in debugging this. There
could be other constructs to adjust similarly to cxxNewExpr that were
not covered by the tests though.
Added tests in pulse that exercises the previous bug.
Reviewed By: da319
Differential Revision: D24796282
fbshipit-source-id: 0790c8d17
4 years ago
|
|
|
"test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_12" -> "test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_13" ;
|
|
|
|
"test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_12" -> "test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_14" ;
|
|
|
|
"test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_13" [label="13: Prune (true branch, for loop) \n PRUNE(n$31, true); [line 35, column 18]\n " shape="invhouse"]
|
|
|
|
|
|
|
|
|
[clang] fix bad interaction between ConditionalOperator and initializers
Summary:
This is several inter-connected changes together to keep the tests
happy.
The ConditionalOperator `b?t:e` is translated by first creating a
placeholder variable to temporarily store the result of the evaluation
in each branch, then the real thing we want to assign to reads that
variable. But, there are situations where that changes the semantics of
the expression, namely when the value created is a struct on the stack
(eg, a C++ temporary). This is because in SIL we cannot assign the
*address* of a program variable, only its contents, so by the time we're
out of the conditional operator we cannot set the struct value
correctly anymore: we can only set its content, which we did, but that
results in a "shifted" struct value that is one dereference away from
where it should be.
So a batch of changes concern `conditionalOperator_trans`:
- instead of systematically creating a temporary for the conditional,
use the `trans_state.var_exp_typ` provided from above if available
when translating `ConditionalOperator`
- don't even set anything if that variable was already initialized by
merely translating the branch expression, eg when it's a constructor
- fix long-standing TODO to propagate these initialization facts
accurately for ConditionalOperator (used by `init_expr_trans` to also
figure out if it should insert a store to the variable being
initialised or not)
The rest of the changes adapt some relevant other constructs to deal
with conditionalOperator properly now that it can set the current
variable itself, instead of storing stuff inside a temp variable. This
change was a problem because some constructs, eg a variable declaration,
will insert nodes that set up the variable before calling its
initialization, and now the initialization happens *before* that setup,
in the translation of the inner conditional operator, which naturally
creates nodes above the current one.
- add a generic helper to force a sequential order between two
translation results, forcing node creation if necessary
- use that in `init_expr_trans` and `cxxNewExpr_trans`
- adjust many places where `var_exp_typ` was incorrectly not reset when translating sub-expressions
The sequentiality business creates more nodes when used, and the
conditionalOperator business uses fewer temporary variables, so the
frontend results change quite a bit.
Note that biabduction tests were invaluable in debugging this. There
could be other constructs to adjust similarly to cxxNewExpr that were
not covered by the tests though.
Added tests in pulse that exercises the previous bug.
Reviewed By: da319
Differential Revision: D24796282
fbshipit-source-id: 0790c8d17
4 years ago
|
|
|
"test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_13" -> "test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_16" ;
|
|
|
|
"test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_14" [label="14: Prune (false branch, for loop) \n PRUNE(!n$31, false); [line 35, column 18]\n " shape="invhouse"]
|
|
|
|
|
|
|
|
|
[clang] fix bad interaction between ConditionalOperator and initializers
Summary:
This is several inter-connected changes together to keep the tests
happy.
The ConditionalOperator `b?t:e` is translated by first creating a
placeholder variable to temporarily store the result of the evaluation
in each branch, then the real thing we want to assign to reads that
variable. But, there are situations where that changes the semantics of
the expression, namely when the value created is a struct on the stack
(eg, a C++ temporary). This is because in SIL we cannot assign the
*address* of a program variable, only its contents, so by the time we're
out of the conditional operator we cannot set the struct value
correctly anymore: we can only set its content, which we did, but that
results in a "shifted" struct value that is one dereference away from
where it should be.
So a batch of changes concern `conditionalOperator_trans`:
- instead of systematically creating a temporary for the conditional,
use the `trans_state.var_exp_typ` provided from above if available
when translating `ConditionalOperator`
- don't even set anything if that variable was already initialized by
merely translating the branch expression, eg when it's a constructor
- fix long-standing TODO to propagate these initialization facts
accurately for ConditionalOperator (used by `init_expr_trans` to also
figure out if it should insert a store to the variable being
initialised or not)
The rest of the changes adapt some relevant other constructs to deal
with conditionalOperator properly now that it can set the current
variable itself, instead of storing stuff inside a temp variable. This
change was a problem because some constructs, eg a variable declaration,
will insert nodes that set up the variable before calling its
initialization, and now the initialization happens *before* that setup,
in the translation of the inner conditional operator, which naturally
creates nodes above the current one.
- add a generic helper to force a sequential order between two
translation results, forcing node creation if necessary
- use that in `init_expr_trans` and `cxxNewExpr_trans`
- adjust many places where `var_exp_typ` was incorrectly not reset when translating sub-expressions
The sequentiality business creates more nodes when used, and the
conditionalOperator business uses fewer temporary variables, so the
frontend results change quite a bit.
Note that biabduction tests were invaluable in debugging this. There
could be other constructs to adjust similarly to cxxNewExpr that were
not covered by the tests though.
Added tests in pulse that exercises the previous bug.
Reviewed By: da319
Differential Revision: D24796282
fbshipit-source-id: 0790c8d17
4 years ago
|
|
|
"test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_14" -> "test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_3" ;
|
|
|
|
"test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_15" [label="15: DeclStmt \n VARIABLE_DECLARED(temp:int); [line 36, column 5]\n n$32=*&value:int [line 36, column 16]\n n$33=*&value:int [line 36, column 24]\n *&temp:int=((n$32 * n$33) + 10) [line 36, column 5]\n " shape="box"]
|
|
|
|
|
|
|
|
|
|
|
|
"test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_15" -> "test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_11" ;
|
|
|
|
"test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_16" [label="16: DeclStmt \n VARIABLE_DECLARED(value:int); [line 35, column 8]\n n$35=_fun_iterator::operator*(&__begin1:iterator&) [line 35, column 18]\n *&value:int=n$35 [line 35, column 8]\n " shape="box"]
|
|
|
|
|
|
|
|
|
|
|
|
"test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_16" -> "test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_15" ;
|
|
|
|
"test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_17" [label="17: DeclStmt \n VARIABLE_DECLARED(__range1:vec&); [line 35, column 20]\n *&__range1:vec&=&vector [line 35, column 20]\n " shape="box"]
|
|
|
|
|
|
|
|
|
|
|
|
"test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_17" -> "test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_9" ;
|
|
|
|
"test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_18" [label="18: DeclStmt \n VARIABLE_DECLARED(vector:vec); [line 34, column 3]\n n$37=_fun_vec::vec(&vector:vec*,10:int) [line 34, column 7]\n " shape="box"]
|
|
|
|
|
|
|
|
|
|
|
|
"test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_18" -> "test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_17" ;
|
|
|
|
"operator++#iterator(class iterator)#(14034081864165661659).574423d3d3249b4f53477fb1be150024_1" [label="1: Start iterator::operator++\nFormals: this:iterator* __return_param:iterator*\nLocals: \n " color=yellow style=filled]
|
|
|
|
|
|
|
|
|
|
|
|
"operator++#iterator(class iterator)#(14034081864165661659).574423d3d3249b4f53477fb1be150024_1" -> "operator++#iterator(class iterator)#(14034081864165661659).574423d3d3249b4f53477fb1be150024_4" ;
|
|
|
|
"operator++#iterator(class iterator)#(14034081864165661659).574423d3d3249b4f53477fb1be150024_2" [label="2: Exit iterator::operator++ \n " color=yellow style=filled]
|
|
|
|
|
|
|
|
|
|
|
|
"operator++#iterator(class iterator)#(14034081864165661659).574423d3d3249b4f53477fb1be150024_3" [label="3: Return Stmt \n n$0=*&__return_param:iterator* [line 13, column 5]\n n$1=*&this:iterator* [line 13, column 13]\n n$2=_fun_iterator::iterator(n$0:iterator*,n$1:iterator&) [line 13, column 12]\n " shape="box"]
|
|
|
|
|
|
|
|
|
|
|
|
"operator++#iterator(class iterator)#(14034081864165661659).574423d3d3249b4f53477fb1be150024_3" -> "operator++#iterator(class iterator)#(14034081864165661659).574423d3d3249b4f53477fb1be150024_2" ;
|
|
|
|
"operator++#iterator(class iterator)#(14034081864165661659).574423d3d3249b4f53477fb1be150024_4" [label="4: BinaryOperatorStmt: AddAssign \n n$3=*&this:iterator* [line 12, column 5]\n n$4=*n$3.val:int [line 12, column 5]\n *n$3.val:int=(n$4 + 1) [line 12, column 5]\n " shape="box"]
|
|
|
|
|
|
|
|
|
|
|
|
"operator++#iterator(class iterator)#(14034081864165661659).574423d3d3249b4f53477fb1be150024_4" -> "operator++#iterator(class iterator)#(14034081864165661659).574423d3d3249b4f53477fb1be150024_3" ;
|
|
|
|
"operator*#iterator#(14296957122470685412).e3f593369544fc43a253ad1e4f5ed136_1" [label="1: Start iterator::operator*\nFormals: this:iterator*\nLocals: \n " color=yellow style=filled]
|
|
|
|
|
|
|
|
|
|
|
|
"operator*#iterator#(14296957122470685412).e3f593369544fc43a253ad1e4f5ed136_1" -> "operator*#iterator#(14296957122470685412).e3f593369544fc43a253ad1e4f5ed136_3" ;
|
|
|
|
"operator*#iterator#(14296957122470685412).e3f593369544fc43a253ad1e4f5ed136_2" [label="2: Exit iterator::operator* \n " color=yellow style=filled]
|
|
|
|
|
|
|
|
|
|
|
|
"operator*#iterator#(14296957122470685412).e3f593369544fc43a253ad1e4f5ed136_3" [label="3: Return Stmt \n n$0=*&this:iterator* [line 16, column 12]\n n$1=*n$0.val:int [line 16, column 12]\n *&return:int=n$1 [line 16, column 5]\n " shape="box"]
|
|
|
|
|
|
|
|
|
|
|
|
"operator*#iterator#(14296957122470685412).e3f593369544fc43a253ad1e4f5ed136_3" -> "operator*#iterator#(14296957122470685412).e3f593369544fc43a253ad1e4f5ed136_2" ;
|
|
|
|
"iterator#iterator#{11413353760466671846|constexpr}.a278508d3bccc69caf1a1db6246cf788_1" [label="1: Start iterator::iterator\nFormals: this:iterator* __param_0:iterator const &\nLocals: \n " color=yellow style=filled]
|
|
|
|
|
|
|
|
|
|
|
|
"iterator#iterator#{11413353760466671846|constexpr}.a278508d3bccc69caf1a1db6246cf788_1" -> "iterator#iterator#{11413353760466671846|constexpr}.a278508d3bccc69caf1a1db6246cf788_3" ;
|
|
|
|
"iterator#iterator#{11413353760466671846|constexpr}.a278508d3bccc69caf1a1db6246cf788_2" [label="2: Exit iterator::iterator \n " color=yellow style=filled]
|
|
|
|
|
|
|
|
|
|
|
|
"iterator#iterator#{11413353760466671846|constexpr}.a278508d3bccc69caf1a1db6246cf788_3" [label="3: Constructor Init \n n$1=*&this:iterator* [line 9, column 8]\n n$2=*&__param_0:iterator const & [line 9, column 8]\n n$3=*n$2.val:int [line 9, column 8]\n *n$1.val:int=n$3 [line 9, column 8]\n " shape="box"]
|
|
|
|
|
|
|
|
|
|
|
|
"iterator#iterator#{11413353760466671846|constexpr}.a278508d3bccc69caf1a1db6246cf788_3" -> "iterator#iterator#{11413353760466671846|constexpr}.a278508d3bccc69caf1a1db6246cf788_2" ;
|
|
|
|
"iterator#iterator#{17107199916075329459}.2fc51ac860d26e778b9b34e5032f02d5_1" [label="1: Start iterator::iterator\nFormals: this:iterator*\nLocals: \n " color=yellow style=filled]
|
|
|
|
|
|
|
|
|
|
|
|
"iterator#iterator#{17107199916075329459}.2fc51ac860d26e778b9b34e5032f02d5_1" -> "iterator#iterator#{17107199916075329459}.2fc51ac860d26e778b9b34e5032f02d5_2" ;
|
|
|
|
"iterator#iterator#{17107199916075329459}.2fc51ac860d26e778b9b34e5032f02d5_2" [label="2: Exit iterator::iterator \n " color=yellow style=filled]
|
|
|
|
|
|
|
|
|
|
|
|
"iterator#iterator#{3083368405611515834|constexpr}.86fcbefb2af88c097bfa7e085c4b4f40_1" [label="1: Start iterator::iterator\nFormals: this:iterator* __param_0:iterator&\nLocals: \n " color=yellow style=filled]
|
|
|
|
|
|
|
|
|
|
|
|
"iterator#iterator#{3083368405611515834|constexpr}.86fcbefb2af88c097bfa7e085c4b4f40_1" -> "iterator#iterator#{3083368405611515834|constexpr}.86fcbefb2af88c097bfa7e085c4b4f40_3" ;
|
|
|
|
"iterator#iterator#{3083368405611515834|constexpr}.86fcbefb2af88c097bfa7e085c4b4f40_2" [label="2: Exit iterator::iterator \n " color=yellow style=filled]
|
|
|
|
|
|
|
|
|
|
|
|
"iterator#iterator#{3083368405611515834|constexpr}.86fcbefb2af88c097bfa7e085c4b4f40_3" [label="3: Constructor Init \n n$1=*&this:iterator* [line 9, column 8]\n n$2=*&__param_0:iterator& [line 9, column 8]\n n$3=*n$2.val:int [line 9, column 8]\n *n$1.val:int=n$3 [line 9, column 8]\n " shape="box"]
|
|
|
|
|
|
|
|
|
|
|
|
"iterator#iterator#{3083368405611515834|constexpr}.86fcbefb2af88c097bfa7e085c4b4f40_3" -> "iterator#iterator#{3083368405611515834|constexpr}.86fcbefb2af88c097bfa7e085c4b4f40_2" ;
|
|
|
|
"end#vec(class iterator)#(14240882620331653738).aed9da65654959634fd17d4511cfa44d_1" [label="1: Start vec::end\nFormals: this:vec* __return_param:iterator*\nLocals: \n " color=yellow style=filled]
|
|
|
|
|
|
|
|
|
|
|
|
"end#vec(class iterator)#(14240882620331653738).aed9da65654959634fd17d4511cfa44d_1" -> "end#vec(class iterator)#(14240882620331653738).aed9da65654959634fd17d4511cfa44d_3" ;
|
|
|
|
"end#vec(class iterator)#(14240882620331653738).aed9da65654959634fd17d4511cfa44d_2" [label="2: Exit vec::end \n " color=yellow style=filled]
|
|
|
|
|
|
|
|
|
|
|
|
"end#vec(class iterator)#(14240882620331653738).aed9da65654959634fd17d4511cfa44d_3" [label="3: Return Stmt \n n$0=*&__return_param:iterator* [line 27, column 20]\n n$1=*&this:vec* [line 27, column 27]\n n$2=_fun_iterator::iterator(n$0:iterator*,n$1.end_:iterator&) [line 27, column 27]\n " shape="box"]
|
|
|
|
|
|
|
|
|
|
|
|
"end#vec(class iterator)#(14240882620331653738).aed9da65654959634fd17d4511cfa44d_3" -> "end#vec(class iterator)#(14240882620331653738).aed9da65654959634fd17d4511cfa44d_2" ;
|
|
|
|
"begin#vec(class iterator)#(1866137161906470488).407edea568a869b61c9e5e8424e0b5f7_1" [label="1: Start vec::begin\nFormals: this:vec* __return_param:iterator*\nLocals: \n " color=yellow style=filled]
|
|
|
|
|
|
|
|
|
|
|
|
"begin#vec(class iterator)#(1866137161906470488).407edea568a869b61c9e5e8424e0b5f7_1" -> "begin#vec(class iterator)#(1866137161906470488).407edea568a869b61c9e5e8424e0b5f7_3" ;
|
|
|
|
"begin#vec(class iterator)#(1866137161906470488).407edea568a869b61c9e5e8424e0b5f7_2" [label="2: Exit vec::begin \n " color=yellow style=filled]
|
|
|
|
|
|
|
|
|
|
|
|
"begin#vec(class iterator)#(1866137161906470488).407edea568a869b61c9e5e8424e0b5f7_3" [label="3: Return Stmt \n n$0=*&__return_param:iterator* [line 26, column 22]\n n$1=*&this:vec* [line 26, column 29]\n n$2=_fun_iterator::iterator(n$0:iterator*,n$1.begin_:iterator&) [line 26, column 29]\n " shape="box"]
|
|
|
|
|
|
|
|
|
|
|
|
"begin#vec(class iterator)#(1866137161906470488).407edea568a869b61c9e5e8424e0b5f7_3" -> "begin#vec(class iterator)#(1866137161906470488).407edea568a869b61c9e5e8424e0b5f7_2" ;
|
|
|
|
"vec#vec#{13876720186060950809}.c3c9a518fcec87e97d6b52a59f13d428_1" [label="1: Start vec::vec\nFormals: this:vec* size:int\nLocals: \n " color=yellow style=filled]
|
|
|
|
|
|
|
|
|
|
|
|
"vec#vec#{13876720186060950809}.c3c9a518fcec87e97d6b52a59f13d428_1" -> "vec#vec#{13876720186060950809}.c3c9a518fcec87e97d6b52a59f13d428_6" ;
|
|
|
|
"vec#vec#{13876720186060950809}.c3c9a518fcec87e97d6b52a59f13d428_2" [label="2: Exit vec::vec \n " color=yellow style=filled]
|
|
|
|
|
|
|
|
|
|
|
|
"vec#vec#{13876720186060950809}.c3c9a518fcec87e97d6b52a59f13d428_3" [label="3: BinaryOperatorStmt: Assign \n n$0=*&this:vec* [line 24, column 5]\n n$1=*&size:int [line 24, column 16]\n *n$0.end_.val:int=n$1 [line 24, column 5]\n " shape="box"]
|
|
|
|
|
|
|
|
|
|
|
|
"vec#vec#{13876720186060950809}.c3c9a518fcec87e97d6b52a59f13d428_3" -> "vec#vec#{13876720186060950809}.c3c9a518fcec87e97d6b52a59f13d428_2" ;
|
|
|
|
"vec#vec#{13876720186060950809}.c3c9a518fcec87e97d6b52a59f13d428_4" [label="4: BinaryOperatorStmt: Assign \n n$2=*&this:vec* [line 23, column 5]\n *n$2.begin_.val:int=0 [line 23, column 5]\n " shape="box"]
|
|
|
|
|
|
|
|
|
|
|
|
"vec#vec#{13876720186060950809}.c3c9a518fcec87e97d6b52a59f13d428_4" -> "vec#vec#{13876720186060950809}.c3c9a518fcec87e97d6b52a59f13d428_3" ;
|
|
|
|
"vec#vec#{13876720186060950809}.c3c9a518fcec87e97d6b52a59f13d428_5" [label="5: Constructor Init \n n$3=*&this:vec* [line 22, column 3]\n n$4=_fun_iterator::iterator(n$3.end_:iterator*) [line 22, column 3]\n " shape="box"]
|
|
|
|
|
|
|
|
|
|
|
|
"vec#vec#{13876720186060950809}.c3c9a518fcec87e97d6b52a59f13d428_5" -> "vec#vec#{13876720186060950809}.c3c9a518fcec87e97d6b52a59f13d428_4" ;
|
|
|
|
"vec#vec#{13876720186060950809}.c3c9a518fcec87e97d6b52a59f13d428_6" [label="6: Constructor Init \n n$5=*&this:vec* [line 22, column 3]\n n$6=_fun_iterator::iterator(n$5.begin_:iterator*) [line 22, column 3]\n " shape="box"]
|
|
|
|
|
|
|
|
|
|
|
|
"vec#vec#{13876720186060950809}.c3c9a518fcec87e97d6b52a59f13d428_6" -> "vec#vec#{13876720186060950809}.c3c9a518fcec87e97d6b52a59f13d428_5" ;
|
|
|
|
}
|