{
systemtap_session& session;
bool& relaxed_p;
-
- const_folder(systemtap_session& s, bool& r):
- session(s), relaxed_p(r), last_number(0), last_string(0) {}
+ bool collapse_defines_p;
+
+ const_folder(systemtap_session& s, bool& r, bool collapse_defines = false):
+ session(s), relaxed_p(r), collapse_defines_p(collapse_defines), last_number(0), last_string(0) {}
literal_number* last_number;
literal_number* get_number(expression*& e);
void
const_folder::visit_defined_op (defined_op* e)
{
- // If a @defined makes it this far, then it is, de facto, undefined.
-
- if (session.verbose>2)
- clog << _("Collapsing untouched @defined check ") << *e->tok << endl;
- relaxed_p = false;
+ // If a @defined makes it this far, then it was not resolved by
+ // previous efforts. We could assume that therefore it is a big fat
+ // zero, but for the @defined(autocast) case PR18079, this just
+ // means that we didn't know yet.
- literal_number* n = new literal_number (0);
- n->tok = e->tok;
- n->visit (this);
+ if (collapse_defines_p)
+ {
+ if (session.verbose>2)
+ clog << _("Collapsing untouched @defined check ") << *e->tok << endl;
+ relaxed_p = false;
+ literal_number* n = new literal_number (0);
+ n->tok = e->tok;
+ n->visit (this);
+ }
+ else
+ {
+ if (session.verbose>2)
+ clog << _("Preserving unresolved @defined check ") << *e->tok << endl;
+ provide (e);
+ }
}
void
ti.current_probe = 0;
ti.current_function = fd;
ti.t = pe_unknown;
+
+ if (ti.assert_resolvability)
+ {
+ // PR18079, rerun the const-folder / dead-block-remover
+ // one last time, in case an unresolvable
+ // @defined($foobar) still persists. This should map
+ // those to 0.
+ bool relaxed_p;
+ const_folder cf (s, relaxed_p, true); // NB: true
+ cf.replace (fd->body);
+ dead_control_remover dc (s, relaxed_p);
+ fd->body->visit (&dc);
+ (void) relaxed_p; // we judge success later by num_still_unresolved, not this flag
+ }
+
fd->body->visit (& ti);
// NB: we don't have to assert a known type for
// functions here, to permit a "void" function.
{
autocast_expanding_visitor aev (ti);
aev.replace (fd->body);
+
+ // PR18079, rerun the const-folder / dead-block-remover
+ // in case autocast evaluation enabled a @defined()
+ bool relaxed_p;
+ const_folder cf (s, relaxed_p);
+ cf.replace (fd->body);
+ dead_control_remover dc (s, relaxed_p);
+ fd->body->visit (&dc);
+ (void) relaxed_p; // we judge success later by num_still_unresolved, not this flag
+
ti.num_available_autocasts = 0;
}
}
ti.current_function = 0;
ti.current_probe = pn;
ti.t = pe_unknown;
+
+ if (ti.assert_resolvability)
+ {
+ // PR18079, rerun the const-folder / dead-block-remover
+ // one last time, in case an unresolvable
+ // @defined($foobar) still persists. This should map
+ // those to 0.
+ bool relaxed_p;
+ const_folder cf (s, relaxed_p, true); // NB: true
+ cf.replace (pn->body);
+ dead_control_remover dc (s, relaxed_p);
+ pn->body->visit (&dc);
+ (void) relaxed_p; // we judge success later by num_still_unresolved, not this flag
+ }
+
pn->body->visit (& ti);
for (unsigned i=0; i < pn->locals.size(); ++i)
ti.check_local (pn->locals[i]);
{
autocast_expanding_visitor aev (ti);
aev.replace (pn->body);
+
+ // PR18079, rerun the const-folder / dead-block-remover
+ // in case autocast evaluation enabled a @defined()
+ bool relaxed_p;
+ const_folder cf (s, relaxed_p);
+ cf.replace (pn->body);
+ dead_control_remover dc (s, relaxed_p);
+ pn->body->visit (&dc);
+ (void) relaxed_p; // we judge success later by num_still_unresolved, not this flag
+
ti.num_available_autocasts = 0;
}
// later unused-expression-elimination pass didn't get rid of it
// either. So we have a target symbol that is believed to be of
// genuine use, yet unresolved by the provider.
-
+ //
+ // PR18079, or it can happen if a $target expression is nested within
+ // a @defined() test that has not yet been resolved (but can be soon).
+ if (! assert_resolvability)
+ {
+ num_still_unresolved ++;
+ return;
+ }
+
if (session.verbose > 2)
{
clog << _("Resolution problem with ");
void
typeresolution_info::visit_defined_op (defined_op* e)
{
- throw SEMANTIC_ERROR(_("unexpected @defined"), e->tok);
+ // PR18079: if a @defined is still around, it may have a parameter that
+ // wasn't resolvable one way or another earlier. Maybe an autocast_op.
+ // Let's give it a visit just in case.
+ e->operand->visit(this);
+
+ if (assert_resolvability)
+ throw SEMANTIC_ERROR(_("unexpected @defined"), e->tok);
+ else
+ num_still_unresolved ++;
}