LCOV - code coverage report
Current view: top level - mnt/wasteland/wcohen/systemtap_write/systemtap - elaborate.cxx (source / functions) Hit Total Coverage
Test: stap.info Lines: 2279 2542 89.7 %
Date: 2013-03-08 Functions: 214 242 88.4 %
Branches: 2677 4676 57.2 %

           Branch data     Line data    Source code
       1                 :            : // elaboration functions
       2                 :            : // Copyright (C) 2005-2013 Red Hat Inc.
       3                 :            : // Copyright (C) 2008 Intel Corporation
       4                 :            : //
       5                 :            : // This file is part of systemtap, and is free software.  You can
       6                 :            : // redistribute it and/or modify it under the terms of the GNU General
       7                 :            : // Public License (GPL); either version 2, or (at your option) any
       8                 :            : // later version.
       9                 :            : 
      10                 :            : #include "config.h"
      11                 :            : #include "elaborate.h"
      12                 :            : #include "translate.h"
      13                 :            : #include "parse.h"
      14                 :            : #include "tapsets.h"
      15                 :            : #include "session.h"
      16                 :            : #include "util.h"
      17                 :            : #include "task_finder.h"
      18                 :            : 
      19                 :            : #include "re2c-migrate/stapregex.h"
      20                 :            : 
      21                 :            : extern "C" {
      22                 :            : #include <sys/utsname.h>
      23                 :            : #include <fnmatch.h>
      24                 :            : #define __STDC_FORMAT_MACROS
      25                 :            : #include <inttypes.h>
      26                 :            : }
      27                 :            : 
      28                 :            : #include <algorithm>
      29                 :            : #include <fstream>
      30                 :            : #include <map>
      31                 :            : #include <cassert>
      32                 :            : #include <set>
      33                 :            : #include <vector>
      34                 :            : #include <algorithm>
      35                 :            : #include <iterator>
      36                 :            : #include <climits>
      37                 :            : 
      38                 :            : 
      39                 :            : using namespace std;
      40                 :            : 
      41                 :            : 
      42                 :            : // ------------------------------------------------------------------------
      43                 :            : 
      44                 :            : // Used in probe_point condition construction.  Either argument may be
      45                 :            : // NULL; if both, return NULL too.  Resulting expression is a deep
      46                 :            : // copy for symbol resolution purposes.
      47                 :      87714 : expression* add_condition (expression* a, expression* b)
      48                 :            : {
      49 [ +  + ][ +  + ]:      87714 :   if (!a && !b) return 0;
      50 [ +  + ][ +  - ]:         11 :   if (! a) return deep_copy_visitor::deep_copy(b);
      51 [ -  + ][ #  # ]:         10 :   if (! b) return deep_copy_visitor::deep_copy(a);
      52         [ +  - ]:         10 :   logical_and_expr la;
      53         [ +  - ]:         10 :   la.op = "&&";
      54                 :         10 :   la.left = a;
      55                 :         10 :   la.right = b;
      56                 :         10 :   la.tok = a->tok; // or could be b->tok
      57 [ +  - ][ +  - ]:      87714 :   return deep_copy_visitor::deep_copy(& la);
      58                 :            : }
      59                 :            : 
      60                 :            : // ------------------------------------------------------------------------
      61                 :            : 
      62                 :            : 
      63                 :            : 
      64                 :     419227 : derived_probe::derived_probe (probe *p, probe_point *l, bool rewrite_loc):
      65         [ +  - ]:     419227 :   base (p), base_pp(l), sdt_semaphore_addr(0), session_index((unsigned)-1)
      66                 :            : {
      67         [ -  + ]:     419227 :   assert (p);
      68                 :     419227 :   this->tok = p->tok;
      69                 :     419227 :   this->privileged = p->privileged;
      70         [ +  - ]:     419227 :   this->body = deep_copy_visitor::deep_copy(p->body);
      71                 :            : 
      72         [ -  + ]:     419227 :   assert (l);
      73                 :            :   // make a copy for subclasses which want to rewrite the location
      74         [ +  + ]:     419227 :   if (rewrite_loc)
      75 [ +  - ][ +  - ]:     353567 :     l = new probe_point(*l);
      76         [ +  - ]:     419227 :   this->locations.push_back (l);
      77                 :     419227 : }
      78                 :            : 
      79                 :            : 
      80                 :            : void
      81                 :      56343 : derived_probe::printsig (ostream& o) const
      82                 :            : {
      83                 :      56343 :   probe::printsig (o);
      84                 :      56343 :   printsig_nested (o);
      85                 :      56343 : }
      86                 :            : 
      87                 :            : void
      88                 :     394204 : derived_probe::printsig_nested (ostream& o) const
      89                 :            : {
      90                 :            :   // We'd like to enclose the probe derivation chain in a /* */
      91                 :            :   // comment delimiter.  But just printing /* base->printsig() */ is
      92                 :            :   // not enough, since base might itself be a derived_probe.  So we,
      93                 :            :   // er, "cleverly" encode our nesting state as a formatting flag for
      94                 :            :   // the ostream.
      95                 :     394204 :   ios::fmtflags f = o.flags (ios::internal);
      96         [ +  + ]:     394204 :   if (f & ios::internal)
      97                 :            :     {
      98                 :            :       // already nested
      99                 :      52421 :       o << " <- ";
     100                 :      52421 :       base->printsig (o);
     101                 :            :     }
     102                 :            :   else
     103                 :            :     {
     104                 :            :       // outermost nesting
     105                 :     341783 :       o << " /* <- ";
     106                 :     341783 :       base->printsig (o);
     107                 :     341783 :       o << " */";
     108                 :            :     }
     109                 :            :   // restore flags
     110                 :     394204 :   (void) o.flags (f);
     111                 :     394204 : }
     112                 :            : 
     113                 :            : 
     114                 :            : void
     115                 :      14886 : derived_probe::collect_derivation_chain (std::vector<probe*> &probes_list)
     116                 :            : {
     117         [ +  - ]:      14886 :   probes_list.push_back(this);
     118                 :      14886 :   base->collect_derivation_chain(probes_list);
     119                 :      14886 : }
     120                 :            : 
     121                 :            : 
     122                 :            : void
     123                 :      54400 : derived_probe::collect_derivation_pp_chain (std::vector<probe_point*> &pp_list)
     124                 :            : {
     125                 :      54400 :   pp_list.push_back(base_pp);
     126                 :      54400 :   base->collect_derivation_pp_chain(pp_list);
     127                 :      54400 : }
     128                 :            : 
     129                 :            : 
     130                 :            : string
     131                 :      33720 : derived_probe::derived_locations ()
     132                 :            : {
     133         [ +  - ]:      33720 :   ostringstream o;
     134         [ +  - ]:      33720 :   vector<probe_point*> reference_point;
     135         [ +  - ]:      33720 :   collect_derivation_pp_chain(reference_point);
     136         [ +  + ]:      88120 :   for(unsigned i=0; i<reference_point.size(); ++i)
     137 [ +  - ][ +  - ]:      54400 :     o << " from: " << reference_point[i]->str(false); // no ?,!,etc
         [ +  - ][ +  - ]
     138 [ +  - ][ +  - ]:      33720 :   return o.str();
                 [ +  - ]
     139                 :            : }
     140                 :            : 
     141                 :            : 
     142                 :            : probe_point*
     143                 :    3765988 : derived_probe::sole_location () const
     144                 :            : {
     145 [ +  - ][ -  + ]:    3765988 :   if (locations.size() == 0 || locations.size() > 1)
                 [ -  + ]
     146                 :            :     throw semantic_error (ngettext("derived_probe with no locations",
     147                 :            :                                    "derived_probe with no locations",
     148 [ #  # ][ #  # ]:          0 :                                    locations.size()), this->tok);
     149                 :            :   else
     150                 :    3765988 :     return locations[0];
     151                 :            : }
     152                 :            : 
     153                 :            : 
     154                 :            : probe_point*
     155                 :      33720 : derived_probe::script_location () const
     156                 :            : {
     157                 :            :   // XXX PR14297 make this more accurate wrt complex wildcard expansions
     158                 :      33720 :   const probe* p = almost_basest();
     159                 :      33720 :   probe_point *a = p->get_alias_loc();
     160         [ +  + ]:      33720 :   if (a) return a;
     161                 :      14962 :   const vector<probe_point*>& locs = p->locations;
     162 [ +  - ][ -  + ]:      14962 :   if (locs.size() == 0 || locs.size() > 1)
                 [ -  + ]
     163                 :            :     throw semantic_error (ngettext("derived_probe with no locations",
     164                 :            :                                    "derived_probe with too many locations",
     165 [ #  # ][ #  # ]:          0 :                                    locs.size()), this->tok);
     166                 :            :   else
     167                 :      33720 :     return locs[0];
     168                 :            : }
     169                 :            : 
     170                 :            : 
     171                 :            : void
     172                 :       7541 : derived_probe::emit_privilege_assertion (translator_output* o)
     173                 :            : {
     174                 :            :   // Emit code which will cause compilation to fail if it is compiled in
     175                 :            :   // unprivileged mode.
     176                 :       7541 :   o->newline() << "#if ! STP_PRIVILEGE_CONTAINS (STP_PRIVILEGE, STP_PR_STAPDEV) && \\";
     177                 :       7541 :   o->newline() << "    ! STP_PRIVILEGE_CONTAINS (STP_PRIVILEGE, STP_PR_STAPSYS)";
     178                 :       7541 :   o->newline() << "#error Internal Error: Probe ";
     179                 :       7541 :   probe::printsig (o->line());
     180                 :       7541 :   o->line()    << " generated in --unprivileged mode";
     181                 :       7541 :   o->newline() << "#endif";
     182                 :       7541 : }
     183                 :            : 
     184                 :            : 
     185                 :            : void
     186                 :         10 : derived_probe::emit_process_owner_assertion (translator_output* o)
     187                 :            : {
     188                 :            :   // Emit code which will abort should the current target not belong to the
     189                 :            :   // user in unprivileged mode.
     190                 :         10 :   o->newline() << "#if ! STP_PRIVILEGE_CONTAINS (STP_PRIVILEGE, STP_PR_STAPDEV) && \\";
     191                 :         10 :   o->newline() << "    ! STP_PRIVILEGE_CONTAINS (STP_PRIVILEGE, STP_PR_STAPSYS)";
     192                 :         10 :   o->newline(1)  << "if (! is_myproc ()) {";
     193                 :         10 :   o->newline(1)  << "snprintf(c->error_buffer, sizeof(c->error_buffer),";
     194                 :         10 :   o->newline()   << "         \"Internal Error: Process %d does not belong to user %d in probe %s in --unprivileged mode\",";
     195                 :         10 :   o->newline()   << "         current->tgid, _stp_uid, c->probe_point);";
     196                 :         10 :   o->newline()   << "c->last_error = c->error_buffer;";
     197                 :            :   // NB: since this check occurs before probe locking, its exit should
     198                 :            :   // not be a "goto out", which would attempt unlocking.
     199                 :         10 :   o->newline()   << "return;";
     200                 :         10 :   o->newline(-1) << "}";
     201                 :         10 :   o->newline(-1) << "#endif";
     202                 :         10 : }
     203                 :            : 
     204                 :            : void
     205                 :       3368 : derived_probe::print_dupe_stamp_unprivileged(ostream& o)
     206                 :            : {
     207                 :       3368 :   o << _("unprivileged users: authorized") << endl;
     208                 :       3368 : }
     209                 :            : 
     210                 :            : void
     211                 :         20 : derived_probe::print_dupe_stamp_unprivileged_process_owner(ostream& o)
     212                 :            : {
     213                 :         20 :   o << _("unprivileged users: authorized for process owner") << endl;
     214                 :         20 : }
     215                 :            : 
     216                 :            : // ------------------------------------------------------------------------
     217                 :            : // Members of derived_probe_builder
     218                 :            : 
     219                 :            : void
     220                 :      17286 : derived_probe_builder::build_with_suffix(systemtap_session & sess,
     221                 :            :                                          probe * use,
     222                 :            :                                          probe_point * location,
     223                 :            :                                          std::map<std::string, literal *>
     224                 :            :                                            const & parameters,
     225                 :            :                                          std::vector<derived_probe *>
     226                 :            :                                            & finished_results,
     227                 :            :                                          std::vector<probe_point::component *>
     228                 :            :                                            const & suffix) {
     229                 :            :   // XXX perhaps build the probe if suffix is empty?
     230                 :            :   // if (suffix.empty()) {
     231                 :            :   //   build (sess, use, location, parameters, finished_results);
     232                 :            :   //   return;
     233                 :            :   // }
     234 [ +  - ][ +  - ]:      17286 :   throw semantic_error (_("invalid suffix for probe"));
     235                 :            : }
     236                 :            : 
     237                 :            : bool
     238                 :     498184 : derived_probe_builder::get_param (std::map<std::string, literal*> const & params,
     239                 :            :                                   const std::string& key,
     240                 :            :                                   std::string& value)
     241                 :            : {
     242         [ +  - ]:     498184 :   map<string, literal *>::const_iterator i = params.find (key);
     243 [ +  - ][ +  + ]:     498184 :   if (i == params.end())
     244                 :     414861 :     return false;
     245 [ +  - ][ +  + ]:      83323 :   literal_string * ls = dynamic_cast<literal_string *>(i->second);
     246         [ +  + ]:      83323 :   if (!ls)
     247                 :        109 :     return false;
     248         [ +  - ]:      83214 :   value = ls->value;
     249                 :     498184 :   return true;
     250                 :            : }
     251                 :            : 
     252                 :            : 
     253                 :            : bool
     254                 :     251771 : derived_probe_builder::get_param (std::map<std::string, literal*> const & params,
     255                 :            :                                   const std::string& key,
     256                 :            :                                   int64_t& value)
     257                 :            : {
     258         [ +  - ]:     251771 :   map<string, literal *>::const_iterator i = params.find (key);
     259 [ +  - ][ +  + ]:     251771 :   if (i == params.end())
     260                 :     202332 :     return false;
     261 [ +  - ][ +  + ]:      49439 :   if (i->second == NULL)
     262                 :       1878 :     return false;
     263 [ +  - ][ -  + ]:      47561 :   literal_number * ln = dynamic_cast<literal_number *>(i->second);
     264         [ +  + ]:      47561 :   if (!ln)
     265                 :      46870 :     return false;
     266                 :        691 :   value = ln->value;
     267                 :     251771 :   return true;
     268                 :            : }
     269                 :            : 
     270                 :            : 
     271                 :            : bool
     272                 :     436745 : derived_probe_builder::has_null_param (std::map<std::string, literal*> const & params,
     273                 :            :                                        const std::string& key)
     274                 :            : {
     275         [ +  - ]:     436745 :   map<string, literal *>::const_iterator i = params.find(key);
     276 [ +  - ][ +  + ]:     436745 :   return (i != params.end() && i->second == NULL);
         [ +  - ][ +  + ]
         [ +  - ][ #  # ]
     277                 :            : }
     278                 :            : 
     279                 :            : 
     280                 :            : 
     281                 :            : // ------------------------------------------------------------------------
     282                 :            : // Members of match_key.
     283                 :            : 
     284                 :    6946908 : match_key::match_key(string const & n)
     285                 :            :   : name(n),
     286                 :            :     have_parameter(false),
     287                 :    6946908 :     parameter_type(pe_unknown)
     288                 :            : {
     289                 :    6946908 : }
     290                 :            : 
     291                 :     291198 : match_key::match_key(probe_point::component const & c)
     292                 :            :   : name(c.functor),
     293                 :            :     have_parameter(c.arg != NULL),
     294         [ +  + ]:     291198 :     parameter_type(c.arg ? c.arg->type : pe_unknown)
     295                 :            : {
     296                 :     291198 : }
     297                 :            : 
     298                 :            : match_key &
     299                 :     103530 : match_key::with_number()
     300                 :            : {
     301                 :     103530 :   have_parameter = true;
     302                 :     103530 :   parameter_type = pe_long;
     303                 :     103530 :   return *this;
     304                 :            : }
     305                 :            : 
     306                 :            : match_key &
     307                 :     101094 : match_key::with_string()
     308                 :            : {
     309                 :     101094 :   have_parameter = true;
     310                 :     101094 :   parameter_type = pe_string;
     311                 :     101094 :   return *this;
     312                 :            : }
     313                 :            : 
     314                 :            : string
     315                 :       3289 : match_key::str() const
     316                 :            : {
     317         [ +  + ]:       3289 :   if (have_parameter)
     318      [ +  +  - ]:        116 :     switch (parameter_type)
     319                 :            :       {
     320                 :         52 :       case pe_string: return name + "(string)";
     321                 :         64 :       case pe_long: return name + "(number)";
     322                 :          0 :       default: return name + "(...)";
     323                 :            :       }
     324                 :       3289 :   return name;
     325                 :            : }
     326                 :            : 
     327                 :            : bool
     328                 :   55762088 : match_key::operator<(match_key const & other) const
     329                 :            : {
     330                 :   55762088 :   return ((name < other.name)
     331                 :            : 
     332                 :   24447423 :           || (name == other.name
     333                 :            :               && have_parameter < other.have_parameter)
     334                 :            : 
     335                 :   24403419 :           || (name == other.name
     336                 :            :               && have_parameter == other.have_parameter
     337   [ +  +  +  + ]:  104612930 :               && parameter_type < other.parameter_type));
           [ +  +  +  + ]
         [ +  + ][ +  + ]
     338                 :            : }
     339                 :            : 
     340                 :            : 
     341                 :            : // NB: these are only used in the probe point name components, where
     342                 :            : // only "*" is permitted.
     343                 :            : //
     344                 :            : // Within module("bar"), function("foo"), process("baz") strings, real
     345                 :            : // wildcards are permitted too. See also util.h:contains_glob_chars
     346                 :            : 
     347                 :            : static bool
     348                 :     291198 : isglob(string const & str)
     349                 :            : {
     350                 :     291198 :   return(str.find('*') != str.npos);
     351                 :            : }
     352                 :            : 
     353                 :            : static bool
     354                 :     296923 : isdoubleglob(string const & str)
     355                 :            : {
     356                 :     296923 :   return(str.find("**") != str.npos);
     357                 :            : }
     358                 :            : 
     359                 :            : bool
     360                 :      73012 : match_key::globmatch(match_key const & other) const
     361                 :            : {
     362                 :      73012 :   const char *other_str = other.name.c_str();
     363                 :      73012 :   const char *name_str = name.c_str();
     364                 :            : 
     365                 :      73012 :   return ((fnmatch(name_str, other_str, FNM_NOESCAPE) == 0)
     366                 :            :           && have_parameter == other.have_parameter
     367 [ +  + ][ +  + ]:      73012 :           && parameter_type == other.parameter_type);
                 [ +  + ]
     368                 :            : }
     369                 :            : 
     370                 :            : // ------------------------------------------------------------------------
     371                 :            : // Members of match_node
     372                 :            : // ------------------------------------------------------------------------
     373                 :            : 
     374                 :    2857761 : match_node::match_node() :
     375         [ +  - ]:    2857761 :   privilege(privilege_t (pr_stapdev | pr_stapsys))
     376                 :            : {
     377                 :    2857761 : }
     378                 :            : 
     379                 :            : match_node *
     380                 :    6946908 : match_node::bind(match_key const & k)
     381                 :            : {
     382 [ +  - ][ +  + ]:    6946908 :   if (k.name == "*")
     383 [ +  - ][ +  - ]:          1 :     throw semantic_error(_("invalid use of wildcard probe point component"));
     384                 :            : 
     385         [ +  - ]:    6946907 :   map<match_key, match_node *>::const_iterator i = sub.find(k);
     386 [ +  - ][ +  + ]:    6946907 :   if (i != sub.end())
     387         [ +  - ]:    4091560 :     return i->second;
     388 [ +  - ][ +  - ]:    2855347 :   match_node * n = new match_node();
     389 [ +  - ][ +  - ]:    2855348 :   sub.insert(make_pair(k, n));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     390                 :    6946907 :   return n;
     391                 :            : }
     392                 :            : 
     393                 :            : void
     394                 :    2687204 : match_node::bind(derived_probe_builder * e)
     395                 :            : {
     396                 :    2687204 :   ends.push_back (e);
     397                 :    2687204 : }
     398                 :            : 
     399                 :            : match_node *
     400                 :    6742284 : match_node::bind(string const & k)
     401                 :            : {
     402         [ +  + ]:    6742284 :   return bind(match_key(k));
     403                 :            : }
     404                 :            : 
     405                 :            : match_node *
     406                 :     101094 : match_node::bind_str(string const & k)
     407                 :            : {
     408         [ +  - ]:     101094 :   return bind(match_key(k).with_string());
     409                 :            : }
     410                 :            : 
     411                 :            : match_node *
     412                 :     103530 : match_node::bind_num(string const & k)
     413                 :            : {
     414         [ +  - ]:     103530 :   return bind(match_key(k).with_number());
     415                 :            : }
     416                 :            : 
     417                 :            : match_node *
     418                 :    2626304 : match_node::bind_privilege(privilege_t p)
     419                 :            : {
     420                 :    2626304 :   privilege = p;
     421                 :    2626304 :   return this;
     422                 :            : }
     423                 :            : 
     424                 :            : void
     425                 :     436366 : match_node::find_and_build (systemtap_session& s,
     426                 :            :                             probe* p, probe_point *loc, unsigned pos,
     427                 :            :                             vector<derived_probe *>& results)
     428                 :            : {
     429         [ -  + ]:     436366 :   assert (pos <= loc->components.size());
     430         [ +  + ]:     436366 :   if (pos == loc->components.size()) // matched all probe point components so far
     431                 :            :     {
     432 [ +  - ][ +  + ]:     139443 :       if (ends.empty())
     433                 :            :         {
     434         [ +  - ]:         20 :           string alternatives;
     435 [ +  - ][ +  - ]:        102 :           for (sub_map_iterator_t i = sub.begin(); i != sub.end(); i++)
                 [ +  + ]
     436 [ +  - ][ +  - ]:         82 :             alternatives += string(" ") + i->first.str();
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     437                 :            : 
     438                 :         20 :           throw semantic_error (_F("probe point truncated (follow: %s)",
     439                 :            :                                    alternatives.c_str()),
     440 [ +  - ][ +  - ]:         20 :                                    loc->components.back()->tok);
         [ +  - ][ +  - ]
     441                 :            :         }
     442                 :            : 
     443 [ +  - ][ -  + ]:     139423 :       if (! pr_contains (privilege, s.privilege))
     444                 :            :         {
     445                 :          0 :           throw semantic_error (_F("probe point is not allowed for --privilege=%s",
     446                 :            :                                    pr_name (s.privilege)),
     447 [ #  # ][ #  # ]:          0 :                                 loc->components.back()->tok);
         [ #  # ][ #  # ]
     448                 :            :         }
     449                 :            : 
     450         [ +  - ]:     139423 :       map<string, literal *> param_map;
     451         [ +  + ]:     506769 :       for (unsigned i=0; i<pos; i++)
     452         [ +  - ]:     367346 :         param_map[loc->components[i]->functor] = loc->components[i]->arg;
     453                 :            :       // maybe 0
     454                 :            : 
     455                 :            :       // Iterate over all bound builders
     456         [ +  + ]:     279034 :       for (unsigned k=0; k<ends.size(); k++) 
     457                 :            :         {
     458                 :     139629 :           derived_probe_builder *b = ends[k];
     459         [ +  + ]:     139629 :           b->build (s, p, loc, param_map, results);
     460         [ +  - ]:     139443 :         }
     461                 :            :     }
     462         [ +  + ]:     296923 :   else if (isdoubleglob(loc->components[pos]->functor)) // ** wildcard?
     463                 :            :     {
     464                 :       5725 :       unsigned int num_results = results.size();
     465                 :            : 
     466                 :            :       // When faced with "foo**bar", we try "foo*bar" and "foo*.**bar"
     467                 :            : 
     468                 :       5725 :       const probe_point::component *comp = loc->components[pos];
     469                 :       5725 :       const string &functor = comp->functor;
     470         [ +  - ]:       5725 :       size_t glob_start = functor.find("**");
     471         [ +  - ]:       5725 :       size_t glob_end = functor.find_first_not_of('*', glob_start);
     472         [ +  - ]:       5725 :       const string prefix = functor.substr(0, glob_start);
     473                 :            :       const string suffix = ((glob_end != string::npos) ?
     474 [ +  + ][ +  - ]:       5725 :                              functor.substr(glob_end) : "");
         [ +  - ][ +  + ]
                 [ #  # ]
     475                 :            : 
     476                 :            :       // Synthesize "foo*bar"
     477 [ +  - ][ +  - ]:       5725 :       probe_point *simple_pp = new probe_point(*loc);
     478 [ +  - ][ +  - ]:       5725 :       probe_point::component *simple_comp = new probe_point::component(*comp);
     479 [ +  - ][ +  - ]:       5725 :       simple_comp->functor = prefix + "*" + suffix;
         [ +  - ][ +  - ]
                 [ +  - ]
     480                 :       5725 :       simple_pp->components[pos] = simple_comp;
     481                 :            :       try
     482                 :            :         {
     483         [ +  + ]:       5725 :           find_and_build (s, p, simple_pp, pos, results);
     484                 :            :         }
     485         [ -  + ]:       4734 :       catch (const semantic_error& e)
     486                 :            :         {
     487                 :            :           // Ignore semantic_errors, but cleanup
     488 [ +  - ][ -  + ]:       2367 :           delete simple_pp;
     489 [ +  - ][ -  + ]:       2367 :           delete simple_comp;
     490                 :            :         }
     491                 :            : 
     492                 :            :       // Synthesize "foo*.**bar"
     493                 :            :       // NB: any component arg should attach to the latter part only
     494 [ +  - ][ +  - ]:       5725 :       probe_point *expanded_pp = new probe_point(*loc);
     495 [ +  - ][ +  - ]:       5725 :       probe_point::component *expanded_comp_pre = new probe_point::component(*comp);
     496 [ +  - ][ +  - ]:       5725 :       expanded_comp_pre->functor = prefix + "*";
                 [ +  - ]
     497                 :       5725 :       expanded_comp_pre->arg = NULL;
     498 [ +  - ][ +  - ]:       5725 :       probe_point::component *expanded_comp_post = new probe_point::component(*comp);
     499 [ +  - ][ +  - ]:       5725 :       expanded_comp_post->functor = "**" + suffix;
                 [ +  - ]
     500                 :       5725 :       expanded_pp->components[pos] = expanded_comp_pre;
     501         [ +  - ]:       5725 :       expanded_pp->components.insert(expanded_pp->components.begin() + pos + 1,
     502 [ +  - ][ +  - ]:       5725 :                                      expanded_comp_post);
                 [ +  - ]
     503                 :            :       try
     504                 :            :         {
     505         [ +  + ]:       5725 :           find_and_build (s, p, expanded_pp, pos, results);
     506                 :            :         }
     507         [ -  + ]:       4738 :       catch (const semantic_error& e)
     508                 :            :         {
     509                 :            :           // Ignore semantic_errors, but cleanup
     510 [ +  - ][ -  + ]:       2369 :           delete expanded_pp;
     511 [ +  - ][ -  + ]:       2369 :           delete expanded_comp_pre;
     512 [ +  - ][ -  + ]:       2369 :           delete expanded_comp_post;
     513                 :            :         }
     514                 :            : 
     515                 :            :       // Try suffix expansion only if no matches found:
     516         [ +  + ]:       5725 :       if (num_results == results.size())
     517                 :            :         try
     518                 :            :           {
     519         [ +  + ]:       5715 :             this->try_suffix_expansion (s, p, loc, pos, results);
     520                 :            :           }
     521         [ +  - ]:       1337 :         catch (const recursive_expansion_error &e)
     522                 :            :           {
     523         [ #  # ]:            :             s.print_error(e); return; // Suppress probe mismatch msg.
     524                 :            :           }
     525                 :            : 
     526 [ +  + ][ +  + ]:       4388 :       if (! loc->optional && num_results == results.size())
                 [ +  + ]
     527                 :            :         {
     528                 :            :           // We didn't find any wildcard matches (since the size of
     529                 :            :           // the result vector didn't change).  Throw an error.
     530         [ +  - ]:       1026 :           string alternatives;
     531 [ +  - ][ +  - ]:       1663 :           for (sub_map_iterator_t i = sub.begin(); i != sub.end(); i++)
                 [ +  + ]
     532 [ +  - ][ +  - ]:        637 :             alternatives += string(" ") + i->first.str();
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     533                 :            : 
     534                 :       1026 :           throw semantic_error(_F("probe point mismatch (alternatives: %s)",
     535 [ +  - ][ +  - ]:       4388 :                                   alternatives.c_str()), comp->tok);
                 [ +  - ]
     536 [ +  - ][ -  + ]:       5725 :         }
         [ +  - ][ +  - ]
     537                 :            :     }
     538         [ +  + ]:     291198 :   else if (isglob(loc->components[pos]->functor)) // wildcard?
     539                 :            :     {
     540         [ +  - ]:      16682 :       match_key match (* loc->components[pos]);
     541                 :            : 
     542                 :            :       // Call find_and_build for each possible match.  Ignore errors -
     543                 :            :       // unless we don't find any match.
     544                 :      16682 :       unsigned int num_results = results.size();
     545 [ +  - ][ +  - ]:      89694 :       for (sub_map_iterator_t i = sub.begin(); i != sub.end(); i++)
                 [ +  + ]
     546                 :            :         {
     547         [ +  - ]:      73012 :           const match_key& subkey = i->first;
     548         [ +  - ]:      73012 :           match_node* subnode = i->second;
     549                 :            : 
     550         [ +  - ]:      73012 :           assert_no_interrupts();
     551                 :            : 
     552 [ +  - ][ +  + ]:      73012 :           if (match.globmatch(subkey))
     553                 :            :             {
     554         [ -  + ]:      59516 :               if (s.verbose > 2)
     555 [ #  # ][ #  # ]:          0 :                 clog << _F("wildcard '%s' matched '%s'",
         [ #  # ][ #  # ]
                 [ #  # ]
     556                 :            :                            loc->components[pos]->functor.c_str(),
     557         [ #  # ]:          0 :                            subkey.name.c_str()) << endl;
     558                 :            : 
     559                 :            :               // When we have a wildcard, we need to create a copy of
     560                 :            :               // the probe point.  Then we'll create a copy of the
     561                 :            :               // wildcard component, and substitute the non-wildcard
     562                 :            :               // functor.
     563 [ +  - ][ +  - ]:      59516 :               probe_point *non_wildcard_pp = new probe_point(*loc);
     564                 :            :               probe_point::component *non_wildcard_component
     565 [ +  - ][ +  - ]:      59516 :                 = new probe_point::component(*loc->components[pos]);
     566         [ +  - ]:      59516 :               non_wildcard_component->functor = subkey.name;
     567                 :      59516 :               non_wildcard_pp->components[pos] = non_wildcard_component;
     568                 :            : 
     569                 :            :               // NB: probe conditions are not attached at the wildcard
     570                 :            :               // (component/functor) level, but at the overall
     571                 :            :               // probe_point level.
     572                 :            : 
     573                 :            :               // recurse (with the non-wildcard probe point)
     574                 :            :               try
     575                 :            :                 {
     576                 :            :                   subnode->find_and_build (s, p, non_wildcard_pp, pos+1,
     577         [ +  + ]:      59516 :                                            results);
     578                 :            :                 }
     579         [ -  + ]:       4322 :               catch (const semantic_error& e)
     580                 :            :                 {
     581                 :            :                   // Ignore semantic_errors while expanding wildcards.
     582                 :            :                   // If we get done and nothing was expanded, the code
     583                 :            :                   // following the loop will complain.
     584                 :            : 
     585                 :            :                   // If this wildcard didn't match, cleanup.
     586 [ +  - ][ -  + ]:       2161 :                   delete non_wildcard_pp;
     587 [ +  - ][ -  + ]:       2161 :                   delete non_wildcard_component;
     588                 :            :                 }
     589                 :            :             }
     590                 :            :         }
     591                 :            : 
     592                 :            :       // Try suffix expansion only if no matches found:
     593         [ +  + ]:      16682 :       if (num_results == results.size())
     594                 :            :         try
     595                 :            :           {
     596         [ +  + ]:      16195 :             this->try_suffix_expansion (s, p, loc, pos, results);
     597                 :            :           }
     598         [ +  - ]:       3620 :         catch (const recursive_expansion_error &e)
     599                 :            :           {
     600         [ #  # ]:            :             s.print_error(e); return; // Suppress probe mismatch msg.
     601                 :            :           }
     602                 :            : 
     603 [ +  + ][ +  + ]:      13062 :       if (! loc->optional && num_results == results.size())
                 [ +  + ]
     604                 :            :         {
     605                 :            :           // We didn't find any wildcard matches (since the size of
     606                 :            :           // the result vector didn't change).  Throw an error.
     607         [ +  - ]:       2195 :           string alternatives;
     608 [ +  - ][ +  - ]:       4624 :           for (sub_map_iterator_t i = sub.begin(); i != sub.end(); i++)
                 [ +  + ]
     609 [ +  - ][ +  - ]:       2429 :             alternatives += string(" ") + i->first.str();
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     610                 :            : 
     611         [ +  - ]:       2195 :           throw semantic_error(_F("probe point mismatch %s didn't find any wildcard matches",
     612                 :            :                                   (alternatives == "" ? "" : _(" (alternatives: ") +
     613 [ +  + ][ +  - ]:      15257 :                                    alternatives + ")").c_str()), loc->components[pos]->tok);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  + ]
                 [ +  + ]
           [ #  #  #  # ]
     614 [ +  - ][ +  - ]:      16682 :         }
     615                 :            :     }
     616                 :            :   else
     617                 :            :     {
     618         [ +  - ]:     274516 :       match_key match (* loc->components[pos]);
     619         [ +  - ]:     274516 :       sub_map_iterator_t i = sub.find (match);
     620                 :            : 
     621 [ +  - ][ +  + ]:     274516 :       if (i != sub.end()) // match found
     622                 :            :         {
     623         [ +  - ]:     274079 :           match_node* subnode = i->second;
     624                 :            :           // recurse
     625         [ +  + ]:     274079 :           subnode->find_and_build (s, p, loc, pos+1, results);
     626                 :            :           return;
     627                 :            :         }
     628                 :            : 
     629                 :        437 :       unsigned int num_results = results.size();
     630                 :            : 
     631                 :            :       try
     632                 :            :         {
     633         [ +  + ]:        437 :           this->try_suffix_expansion (s, p, loc, pos, results);
     634                 :            :         }
     635         [ +  - ]:         87 :       catch (const recursive_expansion_error &e)
     636                 :            :         {
     637         [ #  # ]:            :           s.print_error(e); return; // Suppress probe mismatch msg.
     638                 :            :         }
     639                 :            :       
     640                 :            :       // XXX: how to correctly report alternatives + position numbers
     641                 :            :       // for alias suffixes?  file a separate PR to address the issue
     642 [ +  + ][ +  + ]:        350 :       if (! loc->optional && num_results == results.size())
                 [ +  + ]
     643                 :            :         {
     644                 :            :           // We didn't find any alias suffixes (since the size of the
     645                 :            :           // result vector didn't change).  Throw an error.
     646         [ +  - ]:         14 :           string alternatives;
     647 [ +  - ][ +  - ]:        155 :           for (sub_map_iterator_t i = sub.begin(); i != sub.end(); i++)
                 [ +  + ]
     648 [ +  - ][ +  - ]:        141 :             alternatives += string(" ") + i->first.str();
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     649                 :            : 
     650 [ +  - ][ +  - ]:         39 :           throw semantic_error(_F("probe point mismatch %s",
           [ +  -  +  + ]
                 [ +  + ]
           [ #  #  #  # ]
     651                 :            :                                   (alternatives == "" ? "" : (_(" (alternatives:") + alternatives +
     652                 :            :                                   ")").c_str())),
     653 [ +  + ][ +  - ]:        389 :                                loc->components[pos]->tok);
         [ +  - ][ +  - ]
     654 [ +  - ][ +  + ]:     428150 :         }
     655                 :            :     }
     656                 :            : }
     657                 :            : 
     658                 :            : 
     659                 :            : void
     660                 :      22347 : match_node::try_suffix_expansion (systemtap_session& s,
     661                 :            :                                   probe *p, probe_point *loc, unsigned pos,
     662                 :            :                                   vector<derived_probe *>& results)
     663                 :            : {
     664                 :            :   // PR12210: match alias suffixes. If the components thus far
     665                 :            :   // have been matched, but there is an additional unknown
     666                 :            :   // suffix, we have a potential alias suffix on our hands. We
     667                 :            :   // need to expand the preceding components as probe aliases,
     668                 :            :   // reattach the suffix, and re-run derive_probes() on the
     669                 :            :   // resulting expansion. This is done by the routine
     670                 :            :   // build_with_suffix().
     671                 :            : 
     672         [ +  - ]:      22347 :   if (strverscmp(s.compatible.c_str(), "2.0") >= 0)
     673                 :            :     {
     674                 :            :       // XXX: technically, param_map isn't used here.  So don't
     675                 :            :       // bother actually assembling it unless some
     676                 :            :       // derived_probe_builder appears that actually takes
     677                 :            :       // suffixes *and* consults parameters (currently no such
     678                 :            :       // builders exist).
     679         [ +  - ]:      22347 :       map<string, literal *> param_map;
     680                 :            :       // for (unsigned i=0; i<pos; i++)
     681                 :            :       //   param_map[loc->components[i]->functor] = loc->components[i]->arg;
     682                 :            :       // maybe 0
     683                 :            :       
     684                 :      22347 :       vector<probe_point::component *> suffix (loc->components.begin()+pos,
     685 [ +  - ][ +  - ]:      22347 :                                                loc->components.end());
         [ +  - ][ +  - ]
     686                 :            :       
     687                 :            :       // Multiple derived_probe_builders may be bound at a
     688                 :            :       // match_node due to the possibility of multiply defined
     689                 :            :       // aliases.
     690         [ +  + ]:      39555 :       for (unsigned k=0; k < ends.size(); k++)
     691                 :            :         {
     692                 :      22252 :           derived_probe_builder *b = ends[k];
     693                 :            :           try 
     694                 :            :             {
     695         [ +  + ]:      22252 :               b->build_with_suffix (s, p, loc, param_map, results, suffix);
     696                 :            :             } 
     697                 :          6 :           catch (const recursive_expansion_error &e)
     698                 :            :             {
     699                 :            :               // Re-throw:
     700         [ -  + ]:          3 :               throw semantic_error(e);
     701                 :            :             }
     702      [ -  +  + ]:      37297 :           catch (const semantic_error &e)
     703                 :            :             {
     704                 :            :               // Adjust source coordinate and re-throw:
     705         [ +  + ]:      18647 :               if (! loc->optional)
     706 [ -  + ][ -  + ]:       5041 :                 throw semantic_error(e.what(), loc->components[pos]->tok);
     707                 :            :             }
     708 [ +  - ][ +  - ]:      22347 :         }
     709                 :            :     }
     710                 :      17303 : }
     711                 :            : 
     712                 :            : 
     713                 :            : void
     714                 :    2856565 : match_node::build_no_more (systemtap_session& s)
     715                 :            : {
     716 [ +  - ][ +  - ]:    5711912 :   for (sub_map_iterator_t i = sub.begin(); i != sub.end(); i++)
                 [ +  + ]
     717 [ +  - ][ +  - ]:    2855347 :     i->second->build_no_more (s);
     718         [ +  + ]:    5543769 :   for (unsigned k=0; k<ends.size(); k++) 
     719                 :            :     {
     720                 :    2687204 :       derived_probe_builder *b = ends[k];
     721                 :    2687204 :       b->build_no_more (s);
     722                 :            :     }
     723                 :    2856565 : }
     724                 :            : 
     725                 :            : void
     726                 :          0 : match_node::dump (systemtap_session &s, const string &name)
     727                 :            : {
     728                 :            :   // Dump this node, if it is complete.
     729         [ #  # ]:          0 :   for (unsigned k=0; k<ends.size(); k++)
     730                 :            :     {
     731                 :            :       // Don't print aliases at all (for now) until we can figure out how to determine whether
     732                 :            :       // the probes they resolve to are ok in unprivileged mode.
     733 [ #  # ][ #  # ]:          0 :       if (ends[k]->is_alias ())
     734                 :          0 :         continue;
     735                 :            : 
     736                 :            :       // In unprivileged mode, don't show the probes which are not allowed for unprivileged
     737                 :            :       // users.
     738 [ #  # ][ #  # ]:          0 :       if (pr_contains (privilege, s.privilege))
     739                 :            :         {
     740 [ #  # ][ #  # ]:          0 :           cout << name << endl;
     741                 :          0 :           break; // we need only print one instance.
     742                 :            :         }
     743                 :            :     }
     744                 :            : 
     745                 :            :   // Recursively dump the children of this node
     746         [ #  # ]:          0 :   string dot;
     747 [ #  # ][ #  # ]:          0 :   if (! name.empty ())
     748         [ #  # ]:          0 :     dot = ".";
     749 [ #  # ][ #  # ]:          0 :   for (sub_map_iterator_t i = sub.begin(); i != sub.end(); i++)
                 [ #  # ]
     750                 :            :     {
     751 [ #  # ][ #  # ]:          0 :       i->second->dump (s, name + dot + i->first.str());
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     752         [ #  # ]:          0 :     }
     753                 :          0 : }
     754                 :            : 
     755                 :            : 
     756                 :            : // ------------------------------------------------------------------------
     757                 :            : // Alias probes
     758                 :            : // ------------------------------------------------------------------------
     759                 :            : 
     760         [ #  # ]:          0 : struct alias_derived_probe: public derived_probe
     761                 :            : {
     762                 :            :   alias_derived_probe (probe* base, probe_point *l, const probe_alias *a,
     763                 :            :                        const vector<probe_point::component *> *suffix = 0);
     764                 :            : 
     765 [ #  # ][ #  # ]:          0 :   void upchuck () { throw semantic_error (_("inappropriate"), this->tok); }
     766                 :            : 
     767                 :            :   // Alias probes are immediately expanded to other derived_probe
     768                 :            :   // types, and are not themselves emitted or listed in
     769                 :            :   // systemtap_session.probes
     770                 :            : 
     771                 :          0 :   void join_group (systemtap_session&) { upchuck (); }
     772                 :            : 
     773                 :      55428 :   virtual const probe_alias *get_alias () const { return alias; }
     774                 :      18839 :   virtual probe_point *get_alias_loc () const { return alias_loc; }
     775                 :            : 
     776                 :            : private:
     777                 :            :   const probe_alias *alias; // Used to check for recursion
     778                 :            :   probe_point *alias_loc; // Hack to recover full probe name
     779                 :            : };
     780                 :            : 
     781                 :            : 
     782                 :      63263 : alias_derived_probe::alias_derived_probe(probe *base, probe_point *l,
     783                 :            :                                          const probe_alias *a,
     784                 :            :                                          const vector<probe_point::component *>
     785                 :            :                                            *suffix):
     786                 :      63263 :   derived_probe (base, l), alias(a)
     787                 :            : {
     788                 :            :   // XXX pretty nasty -- this was cribbed from printscript() in main.cxx
     789         [ -  + ]:      63263 :   assert (alias->alias_names.size() >= 1);
     790 [ +  - ][ +  - ]:      63263 :   alias_loc = new probe_point(*alias->alias_names[0]); // XXX: [0] is arbitrary; it would make just as much sense to collect all of the names
     791         [ +  + ]:      63263 :   if (suffix) {
     792                 :            :     alias_loc->components.insert(alias_loc->components.end(),
     793 [ +  - ][ +  - ]:      63174 :                                  suffix->begin(), suffix->end());
         [ +  - ][ +  - ]
     794                 :            :   }
     795                 :      63263 : }
     796                 :            : 
     797                 :            : 
     798                 :            : probe*
     799                 :         89 : probe::create_alias(probe_point* l, probe_point* a)
     800                 :            : {
     801         [ +  - ]:         89 :   vector<probe_point*> aliases(1, a);
     802 [ +  - ][ +  - ]:         89 :   probe_alias* p = new probe_alias(aliases);
     803                 :         89 :   p->tok = tok;
     804         [ +  - ]:         89 :   p->locations.push_back(l);
     805                 :         89 :   p->body = body;
     806                 :         89 :   p->privileged = privileged;
     807                 :         89 :   p->epilogue_style = false;
     808 [ +  - ][ +  - ]:         89 :   return new alias_derived_probe(this, l, p);
                 [ +  - ]
     809                 :            : }
     810                 :            : 
     811                 :            : 
     812                 :            : void
     813                 :      58213 : alias_expansion_builder::build(systemtap_session & sess,
     814                 :            :                                probe * use,
     815                 :            :                                probe_point * location,
     816                 :            :                                std::map<std::string, literal *>
     817                 :            :                                  const & parameters,
     818                 :            :                                vector<derived_probe *> & finished_results)
     819                 :            : {
     820         [ +  - ]:      58213 :   vector<probe_point::component *> empty_suffix;
     821                 :            :   build_with_suffix (sess, use, location, parameters,
     822 [ +  + ][ +  - ]:      58213 :                      finished_results, empty_suffix);
     823                 :      58211 : }
     824                 :            : 
     825                 :            : void
     826                 :      63179 : alias_expansion_builder::build_with_suffix(systemtap_session & sess,
     827                 :            :                                            probe * use,
     828                 :            :                                            probe_point * location,
     829                 :            :                                            std::map<std::string, literal *>
     830                 :            :                                              const &,
     831                 :            :                                            vector<derived_probe *>
     832                 :            :                                              & finished_results,
     833                 :            :                                            vector<probe_point::component *>
     834                 :            :                                              const & suffix)
     835                 :            : {
     836                 :            :   // Don't build the alias expansion if infinite recursion is detected.
     837         [ +  + ]:      63179 :   if (checkForRecursiveExpansion (use)) {
     838         [ +  - ]:          5 :     stringstream msg;
     839 [ +  - ][ +  - ]:         10 :     msg << _F("Recursive loop in alias expansion of %s at %s",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     840         [ +  - ]:          5 :               lex_cast(*location).c_str(), lex_cast(location->components.front()->tok->location).c_str());
     841                 :            :     // semantic_errors thrown here might be ignored, so we need a special class:
     842 [ +  - ][ +  - ]:          5 :     throw recursive_expansion_error (msg.str());
     843                 :            :     // XXX The point of throwing this custom error is to suppress a
     844                 :            :     // cascade of "probe mismatch" messages that appear in addition to
     845                 :            :     // the error. The current approach suppresses most of the error
     846                 :            :     // cascade, but leaves one spurious error; in any case, the way
     847                 :            :     // this particular error is reported could be improved.
     848                 :            :   }
     849                 :            : 
     850                 :            :   // We're going to build a new probe and wrap it up in an
     851                 :            :   // alias_expansion_probe so that the expansion loop recognizes it as
     852                 :            :   // such and re-expands its expansion.
     853                 :            : 
     854         [ +  - ]:      63174 :   alias_derived_probe * n = new alias_derived_probe (use, location /* soon overwritten */, this->alias, &suffix);
     855         [ +  - ]:      63174 :   n->body = new block();
     856                 :            : 
     857                 :            :   // The new probe gets a deep copy of the location list of the alias
     858                 :            :   // (with incoming condition joined) plus the suffix (if any),
     859                 :      63174 :   n->locations.clear();
     860         [ +  + ]:     150888 :   for (unsigned i=0; i<alias->locations.size(); i++)
     861                 :            :     {
     862 [ +  - ][ +  - ]:      87714 :       probe_point *pp = new probe_point(*alias->locations[i]);
     863 [ +  - ][ +  - ]:      87714 :       pp->components.insert(pp->components.end(), suffix.begin(), suffix.end());
         [ +  - ][ +  - ]
     864         [ +  - ]:      87714 :       pp->condition = add_condition (pp->condition, location->condition);
     865         [ +  - ]:      87714 :       n->locations.push_back(pp);
     866                 :            :     }
     867                 :            : 
     868                 :            :   // the token location of the alias,
     869                 :      63174 :   n->tok = location->components.front()->tok;
     870                 :            : 
     871                 :            :   // and statements representing the concatenation of the alias'
     872                 :            :   // body with the use's.
     873                 :            :   //
     874                 :            :   // NB: locals are *not* copied forward, from either alias or
     875                 :            :   // use. The expansion should have its locals re-inferred since
     876                 :            :   // there's concatenated code here and we only want one vardecl per
     877                 :            :   // resulting variable.
     878                 :            : 
     879         [ +  + ]:      63174 :   if (alias->epilogue_style)
     880         [ +  - ]:          1 :     n->body = new block (use->body, alias->body);
     881                 :            :   else
     882         [ +  - ]:      63173 :     n->body = new block (alias->body, use->body);
     883                 :            : 
     884                 :      63174 :   unsigned old_num_results = finished_results.size();
     885                 :            :   // If expanding for an alias suffix, be sure to pass on any errors
     886                 :            :   // to the caller instead of printing them in derive_probes():
     887                 :      63174 :   derive_probes (sess, n, finished_results, location->optional, !suffix.empty());
     888                 :            : 
     889                 :            :   // Check whether we resolved something. If so, put the
     890                 :            :   // whole library into the queue if not already there.
     891         [ +  + ]:      61813 :   if (finished_results.size() > old_num_results)
     892                 :            :     {
     893                 :      47685 :       stapfile *f = alias->tok->location.file;
     894 [ +  - ][ +  - ]:      95370 :       if (find (sess.files.begin(), sess.files.end(), f)
         [ +  - ][ +  + ]
     895 [ +  - ][ +  - ]:      47685 :           == sess.files.end())
     896         [ +  - ]:      47685 :         sess.files.push_back (f);
     897                 :            :     }
     898                 :      61813 : }
     899                 :            : 
     900                 :            : bool
     901                 :      63179 : alias_expansion_builder::checkForRecursiveExpansion (probe *use)
     902                 :            : {
     903                 :            :   // Collect the derivation chain of this probe.
     904         [ +  - ]:      63179 :   vector<probe*>derivations;
     905         [ +  - ]:      63179 :   use->collect_derivation_chain (derivations);
     906                 :            : 
     907                 :            :   // Check all probe points in the alias expansion against the currently-being-expanded probe point
     908                 :            :   // of each of the probes in the derivation chain, looking for a match. This
     909                 :            :   // indicates infinite recursion.
     910                 :            :   // The first element of the derivation chain will be the derived_probe representing 'use', so
     911                 :            :   // start the search with the second element.
     912         [ -  + ]:      63179 :   assert (derivations.size() > 0);
     913         [ -  + ]:      63179 :   assert (derivations[0] == use);
     914         [ +  + ]:      65749 :   for (unsigned d = 1; d < derivations.size(); ++d) {
     915 [ +  - ][ +  - ]:       2575 :     if (use->get_alias() == derivations[d]->get_alias())
                 [ +  + ]
     916                 :          5 :       return true; // recursion detected
     917                 :            :   }
     918         [ +  - ]:      63179 :   return false;
     919                 :            : }
     920                 :            : 
     921                 :            : 
     922                 :            : // ------------------------------------------------------------------------
     923                 :            : // Pattern matching
     924                 :            : // ------------------------------------------------------------------------
     925                 :            : 
     926                 :            : static unsigned max_recursion = 100;
     927                 :            : 
     928                 :            : struct
     929                 :            : recursion_guard
     930                 :            : {
     931                 :            :   unsigned & i;
     932                 :            :   recursion_guard(unsigned & i) : i(i)
     933                 :            :     {
     934                 :            :       if (i > max_recursion)
     935                 :            :         throw semantic_error(_("recursion limit reached"));
     936                 :            :       ++i;
     937                 :            :     }
     938                 :            :   ~recursion_guard()
     939                 :            :     {
     940                 :            :       --i;
     941                 :            :     }
     942                 :            : };
     943                 :            : 
     944                 :            : // The match-and-expand loop.
     945                 :            : void
     946                 :      67868 : derive_probes (systemtap_session& s,
     947                 :            :                probe *p, vector<derived_probe*>& dps,
     948                 :            :                bool optional,
     949                 :            :                bool rethrow_errors)
     950                 :            : {
     951         [ +  + ]:     156522 :   for (unsigned i = 0; i < p->locations.size(); ++i)
     952                 :            :     {
     953                 :      91321 :       assert_no_interrupts();
     954                 :            : 
     955                 :      91321 :       probe_point *loc = p->locations[i];
     956                 :            : 
     957                 :            :       try
     958                 :            :         {
     959                 :      91321 :           unsigned num_atbegin = dps.size();
     960                 :            : 
     961                 :            :           // Pass down optional flag from e.g. alias reference to each
     962                 :            :           // probe_point instance.  We do this by temporarily overriding
     963                 :            :           // the probe_point optional flag.  We could instead deep-copy
     964                 :            :           // and set a flag on the copy permanently.
     965                 :      91321 :           bool old_loc_opt = loc->optional;
     966 [ +  + ][ +  + ]:      91321 :           loc->optional = loc->optional || optional;
     967                 :            :           try
     968                 :            :             {
     969         [ +  + ]:      91321 :               s.pattern_root->find_and_build (s, p, loc, 0, dps); // <-- actual derivation!
     970                 :            :             }
     971         [ -  + ]:       2840 :           catch (const semantic_error& e)
     972                 :            :             {
     973         [ +  + ]:       1420 :               if (!loc->optional)
     974         [ -  + ]:       1419 :                 throw semantic_error(e);
     975                 :            :               else /* tolerate failure for optional probe */
     976                 :          1 :                 continue;
     977                 :            :             }
     978                 :            : 
     979                 :      89901 :           loc->optional = old_loc_opt;
     980                 :      89901 :           unsigned num_atend = dps.size();
     981                 :            : 
     982 [ +  + ][ +  + ]:      89901 :           if (! (loc->optional||optional) && // something required, but
                 [ +  + ]
     983                 :            :               num_atbegin == num_atend) // nothing new derived!
     984 [ +  - ][ +  - ]:        425 :             throw semantic_error (_("no match"));
     985                 :            : 
     986 [ +  + ][ +  + ]:      89476 :           if (loc->sufficient && (num_atend > num_atbegin))
     987                 :            :             {
     988         [ +  + ]:       1306 :               if (s.verbose > 1)
     989                 :            :                 {
     990         [ +  - ]:          7 :                   clog << "Probe point ";
     991         [ +  - ]:          7 :                   p->locations[i]->print(clog);
     992         [ +  - ]:          7 :                   clog << " sufficient, skipped";
     993         [ +  + ]:         15 :                   for (unsigned j = i+1; j < p->locations.size(); ++j)
     994                 :            :                     {
     995         [ +  - ]:          8 :                       clog << " ";
     996         [ +  - ]:          8 :                       p->locations[j]->print(clog);
     997                 :            :                     }
     998         [ +  - ]:          7 :                   clog << endl;
     999                 :            :                 }
    1000                 :       1306 :               break; // we need not try to derive for any other locations
    1001                 :            :             }
    1002                 :            :         }
    1003         [ -  + ]:       3688 :       catch (const semantic_error& e)
    1004                 :            :         {
    1005                 :            :           // The rethrow_errors parameter lets the caller decide an
    1006                 :            :           // alternative to printing the error. This is necessary when
    1007                 :            :           // calling derive_probes() recursively during expansion of
    1008                 :            :           // an alias with suffix -- any message printed here would
    1009                 :            :           // point to the alias declaration and not the invalid suffix
    1010                 :            :           // usage, so the caller needs to catch the error themselves
    1011                 :            :           // and print a more appropriate message.
    1012         [ +  + ]:       1844 :           if (rethrow_errors)
    1013                 :            :             {
    1014         [ -  + ]:       1361 :               throw semantic_error(e);
    1015                 :            :             }
    1016                 :            :           // Only output in listing if -vv is supplied:
    1017 [ +  + ][ +  - ]:        483 :           else if (!s.listing_mode || (s.listing_mode && s.verbose > 1))
                 [ +  + ]
    1018                 :            :             {
    1019                 :            :               // XXX: prefer not to print_error at every nest/unroll level
    1020                 :        462 :               semantic_error* er = new semantic_error (_("while resolving probe point"),
    1021 [ -  + ][ -  + ]:        462 :                                                        loc->components[0]->tok);
         [ -  + ][ -  + ]
    1022                 :        462 :               er->chain = & e;
    1023         [ -  + ]:        462 :               s.print_error (* er);
    1024         [ +  - ]:        462 :               delete er;
    1025                 :            :             }
    1026                 :            :         }
    1027                 :            : 
    1028                 :            :     }
    1029                 :      66507 : }
    1030                 :            : 
    1031                 :            : 
    1032                 :            : 
    1033                 :            : // ------------------------------------------------------------------------
    1034                 :            : //
    1035                 :            : // Indexable usage checks
    1036                 :            : //
    1037                 :            : 
    1038         [ -  + ]:     863766 : struct symbol_fetcher
    1039                 :            :   : public throwing_visitor
    1040                 :            : {
    1041                 :            :   symbol *&sym;
    1042                 :            : 
    1043                 :     863766 :   symbol_fetcher (symbol *&sym): sym(sym)
    1044                 :     863766 :   {}
    1045                 :            : 
    1046                 :     863759 :   void visit_symbol (symbol* e)
    1047                 :            :   {
    1048                 :     863759 :     sym = e;
    1049                 :     863759 :   }
    1050                 :            : 
    1051                 :          6 :   void visit_target_symbol (target_symbol* e)
    1052                 :            :   {
    1053                 :          6 :     sym = e;
    1054                 :          6 :   }
    1055                 :            : 
    1056                 :      74705 :   void visit_arrayindex (arrayindex* e)
    1057                 :            :   {
    1058                 :      74705 :     e->base->visit (this);
    1059                 :      74705 :   }
    1060                 :            : 
    1061                 :          0 :   void visit_cast_op (cast_op* e)
    1062                 :            :   {
    1063                 :          0 :     sym = e;
    1064                 :          0 :   }
    1065                 :            : 
    1066                 :          1 :   void throwone (const token* t)
    1067                 :            :   {
    1068 [ +  - ][ +  - ]:          1 :     throw semantic_error (_("Expecting symbol or array index expression"), t);
    1069                 :            :   }
    1070                 :            : };
    1071                 :            : 
    1072                 :            : symbol *
    1073                 :     863766 : get_symbol_within_expression (expression *e)
    1074                 :            : {
    1075                 :     863766 :   symbol *sym = NULL;
    1076         [ +  - ]:     863766 :   symbol_fetcher fetcher(sym);
    1077         [ +  + ]:     863766 :   e->visit (&fetcher);
    1078         [ +  - ]:     863766 :   return sym; // NB: may be null!
    1079                 :            : }
    1080                 :            : 
    1081                 :            : static symbol *
    1082                 :      31280 : get_symbol_within_indexable (indexable *ix)
    1083                 :            : {
    1084                 :      31280 :   symbol *array = NULL;
    1085                 :      31280 :   hist_op *hist = NULL;
    1086         [ +  - ]:      31280 :   classify_indexable(ix, array, hist);
    1087         [ +  + ]:      31280 :   if (array)
    1088                 :      31271 :     return array;
    1089                 :            :   else
    1090         [ +  - ]:      31280 :     return get_symbol_within_expression (hist->stat);
    1091                 :            : }
    1092                 :            : 
    1093         [ -  + ]:      19590 : struct mutated_var_collector
    1094                 :            :   : public traversing_visitor
    1095                 :            : {
    1096                 :            :   set<vardecl *> * mutated_vars;
    1097                 :            : 
    1098                 :      19590 :   mutated_var_collector (set<vardecl *> * mm)
    1099                 :      19590 :     : mutated_vars (mm)
    1100                 :      19590 :   {}
    1101                 :            : 
    1102                 :      11349 :   void visit_assignment(assignment* e)
    1103                 :            :   {
    1104 [ -  + ][ #  # ]:      11349 :     if (e->type == pe_stats && e->op == "<<<")
                 [ -  + ]
    1105                 :            :       {
    1106         [ #  # ]:          0 :         vardecl *vd = get_symbol_within_expression (e->left)->referent;
    1107         [ #  # ]:          0 :         if (vd)
    1108         [ #  # ]:          0 :           mutated_vars->insert (vd);
    1109                 :            :       }
    1110                 :      11349 :     traversing_visitor::visit_assignment(e);
    1111                 :      11349 :   }
    1112                 :            : 
    1113                 :       2555 :   void visit_arrayindex (arrayindex *e)
    1114                 :            :   {
    1115         [ +  + ]:       2555 :     if (is_active_lvalue (e))
    1116                 :            :       {
    1117                 :            :         symbol *sym;
    1118 [ +  - ][ +  - ]:       1855 :         if (e->base->is_symbol (sym))
    1119         [ +  - ]:       1855 :           mutated_vars->insert (sym->referent);
    1120                 :            :         else
    1121 [ #  # ][ #  # ]:          0 :           throw semantic_error(_("Assignment to read-only histogram bucket"), e->tok);
    1122                 :            :       }
    1123                 :       2555 :     traversing_visitor::visit_arrayindex (e);
    1124                 :       2555 :   }
    1125                 :            : };
    1126                 :            : 
    1127                 :            : 
    1128 [ +  - ][ -  + ]:       1035 : struct no_var_mutation_during_iteration_check
    1129                 :            :   : public traversing_visitor
    1130                 :            : {
    1131                 :            :   systemtap_session & session;
    1132                 :            :   map<functiondecl *,set<vardecl *> *> & function_mutates_vars;
    1133                 :            :   vector<vardecl *> vars_being_iterated;
    1134                 :            : 
    1135                 :       1035 :   no_var_mutation_during_iteration_check
    1136                 :            :   (systemtap_session & sess,
    1137                 :            :    map<functiondecl *,set<vardecl *> *> & fmv)
    1138         [ +  - ]:       1035 :     : session(sess), function_mutates_vars (fmv)
    1139                 :       1035 :   {}
    1140                 :            : 
    1141                 :      76751 :   void visit_arrayindex (arrayindex *e)
    1142                 :            :   {
    1143         [ +  + ]:      76751 :     if (is_active_lvalue(e))
    1144                 :            :       {
    1145                 :      30902 :         vardecl *vd = get_symbol_within_indexable (e->base)->referent;
    1146         [ +  - ]:      30902 :         if (vd)
    1147                 :            :           {
    1148         [ +  + ]:      30958 :             for (unsigned i = 0; i < vars_being_iterated.size(); ++i)
    1149                 :            :               {
    1150                 :         56 :                 vardecl *v = vars_being_iterated[i];
    1151         [ +  + ]:         56 :                 if (v == vd)
    1152                 :            :                   {
    1153 [ +  - ][ +  - ]:          2 :                     string err = _F("variable '%s' modified during 'foreach' iteration",
    1154                 :            :                                     v->name.c_str());
    1155 [ +  - ][ +  - ]:          2 :                     session.print_error (semantic_error (err, e->tok));
                 [ +  - ]
    1156                 :            :                   }
    1157                 :            :               }
    1158                 :            :           }
    1159                 :            :       }
    1160                 :      76751 :     traversing_visitor::visit_arrayindex (e);
    1161                 :      76751 :   }
    1162                 :            : 
    1163                 :     312382 :   void visit_functioncall (functioncall* e)
    1164                 :            :   {
    1165                 :            :     map<functiondecl *,set<vardecl *> *>::const_iterator i
    1166         [ +  - ]:     312382 :       = function_mutates_vars.find (e->referent);
    1167                 :            : 
    1168 [ +  - ][ +  - ]:     312382 :     if (i != function_mutates_vars.end())
    1169                 :            :       {
    1170         [ +  + ]:     312455 :         for (unsigned j = 0; j < vars_being_iterated.size(); ++j)
    1171                 :            :           {
    1172                 :         73 :             vardecl *m = vars_being_iterated[j];
    1173 [ +  - ][ +  - ]:         73 :             if (i->second->find (m) != i->second->end())
         [ +  - ][ +  - ]
                 [ +  + ]
    1174                 :            :               {
    1175 [ +  - ][ +  - ]:          2 :                 string err = _F("function call modifies var '%s' during 'foreach' iteration",
    1176                 :            :                                 m->name.c_str());
    1177 [ +  - ][ +  - ]:          2 :                 session.print_error (semantic_error (err, e->tok));
                 [ +  - ]
    1178                 :            :               }
    1179                 :            :           }
    1180                 :            :       }
    1181                 :            : 
    1182         [ +  - ]:     312382 :     traversing_visitor::visit_functioncall (e);
    1183                 :     312382 :   }
    1184                 :            : 
    1185                 :        378 :   void visit_foreach_loop(foreach_loop* s)
    1186                 :            :   {
    1187         [ +  - ]:        378 :     vardecl *vd = get_symbol_within_indexable (s->base)->referent;
    1188                 :            : 
    1189         [ +  - ]:        378 :     if (vd)
    1190         [ +  - ]:        378 :       vars_being_iterated.push_back (vd);
    1191                 :            : 
    1192         [ +  - ]:        378 :     traversing_visitor::visit_foreach_loop (s);
    1193                 :            : 
    1194         [ +  - ]:        378 :     if (vd)
    1195         [ +  - ]:        378 :       vars_being_iterated.pop_back();
    1196                 :        378 :   }
    1197                 :            : };
    1198                 :            : 
    1199                 :            : 
    1200                 :            : // ------------------------------------------------------------------------
    1201                 :            : 
    1202         [ -  + ]:       1031 : struct stat_decl_collector
    1203                 :            :   : public traversing_visitor
    1204                 :            : {
    1205                 :            :   systemtap_session & session;
    1206                 :            : 
    1207                 :       1031 :   stat_decl_collector(systemtap_session & sess)
    1208                 :       1031 :     : session(sess)
    1209                 :       1031 :   {}
    1210                 :            : 
    1211                 :        758 :   void visit_stat_op (stat_op* e)
    1212                 :            :   {
    1213                 :        758 :     symbol *sym = get_symbol_within_expression (e->stat);
    1214 [ +  - ][ +  + ]:        758 :     if (session.stat_decls.find(sym->name) == session.stat_decls.end())
    1215                 :         31 :       session.stat_decls[sym->name] = statistic_decl();
    1216                 :        758 :   }
    1217                 :            : 
    1218                 :     182717 :   void visit_assignment (assignment* e)
    1219                 :            :   {
    1220         [ +  + ]:     182717 :     if (e->op == "<<<")
    1221                 :            :       {
    1222                 :      11401 :         symbol *sym = get_symbol_within_expression (e->left);
    1223 [ +  - ][ +  + ]:      11401 :         if (session.stat_decls.find(sym->name) == session.stat_decls.end())
    1224                 :        188 :           session.stat_decls[sym->name] = statistic_decl();
    1225                 :            :       }
    1226                 :            :     else
    1227                 :     171316 :       traversing_visitor::visit_assignment(e);
    1228                 :     182717 :   }
    1229                 :            : 
    1230                 :        135 :   void visit_hist_op (hist_op* e)
    1231                 :            :   {
    1232         [ +  - ]:        135 :     symbol *sym = get_symbol_within_expression (e->stat);
    1233                 :        135 :     statistic_decl new_stat;
    1234                 :            : 
    1235         [ +  + ]:        135 :     if (e->htype == hist_linear)
    1236                 :            :       {
    1237                 :         56 :         new_stat.type = statistic_decl::linear;
    1238         [ -  + ]:         56 :         assert (e->params.size() == 3);
    1239                 :         56 :         new_stat.linear_low = e->params[0];
    1240                 :         56 :         new_stat.linear_high = e->params[1];
    1241                 :         56 :         new_stat.linear_step = e->params[2];
    1242                 :            :       }
    1243                 :            :     else
    1244                 :            :       {
    1245         [ -  + ]:         79 :         assert (e->htype == hist_log);
    1246                 :         79 :         new_stat.type = statistic_decl::logarithmic;
    1247         [ -  + ]:         79 :         assert (e->params.size() == 0);
    1248                 :            :       }
    1249                 :            : 
    1250         [ +  - ]:        135 :     map<string, statistic_decl>::iterator i = session.stat_decls.find(sym->name);
    1251 [ +  - ][ -  + ]:        135 :     if (i == session.stat_decls.end())
    1252         [ #  # ]:          0 :       session.stat_decls[sym->name] = new_stat;
    1253                 :            :     else
    1254                 :            :       {
    1255         [ +  - ]:        135 :         statistic_decl & old_stat = i->second;
    1256         [ +  + ]:        135 :         if (!(old_stat == new_stat))
    1257                 :            :           {
    1258         [ +  - ]:         53 :             if (old_stat.type == statistic_decl::none)
    1259         [ +  - ]:         53 :               i->second = new_stat;
    1260                 :            :             else
    1261                 :            :               {
    1262                 :            :                 // FIXME: Support multiple co-declared histogram types
    1263 [ #  # ][ #  # ]:          0 :                 semantic_error se(_F("multiple histogram types declared on '%s'", sym->name.c_str()), e->tok);
         [ #  # ][ #  # ]
    1264         [ #  # ]:          0 :                 session.print_error (se);
    1265                 :            :               }
    1266                 :            :           }
    1267                 :            :       }
    1268                 :        135 :   }
    1269                 :            : 
    1270                 :            : };
    1271                 :            : 
    1272                 :            : static int
    1273                 :       1031 : semantic_pass_stats (systemtap_session & sess)
    1274                 :            : {
    1275         [ +  - ]:       1031 :   stat_decl_collector sdc(sess);
    1276                 :            : 
    1277 [ +  - ][ +  - ]:      20615 :   for (map<string,functiondecl*>::iterator it = sess.functions.begin(); it != sess.functions.end(); it++)
                 [ +  + ]
    1278 [ +  - ][ +  - ]:      19584 :     it->second->body->visit (&sdc);
    1279                 :            : 
    1280         [ +  + ]:     355093 :   for (unsigned i = 0; i < sess.probes.size(); ++i)
    1281         [ +  - ]:     354062 :     sess.probes[i]->body->visit (&sdc);
    1282                 :            : 
    1283         [ +  + ]:       4845 :   for (unsigned i = 0; i < sess.globals.size(); ++i)
    1284                 :            :     {
    1285                 :       3814 :       vardecl *v = sess.globals[i];
    1286         [ +  + ]:       3814 :       if (v->type == pe_stats)
    1287                 :            :         {
    1288                 :            : 
    1289 [ +  - ][ +  - ]:        219 :           if (sess.stat_decls.find(v->name) == sess.stat_decls.end())
                 [ -  + ]
    1290                 :            :             {
    1291 [ #  # ][ #  # ]:          0 :               semantic_error se(_F("unable to infer statistic parameters for global '%s'", v->name.c_str()));
         [ #  # ][ #  # ]
    1292         [ #  # ]:          0 :               sess.print_error (se);
    1293                 :            :             }
    1294                 :            :         }
    1295                 :            :     }
    1296                 :            : 
    1297 [ +  - ][ +  - ]:       1031 :   return sess.num_errors();
    1298                 :            : }
    1299                 :            : 
    1300                 :            : // ------------------------------------------------------------------------
    1301                 :            : 
    1302                 :            : // Enforce variable-related invariants: no modification of
    1303                 :            : // a foreach()-iterated array.
    1304                 :            : static int
    1305                 :       1035 : semantic_pass_vars (systemtap_session & sess)
    1306                 :            : {
    1307                 :            : 
    1308         [ +  - ]:       1035 :   map<functiondecl *, set<vardecl *> *> fmv;
    1309         [ +  - ]:       1035 :   no_var_mutation_during_iteration_check chk(sess, fmv);
    1310                 :            : 
    1311 [ +  - ][ +  - ]:      20625 :   for (map<string,functiondecl*>::iterator it = sess.functions.begin(); it != sess.functions.end(); it++)
                 [ +  + ]
    1312                 :            :     {
    1313         [ +  - ]:      19590 :       functiondecl * fn = it->second;
    1314         [ +  - ]:      19590 :       if (fn->body)
    1315                 :            :         {
    1316 [ +  - ][ +  - ]:      19590 :           set<vardecl *> * m = new set<vardecl *>();
    1317         [ +  - ]:      19590 :           mutated_var_collector mc (m);
    1318         [ +  - ]:      19590 :           fn->body->visit (&mc);
    1319 [ +  - ][ +  - ]:      19590 :           fmv[fn] = m;
    1320                 :            :         }
    1321                 :            :     }
    1322                 :            : 
    1323 [ +  - ][ +  - ]:      20625 :   for (map<string,functiondecl*>::iterator it = sess.functions.begin(); it != sess.functions.end(); it++)
                 [ +  + ]
    1324                 :            :     {
    1325         [ +  - ]:      19590 :       functiondecl * fn = it->second;
    1326 [ +  - ][ +  - ]:      19590 :       if (fn->body) fn->body->visit (&chk);
    1327                 :            :     }
    1328                 :            : 
    1329         [ +  + ]:     355101 :   for (unsigned i = 0; i < sess.probes.size(); ++i)
    1330                 :            :     {
    1331         [ +  - ]:     354066 :       if (sess.probes[i]->body)
    1332         [ +  - ]:     354066 :         sess.probes[i]->body->visit (&chk);
    1333                 :            :     }
    1334                 :            : 
    1335 [ +  - ][ +  - ]:       1035 :   return sess.num_errors();
                 [ +  - ]
    1336                 :            : }
    1337                 :            : 
    1338                 :            : 
    1339                 :            : // ------------------------------------------------------------------------
    1340                 :            : 
    1341                 :            : // Rewrite probe condition expressions into probe bodies.  Tricky and
    1342                 :            : // exciting business, this.  This:
    1343                 :            : //
    1344                 :            : // probe foo if (g1 || g2) { ... }
    1345                 :            : // probe bar { ... g1 ++ ... }
    1346                 :            : //
    1347                 :            : // becomes:
    1348                 :            : //
    1349                 :            : // probe begin(MAX) { if (! (g1 || g2)) %{ disable_probe_foo %} }
    1350                 :            : // probe foo { if (! (g1 || g2)) next; ... }
    1351                 :            : // probe bar { ... g1 ++ ...;
    1352                 :            : //             if (g1 || g2) %{ enable_probe_foo %} else %{ disable_probe_foo %}
    1353                 :            : //           }
    1354                 :            : //
    1355                 :            : // XXX: As a first cut, do only the "inline probe condition" part of the
    1356                 :            : // transform.
    1357                 :            : 
    1358                 :            : static int
    1359                 :       1116 : semantic_pass_conditions (systemtap_session & sess)
    1360                 :            : {
    1361         [ +  + ]:     355433 :   for (unsigned i = 0; i < sess.probes.size(); ++i)
    1362                 :            :     {
    1363                 :     354317 :       derived_probe* p = sess.probes[i];
    1364                 :     354317 :       expression* e = p->sole_location()->condition;
    1365         [ +  + ]:     354317 :       if (e)
    1366                 :            :         {
    1367         [ +  - ]:         15 :           varuse_collecting_visitor vut(sess);
    1368         [ +  - ]:         15 :           e->visit (& vut);
    1369                 :            : 
    1370 [ +  - ][ +  + ]:         15 :           if (! vut.written.empty())
    1371                 :            :             {
    1372         [ +  - ]:          1 :               string err = (_("probe condition must not modify any variables"));
    1373 [ +  - ][ +  - ]:          1 :               sess.print_error (semantic_error (err, e->tok));
                 [ +  - ]
    1374                 :            :             }
    1375         [ -  + ]:         14 :           else if (vut.embedded_seen)
    1376                 :            :             {
    1377 [ #  # ][ #  # ]:          0 :               sess.print_error (semantic_error (_("probe condition must not include impure embedded-C"), e->tok));
         [ #  # ][ #  # ]
    1378                 :            :             }
    1379                 :            : 
    1380                 :            :           // Add the condition expression to the front of the
    1381                 :            :           // derived_probe body.
    1382 [ +  - ][ +  - ]:         15 :           if_statement *ifs = new if_statement ();
    1383                 :         15 :           ifs->tok = e->tok;
    1384 [ +  - ][ +  - ]:         15 :           ifs->thenblock = new next_statement ();
    1385                 :         15 :           ifs->thenblock->tok = e->tok;
    1386                 :         15 :           ifs->elseblock = NULL;
    1387 [ +  - ][ +  - ]:         15 :           unary_expression *notex = new unary_expression ();
    1388         [ +  - ]:         15 :           notex->op = "!";
    1389                 :         15 :           notex->tok = e->tok;
    1390                 :         15 :           notex->operand = e;
    1391                 :         15 :           ifs->condition = notex;
    1392 [ +  - ][ +  - ]:         15 :           p->body = new block (ifs, p->body);
                 [ +  - ]
    1393                 :            :         }
    1394                 :            :     }
    1395                 :            : 
    1396                 :       1116 :   return sess.num_errors();
    1397                 :            : }
    1398                 :            : 
    1399                 :            : // ------------------------------------------------------------------------
    1400                 :            : 
    1401                 :            : 
    1402                 :            : // Simple visitor that just goes through all embedded code blocks that
    1403                 :            : // are available at the end  all the optimizations to register any
    1404                 :            : // relevant pragmas or other indicators found, so that session flags can
    1405                 :            : // be set that can be inspected at translation time to trigger any
    1406                 :            : // necessary initialization of code needed by the embedded code functions.
    1407                 :            : 
    1408                 :            : // This is only for pragmas that don't have any other side-effect than
    1409                 :            : // needing some initialization at module init time. Currently handles
    1410                 :            : // /* pragma:vma */ /* pragma:unwind */ /* pragma:symbol */
    1411                 :            : 
    1412                 :            : // /* pragma:uprobes */ is handled during the typeresolution_info pass.
    1413                 :            : // /* pure */, /* unprivileged */. /* myproc-unprivileged */ and /* guru */
    1414                 :            : // are handled by the varuse_collecting_visitor.
    1415                 :            : 
    1416         [ -  + ]:       1031 : struct embeddedcode_info: public functioncall_traversing_visitor
    1417                 :            : {
    1418                 :            : protected:
    1419                 :            :   systemtap_session& session;
    1420                 :            : 
    1421                 :            : public:
    1422                 :       1031 :   embeddedcode_info (systemtap_session& s): session(s) { }
    1423                 :            : 
    1424                 :      13766 :   void visit_embeddedcode (embeddedcode* c)
    1425                 :            :   {
    1426   [ +  +  +  + ]:      27438 :     if (! vma_tracker_enabled(session)
                 [ +  + ]
    1427                 :      13672 :         && c->code.find("/* pragma:vma */") != string::npos)
    1428                 :            :       {
    1429                 :         24 :         enable_vma_tracker(session);
    1430         [ -  + ]:         24 :         if (session.verbose > 2)
    1431         [ #  # ]:          0 :           clog << _F("Turning on task_finder vma_tracker, pragma:vma found in %s",
    1432         [ #  # ]:          0 :                      current_function->name.c_str()) << endl;
    1433                 :            :       }
    1434                 :            : 
    1435   [ +  +  +  + ]:      27435 :     if (! session.need_unwind
                 [ +  + ]
    1436                 :      13669 :         && c->code.find("/* pragma:unwind */") != string::npos)
    1437                 :            :       {
    1438         [ -  + ]:         29 :         if (session.verbose > 2)
    1439         [ #  # ]:          0 :           clog << _F("Turning on unwind support, pragma:unwind found in %s",
    1440         [ #  # ]:          0 :                     current_function->name.c_str()) << endl;
    1441                 :         29 :         session.need_unwind = true;
    1442                 :            :       }
    1443                 :            : 
    1444   [ +  +  +  + ]:      26772 :     if (! session.need_symbols
                 [ +  + ]
    1445                 :      13006 :         && c->code.find("/* pragma:symbols */") != string::npos)
    1446                 :            :       {
    1447         [ -  + ]:         86 :         if (session.verbose > 2)
    1448         [ #  # ]:          0 :           clog << _F("Turning on symbol data collecting, pragma:symbols found in %s",
    1449         [ #  # ]:          0 :                     current_function->name.c_str()) << endl;
    1450                 :         86 :         session.need_symbols = true;
    1451                 :            :       }
    1452                 :      13766 :   }
    1453                 :            : };
    1454                 :            : 
    1455                 :       1031 : void embeddedcode_info_pass (systemtap_session& s)
    1456                 :            : {
    1457         [ +  - ]:       1031 :   embeddedcode_info eci (s);
    1458         [ +  + ]:     355093 :   for (unsigned i=0; i<s.probes.size(); i++)
    1459 [ +  - ][ +  - ]:     355093 :     s.probes[i]->body->visit (& eci);
    1460                 :       1031 : }
    1461                 :            : 
    1462                 :            : // ------------------------------------------------------------------------
    1463                 :            : 
    1464                 :            : 
    1465                 :            : // Simple visitor that collects all the regular expressions in the
    1466                 :            : // file and adds them to the session DFA table.
    1467                 :            : 
    1468         [ -  + ]:       1036 : struct regex_collecting_visitor: public functioncall_traversing_visitor
    1469                 :            : {
    1470                 :            : protected:
    1471                 :            :   systemtap_session& session;
    1472                 :            : 
    1473                 :            : public:
    1474                 :       1036 :   regex_collecting_visitor (systemtap_session& s): session(s) { }
    1475                 :            : 
    1476                 :         45 :   void visit_regex_query (regex_query *q) {
    1477         [ +  - ]:         45 :     functioncall_traversing_visitor::visit_regex_query (q); // TODOXXX test necessity
    1478                 :            : 
    1479         [ +  - ]:         45 :     string re = q->re->value;
    1480                 :            :     try
    1481                 :            :       {
    1482         [ +  - ]:         45 :         regex_to_stapdfa (&session, re, session.dfa_counter);
    1483                 :            :       }
    1484         [ #  # ]:            :     catch (const semantic_error &e)
    1485                 :            :       {
    1486   [ #  #  #  # ]:            :         throw semantic_error(e.what(), q->right->tok);
    1487         [ +  - ]:         45 :       }
    1488                 :         45 :   }
    1489                 :            : };
    1490                 :            : 
    1491                 :            : // Go through the regex match invocations and generate corresponding DFAs.
    1492                 :       1036 : void gen_dfa_table (systemtap_session& s)
    1493                 :            : {
    1494         [ +  - ]:       1036 :   regex_collecting_visitor rcv(s); // TODOXXX
    1495                 :            : 
    1496         [ +  + ]:     354969 :   for (unsigned i=0; i<s.probes.size(); i++)
    1497                 :            :     {
    1498         [ +  - ]:     353933 :       s.probes[i]->body->visit (& rcv);
    1499                 :            : 
    1500 [ +  - ][ +  + ]:     353933 :       if (s.probes[i]->sole_location()->condition)
    1501 [ +  - ][ +  - ]:         14 :         s.probes[i]->sole_location()->condition->visit (& rcv);
    1502         [ +  - ]:       1036 :     }
    1503                 :       1036 : }
    1504                 :            : 
    1505                 :            : // ------------------------------------------------------------------------
    1506                 :            : 
    1507                 :            : 
    1508                 :            : static int semantic_pass_symbols (systemtap_session&);
    1509                 :            : static int semantic_pass_optimize1 (systemtap_session&);
    1510                 :            : static int semantic_pass_optimize2 (systemtap_session&);
    1511                 :            : static int semantic_pass_types (systemtap_session&);
    1512                 :            : static int semantic_pass_vars (systemtap_session&);
    1513                 :            : static int semantic_pass_stats (systemtap_session&);
    1514                 :            : static int semantic_pass_conditions (systemtap_session&);
    1515                 :            : 
    1516                 :            : 
    1517                 :            : // Link up symbols to their declarations.  Set the session's
    1518                 :            : // files/probes/functions/globals vectors from the transitively
    1519                 :            : // reached set of stapfiles in s.library_files, starting from
    1520                 :            : // s.user_file.  Perform automatic tapset inclusion and probe
    1521                 :            : // alias expansion.
    1522                 :            : static int
    1523                 :       1218 : semantic_pass_symbols (systemtap_session& s)
    1524                 :            : {
    1525         [ +  - ]:       1218 :   symresolution_info sym (s);
    1526                 :            : 
    1527                 :            :   // NB: s.files can grow during this iteration, so size() can
    1528                 :            :   // return gradually increasing numbers.
    1529         [ +  - ]:       1218 :   s.files.push_back (s.user_file);
    1530         [ +  + ]:       6719 :   for (unsigned i = 0; i < s.files.size(); i++)
    1531                 :            :     {
    1532         [ +  - ]:       5501 :       assert_no_interrupts();
    1533                 :       5501 :       stapfile* dome = s.files[i];
    1534                 :            : 
    1535                 :            :       // Pass 1: add globals and functions to systemtap-session master list,
    1536                 :            :       //         so the find_* functions find them
    1537                 :            :       //
    1538                 :            :       // NB: tapset global/function definitions may duplicate or conflict
    1539                 :            :       // with those already in s.globals/functions.  We need to deconflict
    1540                 :            :       // here.
    1541                 :            : 
    1542         [ +  + ]:       7784 :       for (unsigned i=0; i<dome->globals.size(); i++)
    1543                 :            :         {
    1544                 :       2283 :           vardecl* g = dome->globals[i];
    1545         [ +  + ]:      16979 :           for (unsigned j=0; j<s.globals.size(); j++)
    1546                 :            :             {
    1547                 :      14696 :               vardecl* g2 = s.globals[j];
    1548 [ +  - ][ -  + ]:      14696 :               if (g->name == g2->name)
    1549                 :            :                 {
    1550                 :          0 :                   s.print_error (semantic_error (_("conflicting global variables"), 
    1551 [ #  # ][ #  # ]:          0 :                                                  g->tok, g2->tok));
         [ #  # ][ #  # ]
    1552                 :            :                 }
    1553                 :            :             }
    1554         [ +  - ]:       2283 :           s.globals.push_back (g);
    1555                 :            :         }
    1556                 :            : 
    1557         [ +  + ]:     154800 :       for (unsigned i=0; i<dome->functions.size(); i++)
    1558                 :            :         {
    1559                 :     149299 :           functiondecl* f = dome->functions[i];
    1560         [ +  - ]:     149299 :           functiondecl* f2 = s.functions[f->name];
    1561 [ +  + ][ +  + ]:     149299 :           if (f2 && f != f2)
    1562                 :            :             {
    1563                 :          1 :               s.print_error (semantic_error (_("conflicting functions"), 
    1564 [ +  - ][ +  - ]:          1 :                                              f->tok, f2->tok));
         [ +  - ][ +  - ]
    1565                 :            :             }
    1566         [ +  - ]:     149299 :           s.functions[f->name] = f;
    1567                 :            :         }
    1568                 :            : 
    1569                 :            :       // NB: embeds don't conflict with each other
    1570         [ +  + ]:       9903 :       for (unsigned i=0; i<dome->embeds.size(); i++)
    1571         [ +  - ]:       4402 :         s.embeds.push_back (dome->embeds[i]);
    1572                 :            : 
    1573                 :            :       // Pass 2: derive probes and resolve any further symbols in the
    1574                 :            :       // derived results.
    1575                 :            : 
    1576         [ +  + ]:      10035 :       for (unsigned i=0; i<dome->probes.size(); i++)
    1577                 :            :         {
    1578         [ +  - ]:       4534 :           assert_no_interrupts();
    1579                 :       4534 :           probe* p = dome->probes [i];
    1580         [ +  - ]:       4534 :           vector<derived_probe*> dps;
    1581                 :            : 
    1582                 :            :           // much magic happens here: probe alias expansion, wildcard
    1583                 :            :           // matching, low-level derived_probe construction.
    1584         [ +  - ]:       4534 :           derive_probes (s, p, dps);
    1585                 :            : 
    1586         [ +  + ]:     360355 :           for (unsigned j=0; j<dps.size(); j++)
    1587                 :            :             {
    1588         [ +  - ]:     355821 :               assert_no_interrupts();
    1589                 :     355821 :               derived_probe* dp = dps[j];
    1590         [ +  - ]:     355821 :               s.probes.push_back (dp);
    1591         [ +  - ]:     355821 :               dp->join_group (s);
    1592                 :            : 
    1593                 :            :               try
    1594                 :            :                 {
    1595         [ +  + ]:     711642 :                   for (unsigned k=0; k<s.code_filters.size(); k++)
    1596         [ +  - ]:     355821 :                     s.code_filters[k]->replace (dp->body);
    1597                 :            : 
    1598                 :     355821 :                   sym.current_function = 0;
    1599                 :     355821 :                   sym.current_probe = dp;
    1600         [ +  - ]:     355821 :                   dp->body->visit (& sym);
    1601                 :            : 
    1602                 :            :                   // Process the probe-point condition expression.
    1603                 :     355821 :                   sym.current_function = 0;
    1604                 :     355821 :                   sym.current_probe = 0;
    1605 [ +  - ][ +  + ]:     355821 :                   if (dp->sole_location()->condition)
    1606 [ +  - ][ +  + ]:         17 :                     dp->sole_location()->condition->visit (& sym);
    1607                 :            :                 }
    1608         [ -  + ]:          4 :               catch (const semantic_error& e)
    1609                 :            :                 {
    1610         [ -  + ]:          2 :                   s.print_error (e);
    1611                 :            :                 }
    1612                 :            :             }
    1613         [ +  - ]:       4534 :         }
    1614                 :            : 
    1615                 :            :       // Pass 3: process functions
    1616                 :            : 
    1617         [ +  + ]:     248476 :       for (unsigned i=0; i<dome->functions.size(); i++)
    1618                 :            :         {
    1619         [ +  - ]:     242975 :           assert_no_interrupts();
    1620                 :     242975 :           functiondecl* fd = dome->functions[i];
    1621                 :            : 
    1622                 :            :           try
    1623                 :            :             {
    1624         [ +  + ]:     485950 :               for (unsigned j=0; j<s.code_filters.size(); j++)
    1625         [ +  - ]:     242975 :                 s.code_filters[j]->replace (fd->body);
    1626                 :            : 
    1627                 :     242975 :               sym.current_function = fd;
    1628                 :     242975 :               sym.current_probe = 0;
    1629         [ +  - ]:     242975 :               fd->body->visit (& sym);
    1630                 :            :             }
    1631         [ #  # ]:            :           catch (const semantic_error& e)
    1632                 :            :             {
    1633         [ #  # ]:            :               s.print_error (e);
    1634                 :            :             }
    1635                 :            :         }
    1636                 :            :     }
    1637                 :            : 
    1638                 :            :   // Inform all derived_probe builders that we're done with
    1639                 :            :   // all resolution, so it's time to release caches.
    1640         [ +  - ]:       1218 :   s.pattern_root->build_no_more (s);
    1641                 :            : 
    1642         [ +  + ]:       1218 :   if(s.systemtap_v_check){ 
    1643         [ +  + ]:          6 :     for(unsigned i=0;i<s.globals.size();i++){
    1644         [ -  + ]:          4 :       if(s.globals[i]->systemtap_v_conditional)
    1645 [ #  # ][ #  # ]:          0 :         s.print_warning(_("This global uses tapset constructs that are dependent on systemtap version"), s.globals[i]->tok);
                 [ #  # ]
    1646                 :            :     }
    1647                 :            : 
    1648 [ +  - ][ +  - ]:        273 :     for(map<string, functiondecl*>::const_iterator i=s.functions.begin();i != s.functions.end();++i){
                 [ +  + ]
    1649 [ +  - ][ -  + ]:        271 :       if(i->second->systemtap_v_conditional)
    1650 [ #  # ][ #  # ]:          0 :         s.print_warning(_("This function uses tapset constructs that are dependent on systemtap version"), i->second->tok);
         [ #  # ][ #  # ]
    1651                 :            :     }
    1652                 :            : 
    1653         [ +  + ]:          4 :     for(unsigned i=0;i<s.probes.size();i++){
    1654         [ +  - ]:          2 :       vector<probe*> sysvc;
    1655         [ +  - ]:          2 :       s.probes[i]->collect_derivation_chain(sysvc);
    1656         [ +  + ]:          8 :       for(unsigned j=0;j<sysvc.size();j++){
    1657         [ -  + ]:          6 :         if(sysvc[j]->systemtap_v_conditional)
    1658 [ #  # ][ #  # ]:          0 :           s.print_warning(_("This probe uses tapset constructs that are dependent on systemtap version"), sysvc[j]->tok);
                 [ #  # ]
    1659 [ +  - ][ +  + ]:          6 :         if(sysvc[j]->get_alias() && sysvc[j]->get_alias()->systemtap_v_conditional)
         [ +  - ][ +  - ]
                 [ +  + ]
    1660 [ +  - ][ +  - ]:          2 :           s.print_warning(_("This alias uses tapset constructs that are dependent on systemtap version"), sysvc[j]->get_alias()->tok);
         [ +  - ][ +  - ]
    1661                 :            :       }
    1662         [ +  - ]:          2 :     }
    1663                 :            :   }
    1664                 :            : 
    1665 [ +  - ][ +  - ]:       1218 :   return s.num_errors(); // all those print_error calls
    1666                 :            : }
    1667                 :            : 
    1668                 :            : 
    1669                 :            : // Keep unread global variables for probe end value display.
    1670                 :       1036 : void add_global_var_display (systemtap_session& s)
    1671                 :            : {
    1672                 :            :   // Don't generate synthetic end probes when in listings mode;
    1673                 :            :   // it would clutter up the list of probe points with "end ...".
    1674         [ +  + ]:       1036 :   if (s.listing_mode) return;
    1675                 :            : 
    1676         [ +  - ]:        975 :   varuse_collecting_visitor vut(s);
    1677                 :            : 
    1678         [ +  + ]:     342698 :   for (unsigned i=0; i<s.probes.size(); i++)
    1679                 :            :     {
    1680         [ +  + ]:     341724 :       s.probes[i]->body->visit (& vut);
    1681                 :            : 
    1682 [ +  - ][ +  + ]:     341723 :       if (s.probes[i]->sole_location()->condition)
    1683 [ +  - ][ +  - ]:         14 :         s.probes[i]->sole_location()->condition->visit (& vut);
    1684                 :            :     }
    1685                 :            : 
    1686         [ +  + ]:       4790 :   for (unsigned g=0; g < s.globals.size(); g++)
    1687                 :            :     {
    1688                 :       3816 :       vardecl* l = s.globals[g];
    1689 [ +  - ][ +  - ]:      11539 :       if ((vut.read.find (l) != vut.read.end()
           [ +  +  +  +  
           -  + ][ +  - ]
         [ +  - ][ +  +  
             #  #  #  # ]
    1690 [ +  - ][ +  - ]:       7506 :            && vut.used.find (l) != vut.used.end())
         [ +  + ][ +  + ]
           [ #  #  #  # ]
    1691 [ +  - ][ +  - ]:       4033 :           || vut.written.find (l) == vut.written.end())
         [ +  + ][ +  + ]
           [ #  #  #  # ]
    1692                 :       3599 :         continue;
    1693                 :            : 
    1694                 :            :       // Don't generate synthetic end probes for unread globals
    1695                 :            :       // declared only within tapsets. (RHBZ 468139), but rather
    1696                 :            :       // only within the end-user script.
    1697                 :            : 
    1698                 :        217 :       bool tapset_global = false;
    1699         [ +  + ]:      19356 :       for (size_t m=0; m < s.library_files.size(); m++)
    1700                 :            :         {
    1701         [ +  + ]:      35169 :           for (size_t n=0; n < s.library_files[m]->globals.size(); n++)
    1702                 :            :             {
    1703 [ +  - ][ +  + ]:      16113 :               if (l->name == s.library_files[m]->globals[n]->name)
    1704                 :         83 :                 {tapset_global = true; break;}
    1705                 :            :             }
    1706                 :            :         }
    1707         [ +  + ]:        217 :       if (tapset_global)
    1708                 :         83 :         continue;
    1709                 :            : 
    1710 [ +  - ][ +  - ]:        134 :       probe_point::component* c = new probe_point::component("end");
         [ +  - ][ +  - ]
    1711 [ +  - ][ +  - ]:        134 :       probe_point* pl = new probe_point;
    1712         [ +  - ]:        134 :       pl->components.push_back (c);
    1713                 :            : 
    1714         [ +  - ]:        134 :       vector<derived_probe*> dps;
    1715 [ +  - ][ +  - ]:        134 :       block *b = new block;
    1716                 :        134 :       b->tok = l->tok;
    1717                 :            : 
    1718 [ +  - ][ +  - ]:        134 :       probe* p = new probe;
    1719                 :        134 :       p->tok = l->tok;
    1720         [ +  - ]:        134 :       p->locations.push_back (pl);
    1721                 :            : 
    1722                 :            :       // Create a symbol
    1723 [ +  - ][ +  - ]:        134 :       symbol* g_sym = new symbol;
    1724         [ +  - ]:        134 :       g_sym->name = l->name;
    1725                 :        134 :       g_sym->tok = l->tok;
    1726                 :        134 :       g_sym->type = l->type;
    1727                 :        134 :       g_sym->referent = l;
    1728                 :            : 
    1729 [ +  - ][ +  - ]:        134 :       token* print_tok = new token(*l->tok);
    1730                 :        134 :       print_tok->type = tok_identifier;
    1731         [ +  - ]:        134 :       print_tok->content = "printf";
    1732                 :            : 
    1733         [ +  - ]:        134 :       print_format* pf = print_format::create(print_tok);
    1734         [ +  - ]:        134 :       pf->raw_components += l->name;
    1735                 :            : 
    1736         [ +  + ]:        134 :       if (l->index_types.size() == 0) // Scalar
    1737                 :            :         {
    1738         [ +  + ]:         36 :           if (l->type == pe_stats)
    1739 [ +  - ][ +  - ]:          5 :             if (strverscmp(s.compatible.c_str(), "1.4") >= 0)
    1740         [ +  - ]:          5 :               pf->raw_components += " @count=%#d @min=%#d @max=%#d @sum=%#d @avg=%#d\\n";
    1741                 :            :                     else
    1742         [ #  # ]:          0 :               pf->raw_components += " @count=%#x @min=%#x @max=%#x @sum=%#x @avg=%#x\\n";
    1743         [ +  + ]:         31 :           else if (l->type == pe_string)
    1744         [ +  - ]:          5 :             pf->raw_components += "=\"%#s\"\\n";
    1745                 :            :           else
    1746         [ +  - ]:         26 :             pf->raw_components += "=%#x\\n";
    1747 [ +  - ][ +  - ]:         36 :           pf->components = print_format::string_to_components(pf->raw_components);
                 [ +  - ]
    1748 [ +  - ][ +  - ]:         36 :           expr_statement* feb = new expr_statement;
    1749                 :         36 :           feb->value = pf;
    1750                 :         36 :           feb->tok = print_tok;
    1751         [ +  + ]:         36 :           if (l->type == pe_stats)
    1752                 :            :             {
    1753                 :            :               struct stat_op* so [5];
    1754                 :          5 :               const stat_component_type stypes[] = {sc_count, sc_min, sc_max, sc_sum, sc_average};
    1755                 :            : 
    1756         [ +  + ]:         30 :               for (unsigned si = 0;
    1757                 :            :                    si < (sizeof(so)/sizeof(struct stat_op*));
    1758                 :            :                    si++)
    1759                 :            :                 {
    1760 [ +  - ][ +  - ]:         25 :                   so[si]= new stat_op;
    1761                 :         25 :                   so[si]->ctype = stypes[si];
    1762                 :         25 :                   so[si]->type = pe_long;
    1763                 :         25 :                   so[si]->stat = g_sym;
    1764                 :         25 :                   so[si]->tok = l->tok;
    1765         [ +  - ]:         25 :                   pf->args.push_back(so[si]);
    1766                 :            :                 }
    1767                 :            :             }
    1768                 :            :           else
    1769         [ +  - ]:         31 :             pf->args.push_back(g_sym);
    1770                 :            : 
    1771                 :            :           /* PR7053: Checking empty aggregate for global variable */
    1772         [ +  + ]:         36 :           if (l->type == pe_stats) {
    1773 [ +  - ][ +  - ]:          5 :               stat_op *so= new stat_op;
    1774                 :          5 :               so->ctype = sc_count;
    1775                 :          5 :               so->type = pe_long;
    1776                 :          5 :               so->stat = g_sym;
    1777                 :          5 :               so->tok = l->tok;
    1778 [ +  - ][ +  - ]:          5 :               comparison *be = new comparison;
    1779         [ +  - ]:          5 :               be->op = ">";
    1780                 :          5 :               be->tok = l->tok;
    1781                 :          5 :               be->left = so;
    1782 [ +  - ][ +  - ]:          5 :               be->right = new literal_number(0);
    1783                 :            : 
    1784                 :            :               /* Create printf @count=0x0 in else block */
    1785         [ +  - ]:          5 :               print_format* pf_0 = print_format::create(print_tok);
    1786         [ +  - ]:          5 :               pf_0->raw_components += l->name;
    1787         [ +  - ]:          5 :               pf_0->raw_components += " @count=0x0\\n";
    1788 [ +  - ][ +  - ]:          5 :               pf_0->components = print_format::string_to_components(pf_0->raw_components);
                 [ +  - ]
    1789 [ +  - ][ +  - ]:          5 :               expr_statement* feb_else = new expr_statement;
    1790                 :          5 :               feb_else->value = pf_0;
    1791                 :          5 :               feb_else->tok = print_tok;
    1792 [ +  - ][ +  - ]:          5 :               if_statement *ifs = new if_statement;
    1793                 :          5 :               ifs->tok = l->tok;
    1794                 :          5 :               ifs->condition = be;
    1795                 :          5 :               ifs->thenblock = feb ;
    1796                 :          5 :               ifs->elseblock = feb_else;
    1797         [ +  - ]:          5 :               b->statements.push_back(ifs);
    1798                 :            :             }
    1799                 :            :           else /* other non-stat cases */
    1800         [ +  - ]:         31 :             b->statements.push_back(feb);
    1801                 :            :         }
    1802                 :            :       else                      // Array
    1803                 :            :         {
    1804                 :         98 :           int idx_count = l->index_types.size();
    1805                 :         98 :           symbol* idx_sym[idx_count];
    1806                 :         98 :           vardecl* idx_v[idx_count];
    1807                 :            :           // Create a foreach loop
    1808 [ +  - ][ +  - ]:         98 :           foreach_loop* fe = new foreach_loop;
    1809                 :         98 :           fe->sort_direction = -1; // imply decreasing sort on value
    1810                 :         98 :           fe->sort_column = 0;     // as in   foreach ([a,b,c] in array-) { }
    1811                 :         98 :           fe->sort_aggr = sc_none; // as in default @count
    1812                 :         98 :           fe->value = NULL;
    1813                 :         98 :           fe->limit = NULL;
    1814                 :         98 :           fe->tok = l->tok;
    1815                 :            : 
    1816                 :            :           // Create indices for the foreach loop
    1817         [ +  + ]:        422 :           for (int i=0; i < idx_count; i++)
    1818                 :            :             {
    1819                 :            :               char *idx_name;
    1820         [ -  + ]:        324 :               if (asprintf (&idx_name, "idx%d", i) < 0) {
    1821 [ #  # ][ #  # ]:          0 :                delete pf;
    1822 [ #  # ][ #  # ]:          0 :                delete b;
    1823 [ #  # ][ #  # ]:          0 :                delete p;
    1824 [ #  # ][ #  # ]:          0 :                delete g_sym;
    1825 [ #  # ][ #  # ]:          0 :                delete fe;
    1826                 :            :                return;
    1827                 :            :               }
    1828 [ +  - ][ +  - ]:        324 :               idx_sym[i] = new symbol;
    1829         [ +  - ]:        324 :               idx_sym[i]->name = idx_name;
    1830                 :        324 :               idx_sym[i]->tok = l->tok;
    1831 [ +  - ][ +  - ]:        324 :               idx_v[i] = new vardecl;
    1832         [ +  - ]:        324 :               idx_v[i]->name = idx_name;
    1833                 :        324 :               idx_v[i]->type = l->index_types[i];
    1834                 :        324 :               idx_v[i]->tok = l->tok;
    1835                 :        324 :               idx_sym[i]->referent = idx_v[i];
    1836         [ +  - ]:        324 :               fe->indexes.push_back (idx_sym[i]);
    1837                 :            :             }
    1838                 :            : 
    1839                 :            :           // Create a printf for the foreach loop
    1840         [ +  - ]:         98 :           pf->raw_components += "[";
    1841         [ +  + ]:        422 :           for (int i=0; i < idx_count; i++)
    1842                 :            :             {
    1843         [ +  + ]:        324 :               if (i > 0)
    1844         [ +  - ]:        226 :                 pf->raw_components += ",";
    1845         [ +  + ]:        324 :               if (l->index_types[i] == pe_string)
    1846         [ +  - ]:        147 :                 pf->raw_components += "\"%#s\"";
    1847                 :            :               else
    1848         [ +  - ]:        177 :                 pf->raw_components += "%#d";
    1849                 :            :             }
    1850         [ +  - ]:         98 :           pf->raw_components += "]";
    1851         [ +  + ]:         98 :           if (l->type == pe_stats)
    1852 [ +  - ][ +  - ]:         32 :             if (strverscmp(s.compatible.c_str(), "1.4") >= 0)
    1853         [ +  - ]:         32 :               pf->raw_components += " @count=%#d @min=%#d @max=%#d @sum=%#d @avg=%#d\\n";
    1854                 :            :             else
    1855         [ #  # ]:          0 :               pf->raw_components += " @count=%#x @min=%#x @max=%#x @sum=%#x @avg=%#x\\n";
    1856         [ +  + ]:         66 :           else if (l->type == pe_string)
    1857         [ +  - ]:         15 :             pf->raw_components += "=\"%#s\"\\n";
    1858                 :            :           else
    1859         [ +  - ]:         51 :             pf->raw_components += "=%#x\\n";
    1860                 :            : 
    1861                 :            :           // Create an index for the array
    1862 [ +  - ][ +  - ]:         98 :           struct arrayindex* ai = new arrayindex;
    1863                 :         98 :           ai->tok = l->tok;
    1864                 :         98 :           ai->base = g_sym;
    1865                 :            : 
    1866         [ +  + ]:        422 :           for (int i=0; i < idx_count; i++)
    1867                 :            :             {
    1868         [ +  - ]:        324 :               ai->indexes.push_back (idx_sym[i]);
    1869         [ +  - ]:        324 :               pf->args.push_back(idx_sym[i]);
    1870                 :            :             }
    1871         [ +  + ]:         98 :           if (l->type == pe_stats)
    1872                 :            :             {
    1873                 :            :               struct stat_op* so [5];
    1874                 :         32 :               const stat_component_type stypes[] = {sc_count, sc_min, sc_max, sc_sum, sc_average};
    1875                 :            : 
    1876                 :         32 :               ai->type = pe_stats;
    1877         [ +  + ]:        192 :               for (unsigned si = 0;
    1878                 :            :                    si < (sizeof(so)/sizeof(struct stat_op*));
    1879                 :            :                    si++)
    1880                 :            :                 {
    1881 [ +  - ][ +  - ]:        160 :                   so[si]= new stat_op;
    1882                 :        160 :                   so[si]->ctype = stypes[si];
    1883                 :        160 :                   so[si]->type = pe_long;
    1884                 :        160 :                   so[si]->stat = ai;
    1885                 :        160 :                   so[si]->tok = l->tok;
    1886         [ +  - ]:        160 :                   pf->args.push_back(so[si]);
    1887                 :            :                 }
    1888                 :            :             }
    1889                 :            :           else
    1890                 :            :             {
    1891                 :            :               // Create value for the foreach loop
    1892 [ +  - ][ +  - ]:         66 :               fe->value = new symbol;
    1893         [ +  - ]:         66 :               fe->value->name = "val";
    1894                 :         66 :               fe->value->tok = l->tok;
    1895         [ +  - ]:         66 :               pf->args.push_back(fe->value);
    1896                 :            :             }
    1897                 :            : 
    1898 [ +  - ][ +  - ]:         98 :           pf->components = print_format::string_to_components(pf->raw_components);
                 [ +  - ]
    1899 [ +  - ][ +  - ]:         98 :           expr_statement* feb = new expr_statement;
    1900                 :         98 :           feb->value = pf;
    1901                 :         98 :           feb->tok = l->tok;
    1902                 :         98 :           fe->base = g_sym;
    1903                 :         98 :           fe->block = (statement*)feb;
    1904 [ +  - ][ -  + ]:         98 :           b->statements.push_back(fe);
    1905                 :            :         }
    1906                 :            : 
    1907                 :            :       // Add created probe
    1908                 :        134 :       p->body = b;
    1909         [ +  - ]:        134 :       derive_probes (s, p, dps);
    1910         [ +  + ]:        268 :       for (unsigned i = 0; i < dps.size(); i++)
    1911                 :            :         {
    1912                 :        134 :           derived_probe* dp = dps[i];
    1913         [ +  - ]:        134 :           s.probes.push_back (dp);
    1914         [ +  - ]:        134 :           dp->join_group (s);
    1915                 :            :         }
    1916                 :            :       // Repopulate symbol and type info
    1917         [ +  - ]:        134 :       symresolution_info sym (s);
    1918                 :        134 :       sym.current_function = 0;
    1919                 :        134 :       sym.current_probe = dps[0];
    1920         [ +  - ]:        134 :       dps[0]->body->visit (& sym);
    1921                 :            : 
    1922         [ +  - ]:        134 :       semantic_pass_types(s);
    1923                 :            :       // Mark that variable is read
    1924         [ +  - ]:        134 :       vut.read.insert (l);
    1925 [ +  - ][ +  - ]:       4852 :     }
         [ +  - ][ +  - ]
                 [ +  - ]
    1926                 :            : }
    1927                 :            : 
    1928                 :            : int
    1929                 :       1218 : semantic_pass (systemtap_session& s)
    1930                 :            : {
    1931                 :       1218 :   int rc = 0;
    1932                 :            : 
    1933                 :            :   try
    1934                 :            :     {
    1935         [ +  - ]:       1218 :       s.register_library_aliases();
    1936         [ +  - ]:       1218 :       register_standard_tapsets(s);
    1937                 :            : 
    1938 [ +  - ][ +  - ]:       1218 :       if (rc == 0) rc = semantic_pass_symbols (s);
    1939 [ +  + ][ +  - ]:       1218 :       if (rc == 0) rc = semantic_pass_conditions (s);
    1940 [ +  + ][ +  + ]:       1218 :       if (rc == 0) rc = semantic_pass_optimize1 (s);
    1941 [ +  + ][ +  + ]:       1209 :       if (rc == 0) rc = semantic_pass_types (s);
    1942 [ +  + ][ +  - ]:       1182 :       if (rc == 0) gen_dfa_table(s); // TODOXXX set rc?
    1943 [ +  + ][ +  + ]:       1182 :       if (rc == 0) add_global_var_display (s);
    1944 [ +  + ][ +  - ]:       1181 :       if (rc == 0) rc = semantic_pass_optimize2 (s);
    1945 [ +  + ][ +  - ]:       1181 :       if (rc == 0) rc = semantic_pass_vars (s);
    1946 [ +  + ][ +  - ]:       1181 :       if (rc == 0) rc = semantic_pass_stats (s);
    1947 [ +  + ][ +  - ]:       1181 :       if (rc == 0) embeddedcode_info_pass (s);
    1948                 :            : 
    1949 [ +  - ][ +  + ]:       1181 :       if (s.num_errors() == 0 && s.probes.size() == 0 && !s.listing_mode)
         [ +  + ][ -  + ]
                 [ -  + ]
    1950 [ #  # ][ #  # ]:          0 :         throw semantic_error (_("no probes found"));
    1951                 :            :     }
    1952         [ -  + ]:         74 :   catch (const semantic_error& e)
    1953                 :            :     {
    1954         [ -  + ]:         37 :       s.print_error (e);
    1955                 :         37 :       rc ++;
    1956                 :            :     }
    1957                 :            : 
    1958                 :            :   // PR11443
    1959                 :            :   // NB: listing mode only cares whether we have any probes,
    1960                 :            :   // so all previous error conditions are disregarded.
    1961         [ +  + ]:       1218 :   if (s.listing_mode)
    1962                 :         62 :     rc = s.probes.empty();
    1963                 :            : 
    1964                 :       1218 :   return rc;
    1965                 :            : }
    1966                 :            : 
    1967                 :            : 
    1968                 :            : // ------------------------------------------------------------------------
    1969                 :            : // semantic processing: symbol resolution
    1970                 :            : 
    1971                 :            : 
    1972                 :       1352 : symresolution_info::symresolution_info (systemtap_session& s):
    1973                 :       1352 :   session (s), current_function (0), current_probe (0)
    1974                 :            : {
    1975                 :       1352 : }
    1976                 :            : 
    1977                 :            : 
    1978                 :            : void
    1979                 :     541932 : symresolution_info::visit_block (block* e)
    1980                 :            : {
    1981         [ +  + ]:    1228493 :   for (unsigned i=0; i<e->statements.size(); i++)
    1982                 :            :     {
    1983                 :            :       try
    1984                 :            :         {
    1985         [ +  + ]:     686561 :           e->statements[i]->visit (this);
    1986                 :            :         }
    1987         [ -  + ]:         24 :       catch (const semantic_error& e)
    1988                 :            :         {
    1989         [ -  + ]:         12 :           session.print_error (e);
    1990                 :            :         }
    1991                 :            :     }
    1992                 :     541932 : }
    1993                 :            : 
    1994                 :            : 
    1995                 :            : void
    1996                 :        406 : symresolution_info::visit_foreach_loop (foreach_loop* e)
    1997                 :            : {
    1998         [ +  + ]:       1185 :   for (unsigned i=0; i<e->indexes.size(); i++)
    1999         [ +  - ]:        779 :     e->indexes[i]->visit (this);
    2000                 :            : 
    2001                 :        406 :   symbol *array = NULL;
    2002                 :        406 :   hist_op *hist = NULL;
    2003         [ +  - ]:        406 :   classify_indexable (e->base, array, hist);
    2004                 :            : 
    2005         [ +  + ]:        406 :   if (array)
    2006                 :            :     {
    2007         [ +  - ]:        397 :       if (!array->referent)
    2008                 :            :         {
    2009         [ +  - ]:        397 :           vardecl* d = find_var (array->name, e->indexes.size (), array->tok);
    2010         [ +  - ]:        397 :           if (d)
    2011                 :        397 :             array->referent = d;
    2012                 :            :           else
    2013                 :            :             {
    2014         [ #  # ]:          0 :               stringstream msg;
    2015 [ #  # ][ #  # ]:          0 :               msg << _F("unresolved arity-%zu global array %s, missing global declaration?",
                 [ #  # ]
    2016         [ #  # ]:          0 :                         e->indexes.size(), array->name.c_str());
    2017 [ #  # ][ #  # ]:          0 :               throw semantic_error (msg.str(), e->tok);
    2018                 :            :             }
    2019                 :            :         }
    2020                 :            :     }
    2021                 :            :   else
    2022                 :            :     {
    2023         [ -  + ]:          9 :       assert (hist);
    2024         [ +  - ]:          9 :       hist->visit (this);
    2025                 :            :     }
    2026                 :            : 
    2027         [ +  + ]:        406 :   if (e->value)
    2028         [ +  - ]:         73 :     e->value->visit (this);
    2029                 :            : 
    2030         [ +  + ]:        406 :   if (e->limit)
    2031         [ +  - ]:         62 :     e->limit->visit (this);
    2032                 :            : 
    2033         [ +  - ]:        406 :   e->block->visit (this);
    2034                 :        406 : }
    2035                 :            : 
    2036                 :            : 
    2037                 :            : struct
    2038         [ -  + ]:       3499 : delete_statement_symresolution_info:
    2039                 :            :   public traversing_visitor
    2040                 :            : {
    2041                 :            :   symresolution_info *parent;
    2042                 :            : 
    2043                 :       3499 :   delete_statement_symresolution_info (symresolution_info *p):
    2044                 :       3499 :     parent(p)
    2045                 :       3499 :   {}
    2046                 :            : 
    2047                 :       3306 :   void visit_arrayindex (arrayindex* e)
    2048                 :            :   {
    2049                 :       3306 :     parent->visit_arrayindex (e);
    2050                 :       3306 :   }
    2051                 :          0 :   void visit_functioncall (functioncall* e)
    2052                 :            :   {
    2053                 :          0 :     parent->visit_functioncall (e);
    2054                 :          0 :   }
    2055                 :            : 
    2056                 :        193 :   void visit_symbol (symbol* e)
    2057                 :            :   {
    2058         [ -  + ]:        193 :     if (e->referent)
    2059                 :        193 :       return;
    2060                 :            : 
    2061                 :        193 :     vardecl* d = parent->find_var (e->name, -1, e->tok);
    2062         [ +  - ]:        193 :     if (d)
    2063                 :        193 :       e->referent = d;
    2064                 :            :     else
    2065 [ #  # ][ #  # ]:          0 :       throw semantic_error (_("unresolved array in delete statement"), e->tok);
    2066                 :            :   }
    2067                 :            : };
    2068                 :            : 
    2069                 :            : void
    2070                 :       3499 : symresolution_info::visit_delete_statement (delete_statement* s)
    2071                 :            : {
    2072         [ +  - ]:       3499 :   delete_statement_symresolution_info di (this);
    2073 [ +  - ][ +  - ]:       3499 :   s->value->visit (&di);
    2074                 :       3499 : }
    2075                 :            : 
    2076                 :            : 
    2077                 :            : void
    2078                 :     712999 : symresolution_info::visit_symbol (symbol* e)
    2079                 :            : {
    2080         [ +  + ]:     712999 :   if (e->referent)
    2081                 :     712996 :     return;
    2082                 :            : 
    2083                 :     697261 :   vardecl* d = find_var (e->name, 0, e->tok);
    2084         [ +  + ]:     697259 :   if (d)
    2085                 :     503489 :     e->referent = d;
    2086                 :            :   else
    2087                 :            :     {
    2088                 :            :       // new local
    2089 [ +  - ][ +  - ]:     193770 :       vardecl* v = new vardecl;
    2090         [ +  - ]:     193770 :       v->name = e->name;
    2091                 :     193770 :       v->tok = e->tok;
    2092         [ +  - ]:     193770 :       v->set_arity(0, e->tok);
    2093         [ +  + ]:     193770 :       if (current_function)
    2094         [ +  - ]:       9042 :         current_function->locals.push_back (v);
    2095         [ +  + ]:     184728 :       else if (current_probe)
    2096         [ +  - ]:     184727 :         current_probe->locals.push_back (v);
    2097                 :            :       else
    2098                 :            :         // must be probe-condition expression
    2099 [ +  - ][ +  - ]:          1 :         throw semantic_error (_("probe condition must not reference undeclared global"), e->tok);
    2100                 :     193769 :       e->referent = v;
    2101                 :            :     }
    2102                 :            : }
    2103                 :            : 
    2104                 :            : 
    2105                 :            : void
    2106                 :      84455 : symresolution_info::visit_arrayindex (arrayindex* e)
    2107                 :            : {
    2108         [ +  + ]:     183934 :   for (unsigned i=0; i<e->indexes.size(); i++)
    2109         [ +  - ]:      99479 :     e->indexes[i]->visit (this);
    2110                 :            : 
    2111                 :      84455 :   symbol *array = NULL;
    2112                 :      84455 :   hist_op *hist = NULL;
    2113         [ +  - ]:      84455 :   classify_indexable(e->base, array, hist);
    2114                 :            : 
    2115         [ +  + ]:      84455 :   if (array)
    2116                 :            :     {
    2117         [ +  + ]:      84429 :       if (array->referent)
    2118                 :      84449 :         return;
    2119                 :            : 
    2120         [ +  + ]:      80056 :       vardecl* d = find_var (array->name, e->indexes.size (), array->tok);
    2121         [ +  + ]:      80054 :       if (d)
    2122                 :      80050 :         array->referent = d;
    2123                 :            :       else
    2124                 :            :         {
    2125         [ +  - ]:          4 :           stringstream msg;
    2126 [ +  - ][ +  - ]:          8 :           msg << _F("unresolved arity-%zu global array %s, missing global declaration?",
                 [ +  - ]
    2127         [ +  - ]:          4 :                     e->indexes.size(), array->name.c_str());
    2128 [ +  - ][ +  - ]:          6 :           throw semantic_error (msg.str(), e->tok);
    2129                 :            :         }
    2130                 :            :     }
    2131                 :            :   else
    2132                 :            :     {
    2133         [ -  + ]:         26 :       assert (hist);
    2134         [ +  - ]:      84449 :       hist->visit (this);
    2135                 :            :     }
    2136                 :            : }
    2137                 :            : 
    2138                 :            : 
    2139                 :            : void
    2140                 :     440764 : symresolution_info::visit_functioncall (functioncall* e)
    2141                 :            : {
    2142                 :            :   // XXX: we could relax this, if we're going to examine the
    2143                 :            :   // vartracking data recursively.  See testsuite/semko/fortytwo.stp.
    2144 [ +  + ][ +  + ]:     440764 :   if (! (current_function || current_probe))
    2145                 :            :     {
    2146                 :            :       // must be probe-condition expression
    2147 [ +  - ][ +  - ]:          1 :       throw semantic_error (_("probe condition must not reference function"), e->tok);
    2148                 :            :     }
    2149                 :            : 
    2150         [ +  + ]:     612104 :   for (unsigned i=0; i<e->args.size(); i++)
    2151                 :     171341 :     e->args[i]->visit (this);
    2152                 :            : 
    2153         [ +  + ]:     440763 :   if (e->referent)
    2154                 :     440759 :     return;
    2155                 :            : 
    2156                 :     440343 :   functiondecl* d = find_function (e->function, e->args.size ());
    2157         [ +  + ]:     440343 :   if (d)
    2158                 :     440339 :     e->referent = d;
    2159                 :            :   else
    2160                 :            :     {
    2161         [ +  - ]:          4 :       stringstream msg;
    2162 [ +  - ][ +  - ]:          4 :       msg << _F("unresolved arity-%zu function", e->args.size());
                 [ +  - ]
    2163 [ +  - ][ +  - ]:          4 :       throw semantic_error (msg.str(), e->tok);
    2164                 :            :     }
    2165                 :            : }
    2166                 :            : 
    2167                 :            : /*find_var will return an argument other than zero if the name matches the var
    2168                 :            :  * name ie, if the current local name matches the name passed to find_var*/
    2169                 :            : vardecl*
    2170                 :     777907 : symresolution_info::find_var (const string& name, int arity, const token* tok)
    2171                 :            : {
    2172 [ +  + ][ +  + ]:     777907 :   if (current_function || current_probe)
    2173                 :            :     {
    2174                 :            :       // search locals
    2175                 :            :       vector<vardecl*>& locals = (current_function ?
    2176                 :            :                                   current_function->locals :
    2177         [ +  + ]:     777886 :                                   current_probe->locals);
    2178                 :            : 
    2179                 :            : 
    2180         [ +  + ]:    2286313 :       for (unsigned i=0; i<locals.size(); i++)
    2181         [ +  + ]:    1713732 :         if (locals[i]->name == name)
    2182                 :            :           {
    2183                 :     205305 :             locals[i]->set_arity (arity, tok);
    2184                 :     205305 :             return locals[i];
    2185                 :            :           }
    2186                 :            :     }
    2187                 :            : 
    2188                 :            :   // search function formal parameters (for scalars)
    2189 [ +  + ][ +  + ]:     572602 :   if (arity == 0 && current_function)
    2190         [ +  + ]:     164495 :     for (unsigned i=0; i<current_function->formal_args.size(); i++)
    2191         [ +  + ]:     154669 :       if (current_function->formal_args[i]->name == name)
    2192                 :            :         {
    2193                 :            :           // NB: no need to check arity here: formal args always scalar
    2194                 :     112718 :           current_function->formal_args[i]->set_arity (0, tok);
    2195                 :     112718 :           return current_function->formal_args[i];
    2196                 :            :         }
    2197                 :            : 
    2198                 :            :   // search processed globals
    2199         [ +  + ]:    4235898 :   for (unsigned i=0; i<session.globals.size(); i++)
    2200         [ +  + ]:    4041459 :     if (session.globals[i]->name == name)
    2201                 :            :       {
    2202         [ +  + ]:     265445 :         if (! session.suppress_warnings)
    2203                 :            :           {
    2204                 :     259173 :             vardecl* v = session.globals[i];
    2205                 :            :             // clog << "resolved " << *tok << " to global " << *v->tok << endl;
    2206         [ +  + ]:     259173 :             if (v->tok->location.file != tok->location.file)
    2207                 :            :               {
    2208                 :         40 :                 session.print_warning (_F("cross-file global variable reference to %s from",
    2209 [ +  - ][ +  - ]:         40 :                                           lex_cast(*v->tok).c_str()), tok);
         [ +  - ][ +  - ]
    2210                 :            :               }
    2211                 :            :           }
    2212                 :     265445 :         session.globals[i]->set_arity (arity, tok);
    2213                 :     265441 :         return session.globals[i];
    2214                 :            :       }
    2215                 :            : 
    2216                 :            :   // search library globals
    2217         [ +  + ]:   17280151 :   for (unsigned i=0; i<session.library_files.size(); i++)
    2218                 :            :     {
    2219                 :   17086377 :       stapfile* f = session.library_files[i];
    2220         [ +  + ]:   31647962 :       for (unsigned j=0; j<f->globals.size(); j++)
    2221                 :            :         {
    2222                 :   14562250 :           vardecl* g = f->globals[j];
    2223 [ +  - ][ +  + ]:   14562250 :           if (g->name == name)
    2224                 :            :             {
    2225         [ +  - ]:        665 :               g->set_arity (arity, tok);
    2226                 :            : 
    2227                 :            :               // put library into the queue if not already there
    2228 [ +  - ][ +  - ]:       1330 :               if (find (session.files.begin(), session.files.end(), f)
         [ +  - ][ +  + ]
    2229 [ +  - ][ +  - ]:        665 :                   == session.files.end())
    2230         [ +  - ]:        106 :                 session.files.push_back (f);
    2231                 :            : 
    2232                 :        665 :               return g;
    2233                 :            :             }
    2234                 :            :         }
    2235                 :            :     }
    2236                 :            : 
    2237                 :     777903 :   return 0;
    2238                 :            : }
    2239                 :            : 
    2240                 :            : 
    2241                 :            : functiondecl*
    2242                 :     440343 : symresolution_info::find_function (const string& name, unsigned arity)
    2243                 :            : {
    2244                 :            :   // the common path
    2245 [ +  - ][ +  + ]:     440343 :   if (session.functions.find(name) != session.functions.end())
    2246                 :            :     {
    2247                 :     200774 :       functiondecl* fd = session.functions[name];
    2248         [ -  + ]:     200774 :       assert (fd->name == name);
    2249         [ +  + ]:     200774 :       if (fd->formal_args.size() == arity)
    2250                 :     200773 :         return fd;
    2251                 :            : 
    2252                 :          1 :       session.print_warning (_F("mismatched arity-%zu function found", fd->formal_args.size()),
    2253         [ +  - ]:          1 :                              fd->tok);
    2254                 :            :       // and some semantic_error will shortly follow
    2255                 :            :     }
    2256                 :            : 
    2257                 :            :   // search library functions
    2258         [ +  + ]:    8563884 :   for (unsigned i=0; i<session.library_files.size(); i++)
    2259                 :            :     {
    2260                 :    8563880 :       stapfile* f = session.library_files[i];
    2261         [ +  + ]:  123143265 :       for (unsigned j=0; j<f->functions.size(); j++)
    2262         [ +  - ]:  115058517 :         if (f->functions[j]->name == name &&
           [ +  +  +  - ]
                 [ +  + ]
    2263                 :     239566 :             f->functions[j]->formal_args.size() == arity)
    2264                 :            :           {
    2265                 :            :             // put library into the queue if not already there
    2266                 :            :             if (0) // session.verbose_resolution
    2267                 :            :               cerr << _F("      function %s is defined from %s",
    2268                 :            :                          name.c_str(), f->name.c_str()) << endl;
    2269                 :            : 
    2270 [ +  - ][ +  - ]:     479132 :             if (find (session.files.begin(), session.files.end(), f)
         [ +  - ][ +  + ]
    2271 [ +  - ][ +  - ]:     239566 :                 == session.files.end())
    2272         [ +  - ]:       3761 :               session.files.push_back (f);
    2273                 :            :             // else .. print different message?
    2274                 :            : 
    2275                 :     239566 :             return f->functions[j];
    2276                 :            :           }
    2277                 :            :     }
    2278                 :            : 
    2279                 :     440343 :   return 0;
    2280                 :            : }
    2281                 :            : 
    2282                 :            : 
    2283                 :            : 
    2284                 :            : // ------------------------------------------------------------------------
    2285                 :            : // optimization
    2286                 :            : 
    2287                 :            : 
    2288                 :            : // Do away with functiondecls that are never (transitively) called
    2289                 :            : // from probes.
    2290                 :       2400 : void semantic_pass_opt1 (systemtap_session& s, bool& relaxed_p)
    2291                 :            : {
    2292         [ +  - ]:       2400 :   functioncall_traversing_visitor ftv;
    2293         [ +  + ]:     529985 :   for (unsigned i=0; i<s.probes.size(); i++)
    2294                 :            :     {
    2295         [ +  - ]:     527585 :       s.probes[i]->body->visit (& ftv);
    2296 [ +  - ][ +  + ]:     527585 :       if (s.probes[i]->sole_location()->condition)
    2297 [ +  - ][ +  - ]:         28 :         s.probes[i]->sole_location()->condition->visit (& ftv);
    2298                 :            :     }
    2299         [ +  - ]:       2400 :   vector<functiondecl*> new_unused_functions;
    2300 [ +  - ][ +  - ]:     490838 :   for (map<string,functiondecl*>::iterator it = s.functions.begin(); it != s.functions.end(); it++)
                 [ +  + ]
    2301                 :            :     {
    2302         [ +  - ]:     488438 :       functiondecl* fd = it->second;
    2303 [ +  - ][ +  - ]:     488438 :       if (ftv.traversed.find(fd) == ftv.traversed.end())
                 [ +  + ]
    2304                 :            :         {
    2305 [ +  - ][ +  + ]:      96396 :           if (fd->tok->location.file->name == s.user_file->name && ! fd->synthetic)// !tapset
         [ +  + ][ +  + ]
    2306 [ +  - ][ +  - ]:         27 :             s.print_warning (_F("Eliding unused function '%s'", fd->name.c_str()), fd->tok);
         [ +  - ][ +  - ]
    2307                 :            :           // s.functions.erase (it); // NB: can't, since we're already iterating upon it
    2308         [ +  - ]:      96396 :           new_unused_functions.push_back (fd);
    2309                 :      96396 :           relaxed_p = false;
    2310                 :            :         }
    2311                 :            :     }
    2312         [ +  + ]:      98796 :   for (unsigned i=0; i<new_unused_functions.size(); i++)
    2313                 :            :     {
    2314         [ +  - ]:      96396 :       map<string,functiondecl*>::iterator where = s.functions.find (new_unused_functions[i]->name);
    2315 [ +  - ][ -  + ]:      96396 :       assert (where != s.functions.end());
    2316         [ +  - ]:      96396 :       s.functions.erase (where);
    2317         [ -  + ]:      96396 :       if (s.tapset_compile_coverage)
    2318         [ #  # ]:          0 :         s.unused_functions.push_back (new_unused_functions[i]);
    2319 [ +  - ][ +  - ]:       2400 :     }
    2320                 :       2400 : }
    2321                 :            : 
    2322                 :            : 
    2323                 :            : // ------------------------------------------------------------------------
    2324                 :            : 
    2325                 :            : // Do away with local & global variables that are never
    2326                 :            : // written nor read.
    2327                 :       2400 : void semantic_pass_opt2 (systemtap_session& s, bool& relaxed_p, unsigned iterations)
    2328                 :            : {
    2329         [ +  - ]:       2400 :   varuse_collecting_visitor vut(s);
    2330                 :            : 
    2331         [ +  + ]:     529977 :   for (unsigned i=0; i<s.probes.size(); i++)
    2332                 :            :     {
    2333         [ +  + ]:     527585 :       s.probes[i]->body->visit (& vut);
    2334                 :            : 
    2335 [ +  - ][ +  + ]:     527577 :       if (s.probes[i]->sole_location()->condition)
    2336 [ +  - ][ +  - ]:         28 :         s.probes[i]->sole_location()->condition->visit (& vut);
    2337                 :            :     }
    2338                 :            : 
    2339                 :            :   // NB: Since varuse_collecting_visitor also traverses down
    2340                 :            :   // actually called functions, we don't need to explicitly
    2341                 :            :   // iterate over them.  Uncalled ones should have been pruned
    2342                 :            :   // in _opt1 above.
    2343                 :            :   //
    2344                 :            :   // for (unsigned i=0; i<s.functions.size(); i++)
    2345                 :            :   //   s.functions[i]->body->visit (& vut);
    2346                 :            : 
    2347                 :            :   // Now in vut.read/written, we have a mixture of all locals, globals
    2348                 :            : 
    2349         [ +  + ]:     529969 :   for (unsigned i=0; i<s.probes.size(); i++)
    2350         [ +  + ]:    1154399 :     for (unsigned j=0; j<s.probes[i]->locals.size(); /* see below */)
    2351                 :            :       {
    2352                 :     626822 :         vardecl* l = s.probes[i]->locals[j];
    2353                 :            : 
    2354                 :            :         // skip over "special" locals
    2355         [ +  + ]:     626822 :         if (l->synthetic) { j++; continue; }
    2356                 :            : 
    2357 [ +  - ][ +  - ]:    1384340 :         if (vut.read.find (l) == vut.read.end() &&
           [ +  +  +  + ]
         [ +  - ][ +  - ]
           [ +  +  #  #  
                   #  # ]
    2358 [ +  - ][ +  - ]:     762676 :             vut.written.find (l) == vut.written.end())
         [ +  + ][ +  + ]
           [ #  #  #  # ]
    2359                 :            :           {
    2360 [ +  - ][ +  + ]:      70539 :             if (l->tok->location.file->name == s.user_file->name) // !tapset
    2361 [ +  - ][ +  - ]:        114 :               s.print_warning (_F("Eliding unused variable '%s'", l->name.c_str()), l->tok);
         [ +  - ][ +  - ]
    2362         [ -  + ]:      70539 :             if (s.tapset_compile_coverage) {
    2363                 :          0 :               s.probes[i]->unused_locals.push_back
    2364         [ #  # ]:          0 :                       (s.probes[i]->locals[j]);
    2365                 :            :             }
    2366 [ +  - ][ +  - ]:      70539 :             s.probes[i]->locals.erase(s.probes[i]->locals.begin() + j);
                 [ +  - ]
    2367                 :      70539 :             relaxed_p = false;
    2368                 :            :             // don't increment j
    2369                 :            :           }
    2370                 :            :         else
    2371                 :            :           {
    2372 [ +  - ][ +  - ]:     551125 :             if (vut.written.find (l) == vut.written.end())
                 [ +  + ]
    2373 [ +  + ][ +  + ]:       2458 :               if (iterations == 0 && ! s.suppress_warnings)
    2374                 :            :                   {
    2375         [ +  - ]:         59 :                     stringstream o;
    2376                 :         59 :                     vector<vardecl*>::iterator it;
    2377 [ +  - ][ +  - ]:       1261 :                     for (it = s.probes[i]->locals.begin(); it != s.probes[i]->locals.end(); it++)
         [ +  - ][ +  - ]
                 [ +  + ]
    2378 [ +  - ][ +  + ]:       1202 :                       if (l->name != (*it)->name)
    2379 [ +  - ][ +  - ]:       1143 :                         o << " " <<  (*it)->name;
    2380 [ +  - ][ +  - ]:         77 :                     for (it = s.globals.begin(); it != s.globals.end(); it++)
         [ +  - ][ +  - ]
                 [ +  + ]
    2381 [ +  - ][ +  - ]:         18 :                       if (l->name != (*it)->name)
    2382 [ +  - ][ +  - ]:         18 :                         o << " " <<  (*it)->name;
    2383                 :            : 
    2384 [ +  - ][ +  - ]:        118 :                     s.print_warning (_F("never-assigned local variable '%s' %s",
                 [ +  - ]
    2385                 :            :                                      l->name.c_str(), (o.str() == "" ? "" :
    2386 [ +  - ][ +  + ]:        177 :                                      (_("(alternatives:") + o.str() + ")")).c_str()), l->tok);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  + ]
         [ +  - ][ +  + ]
         [ +  - ][ +  + ]
         [ +  - ][ #  #  
             #  #  #  # ]
    2387                 :            :                   }
    2388                 :     621664 :             j++;
    2389                 :            :           }
    2390                 :            :       }
    2391                 :            : 
    2392 [ +  - ][ +  - ]:     394409 :   for (map<string,functiondecl*>::iterator it = s.functions.begin(); it != s.functions.end(); it++)
                 [ +  + ]
    2393                 :            :     {
    2394         [ +  - ]:     392017 :       functiondecl *fd = it->second;
    2395         [ +  + ]:     401367 :       for (unsigned j=0; j<fd->locals.size(); /* see below */)
    2396                 :            :         {
    2397                 :       9350 :           vardecl* l = fd->locals[j];
    2398 [ +  - ][ +  - ]:      18726 :           if (vut.read.find (l) == vut.read.end() &&
           [ +  +  +  + ]
         [ +  - ][ +  - ]
           [ +  +  #  #  
                   #  # ]
    2399 [ +  - ][ +  - ]:       9376 :               vut.written.find (l) == vut.written.end())
         [ +  + ][ +  + ]
           [ #  #  #  # ]
    2400                 :            :             {
    2401 [ +  - ][ +  - ]:         12 :               if (l->tok->location.file->name == s.user_file->name) // !tapset
    2402 [ +  - ][ +  - ]:         12 :                 s.print_warning (_F("Eliding unused variable '%s'", l->name.c_str()), l->tok);
         [ +  - ][ +  - ]
    2403         [ -  + ]:         12 :               if (s.tapset_compile_coverage) {
    2404         [ #  # ]:          0 :                 fd->unused_locals.push_back (fd->locals[j]);
    2405                 :            :               }
    2406 [ +  - ][ +  - ]:         12 :               fd->locals.erase(fd->locals.begin() + j);
                 [ +  - ]
    2407                 :         12 :               relaxed_p = false;
    2408                 :            :               // don't increment j
    2409                 :            :             }
    2410                 :            :           else
    2411                 :            :             {
    2412 [ +  - ][ +  - ]:       9338 :               if (vut.written.find (l) == vut.written.end())
                 [ +  + ]
    2413 [ +  + ][ +  - ]:          9 :                 if (iterations == 0 && ! s.suppress_warnings)
    2414                 :            :                   {
    2415         [ +  - ]:          3 :                     stringstream o;
    2416                 :          3 :                     vector<vardecl*>::iterator it;
    2417 [ +  - ][ +  - ]:          8 :                     for (it = fd->formal_args.begin() ;
         [ +  - ][ +  + ]
    2418         [ +  - ]:          4 :                          it != fd->formal_args.end(); it++)
    2419 [ +  - ][ +  - ]:          1 :                       if (l->name != (*it)->name)
    2420 [ +  - ][ +  - ]:          1 :                         o << " " << (*it)->name;
    2421 [ +  - ][ +  - ]:          9 :                     for (it = fd->locals.begin(); it != fd->locals.end(); it++)
         [ +  - ][ +  - ]
                 [ +  + ]
    2422 [ +  - ][ +  + ]:          6 :                       if (l->name != (*it)->name)
    2423 [ +  - ][ +  - ]:          3 :                         o << " " << (*it)->name;
    2424 [ +  - ][ +  - ]:          6 :                     for (it = s.globals.begin(); it != s.globals.end(); it++)
         [ +  - ][ +  - ]
                 [ +  + ]
    2425 [ +  - ][ +  - ]:          3 :                       if (l->name != (*it)->name)
    2426 [ +  - ][ +  - ]:          3 :                         o << " " << (*it)->name;
    2427                 :            : 
    2428 [ +  - ][ +  - ]:          6 :                     s.print_warning (_F("never-assigned local variable '%s' %s",
                 [ +  - ]
    2429                 :            :                                         l->name.c_str(), (o.str() == "" ? "" :
    2430 [ +  - ][ -  + ]:          9 :                                         (_("(alternatives:") + o.str() + ")")).c_str()), l->tok);
         [ #  # ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ -  + ]
         [ +  - ][ #  #  
             #  #  #  # ]
    2431                 :            :                   }
    2432                 :            : 
    2433                 :       9350 :               j++;
    2434                 :            :             }
    2435                 :            :         }
    2436                 :            :     }
    2437         [ +  + ]:      14564 :   for (unsigned i=0; i<s.globals.size(); /* see below */)
    2438                 :            :     {
    2439                 :      12172 :       vardecl* l = s.globals[i];
    2440 [ +  - ][ +  - ]:      25103 :       if (vut.read.find (l) == vut.read.end() &&
           [ +  +  +  + ]
         [ +  - ][ +  - ]
           [ +  +  #  #  
                   #  # ]
    2441 [ +  - ][ +  - ]:      12931 :           vut.written.find (l) == vut.written.end())
         [ +  + ][ +  + ]
           [ #  #  #  # ]
    2442                 :            :         {
    2443 [ +  - ][ +  + ]:        507 :           if (l->tok->location.file->name == s.user_file->name) // !tapset
    2444 [ +  - ][ +  - ]:         31 :             s.print_warning (_F("Eliding unused variable '%s'", l->name.c_str()), l->tok);
         [ +  - ][ +  - ]
    2445         [ -  + ]:        507 :           if (s.tapset_compile_coverage) {
    2446         [ #  # ]:          0 :             s.unused_globals.push_back(s.globals[i]);
    2447                 :            :           }
    2448 [ +  - ][ +  - ]:        507 :           s.globals.erase(s.globals.begin() + i);
                 [ +  - ]
    2449                 :        507 :           relaxed_p = false;
    2450                 :            :           // don't increment i
    2451                 :            :         }
    2452                 :            :       else
    2453                 :            :         {
    2454 [ +  - ][ +  - ]:      11665 :           if (vut.written.find (l) == vut.written.end() && ! l->init) // no initializer
         [ +  + ][ +  + ]
         [ +  - ][ +  - ]
           [ +  +  #  #  
                   #  # ]
    2455 [ +  + ][ +  + ]:         25 :             if (iterations == 0 && ! s.suppress_warnings)
    2456                 :            :               {
    2457         [ +  - ]:         11 :                 stringstream o;
    2458                 :         11 :                 vector<vardecl*>::iterator it;
    2459 [ +  - ][ +  - ]:         73 :                 for (it = s.globals.begin(); it != s.globals.end(); it++)
         [ +  - ][ +  - ]
                 [ +  + ]
    2460 [ +  - ][ +  + ]:         62 :                   if (l->name != (*it)->name)
    2461 [ +  - ][ +  - ]:         51 :                     o << " " << (*it)->name;
    2462                 :            : 
    2463 [ +  - ][ +  - ]:         22 :                 s.print_warning (_F("never assigned global variable '%s' %s", l->name.c_str(),
                 [ +  - ]
    2464 [ +  - ][ -  + ]:         33 :                                    (o.str() == "" ? "" : (_("(alternatives:") + o.str() + ")")).c_str()), l->tok);
         [ #  # ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ -  + ]
         [ +  - ][ #  #  
             #  #  #  # ]
    2465                 :            :               }
    2466                 :            : 
    2467                 :      12172 :           i++;
    2468                 :            :         }
    2469         [ +  - ]:       2400 :     }
    2470                 :       2392 : }
    2471                 :            : 
    2472                 :            : 
    2473                 :            : // ------------------------------------------------------------------------
    2474                 :            : 
    2475         [ -  + ]:       2392 : struct dead_assignment_remover: public update_visitor
    2476                 :            : {
    2477                 :            :   systemtap_session& session;
    2478                 :            :   bool& relaxed_p;
    2479                 :            :   const varuse_collecting_visitor& vut;
    2480                 :            : 
    2481                 :       2392 :   dead_assignment_remover(systemtap_session& s, bool& r,
    2482                 :            :                           const varuse_collecting_visitor& v):
    2483                 :       2392 :     session(s), relaxed_p(r), vut(v) {}
    2484                 :            : 
    2485                 :            :   void visit_assignment (assignment* e);
    2486                 :            :   void visit_try_block (try_block *s);
    2487                 :            : };
    2488                 :            : 
    2489                 :            : 
    2490                 :            : void
    2491                 :     850057 : dead_assignment_remover::visit_assignment (assignment* e)
    2492                 :            : {
    2493         [ +  - ]:     850057 :   replace (e->left);
    2494         [ +  - ]:     850057 :   replace (e->right);
    2495                 :            : 
    2496         [ +  + ]:     850057 :   symbol* left = get_symbol_within_expression (e->left);
    2497                 :     850056 :   vardecl* leftvar = left->referent; // NB: may be 0 for unresolved $target
    2498         [ +  + ]:     850056 :   if (leftvar) // not unresolved $target, so intended sideeffect may be elided
    2499                 :            :     {
    2500 [ +  - ][ +  - ]:     850050 :       if (vut.read.find(leftvar) == vut.read.end()) // var never read?
                 [ +  + ]
    2501                 :            :         {
    2502                 :            :           // NB: Not so fast!  The left side could be an array whose
    2503                 :            :           // index expressions may have side-effects.  This would be
    2504                 :            :           // OK if we could replace the array assignment with a
    2505                 :            :           // statement-expression containing all the index expressions
    2506                 :            :           // and the rvalue... but we can't.
    2507                 :            :           // Another possibility is that we have an unread global variable
    2508                 :            :           // which are kept for probe end value display.
    2509                 :            : 
    2510                 :      84209 :           bool is_global = false;
    2511                 :      84209 :           vector<vardecl*>::iterator it;
    2512 [ +  - ][ +  - ]:     705247 :           for (it = session.globals.begin(); it != session.globals.end(); it++)
         [ +  - ][ +  - ]
                 [ +  + ]
    2513 [ +  - ][ +  + ]:     633642 :             if (leftvar->name == (*it)->name)
    2514                 :            :               {
    2515                 :      12604 :                 is_global = true;
    2516                 :      12604 :                 break;
    2517                 :            :               }
    2518                 :            : 
    2519         [ +  - ]:      84209 :           varuse_collecting_visitor lvut(session);
    2520         [ +  - ]:      84209 :           e->left->visit (& lvut);
    2521 [ +  - ][ +  + ]:      84209 :           if (lvut.side_effect_free () && !is_global // XXX: use _wrt() once we track focal_vars
         [ +  + ][ +  + ]
                 [ +  + ]
    2522                 :      71605 :               && !leftvar->synthetic) // don't elide assignment to synthetic $context variables
    2523                 :            :             {
    2524                 :            :               /* PR 1119: NB: This is not necessary here.  A write-only
    2525                 :            :                  variable will also be elided soon at the next _opt2 iteration.
    2526                 :            :               if (e->left->tok->location.file->name == session.user_file->name) // !tapset
    2527                 :            :                 session.print_warning("eliding write-only ", *e->left->tok);
    2528                 :            :               else
    2529                 :            :               */
    2530 [ +  - ][ +  + ]:      71594 :               if (e->left->tok->location.file->name == session.user_file->name) // !tapset
    2531 [ +  - ][ +  - ]:         52 :                 session.print_warning(_F("Eliding assignment to %s at %s", leftvar->name.c_str(), lex_cast(*e->tok).c_str()));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2532         [ +  - ]:      71594 :               provide (e->right); // goodbye assignment*
    2533                 :      84209 :               relaxed_p = false;
    2534                 :     850056 :               return;
    2535 [ +  - ][ +  + ]:      84210 :             }
    2536                 :            :         }
    2537                 :            :     }
    2538         [ +  - ]:     778462 :   provide (e);
    2539                 :            : }
    2540                 :            : 
    2541                 :            : 
    2542                 :            : void
    2543                 :       5073 : dead_assignment_remover::visit_try_block (try_block *s)
    2544                 :            : {
    2545                 :       5073 :   replace (s->try_block);
    2546         [ +  + ]:       5073 :   if (s->catch_error_var)
    2547                 :            :     {
    2548                 :          4 :       vardecl* errvar = s->catch_error_var->referent;
    2549 [ +  - ][ +  - ]:          4 :       if (vut.read.find(errvar) == vut.read.end()) // never read?
                 [ -  + ]
    2550                 :            :         {
    2551         [ #  # ]:          0 :           if (session.verbose>2)
    2552 [ #  # ][ #  # ]:          0 :             clog << _F("Eliding unused error string catcher %s at %s",
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    2553         [ #  # ]:          0 :                       errvar->name.c_str(), lex_cast(*s->tok).c_str()) << endl;
    2554                 :          4 :           s->catch_error_var = 0;
    2555                 :            :         }
    2556                 :            :     }
    2557                 :       5073 :   replace (s->catch_block);
    2558                 :       5073 :   provide (s);
    2559                 :       5073 : }
    2560                 :            : 
    2561                 :            : 
    2562                 :            : // Let's remove assignments to variables that are never read.  We
    2563                 :            : // rewrite "(foo = expr)" as "(expr)".  This makes foo a candidate to
    2564                 :            : // be optimized away as an unused variable, and expr a candidate to be
    2565                 :            : // removed as a side-effect-free statement expression.  Wahoo!
    2566                 :       2392 : void semantic_pass_opt3 (systemtap_session& s, bool& relaxed_p)
    2567                 :            : {
    2568                 :            :   // Recompute the varuse data, which will probably match the opt2
    2569                 :            :   // copy of the computation, except for those totally unused
    2570                 :            :   // variables that opt2 removed.
    2571         [ +  - ]:       2392 :   varuse_collecting_visitor vut(s);
    2572         [ +  + ]:     529969 :   for (unsigned i=0; i<s.probes.size(); i++)
    2573         [ +  - ]:     527577 :     s.probes[i]->body->visit (& vut); // includes reachable functions too
    2574                 :            : 
    2575         [ +  - ]:       2392 :   dead_assignment_remover dar (s, relaxed_p, vut);
    2576                 :            :   // This instance may be reused for multiple probe/function body trims.
    2577                 :            : 
    2578         [ +  + ]:     529968 :   for (unsigned i=0; i<s.probes.size(); i++)
    2579         [ +  + ]:     527577 :     dar.replace (s.probes[i]->body);
    2580 [ +  - ][ +  + ]:     788816 :   for (map<string,functiondecl*>::iterator it = s.functions.begin();
    2581         [ +  - ]:     394408 :        it != s.functions.end(); it++)
    2582 [ +  - ][ +  - ]:     394409 :     dar.replace (it->second->body);
         [ +  - ][ +  - ]
    2583                 :            :   // The rewrite operation is performed within the visitor.
    2584                 :            : 
    2585                 :            :   // XXX: we could also zap write-only globals here
    2586                 :       2391 : }
    2587                 :            : 
    2588                 :            : 
    2589                 :            : // ------------------------------------------------------------------------
    2590                 :            : 
    2591 [ +  - ][ -  + ]:       2391 : struct dead_stmtexpr_remover: public update_visitor
    2592                 :            : {
    2593                 :            :   systemtap_session& session;
    2594                 :            :   bool& relaxed_p;
    2595                 :            :   set<vardecl*> focal_vars; // vars considered subject to side-effects
    2596                 :            : 
    2597                 :       2391 :   dead_stmtexpr_remover(systemtap_session& s, bool& r):
    2598         [ +  - ]:       2391 :     session(s), relaxed_p(r) {}
    2599                 :            : 
    2600                 :            :   void visit_block (block *s);
    2601                 :            :   void visit_try_block (try_block *s);
    2602                 :            :   void visit_null_statement (null_statement *s);
    2603                 :            :   void visit_if_statement (if_statement* s);
    2604                 :            :   void visit_foreach_loop (foreach_loop *s);
    2605                 :            :   void visit_for_loop (for_loop *s);
    2606                 :            :   // XXX: and other places where stmt_expr's might be nested
    2607                 :            : 
    2608                 :            :   void visit_expr_statement (expr_statement *s);
    2609                 :            : };
    2610                 :            : 
    2611                 :            : 
    2612                 :            : void
    2613                 :       2233 : dead_stmtexpr_remover::visit_null_statement (null_statement *s)
    2614                 :            : {
    2615                 :            :   // easy!
    2616         [ -  + ]:       2233 :   if (session.verbose>2)
    2617                 :          0 :     clog << _("Eliding side-effect-free null statement ") << *s->tok << endl;
    2618                 :       2233 :   s = 0;
    2619                 :       2233 :   provide (s);
    2620                 :       2233 : }
    2621                 :            : 
    2622                 :            : 
    2623                 :            : void
    2624                 :     842240 : dead_stmtexpr_remover::visit_block (block *s)
    2625                 :            : {
    2626         [ +  - ]:     842240 :   vector<statement*> new_stmts;
    2627         [ +  + ]:    2699467 :   for (unsigned i=0; i<s->statements.size(); i++ )
    2628                 :            :     {
    2629         [ +  - ]:    1857227 :       statement* new_stmt = require (s->statements[i], true);
    2630         [ +  + ]:    1857227 :       if (new_stmt != 0)
    2631                 :            :         {
    2632                 :            :           // flatten nested blocks into this one
    2633         [ -  + ]:    1772447 :           block *b = dynamic_cast<block *>(new_stmt);
    2634         [ +  + ]:    1772447 :           if (b)
    2635                 :            :             {
    2636         [ -  + ]:      29949 :               if (session.verbose>2)
    2637 [ #  # ][ #  # ]:          0 :                 clog << _("Flattening nested block ") << *b->tok << endl;
                 [ #  # ]
    2638                 :            :               new_stmts.insert(new_stmts.end(),
    2639 [ +  - ][ +  - ]:      29949 :                   b->statements.begin(), b->statements.end());
         [ +  - ][ +  - ]
    2640                 :      29949 :               relaxed_p = false;
    2641                 :            :             }
    2642                 :            :           else
    2643         [ +  - ]:    1742498 :             new_stmts.push_back (new_stmt);
    2644                 :            :         }
    2645                 :            :     }
    2646         [ +  + ]:     842240 :   if (new_stmts.size() == 0)
    2647                 :            :     {
    2648         [ +  + ]:     269928 :       if (session.verbose>2)
    2649 [ +  - ][ +  - ]:          1 :         clog << _("Eliding side-effect-free empty block ") << *s->tok << endl;
                 [ +  - ]
    2650                 :     269928 :       s = 0;
    2651                 :            :     }
    2652         [ +  + ]:     572312 :   else if (new_stmts.size() == 1)
    2653                 :            :     {
    2654         [ -  + ]:     102501 :       if (session.verbose>2)
    2655 [ #  # ][ #  # ]:          0 :         clog << _("Eliding side-effect-free singleton block ") << *s->tok << endl;
                 [ #  # ]
    2656         [ +  - ]:     102501 :       provide (new_stmts[0]);
    2657                 :     842240 :       return;
    2658                 :            :     }
    2659                 :            :   else
    2660         [ +  - ]:     469811 :     s->statements = new_stmts;
    2661 [ +  - ][ +  - ]:     842240 :   provide (s);
                 [ +  + ]
    2662                 :            : }
    2663                 :            : 
    2664                 :            : 
    2665                 :            : void
    2666                 :       5073 : dead_stmtexpr_remover::visit_try_block (try_block *s)
    2667                 :            : {
    2668                 :       5073 :   replace (s->try_block, true);
    2669                 :       5073 :   replace (s->catch_block, true); // null catch{} is ok and useful
    2670         [ +  + ]:       5073 :   if (s->try_block == 0)
    2671                 :            :     {
    2672         [ -  + ]:          4 :       if (session.verbose>2)
    2673                 :          0 :         clog << _("Eliding empty try {} block ") << *s->tok << endl;
    2674                 :          4 :       s = 0;
    2675                 :            :     }
    2676                 :       5073 :   provide (s);
    2677                 :       5073 : }
    2678                 :            : 
    2679                 :            : 
    2680                 :            : void
    2681                 :     643912 : dead_stmtexpr_remover::visit_if_statement (if_statement *s)
    2682                 :            : {
    2683                 :     643912 :   replace (s->thenblock, true);
    2684                 :     643912 :   replace (s->elseblock, true);
    2685                 :            : 
    2686         [ +  + ]:     643912 :   if (s->thenblock == 0)
    2687                 :            :     {
    2688         [ +  + ]:        774 :       if (s->elseblock == 0)
    2689                 :            :         {
    2690                 :            :           // We may be able to elide this statement, if the condition
    2691                 :            :           // expression is side-effect-free.
    2692         [ +  - ]:        573 :           varuse_collecting_visitor vct(session);
    2693         [ +  - ]:        573 :           s->condition->visit(& vct);
    2694 [ +  - ][ +  + ]:        573 :           if (vct.side_effect_free ())
    2695                 :            :             {
    2696         [ -  + ]:        553 :               if (session.verbose>2)
    2697         [ #  # ]:          0 :                 clog << _("Eliding side-effect-free if statement ")
    2698 [ #  # ][ #  # ]:          0 :                      << *s->tok << endl;
    2699                 :        553 :               s = 0; // yeah, baby
    2700                 :            :             }
    2701                 :            :           else
    2702                 :            :             {
    2703                 :            :               // We can still turn it into a simple expr_statement though...
    2704         [ -  + ]:         20 :               if (session.verbose>2)
    2705         [ #  # ]:          0 :                 clog << _("Creating simple evaluation from if statement ")
    2706 [ #  # ][ #  # ]:          0 :                      << *s->tok << endl;
    2707 [ +  - ][ +  - ]:         20 :               expr_statement *es = new expr_statement;
    2708                 :         20 :               es->value = s->condition;
    2709                 :         20 :               es->tok = es->value->tok;
    2710         [ +  - ]:         20 :               provide (es);
    2711                 :     643912 :               return;
    2712 [ +  - ][ +  + ]:        573 :             }
    2713                 :            :         }
    2714                 :            :       else
    2715                 :            :         {
    2716                 :            :           // For an else without a then, we can invert the condition logic to
    2717                 :            :           // avoid having a null statement in the thenblock
    2718         [ -  + ]:        201 :           if (session.verbose>2)
    2719                 :          0 :             clog << _("Inverting the condition of if statement ")
    2720                 :          0 :                  << *s->tok << endl;
    2721         [ +  - ]:        201 :           unary_expression *ue = new unary_expression;
    2722                 :        201 :           ue->operand = s->condition;
    2723                 :        201 :           ue->tok = ue->operand->tok;
    2724                 :        201 :           ue->op = "!";
    2725                 :        201 :           s->condition = ue;
    2726                 :        201 :           s->thenblock = s->elseblock;
    2727                 :        201 :           s->elseblock = 0;
    2728                 :            :         }
    2729                 :            :     }
    2730                 :     643892 :   provide (s);
    2731                 :            : }
    2732                 :            : 
    2733                 :            : void
    2734                 :        766 : dead_stmtexpr_remover::visit_foreach_loop (foreach_loop *s)
    2735                 :            : {
    2736                 :        766 :   replace (s->block, true);
    2737                 :            : 
    2738         [ +  + ]:        766 :   if (s->block == 0)
    2739                 :            :     {
    2740                 :            :       // XXX what if s->limit has side effects?
    2741                 :            :       // XXX what about s->indexes or s->value used outside the loop?
    2742         [ -  + ]:          4 :       if(session.verbose > 2)
    2743                 :          0 :         clog << _("Eliding side-effect-free foreach statement ") << *s->tok << endl;
    2744                 :          4 :       s = 0; // yeah, baby
    2745                 :            :     }
    2746                 :        766 :   provide (s);
    2747                 :        766 : }
    2748                 :            : 
    2749                 :            : void
    2750                 :       1200 : dead_stmtexpr_remover::visit_for_loop (for_loop *s)
    2751                 :            : {
    2752                 :       1200 :   replace (s->block, true);
    2753                 :            : 
    2754         [ +  + ]:       1200 :   if (s->block == 0)
    2755                 :            :     {
    2756                 :            :       // We may be able to elide this statement, if the condition
    2757                 :            :       // expression is side-effect-free.
    2758         [ +  - ]:         48 :       varuse_collecting_visitor vct(session);
    2759 [ +  + ][ +  - ]:         48 :       if (s->init) s->init->visit(& vct);
    2760         [ +  - ]:         48 :       s->cond->visit(& vct);
    2761 [ +  + ][ +  - ]:         48 :       if (s->incr) s->incr->visit(& vct);
    2762 [ +  - ][ +  + ]:         48 :       if (vct.side_effect_free ())
    2763                 :            :         {
    2764         [ -  + ]:          5 :           if (session.verbose>2)
    2765 [ #  # ][ #  # ]:          0 :             clog << _("Eliding side-effect-free for statement ") << *s->tok << endl;
                 [ #  # ]
    2766                 :          5 :           s = 0; // yeah, baby
    2767                 :            :         }
    2768                 :            :       else
    2769                 :            :         {
    2770                 :            :           // Can't elide this whole statement; put a null in there.
    2771 [ +  - ][ +  - ]:         43 :           s->block = new null_statement(s->tok);
    2772         [ +  - ]:         48 :         }
    2773                 :            :     }
    2774                 :       1200 :   provide (s);
    2775                 :       1200 : }
    2776                 :            : 
    2777                 :            : 
    2778                 :            : 
    2779                 :            : void
    2780                 :    1497536 : dead_stmtexpr_remover::visit_expr_statement (expr_statement *s)
    2781                 :            : {
    2782                 :            :   // Run a varuse query against the operand expression.  If it has no
    2783                 :            :   // side-effects, replace the entire statement expression by a null
    2784                 :            :   // statement with the provide() call.
    2785                 :            :   //
    2786                 :            :   // Unlike many other visitors, we do *not* traverse this outermost
    2787                 :            :   // one into the expression subtrees.  There is no need - no
    2788                 :            :   // expr_statement nodes will be found there.  (Function bodies
    2789                 :            :   // need to be visited explicitly by our caller.)
    2790                 :            :   //
    2791                 :            :   // NB.  While we don't share nodes in the parse tree, let's not
    2792                 :            :   // deallocate *s anyway, just in case...
    2793                 :            : 
    2794         [ +  - ]:    1497536 :   varuse_collecting_visitor vut(session);
    2795         [ +  - ]:    1497536 :   s->value->visit (& vut);
    2796                 :            : 
    2797 [ +  - ][ +  + ]:    1497536 :   if (vut.side_effect_free_wrt (focal_vars))
    2798                 :            :     {
    2799                 :            :       /* PR 1119: NB: this message is not a good idea here.  It can
    2800                 :            :          name some arbitrary RHS expression of an assignment.
    2801                 :            :       if (s->value->tok->location.file->name == session.user_file->name) // not tapset
    2802                 :            :         session.print_warning("eliding never-assigned ", *s->value->tok);
    2803                 :            :       else
    2804                 :            :       */
    2805 [ +  - ][ +  + ]:      78724 :       if (s->value->tok->location.file->name == session.user_file->name) // not tapset
    2806 [ +  - ][ +  - ]:        250 :         session.print_warning("Eliding side-effect-free expression ", s->tok);
                 [ +  - ]
    2807                 :            : 
    2808                 :            :       // NB: this 0 pointer is invalid to leave around for any length of
    2809                 :            :       // time, but the parent parse tree objects above handle it.
    2810                 :      78724 :       s = 0;
    2811                 :      78724 :       relaxed_p = false;
    2812                 :            :     }
    2813 [ +  - ][ +  - ]:    1497536 :   provide (s);
    2814                 :    1497536 : }
    2815                 :            : 
    2816                 :            : 
    2817                 :       2391 : void semantic_pass_opt4 (systemtap_session& s, bool& relaxed_p)
    2818                 :            : {
    2819                 :            :   // Finally, let's remove some statement-expressions that have no
    2820                 :            :   // side-effect.  These should be exactly those whose private varuse
    2821                 :            :   // visitors come back with an empty "written" and "embedded" lists.
    2822                 :            : 
    2823         [ +  - ]:       2391 :   dead_stmtexpr_remover duv (s, relaxed_p);
    2824                 :            :   // This instance may be reused for multiple probe/function body trims.
    2825                 :            : 
    2826         [ +  + ]:     529967 :   for (unsigned i=0; i<s.probes.size(); i++)
    2827                 :            :     {
    2828         [ +  - ]:     527576 :       assert_no_interrupts();
    2829                 :            : 
    2830                 :     527576 :       derived_probe* p = s.probes[i];
    2831                 :            : 
    2832         [ +  - ]:     527576 :       duv.focal_vars.clear ();
    2833                 :            :       duv.focal_vars.insert (s.globals.begin(),
    2834 [ +  - ][ +  - ]:     527576 :                              s.globals.end());
                 [ +  - ]
    2835                 :            :       duv.focal_vars.insert (p->locals.begin(),
    2836 [ +  - ][ +  - ]:     527576 :                              p->locals.end());
                 [ +  - ]
    2837                 :            : 
    2838         [ +  - ]:     527576 :       duv.replace (p->body, true);
    2839         [ +  + ]:     527576 :       if (p->body == 0)
    2840                 :            :         {
    2841         [ +  + ]:     265372 :           if (! s.timing) // PR10070
    2842 [ +  - ][ +  - ]:     264084 :             s.print_warning (_F("side-effect-free probe '%s'", p->name.c_str()), p->tok);
         [ +  - ][ +  - ]
    2843                 :            : 
    2844 [ +  - ][ +  - ]:     265372 :           p->body = new null_statement(p->tok);
    2845                 :            : 
    2846                 :            :           // XXX: possible duplicate warnings; see below
    2847                 :            :         }
    2848                 :            :     }
    2849 [ +  - ][ +  - ]:     394408 :   for (map<string,functiondecl*>::iterator it = s.functions.begin(); it != s.functions.end(); it++)
                 [ +  + ]
    2850                 :            :     {
    2851         [ +  - ]:     392017 :       assert_no_interrupts();
    2852                 :            : 
    2853         [ +  - ]:     392017 :       functiondecl* fn = it->second;
    2854         [ +  - ]:     392017 :       duv.focal_vars.clear ();
    2855                 :            :       duv.focal_vars.insert (fn->locals.begin(),
    2856 [ +  - ][ +  - ]:     392017 :                              fn->locals.end());
                 [ +  - ]
    2857                 :            :       duv.focal_vars.insert (fn->formal_args.begin(),
    2858 [ +  - ][ +  - ]:     392017 :                              fn->formal_args.end());
                 [ +  - ]
    2859                 :            :       duv.focal_vars.insert (s.globals.begin(),
    2860 [ +  - ][ +  - ]:     392017 :                              s.globals.end());
                 [ +  - ]
    2861                 :            : 
    2862         [ +  - ]:     392017 :       duv.replace (fn->body, true);
    2863         [ +  + ]:     392017 :       if (fn->body == 0)
    2864                 :            :         {
    2865 [ +  - ][ +  - ]:          8 :           s.print_warning (_F("side-effect-free function '%s'", fn->name.c_str()), fn->tok);
         [ +  - ][ +  - ]
    2866                 :            : 
    2867 [ +  - ][ +  - ]:          8 :           fn->body = new null_statement(fn->tok);
    2868                 :            : 
    2869                 :            :           // XXX: the next iteration of the outer optimization loop may
    2870                 :            :           // take this new null_statement away again, and thus give us a
    2871                 :            :           // fresh warning.  It would be better if this fixup was performed
    2872                 :            :           // only after the relaxation iterations.
    2873                 :            :           // XXX: or else see bug #6469.
    2874                 :            :         }
    2875         [ +  - ]:       2391 :     }
    2876                 :       2391 : }
    2877                 :            : 
    2878                 :            : 
    2879                 :            : // ------------------------------------------------------------------------
    2880                 :            : 
    2881                 :            : // The goal of this visitor is to reduce top-level expressions in void context
    2882                 :            : // into separate statements that evaluate each subcomponent of the expression.
    2883                 :            : // The dead-statement-remover can later remove some parts if they have no side
    2884                 :            : // effects.
    2885                 :            : //
    2886                 :            : // All expressions must be overridden here so we never visit their subexpressions
    2887                 :            : // accidentally.  Thus, the only visited expressions should be value of an
    2888                 :            : // expr_statement.
    2889                 :            : //
    2890                 :            : // For an expression to replace its expr_statement with something else, it will
    2891                 :            : // let the new statement provide(), and then provide(0) for itself.  The
    2892                 :            : // expr_statement will take this as a sign that it's been replaced.
    2893 [ +  - ][ -  + ]:       2391 : struct void_statement_reducer: public update_visitor
    2894                 :            : {
    2895                 :            :   systemtap_session& session;
    2896                 :            :   bool& relaxed_p;
    2897                 :            :   set<vardecl*> focal_vars; // vars considered subject to side-effects
    2898                 :            : 
    2899                 :       2391 :   void_statement_reducer(systemtap_session& s, bool& r):
    2900         [ +  - ]:       2391 :     session(s), relaxed_p(r) {}
    2901                 :            : 
    2902                 :            :   void visit_expr_statement (expr_statement* s);
    2903                 :            : 
    2904                 :            :   // expressions in conditional / loop controls are definitely a side effect,
    2905                 :            :   // but still recurse into the child statements
    2906                 :            :   void visit_if_statement (if_statement* s);
    2907                 :            :   void visit_for_loop (for_loop* s);
    2908                 :            :   void visit_foreach_loop (foreach_loop* s);
    2909                 :            : 
    2910                 :            :   // these expressions get rewritten into their statement equivalents
    2911                 :            :   void visit_logical_or_expr (logical_or_expr* e);
    2912                 :            :   void visit_logical_and_expr (logical_and_expr* e);
    2913                 :            :   void visit_ternary_expression (ternary_expression* e);
    2914                 :            : 
    2915                 :            :   // all of these can (usually) be reduced into simpler statements
    2916                 :            :   void visit_binary_expression (binary_expression* e);
    2917                 :            :   void visit_unary_expression (unary_expression* e);
    2918                 :            :   void visit_regex_query (regex_query* e); // TODOXXX may or may not be reducible
    2919                 :            :   void visit_comparison (comparison* e);
    2920                 :            :   void visit_concatenation (concatenation* e);
    2921                 :            :   void visit_functioncall (functioncall* e);
    2922                 :            :   void visit_print_format (print_format* e);
    2923                 :            :   void visit_target_symbol (target_symbol* e);
    2924                 :            :   void visit_cast_op (cast_op* e);
    2925                 :            :   void visit_defined_op (defined_op* e);
    2926                 :            : 
    2927                 :            :   // these are a bit hairy to grok due to the intricacies of indexables and
    2928                 :            :   // stats, so I'm chickening out and skipping them...
    2929                 :          0 :   void visit_array_in (array_in* e) { provide (e); }
    2930                 :          1 :   void visit_arrayindex (arrayindex* e) { provide (e); }
    2931                 :          0 :   void visit_stat_op (stat_op* e) { provide (e); }
    2932                 :          0 :   void visit_hist_op (hist_op* e) { provide (e); }
    2933                 :            : 
    2934                 :            :   // these can't be reduced because they always have an effect
    2935                 :     152595 :   void visit_return_statement (return_statement* s) { provide (s); }
    2936                 :      11511 :   void visit_delete_statement (delete_statement* s) { provide (s); }
    2937                 :         95 :   void visit_pre_crement (pre_crement* e) { provide (e); }
    2938                 :     188715 :   void visit_post_crement (post_crement* e) { provide (e); }
    2939                 :     777422 :   void visit_assignment (assignment* e) { provide (e); }
    2940                 :            : };
    2941                 :            : 
    2942                 :            : 
    2943                 :            : void
    2944                 :    1421028 : void_statement_reducer::visit_expr_statement (expr_statement* s)
    2945                 :            : {
    2946                 :    1421028 :   replace (s->value, true);
    2947                 :            : 
    2948                 :            :   // if the expression provides 0, that's our signal that a new
    2949                 :            :   // statement has been provided, so we shouldn't provide this one.
    2950         [ +  + ]:    1421028 :   if (s->value != 0)
    2951                 :    1419013 :     provide(s);
    2952                 :    1421028 : }
    2953                 :            : 
    2954                 :            : void
    2955                 :     643359 : void_statement_reducer::visit_if_statement (if_statement* s)
    2956                 :            : {
    2957                 :            :   // s->condition is never void
    2958                 :     643359 :   replace (s->thenblock);
    2959                 :     643359 :   replace (s->elseblock);
    2960                 :     643359 :   provide (s);
    2961                 :     643359 : }
    2962                 :            : 
    2963                 :            : void
    2964                 :       1195 : void_statement_reducer::visit_for_loop (for_loop* s)
    2965                 :            : {
    2966                 :            :   // s->init/cond/incr are never void
    2967                 :       1195 :   replace (s->block);
    2968                 :       1195 :   provide (s);
    2969                 :       1195 : }
    2970                 :            : 
    2971                 :            : void
    2972                 :        762 : void_statement_reducer::visit_foreach_loop (foreach_loop* s)
    2973                 :            : {
    2974                 :            :   // s->indexes/base/value/limit are never void
    2975                 :        762 :   replace (s->block);
    2976                 :        762 :   provide (s);
    2977                 :        762 : }
    2978                 :            : 
    2979                 :            : void
    2980                 :          2 : void_statement_reducer::visit_logical_or_expr (logical_or_expr* e)
    2981                 :            : {
    2982                 :            :   // In void context, the evaluation of "a || b" is exactly like
    2983                 :            :   // "if (!a) b", so let's do that instead.
    2984                 :            : 
    2985         [ -  + ]:          2 :   if (session.verbose>2)
    2986                 :          0 :     clog << _("Creating if statement from unused logical-or ")
    2987                 :          0 :          << *e->tok << endl;
    2988                 :            : 
    2989         [ +  - ]:          2 :   if_statement *is = new if_statement;
    2990                 :          2 :   is->tok = e->tok;
    2991                 :          2 :   is->elseblock = 0;
    2992                 :            : 
    2993         [ +  - ]:          2 :   unary_expression *ue = new unary_expression;
    2994                 :          2 :   ue->operand = e->left;
    2995                 :          2 :   ue->tok = e->tok;
    2996                 :          2 :   ue->op = "!";
    2997                 :          2 :   is->condition = ue;
    2998                 :            : 
    2999         [ +  - ]:          2 :   expr_statement *es = new expr_statement;
    3000                 :          2 :   es->value = e->right;
    3001                 :          2 :   es->tok = es->value->tok;
    3002                 :          2 :   is->thenblock = es;
    3003                 :            : 
    3004                 :          2 :   is->visit(this);
    3005                 :          2 :   relaxed_p = false;
    3006                 :          2 :   e = 0;
    3007                 :          2 :   provide (e);
    3008                 :          2 : }
    3009                 :            : 
    3010                 :            : void
    3011                 :          1 : void_statement_reducer::visit_logical_and_expr (logical_and_expr* e)
    3012                 :            : {
    3013                 :            :   // In void context, the evaluation of "a && b" is exactly like
    3014                 :            :   // "if (a) b", so let's do that instead.
    3015                 :            : 
    3016         [ -  + ]:          1 :   if (session.verbose>2)
    3017                 :          0 :     clog << _("Creating if statement from unused logical-and ")
    3018                 :          0 :          << *e->tok << endl;
    3019                 :            : 
    3020         [ +  - ]:          1 :   if_statement *is = new if_statement;
    3021                 :          1 :   is->tok = e->tok;
    3022                 :          1 :   is->elseblock = 0;
    3023                 :          1 :   is->condition = e->left;
    3024                 :            : 
    3025         [ +  - ]:          1 :   expr_statement *es = new expr_statement;
    3026                 :          1 :   es->value = e->right;
    3027                 :          1 :   es->tok = es->value->tok;
    3028                 :          1 :   is->thenblock = es;
    3029                 :            : 
    3030                 :          1 :   is->visit(this);
    3031                 :          1 :   relaxed_p = false;
    3032                 :          1 :   e = 0;
    3033                 :          1 :   provide (e);
    3034                 :          1 : }
    3035                 :            : 
    3036                 :            : void
    3037                 :         17 : void_statement_reducer::visit_ternary_expression (ternary_expression* e)
    3038                 :            : {
    3039                 :            :   // In void context, the evaluation of "a ? b : c" is exactly like
    3040                 :            :   // "if (a) b else c", so let's do that instead.
    3041                 :            : 
    3042         [ -  + ]:         17 :   if (session.verbose>2)
    3043                 :          0 :     clog << _("Creating if statement from unused ternary expression ")
    3044                 :          0 :          << *e->tok << endl;
    3045                 :            : 
    3046         [ +  - ]:         17 :   if_statement *is = new if_statement;
    3047                 :         17 :   is->tok = e->tok;
    3048                 :         17 :   is->condition = e->cond;
    3049                 :            : 
    3050         [ +  - ]:         17 :   expr_statement *es = new expr_statement;
    3051                 :         17 :   es->value = e->truevalue;
    3052                 :         17 :   es->tok = es->value->tok;
    3053                 :         17 :   is->thenblock = es;
    3054                 :            : 
    3055         [ +  - ]:         17 :   es = new expr_statement;
    3056                 :         17 :   es->value = e->falsevalue;
    3057                 :         17 :   es->tok = es->value->tok;
    3058                 :         17 :   is->elseblock = es;
    3059                 :            : 
    3060                 :         17 :   is->visit(this);
    3061                 :         17 :   relaxed_p = false;
    3062                 :         17 :   e = 0;
    3063                 :         17 :   provide (e);
    3064                 :         17 : }
    3065                 :            : 
    3066                 :            : void
    3067                 :         73 : void_statement_reducer::visit_binary_expression (binary_expression* e)
    3068                 :            : {
    3069                 :            :   // When the result of a binary operation isn't needed, it's just as good to
    3070                 :            :   // evaluate the operands as sequential statements in a block.
    3071                 :            : 
    3072         [ -  + ]:         73 :   if (session.verbose>2)
    3073                 :          0 :     clog << _("Eliding unused binary ") << *e->tok << endl;
    3074                 :            : 
    3075         [ +  - ]:         73 :   block *b = new block;
    3076                 :         73 :   b->tok = e->tok;
    3077                 :            : 
    3078         [ +  - ]:         73 :   expr_statement *es = new expr_statement;
    3079                 :         73 :   es->value = e->left;
    3080                 :         73 :   es->tok = es->value->tok;
    3081         [ +  - ]:         73 :   b->statements.push_back(es);
    3082                 :            : 
    3083         [ +  - ]:         73 :   es = new expr_statement;
    3084                 :         73 :   es->value = e->right;
    3085                 :         73 :   es->tok = es->value->tok;
    3086         [ +  - ]:         73 :   b->statements.push_back(es);
    3087                 :            : 
    3088                 :         73 :   b->visit(this);
    3089                 :         73 :   relaxed_p = false;
    3090                 :         73 :   e = 0;
    3091                 :         73 :   provide (e);
    3092                 :         73 : }
    3093                 :            : 
    3094                 :            : void
    3095                 :          5 : void_statement_reducer::visit_unary_expression (unary_expression* e)
    3096                 :            : {
    3097                 :            :   // When the result of a unary operation isn't needed, it's just as good to
    3098                 :            :   // evaluate the operand directly
    3099                 :            : 
    3100         [ -  + ]:          5 :   if (session.verbose>2)
    3101                 :          0 :     clog << _("Eliding unused unary ") << *e->tok << endl;
    3102                 :            : 
    3103                 :          5 :   relaxed_p = false;
    3104                 :          5 :   e->operand->visit(this);
    3105                 :          5 : }
    3106                 :            : 
    3107                 :            : void
    3108                 :          0 : void_statement_reducer::visit_regex_query (regex_query* e)
    3109                 :            : {
    3110                 :            :   // Whether we need to run a regex query depends on whether
    3111                 :            :   // subexpression extraction is enabled, as in:
    3112                 :            :   //
    3113                 :            :   // str =~ "pat";
    3114                 :            :   // println(matched(0)); // NOTE: not totally nice -- are we SURE it matched?
    3115                 :            :   // TODOXXX it's debatable whether we should allow this, though
    3116                 :            : 
    3117                 :            :   // TODOXXX since subexpression extraction is not yet implemented,
    3118                 :            :   // just treat it as a unary expression wrt the left operand -- since
    3119                 :            :   // the right hand side must be a literal (verified by the parses),
    3120                 :            :   // evaluating it never has side effects.
    3121                 :            : 
    3122         [ #  # ]:          0 :   if (session.verbose>2)
    3123                 :          0 :     clog << _("Eliding regex query ") << *e->tok << endl;
    3124                 :            : 
    3125                 :          0 :   relaxed_p = false;
    3126                 :          0 :   e->left->visit(this);
    3127                 :          0 : }
    3128                 :            : 
    3129                 :            : void
    3130                 :         29 : void_statement_reducer::visit_comparison (comparison* e)
    3131                 :            : {
    3132                 :         29 :   visit_binary_expression(e);
    3133                 :         29 : }
    3134                 :            : 
    3135                 :            : void
    3136                 :          3 : void_statement_reducer::visit_concatenation (concatenation* e)
    3137                 :            : {
    3138                 :          3 :   visit_binary_expression(e);
    3139                 :          3 : }
    3140                 :            : 
    3141                 :            : void
    3142                 :      54214 : void_statement_reducer::visit_functioncall (functioncall* e)
    3143                 :            : {
    3144                 :            :   // If a function call is pure and its result ignored, we can elide the call
    3145                 :            :   // and just evaluate the arguments in sequence
    3146                 :            : 
    3147         [ +  + ]:      54214 :   if (!e->args.size())
    3148                 :            :     {
    3149         [ +  - ]:       4407 :       provide (e);
    3150                 :            :       return;
    3151                 :            :     }
    3152                 :            : 
    3153         [ +  - ]:      49807 :   varuse_collecting_visitor vut(session);
    3154         [ +  - ]:      49807 :   vut.traversed.insert (e->referent);
    3155                 :      49807 :   vut.current_function = e->referent;
    3156         [ +  - ]:      49807 :   e->referent->body->visit (& vut);
    3157 [ +  - ][ +  + ]:      49807 :   if (!vut.side_effect_free_wrt (focal_vars))
    3158                 :            :     {
    3159         [ +  - ]:      47903 :       provide (e);
    3160                 :            :       return;
    3161                 :            :     }
    3162                 :            : 
    3163         [ -  + ]:       1904 :   if (session.verbose>2)
    3164 [ #  # ][ #  # ]:          0 :     clog << _("Eliding side-effect-free function call ") << *e->tok << endl;
                 [ #  # ]
    3165                 :            : 
    3166 [ +  - ][ +  - ]:       1904 :   block *b = new block;
    3167                 :       1904 :   b->tok = e->tok;
    3168                 :            : 
    3169         [ +  + ]:       3846 :   for (unsigned i=0; i<e->args.size(); i++ )
    3170                 :            :     {
    3171 [ +  - ][ +  - ]:       1942 :       expr_statement *es = new expr_statement;
    3172                 :       1942 :       es->value = e->args[i];
    3173                 :       1942 :       es->tok = es->value->tok;
    3174         [ +  - ]:       1942 :       b->statements.push_back(es);
    3175                 :            :     }
    3176                 :            : 
    3177         [ +  - ]:       1904 :   b->visit(this);
    3178                 :       1904 :   relaxed_p = false;
    3179                 :       1904 :   e = 0;
    3180 [ +  - ][ +  - ]:      54214 :   provide (e);
                 [ +  + ]
    3181                 :            : }
    3182                 :            : 
    3183                 :            : void
    3184                 :     400330 : void_statement_reducer::visit_print_format (print_format* e)
    3185                 :            : {
    3186                 :            :   // When an sprint's return value is ignored, we can simply evaluate the
    3187                 :            :   // arguments in sequence
    3188                 :            : 
    3189 [ +  + ][ -  + ]:     400330 :   if (e->print_to_stream || !e->args.size())
                 [ +  + ]
    3190                 :            :     {
    3191                 :     400312 :       provide (e);
    3192                 :     400330 :       return;
    3193                 :            :     }
    3194                 :            : 
    3195         [ -  + ]:         18 :   if (session.verbose>2)
    3196                 :          0 :     clog << _("Eliding unused print ") << *e->tok << endl;
    3197                 :            : 
    3198         [ +  - ]:         18 :   block *b = new block;
    3199                 :         18 :   b->tok = e->tok;
    3200                 :            : 
    3201         [ +  + ]:         91 :   for (unsigned i=0; i<e->args.size(); i++ )
    3202                 :            :     {
    3203         [ +  - ]:         73 :       expr_statement *es = new expr_statement;
    3204                 :         73 :       es->value = e->args[i];
    3205                 :         73 :       es->tok = es->value->tok;
    3206         [ +  - ]:         73 :       b->statements.push_back(es);
    3207                 :            :     }
    3208                 :            : 
    3209                 :         18 :   b->visit(this);
    3210                 :         18 :   relaxed_p = false;
    3211                 :         18 :   e = 0;
    3212                 :         18 :   provide (e);
    3213                 :            : }
    3214                 :            : 
    3215                 :            : void
    3216                 :         12 : void_statement_reducer::visit_target_symbol (target_symbol* e)
    3217                 :            : {
    3218                 :            :   // When target_symbol isn't needed, it's just as good to
    3219                 :            :   // evaluate any array indexes directly
    3220                 :            : 
    3221         [ +  - ]:         12 :   block *b = new block;
    3222                 :         12 :   b->tok = e->tok;
    3223                 :            : 
    3224         [ -  + ]:         12 :   for (unsigned i=0; i<e->components.size(); i++ )
    3225                 :            :     {
    3226         [ #  # ]:          0 :       if (e->components[i].type != target_symbol::comp_expression_array_index)
    3227                 :          0 :         continue;
    3228                 :            : 
    3229         [ #  # ]:          0 :       expr_statement *es = new expr_statement;
    3230                 :          0 :       es->value = e->components[i].expr_index;
    3231                 :          0 :       es->tok = es->value->tok;
    3232         [ #  # ]:          0 :       b->statements.push_back(es);
    3233                 :            :     }
    3234                 :            : 
    3235         [ +  - ]:         12 :   if (b->statements.empty())
    3236                 :            :     {
    3237         [ +  - ]:         12 :       delete b;
    3238                 :         12 :       provide (e);
    3239                 :         12 :       return;
    3240                 :            :     }
    3241                 :            : 
    3242         [ #  # ]:          0 :   if (session.verbose>2)
    3243                 :          0 :     clog << _("Eliding unused target symbol ") << *e->tok << endl;
    3244                 :            : 
    3245                 :          0 :   b->visit(this);
    3246                 :          0 :   relaxed_p = false;
    3247                 :          0 :   e = 0;
    3248                 :          0 :   provide (e);
    3249                 :            : }
    3250                 :            : 
    3251                 :            : void
    3252                 :          0 : void_statement_reducer::visit_cast_op (cast_op* e)
    3253                 :            : {
    3254                 :            :   // When the result of a cast operation isn't needed, it's just as good to
    3255                 :            :   // evaluate the operand and any array indexes directly
    3256                 :            : 
    3257         [ #  # ]:          0 :   block *b = new block;
    3258                 :          0 :   b->tok = e->tok;
    3259                 :            : 
    3260         [ #  # ]:          0 :   expr_statement *es = new expr_statement;
    3261                 :          0 :   es->value = e->operand;
    3262                 :          0 :   es->tok = es->value->tok;
    3263         [ #  # ]:          0 :   b->statements.push_back(es);
    3264                 :            : 
    3265         [ #  # ]:          0 :   for (unsigned i=0; i<e->components.size(); i++ )
    3266                 :            :     {
    3267         [ #  # ]:          0 :       if (e->components[i].type != target_symbol::comp_expression_array_index)
    3268                 :          0 :         continue;
    3269                 :            : 
    3270         [ #  # ]:          0 :       es = new expr_statement;
    3271                 :          0 :       es->value = e->components[i].expr_index;
    3272                 :          0 :       es->tok = es->value->tok;
    3273         [ #  # ]:          0 :       b->statements.push_back(es);
    3274                 :            :     }
    3275                 :            : 
    3276         [ #  # ]:          0 :   if (session.verbose>2)
    3277                 :          0 :     clog << _("Eliding unused typecast ") << *e->tok << endl;
    3278                 :            : 
    3279                 :          0 :   b->visit(this);
    3280                 :          0 :   relaxed_p = false;
    3281                 :          0 :   e = 0;
    3282                 :          0 :   provide (e);
    3283                 :          0 : }
    3284                 :            : 
    3285                 :            : 
    3286                 :            : void
    3287                 :          0 : void_statement_reducer::visit_defined_op (defined_op* e)
    3288                 :            : {
    3289                 :            :   // When the result of a @defined operation isn't needed, just elide
    3290                 :            :   // it entirely.  Its operand $expression must already be
    3291                 :            :   // side-effect-free.
    3292                 :            : 
    3293         [ #  # ]:          0 :   if (session.verbose>2)
    3294                 :          0 :     clog << _("Eliding unused check ") << *e->tok << endl;
    3295                 :            : 
    3296                 :          0 :   relaxed_p = false;
    3297                 :          0 :   e = 0;
    3298                 :          0 :   provide (e);
    3299                 :          0 : }
    3300                 :            : 
    3301                 :            : 
    3302                 :            : 
    3303                 :       2391 : void semantic_pass_opt5 (systemtap_session& s, bool& relaxed_p)
    3304                 :            : {
    3305                 :            :   // Let's simplify statements with unused computed values.
    3306                 :            : 
    3307         [ +  - ]:       2391 :   void_statement_reducer vuv (s, relaxed_p);
    3308                 :            :   // This instance may be reused for multiple probe/function body trims.
    3309                 :            : 
    3310 [ +  - ][ +  - ]:       2391 :   vuv.focal_vars.insert (s.globals.begin(), s.globals.end());
                 [ +  - ]
    3311                 :            : 
    3312         [ +  + ]:     529967 :   for (unsigned i=0; i<s.probes.size(); i++)
    3313         [ +  - ]:     527576 :     vuv.replace (s.probes[i]->body);
    3314 [ +  - ][ +  + ]:     788816 :   for (map<string,functiondecl*>::iterator it = s.functions.begin();
    3315         [ +  - ]:     394408 :        it != s.functions.end(); it++)
    3316 [ +  - ][ +  - ]:     394408 :     vuv.replace (it->second->body);
                 [ +  - ]
    3317                 :       2391 : }
    3318                 :            : 
    3319                 :            : 
    3320         [ -  + ]:       2448 : struct const_folder: public update_visitor
    3321                 :            : {
    3322                 :            :   systemtap_session& session;
    3323                 :            :   bool& relaxed_p;
    3324                 :            : 
    3325                 :       2448 :   const_folder(systemtap_session& s, bool& r):
    3326                 :       2448 :     session(s), relaxed_p(r), last_number(0), last_string(0) {}
    3327                 :            : 
    3328                 :            :   literal_number* last_number;
    3329                 :            :   literal_number* get_number(expression*& e);
    3330                 :            :   void visit_literal_number (literal_number* e);
    3331                 :            : 
    3332                 :            :   literal_string* last_string;
    3333                 :            :   literal_string* get_string(expression*& e);
    3334                 :            :   void visit_literal_string (literal_string* e);
    3335                 :            : 
    3336                 :            :   void get_literal(expression*& e, literal_number*& n, literal_string*& s);
    3337                 :            : 
    3338                 :            :   void visit_if_statement (if_statement* s);
    3339                 :            :   void visit_for_loop (for_loop* s);
    3340                 :            :   void visit_foreach_loop (foreach_loop* s);
    3341                 :            :   void visit_binary_expression (binary_expression* e);
    3342                 :            :   void visit_unary_expression (unary_expression* e);
    3343                 :            :   void visit_logical_or_expr (logical_or_expr* e);
    3344                 :            :   void visit_logical_and_expr (logical_and_expr* e);
    3345                 :            :   // TODOXXX visit_regex_query could be done if we could run dfa at compiletime
    3346                 :            :   void visit_comparison (comparison* e);
    3347                 :            :   void visit_concatenation (concatenation* e);
    3348                 :            :   void visit_ternary_expression (ternary_expression* e);
    3349                 :            :   void visit_defined_op (defined_op* e);
    3350                 :            :   void visit_target_symbol (target_symbol* e);
    3351                 :            : };
    3352                 :            : 
    3353                 :            : void
    3354                 :     697610 : const_folder::get_literal(expression*& e,
    3355                 :            :                           literal_number*& n,
    3356                 :            :                           literal_string*& s)
    3357                 :            : {
    3358                 :     697610 :   replace (e);
    3359         [ +  + ]:     697610 :   n = (e == last_number) ? last_number : NULL;
    3360         [ +  + ]:     697610 :   s = (e == last_string) ? last_string : NULL;
    3361                 :     697610 : }
    3362                 :            : 
    3363                 :            : literal_number*
    3364                 :     772680 : const_folder::get_number(expression*& e)
    3365                 :            : {
    3366                 :     772680 :   replace (e);
    3367         [ +  + ]:     772680 :   return (e == last_number) ? last_number : NULL;
    3368                 :            : }
    3369                 :            : 
    3370                 :            : void
    3371                 :     682453 : const_folder::visit_literal_number (literal_number* e)
    3372                 :            : {
    3373                 :     682453 :   last_number = e;
    3374                 :     682453 :   provide (e);
    3375                 :     682453 : }
    3376                 :            : 
    3377                 :            : literal_string*
    3378                 :      64542 : const_folder::get_string(expression*& e)
    3379                 :            : {
    3380                 :      64542 :   replace (e);
    3381         [ +  + ]:      64542 :   return (e == last_string) ? last_string : NULL;
    3382                 :            : }
    3383                 :            : 
    3384                 :            : void
    3385                 :     338901 : const_folder::visit_literal_string (literal_string* e)
    3386                 :            : {
    3387                 :     338901 :   last_string = e;
    3388                 :     338901 :   provide (e);
    3389                 :     338901 : }
    3390                 :            : 
    3391                 :            : void
    3392                 :     644285 : const_folder::visit_if_statement (if_statement* s)
    3393                 :            : {
    3394                 :     644285 :   literal_number* cond = get_number (s->condition);
    3395         [ +  + ]:     644285 :   if (!cond)
    3396                 :            :     {
    3397                 :     643511 :       replace (s->thenblock);
    3398                 :     643511 :       replace (s->elseblock);
    3399                 :     643511 :       provide (s);
    3400                 :            :     }
    3401                 :            :   else
    3402                 :            :     {
    3403         [ -  + ]:        774 :       if (session.verbose>2)
    3404 [ #  # ][ #  # ]:          0 :         clog << _F("Collapsing constant-%" PRIi64 " if-statement %s",
         [ #  # ][ #  # ]
    3405         [ #  # ]:          0 :                    cond->value, lex_cast(*s->tok).c_str()) << endl;
    3406                 :        774 :       relaxed_p = false;
    3407                 :            : 
    3408         [ +  + ]:        774 :       statement* n = cond->value ? s->thenblock : s->elseblock;
    3409         [ +  + ]:        774 :       if (n)
    3410                 :        635 :         n->visit (this);
    3411                 :            :       else
    3412         [ +  - ]:        139 :         provide (new null_statement (s->tok));
    3413                 :            :     }
    3414                 :     644285 : }
    3415                 :            : 
    3416                 :            : void
    3417                 :       1235 : const_folder::visit_for_loop (for_loop* s)
    3418                 :            : {
    3419                 :       1235 :   literal_number* cond = get_number (s->cond);
    3420 [ +  + ][ +  - ]:       1235 :   if (!cond || cond->value)
    3421                 :            :     {
    3422                 :       1235 :       replace (s->init);
    3423                 :       1235 :       replace (s->incr);
    3424                 :       1235 :       replace (s->block);
    3425                 :       1235 :       provide (s);
    3426                 :            :     }
    3427                 :            :   else
    3428                 :            :     {
    3429         [ #  # ]:          0 :       if (session.verbose>2)
    3430                 :          0 :         clog << _("Collapsing constantly-false for-loop ") << *s->tok << endl;
    3431                 :          0 :       relaxed_p = false;
    3432                 :            : 
    3433         [ #  # ]:          0 :       if (s->init)
    3434                 :          0 :         s->init->visit (this);
    3435                 :            :       else
    3436         [ #  # ]:          0 :         provide (new null_statement (s->tok));
    3437                 :            :     }
    3438                 :       1235 : }
    3439                 :            : 
    3440                 :            : void
    3441                 :        761 : const_folder::visit_foreach_loop (foreach_loop* s)
    3442                 :            : {
    3443                 :        761 :   literal_number* limit = get_number (s->limit);
    3444 [ +  + ][ +  - ]:        761 :   if (!limit || limit->value > 0)
    3445                 :            :     {
    3446         [ +  + ]:       1929 :       for (unsigned i = 0; i < s->indexes.size(); ++i)
    3447                 :       1168 :         replace (s->indexes[i]);
    3448                 :        761 :       replace (s->base);
    3449                 :        761 :       replace (s->value);
    3450                 :        761 :       replace (s->block);
    3451                 :        761 :       provide (s);
    3452                 :            :     }
    3453                 :            :   else
    3454                 :            :     {
    3455         [ #  # ]:          0 :       if (session.verbose>2)
    3456                 :          0 :         clog << _("Collapsing constantly-limited foreach-loop ") << *s->tok << endl;
    3457                 :          0 :       relaxed_p = false;
    3458                 :            : 
    3459         [ #  # ]:          0 :       provide (new null_statement (s->tok));
    3460                 :            :     }
    3461                 :        761 : }
    3462                 :            : 
    3463                 :            : void
    3464                 :      43270 : const_folder::visit_binary_expression (binary_expression* e)
    3465                 :            : {
    3466                 :            :   int64_t value;
    3467                 :      43270 :   literal_number* left = get_number (e->left);
    3468                 :      43270 :   literal_number* right = get_number (e->right);
    3469                 :            : 
    3470 [ +  + ][ +  + ]:      43270 :   if (right && !right->value && (e->op == "/" || e->op == "%"))
         [ +  + ][ -  + ]
                 [ +  + ]
    3471                 :            :     {
    3472                 :            :       // Give divide-by-zero a chance to be optimized out elsewhere,
    3473                 :            :       // and if not it will be a runtime error anyway...
    3474                 :          8 :       provide (e);
    3475                 :          8 :       return;
    3476                 :            :     }
    3477                 :            : 
    3478 [ +  + ][ +  + ]:      43262 :   if (left && right)
    3479                 :            :     {
    3480         [ +  + ]:        160 :       if (e->op == "+")
    3481                 :         10 :         value = left->value + right->value;
    3482         [ +  + ]:         70 :       else if (e->op == "-")
    3483                 :         13 :         value = left->value - right->value;
    3484         [ +  + ]:         57 :       else if (e->op == "*")
    3485                 :         20 :         value = left->value * right->value;
    3486         [ +  + ]:         37 :       else if (e->op == "&")
    3487                 :          1 :         value = left->value & right->value;
    3488         [ +  + ]:         36 :       else if (e->op == "|")
    3489                 :          3 :         value = left->value | right->value;
    3490         [ +  + ]:         33 :       else if (e->op == "^")
    3491                 :          1 :         value = left->value ^ right->value;
    3492         [ +  + ]:         32 :       else if (e->op == ">>")
    3493                 :          4 :         value = left->value >> max(min(right->value, (int64_t)64), (int64_t)0);
    3494         [ +  + ]:         28 :       else if (e->op == "<<")
    3495                 :          9 :         value = left->value << max(min(right->value, (int64_t)64), (int64_t)0);
    3496         [ +  + ]:         19 :       else if (e->op == "/")
    3497                 :            :         value = (left->value == LLONG_MIN && right->value == -1) ? LLONG_MIN :
    3498 [ -  + ][ #  # ]:         13 :                 left->value / right->value;
    3499         [ +  - ]:          6 :       else if (e->op == "%")
    3500                 :            :         value = (left->value == LLONG_MIN && right->value == -1) ? 0 :
    3501 [ +  + ][ -  + ]:          6 :                 left->value % right->value;
    3502                 :            :       else
    3503 [ #  # ][ #  # ]:          0 :         throw semantic_error (_("unsupported binary operator ") + e->op);
    3504                 :            :     }
    3505                 :            : 
    3506 [ +  + ][ +  + ]:      50195 :   else if ((left && ((left->value == 0 && (e->op == "*" || e->op == "&" ||
         [ +  + ][ +  -  
             +  -  +  - ]
           [ +  +  +  -  
           +  - ][ +  + ]
           [ +  +  +  -  
                   +  + ]
           [ +  +  +  + ]
           [ +  +  +  -  
           -  + ][ +  + ]
    3507                 :         12 :                                            e->op == ">>" || e->op == "<<" )) ||
    3508                 :          4 :                      (left->value ==-1 && (e->op == "|" || e->op == ">>"))))
    3509                 :            :            ||
    3510                 :        180 :            (right && ((right->value == 0 && (e->op == "*" || e->op == "&")) ||
    3511                 :       6793 :                       (right->value == 1 && (e->op == "%")) ||
    3512                 :         24 :                       (right->value ==-1 && (e->op == "%" || e->op == "|")))))
    3513                 :            :     {
    3514         [ +  + ]:         95 :       expression* other = left ? e->right : e->left;
    3515         [ +  - ]:         95 :       varuse_collecting_visitor vu(session);
    3516         [ +  - ]:         95 :       other->visit(&vu);
    3517 [ +  - ][ +  + ]:         95 :       if (!vu.side_effect_free())
    3518                 :            :         {
    3519         [ +  - ]:          5 :           provide (e);
    3520                 :            :           return;
    3521                 :            :         }
    3522                 :            : 
    3523         [ +  + ]:         90 :       if (left)
    3524                 :          1 :         value = left->value;
    3525 [ +  - ][ +  + ]:         89 :       else if (e->op == "%")
    3526                 :          2 :         value = 0;
    3527                 :            :       else
    3528 [ +  - ][ +  + ]:         95 :         value = right->value;
    3529                 :            :     }
    3530                 :            : 
    3531 [ +  + ][ +  + ]:      57565 :   else if ((left && ((left->value == 0 && (e->op == "+" || e->op == "|" ||
                 [ +  - ]
           [ +  -  +  - ]
           [ +  +  +  - ]
           [ +  +  +  - ]
         [ +  + ][ +  +  
          -  +  #  #  #  
           #  #  # ][ +  
             +  +  -  +  
                      - ]
           [ +  +  +  - ]
           [ +  +  +  -  
           -  + ][ +  + ]
    3532                 :          6 :                                            e->op == "^")) ||
    3533                 :         19 :                      (left->value == 1 && (e->op == "*")) ||
    3534                 :          2 :                      (left->value ==-1 && (e->op == "&"))))
    3535                 :            :            ||
    3536                 :          3 :            (right && ((right->value == 0 && (e->op == "+" || e->op == "-" ||
    3537                 :          0 :                                              e->op == "|" || e->op == "^")) ||
    3538                 :      13582 :                       (right->value == 1 && (e->op == "*" || e->op == "/")) ||
    3539                 :         12 :                       (right->value ==-1 && (e->op == "&")) ||
    3540                 :        854 :                       (right->value <= 0 && (e->op == ">>" || e->op == "<<")))))
    3541                 :            :     {
    3542         [ -  + ]:          3 :       if (session.verbose>2)
    3543                 :          0 :         clog << _("Collapsing constant-identity binary operator ") << *e->tok << endl;
    3544                 :          3 :       relaxed_p = false;
    3545                 :            : 
    3546         [ -  + ]:          3 :       provide (left ? e->right : e->left);
    3547                 :          3 :       return;
    3548                 :            :     }
    3549                 :            : 
    3550                 :            :   else
    3551                 :            :     {
    3552                 :      43084 :       provide (e);
    3553                 :      43084 :       return;
    3554                 :            :     }
    3555                 :            : 
    3556         [ -  + ]:        170 :   if (session.verbose>2)
    3557 [ #  # ][ #  # ]:          0 :     clog << _F("Collapsing constant-%" PRIi64 " binary operator %s",
         [ #  # ][ #  # ]
    3558         [ #  # ]:          0 :                value, lex_cast(*e->tok).c_str()) << endl;
    3559                 :        170 :   relaxed_p = false;
    3560                 :            : 
    3561         [ +  - ]:        170 :   literal_number* n = new literal_number(value);
    3562                 :        170 :   n->tok = e->tok;
    3563                 :      43270 :   n->visit (this);
    3564                 :            : }
    3565                 :            : 
    3566                 :            : void
    3567                 :      12213 : const_folder::visit_unary_expression (unary_expression* e)
    3568                 :            : {
    3569                 :      12213 :   literal_number* operand = get_number (e->operand);
    3570         [ +  + ]:      12213 :   if (!operand)
    3571                 :       9878 :     provide (e);
    3572                 :            :   else
    3573                 :            :     {
    3574         [ -  + ]:       2335 :       if (session.verbose>2)
    3575                 :          0 :         clog << _("Collapsing constant unary ") << *e->tok << endl;
    3576                 :       2335 :       relaxed_p = false;
    3577                 :            : 
    3578                 :       2335 :       literal_number* n = new literal_number (*operand);
    3579                 :       2335 :       n->tok = e->tok;
    3580         [ +  - ]:       2335 :       if (e->op == "+")
    3581                 :            :         ; // nothing to do
    3582         [ +  + ]:       2335 :       else if (e->op == "-")
    3583                 :       2237 :         n->value = -n->value;
    3584         [ +  + ]:         98 :       else if (e->op == "!")
    3585                 :         14 :         n->value = !n->value;
    3586         [ +  - ]:         84 :       else if (e->op == "~")
    3587                 :         84 :         n->value = ~n->value;
    3588                 :            :       else
    3589 [ #  # ][ #  # ]:          0 :         throw semantic_error (_("unsupported unary operator ") + e->op);
    3590                 :       2335 :       n->visit (this);
    3591                 :            :     }
    3592                 :      12213 : }
    3593                 :            : 
    3594                 :            : void
    3595                 :       3993 : const_folder::visit_logical_or_expr (logical_or_expr* e)
    3596                 :            : {
    3597                 :            :   int64_t value;
    3598                 :       3993 :   literal_number* left = get_number (e->left);
    3599                 :       3993 :   literal_number* right = get_number (e->right);
    3600                 :            : 
    3601 [ +  + ][ +  - ]:       3993 :   if (left && right)
    3602 [ +  + ][ -  + ]:          3 :     value = left->value || right->value;
    3603                 :            : 
    3604 [ -  + ][ #  # ]:       3990 :   else if ((left && left->value) || (right && right->value))
         [ +  + ][ -  + ]
    3605                 :            :     {
    3606                 :            :       // If the const is on the left, we get to short-circuit the right
    3607                 :            :       // immediately.  Otherwise, we can only eliminate the LHS if it's pure.
    3608         [ #  # ]:          0 :       if (right)
    3609                 :            :         {
    3610         [ #  # ]:          0 :           varuse_collecting_visitor vu(session);
    3611         [ #  # ]:          0 :           e->left->visit(&vu);
    3612 [ #  # ][ #  # ]:          0 :           if (!vu.side_effect_free())
    3613                 :            :             {
    3614         [ #  # ]:          0 :               provide (e);
    3615                 :            :               return;
    3616 [ #  # ][ #  # ]:          0 :             }
    3617                 :            :         }
    3618                 :            : 
    3619                 :          0 :       value = 1;
    3620                 :            :     }
    3621                 :            : 
    3622                 :            :   // We might also get rid of useless "0||x" and "x||0", except it does
    3623                 :            :   // normalize x to 0 or 1.  We could change it to "!!x", but it's not clear
    3624                 :            :   // that this would gain us much.
    3625                 :            : 
    3626                 :            :   else
    3627                 :            :     {
    3628                 :       3990 :       provide (e);
    3629                 :       3990 :       return;
    3630                 :            :     }
    3631                 :            : 
    3632         [ -  + ]:          3 :   if (session.verbose>2)
    3633                 :          0 :     clog << _("Collapsing constant logical-OR ") << *e->tok << endl;
    3634                 :          3 :   relaxed_p = false;
    3635                 :            : 
    3636         [ +  - ]:          3 :   literal_number* n = new literal_number(value);
    3637                 :          3 :   n->tok = e->tok;
    3638                 :       3993 :   n->visit (this);
    3639                 :            : }
    3640                 :            : 
    3641                 :            : void
    3642                 :       7847 : const_folder::visit_logical_and_expr (logical_and_expr* e)
    3643                 :            : {
    3644                 :            :   int64_t value;
    3645                 :       7847 :   literal_number* left = get_number (e->left);
    3646                 :       7847 :   literal_number* right = get_number (e->right);
    3647                 :            : 
    3648 [ +  + ][ +  + ]:       7847 :   if (left && right)
    3649 [ +  + ][ +  - ]:          9 :     value = left->value && right->value;
    3650                 :            : 
    3651 [ +  + ][ +  + ]:       7838 :   else if ((left && !left->value) || (right && !right->value))
         [ +  + ][ -  + ]
    3652                 :            :     {
    3653                 :            :       // If the const is on the left, we get to short-circuit the right
    3654                 :            :       // immediately.  Otherwise, we can only eliminate the LHS if it's pure.
    3655         [ -  + ]:          2 :       if (right)
    3656                 :            :         {
    3657         [ #  # ]:          0 :           varuse_collecting_visitor vu(session);
    3658         [ #  # ]:          0 :           e->left->visit(&vu);
    3659 [ #  # ][ #  # ]:          0 :           if (!vu.side_effect_free())
    3660                 :            :             {
    3661         [ #  # ]:          0 :               provide (e);
    3662                 :            :               return;
    3663 [ #  # ][ #  # ]:          0 :             }
    3664                 :            :         }
    3665                 :            : 
    3666                 :          2 :       value = 0;
    3667                 :            :     }
    3668                 :            : 
    3669                 :            :   // We might also get rid of useless "1&&x" and "x&&1", except it does
    3670                 :            :   // normalize x to 0 or 1.  We could change it to "!!x", but it's not clear
    3671                 :            :   // that this would gain us much.
    3672                 :            : 
    3673                 :            :   else
    3674                 :            :     {
    3675                 :       7836 :       provide (e);
    3676                 :       7836 :       return;
    3677                 :            :     }
    3678                 :            : 
    3679         [ -  + ]:         11 :   if (session.verbose>2)
    3680                 :          0 :     clog << _("Collapsing constant logical-AND ") << *e->tok << endl;
    3681                 :         11 :   relaxed_p = false;
    3682                 :            : 
    3683         [ +  - ]:         11 :   literal_number* n = new literal_number(value);
    3684                 :         11 :   n->tok = e->tok;
    3685                 :       7847 :   n->visit (this);
    3686                 :            : }
    3687                 :            : 
    3688                 :            : void
    3689                 :     348805 : const_folder::visit_comparison (comparison* e)
    3690                 :            : {
    3691                 :            :   int comp;
    3692                 :            : 
    3693                 :            :   literal_number *left_num, *right_num;
    3694                 :            :   literal_string *left_str, *right_str;
    3695         [ +  - ]:     348805 :   get_literal(e->left, left_num, left_str);
    3696         [ +  - ]:     348805 :   get_literal(e->right, right_num, right_str);
    3697                 :            : 
    3698 [ +  + ][ +  + ]:     348805 :   if (left_str && right_str)
    3699         [ +  - ]:         17 :     comp = left_str->value.compare(right_str->value);
    3700                 :            : 
    3701 [ +  + ][ +  + ]:     348788 :   else if (left_num && right_num)
    3702                 :            :     comp = left_num->value < right_num->value ? -1 :
    3703 [ +  + ][ +  + ]:        144 :            left_num->value > right_num->value ? 1 : 0;
    3704                 :            : 
    3705 [ +  + ][ -  + ]:     348644 :   else if ((left_num && ((left_num->value == LLONG_MIN &&
         [ #  # ][ #  # ]
         [ -  + ][ #  # ]
         [ #  # ][ +  + ]
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
         [ #  # ][ #  # ]
                 [ -  + ]
    3706 [ #  # ][ #  # ]:          0 :                           (e->op == "<=" || e->op == ">")) ||
    3707                 :            :                          (left_num->value == LLONG_MAX &&
    3708 [ #  # ][ #  # ]:          0 :                           (e->op == ">=" || e->op == "<"))))
    3709                 :            :            ||
    3710                 :            :            (right_num && ((right_num->value == LLONG_MIN &&
    3711 [ #  # ][ #  # ]:          0 :                             (e->op == ">=" || e->op == "<")) ||
    3712                 :            :                            (right_num->value == LLONG_MAX &&
    3713 [ #  # ][ #  # ]:          0 :                             (e->op == "<=" || e->op == ">")))))
    3714                 :            :     {
    3715         [ #  # ]:          0 :       expression* other = left_num ? e->right : e->left;
    3716         [ #  # ]:          0 :       varuse_collecting_visitor vu(session);
    3717         [ #  # ]:          0 :       other->visit(&vu);
    3718 [ #  # ][ #  # ]:          0 :       if (!vu.side_effect_free())
    3719         [ #  # ]:          0 :         provide (e);
    3720                 :            :       else
    3721                 :            :         {
    3722         [ #  # ]:          0 :           if (session.verbose>2)
    3723 [ #  # ][ #  # ]:          0 :             clog << _("Collapsing constant-boundary comparison ") << *e->tok << endl;
                 [ #  # ]
    3724                 :          0 :           relaxed_p = false;
    3725                 :            : 
    3726                 :            :           // ops <= and >= are true, < and > are false
    3727 [ #  # ][ #  # ]:          0 :           literal_number* n = new literal_number( e->op.length() == 2 );
                 [ #  # ]
    3728                 :          0 :           n->tok = e->tok;
    3729         [ #  # ]:          0 :           n->visit (this);
    3730                 :            :         }
    3731         [ #  # ]:          0 :       return;
    3732                 :            :     }
    3733                 :            : 
    3734                 :            :   else
    3735                 :            :     {
    3736         [ +  - ]:     348644 :       provide (e);
    3737                 :            :       return;
    3738                 :            :     }
    3739                 :            : 
    3740         [ -  + ]:        161 :   if (session.verbose>2)
    3741 [ #  # ][ #  # ]:          0 :     clog << _("Collapsing constant comparison ") << *e->tok << endl;
                 [ #  # ]
    3742                 :        161 :   relaxed_p = false;
    3743                 :            : 
    3744                 :            :   int64_t value;
    3745 [ +  - ][ +  + ]:        161 :   if (e->op == "==")
    3746                 :        141 :     value = comp == 0;
    3747 [ +  - ][ +  + ]:         20 :   else if (e->op == "!=")
    3748                 :         10 :     value = comp != 0;
    3749 [ +  - ][ +  + ]:         10 :   else if (e->op == "<")
    3750                 :          5 :     value = comp < 0;
    3751 [ +  - ][ +  + ]:          5 :   else if (e->op == ">")
    3752                 :          2 :     value = comp > 0;
    3753 [ +  - ][ +  + ]:          3 :   else if (e->op == "<=")
    3754                 :          2 :     value = comp <= 0;
    3755 [ +  - ][ +  - ]:          1 :   else if (e->op == ">=")
    3756                 :          1 :     value = comp >= 0;
    3757                 :            :   else
    3758 [ #  # ][ #  # ]:          0 :     throw semantic_error (_("unsupported comparison operator ") + e->op);
    3759                 :            : 
    3760 [ +  - ][ +  - ]:        161 :   literal_number* n = new literal_number(value);
    3761                 :        161 :   n->tok = e->tok;
    3762         [ +  - ]:     348805 :   n->visit (this);
    3763                 :            : }
    3764                 :            : 
    3765                 :            : void
    3766                 :      32271 : const_folder::visit_concatenation (concatenation* e)
    3767                 :            : {
    3768                 :      32271 :   literal_string* left = get_string (e->left);
    3769                 :      32271 :   literal_string* right = get_string (e->right);
    3770                 :            : 
    3771 [ +  + ][ +  + ]:      32271 :   if (left && right)
    3772                 :            :     {
    3773         [ -  + ]:        395 :       if (session.verbose>2)
    3774                 :          0 :         clog << _("Collapsing constant concatenation ") << *e->tok << endl;
    3775                 :        395 :       relaxed_p = false;
    3776                 :            : 
    3777         [ +  - ]:        395 :       literal_string* n = new literal_string (*left);
    3778                 :        395 :       n->tok = e->tok;
    3779                 :        395 :       n->value.append(right->value);
    3780                 :        395 :       n->visit (this);
    3781                 :            :     }
    3782 [ +  + ][ +  - ]:      42394 :   else if ((left && left->value.empty()) ||
           [ +  +  +  + ]
                 [ +  + ]
    3783                 :      10518 :            (right && right->value.empty()))
    3784                 :            :     {
    3785         [ -  + ]:          4 :       if (session.verbose>2)
    3786                 :          0 :         clog << _("Collapsing identity concatenation ") << *e->tok << endl;
    3787                 :          4 :       relaxed_p = false;
    3788         [ -  + ]:          4 :       provide(left ? e->right : e->left);
    3789                 :            :     }
    3790                 :            :   else
    3791                 :      31872 :     provide (e);
    3792                 :      32271 : }
    3793                 :            : 
    3794                 :            : void
    3795                 :       3966 : const_folder::visit_ternary_expression (ternary_expression* e)
    3796                 :            : {
    3797                 :       3966 :   literal_number* cond = get_number (e->cond);
    3798         [ +  + ]:       3966 :   if (!cond)
    3799                 :            :     {
    3800                 :       1421 :       replace (e->truevalue);
    3801                 :       1421 :       replace (e->falsevalue);
    3802                 :       1421 :       provide (e);
    3803                 :            :     }
    3804                 :            :   else
    3805                 :            :     {
    3806         [ -  + ]:       2545 :       if (session.verbose>2)
    3807 [ #  # ][ #  # ]:          0 :         clog << _F("Collapsing constant-%" PRIi64 " ternary %s",
         [ #  # ][ #  # ]
    3808         [ #  # ]:          0 :                    cond->value, lex_cast(*e->tok).c_str()) << endl;
    3809                 :       2545 :       relaxed_p = false;
    3810                 :            : 
    3811         [ +  + ]:       2545 :       expression* n = cond->value ? e->truevalue : e->falsevalue;
    3812                 :       2545 :       n->visit (this);
    3813                 :            :     }
    3814                 :       3966 : }
    3815                 :            : 
    3816                 :            : void
    3817                 :         12 : const_folder::visit_defined_op (defined_op* e)
    3818                 :            : {
    3819                 :            :   // If a @defined makes it this far, then it is, de facto, undefined.
    3820                 :            : 
    3821         [ -  + ]:         12 :   if (session.verbose>2)
    3822                 :          0 :     clog << _("Collapsing untouched @defined check ") << *e->tok << endl;
    3823                 :         12 :   relaxed_p = false;
    3824                 :            : 
    3825         [ +  - ]:         12 :   literal_number* n = new literal_number (0);
    3826                 :         12 :   n->tok = e->tok;
    3827                 :         12 :   n->visit (this);
    3828                 :         12 : }
    3829                 :            : 
    3830                 :            : void
    3831                 :        258 : const_folder::visit_target_symbol (target_symbol* e)
    3832                 :            : {
    3833         [ +  + ]:        258 :   if (session.skip_badvars)
    3834                 :            :     {
    3835                 :            :       // Upon user request for ignoring context, the symbol is replaced
    3836                 :            :       // with a literal 0 and a warning message displayed
    3837                 :            :       // XXX this ignores possible side-effects, e.g. in array indexes
    3838         [ +  - ]:          1 :       literal_number* ln_zero = new literal_number (0);
    3839                 :          1 :       ln_zero->tok = e->tok;
    3840                 :          1 :       provide (ln_zero);
    3841                 :          1 :       session.print_warning (_("Bad $context variable being substituted with literal 0"),
    3842 [ +  - ][ +  - ]:          1 :                                e->tok);
                 [ +  - ]
    3843                 :          1 :       relaxed_p = false;
    3844                 :            :     }
    3845                 :            :   else
    3846                 :        257 :     update_visitor::visit_target_symbol (e);
    3847                 :        258 : }
    3848                 :            : 
    3849                 :       2448 : static void semantic_pass_const_fold (systemtap_session& s, bool& relaxed_p)
    3850                 :            : {
    3851                 :            :   // Let's simplify statements with constant values.
    3852                 :            : 
    3853         [ +  - ]:       2448 :   const_folder cf (s, relaxed_p);
    3854                 :            :   // This instance may be reused for multiple probe/function body trims.
    3855                 :            : 
    3856         [ +  + ]:     542472 :   for (unsigned i=0; i<s.probes.size(); i++)
    3857         [ +  - ]:     540024 :     cf.replace (s.probes[i]->body);
    3858 [ +  - ][ +  + ]:     790486 :   for (map<string,functiondecl*>::iterator it = s.functions.begin();
    3859         [ +  - ]:     395243 :        it != s.functions.end(); it++)
    3860 [ +  - ][ +  - ]:     395243 :     cf.replace (it->second->body);
                 [ +  - ]
    3861                 :       2448 : }
    3862                 :            : 
    3863                 :            : 
    3864         [ -  + ]:        250 : struct duplicate_function_remover: public functioncall_traversing_visitor
    3865                 :            : {
    3866                 :            :   systemtap_session& s;
    3867                 :            :   map<functiondecl*, functiondecl*>& duplicate_function_map;
    3868                 :            : 
    3869                 :        250 :   duplicate_function_remover(systemtap_session& sess,
    3870                 :            :                              map<functiondecl*, functiondecl*>&dfm):
    3871                 :        250 :     s(sess), duplicate_function_map(dfm) {};
    3872                 :            : 
    3873                 :            :   void visit_functioncall (functioncall* e);
    3874                 :            : };
    3875                 :            : 
    3876                 :            : void
    3877                 :     366702 : duplicate_function_remover::visit_functioncall (functioncall *e)
    3878                 :            : {
    3879                 :     366702 :   functioncall_traversing_visitor::visit_functioncall (e);
    3880                 :            : 
    3881                 :            :   // If the current function call reference points to a function that
    3882                 :            :   // is a duplicate, replace it.
    3883         [ +  + ]:     366702 :   if (duplicate_function_map.count(e->referent) != 0)
    3884                 :            :     {
    3885         [ -  + ]:     124629 :       if (s.verbose>2)
    3886                 :          0 :           clog << _F("Changing %s reference to %s reference\n",
    3887         [ #  # ]:          0 :                      e->referent->name.c_str(), duplicate_function_map[e->referent]->name.c_str());
    3888                 :     124629 :       e->tok = duplicate_function_map[e->referent]->tok;
    3889                 :     124629 :       e->function = duplicate_function_map[e->referent]->name;
    3890                 :     124629 :       e->referent = duplicate_function_map[e->referent];
    3891                 :            :     }
    3892                 :     366702 : }
    3893                 :            : 
    3894                 :            : static string
    3895                 :     161732 : get_functionsig (functiondecl* f)
    3896                 :            : {
    3897         [ +  - ]:     161732 :   ostringstream s;
    3898                 :            : 
    3899                 :            :   // Get the "name:args body" of the function in s.  We have to
    3900                 :            :   // include the args since the function 'x1(a, b)' is different than
    3901                 :            :   // the function 'x2(b, a)' even if the bodies of the two functions
    3902                 :            :   // are exactly the same.
    3903         [ +  - ]:     161732 :   f->printsig(s);
    3904         [ +  - ]:     161732 :   f->body->print(s);
    3905                 :            : 
    3906                 :            :   // printsig puts f->name + ':' on the front.  Remove this
    3907                 :            :   // (otherwise, functions would never compare equal).
    3908 [ +  - ][ +  - ]:     161732 :   string str = s.str().erase(0, f->name.size() + 1);
         [ +  - ][ +  - ]
                 [ +  - ]
    3909                 :            : 
    3910                 :            :   // Return the function signature.
    3911         [ +  - ]:     161732 :   return str;
    3912                 :            : }
    3913                 :            : 
    3914                 :       1250 : void semantic_pass_opt6 (systemtap_session& s, bool& relaxed_p)
    3915                 :            : {
    3916                 :            :   // Walk through all the functions, looking for duplicates.
    3917         [ +  - ]:       1250 :   map<string, functiondecl*> functionsig_map;
    3918         [ +  - ]:       1250 :   map<functiondecl*, functiondecl*> duplicate_function_map;
    3919                 :            : 
    3920                 :            : 
    3921         [ +  - ]:       1250 :   vector<functiondecl*> newly_zapped_functions;
    3922 [ +  - ][ +  - ]:     162982 :   for (map<string,functiondecl*>::iterator it = s.functions.begin(); it != s.functions.end(); it++)
                 [ +  + ]
    3923                 :            :     {
    3924         [ +  - ]:     161732 :       functiondecl *fd = it->second;
    3925         [ +  - ]:     161732 :       string functionsig = get_functionsig(fd);
    3926                 :            : 
    3927 [ +  - ][ +  + ]:     161732 :       if (functionsig_map.count(functionsig) == 0)
    3928                 :            :         {
    3929                 :            :           // This function is unique.  Remember it.
    3930         [ +  - ]:      40580 :           functionsig_map[functionsig] = fd;
    3931                 :            :         }
    3932                 :            :       else
    3933                 :            :         {
    3934                 :            :           // This function is a duplicate.
    3935 [ +  - ][ +  - ]:     121152 :           duplicate_function_map[fd] = functionsig_map[functionsig];
    3936         [ +  - ]:     121152 :           newly_zapped_functions.push_back (fd);
    3937                 :     121152 :           relaxed_p = false;
    3938                 :            :         }
    3939         [ +  - ]:     161732 :     }
    3940         [ +  + ]:     122402 :   for (unsigned i=0; i<newly_zapped_functions.size(); i++)
    3941                 :            :     {
    3942         [ +  - ]:     121152 :       map<string,functiondecl*>::iterator where = s.functions.find (newly_zapped_functions[i]->name);
    3943 [ +  - ][ -  + ]:     121152 :       assert (where != s.functions.end());
    3944         [ +  - ]:     121152 :       s.functions.erase (where);
    3945                 :            :     }
    3946                 :            : 
    3947                 :            : 
    3948                 :            :   // If we have duplicate functions, traverse down the tree, replacing
    3949                 :            :   // the appropriate function calls.
    3950                 :            :   // duplicate_function_remover::visit_functioncall() handles the
    3951                 :            :   // details of replacing the function calls.
    3952 [ +  - ][ +  + ]:       1250 :   if (duplicate_function_map.size() != 0)
    3953                 :            :     {
    3954         [ +  - ]:        250 :       duplicate_function_remover dfr (s, duplicate_function_map);
    3955                 :            : 
    3956         [ +  + ]:      73655 :       for (unsigned i=0; i < s.probes.size(); i++)
    3957 [ +  - ][ +  - ]:      73655 :         s.probes[i]->body->visit(&dfr);
    3958 [ +  - ][ +  - ]:       1250 :     }
                 [ +  - ]
    3959                 :       1250 : }
    3960                 :            : 
    3961                 :            : 
    3962                 :            : static int
    3963                 :       1115 : semantic_pass_optimize1 (systemtap_session& s)
    3964                 :            : {
    3965                 :            :   // In this pass, we attempt to rewrite probe/function bodies to
    3966                 :            :   // eliminate some blatantly unnecessary code.  This is run before
    3967                 :            :   // type inference, but after symbol resolution and derived_probe
    3968                 :            :   // creation.  We run an outer "relaxation" loop that repeats the
    3969                 :            :   // optimizations until none of them find anything to remove.
    3970                 :            : 
    3971                 :       1115 :   int rc = 0;
    3972                 :            : 
    3973                 :            :   // Save the old value of suppress_warnings, as we will be changing
    3974                 :            :   // it below.
    3975                 :       1115 :   save_and_restore<bool> suppress_warnings(& s.suppress_warnings);
    3976                 :            : 
    3977                 :       1115 :   bool relaxed_p = false;
    3978                 :       1115 :   unsigned iterations = 0;
    3979         [ +  + ]:       3563 :   while (! relaxed_p)
    3980                 :            :     {
    3981         [ +  - ]:       2457 :       assert_no_interrupts();
    3982                 :            : 
    3983                 :       2457 :       relaxed_p = true; // until proven otherwise
    3984                 :            : 
    3985                 :            :       // If the verbosity is high enough, always print warnings (overrides -w),
    3986                 :            :       // or if not, always suppress warnings for every itteration after the first.
    3987         [ +  + ]:       2457 :       if(s.verbose > 2)
    3988                 :          1 :         s.suppress_warnings = false;
    3989         [ +  + ]:       2456 :       else if (iterations > 0)
    3990                 :       1342 :         s.suppress_warnings = true;
    3991                 :            : 
    3992         [ +  + ]:       2457 :       if (!s.unoptimized)
    3993                 :            :         {
    3994         [ +  - ]:       2400 :           semantic_pass_opt1 (s, relaxed_p);
    3995         [ +  + ]:       2400 :           semantic_pass_opt2 (s, relaxed_p, iterations); // produce some warnings only on iteration=0
    3996         [ +  + ]:       2392 :           semantic_pass_opt3 (s, relaxed_p);
    3997         [ +  - ]:       2391 :           semantic_pass_opt4 (s, relaxed_p);
    3998         [ +  - ]:       2391 :           semantic_pass_opt5 (s, relaxed_p);
    3999                 :            :         }
    4000                 :            : 
    4001                 :            :       // For listing mode, we need const-folding regardless of optimization so
    4002                 :            :       // that @defined expressions can be properly resolved.  PR11360
    4003                 :            :       // We also want it in case variables are used in if/case expressions,
    4004                 :            :       // so enable always.  PR11366
    4005         [ +  - ]:       2448 :       semantic_pass_const_fold (s, relaxed_p);
    4006                 :            : 
    4007                 :       2448 :       iterations ++;
    4008                 :            :     }
    4009                 :            : 
    4010                 :       1115 :   return rc;
    4011                 :            : }
    4012                 :            : 
    4013                 :            : 
    4014                 :            : static int
    4015                 :       1035 : semantic_pass_optimize2 (systemtap_session& s)
    4016                 :            : {
    4017                 :            :   // This is run after type inference.  We run an outer "relaxation"
    4018                 :            :   // loop that repeats the optimizations until none of them find
    4019                 :            :   // anything to remove.
    4020                 :            : 
    4021                 :       1035 :   int rc = 0;
    4022                 :            : 
    4023                 :            :   // Save the old value of suppress_warnings, as we will be changing
    4024                 :            :   // it below.
    4025                 :       1035 :   save_and_restore<bool> suppress_warnings(& s.suppress_warnings);
    4026                 :            : 
    4027                 :       1035 :   bool relaxed_p = false;
    4028                 :       1035 :   unsigned iterations = 0;
    4029         [ +  + ]:       2320 :   while (! relaxed_p)
    4030                 :            :     {
    4031         [ +  - ]:       1285 :       assert_no_interrupts();
    4032                 :       1285 :       relaxed_p = true; // until proven otherwise
    4033                 :            : 
    4034                 :            :       // If the verbosity is high enough, always print warnings (overrides -w),
    4035                 :            :       // or if not, always suppress warnings for every itteration after the first.
    4036         [ +  + ]:       1285 :       if(s.verbose > 2)
    4037                 :          1 :         s.suppress_warnings = false;
    4038         [ +  + ]:       1284 :       else if (iterations > 0)
    4039                 :        250 :         s.suppress_warnings = true;
    4040                 :            : 
    4041         [ +  + ]:       1285 :       if (!s.unoptimized)
    4042         [ +  - ]:       1250 :         semantic_pass_opt6 (s, relaxed_p);
    4043                 :            : 
    4044                 :       1285 :       iterations++;
    4045                 :            :     }
    4046                 :            : 
    4047                 :       1035 :   return rc;
    4048                 :            : }
    4049                 :            : 
    4050                 :            : 
    4051                 :            : 
    4052                 :            : // ------------------------------------------------------------------------
    4053                 :            : // type resolution
    4054                 :            : 
    4055                 :            : 
    4056                 :            : static int
    4057                 :       1240 : semantic_pass_types (systemtap_session& s)
    4058                 :            : {
    4059                 :       1240 :   int rc = 0;
    4060                 :            : 
    4061                 :            :   // next pass: type inference
    4062                 :       1240 :   unsigned iterations = 0;
    4063         [ +  - ]:       1240 :   typeresolution_info ti (s);
    4064                 :            : 
    4065                 :       1240 :   ti.assert_resolvability = false;
    4066                 :            :   // XXX: maybe convert to exception-based error signalling
    4067                 :       2175 :   while (1)
    4068                 :            :     {
    4069         [ +  - ]:       3415 :       assert_no_interrupts();
    4070                 :            : 
    4071                 :       3415 :       iterations ++;
    4072                 :       3415 :       ti.num_newly_resolved = 0;
    4073                 :       3415 :       ti.num_still_unresolved = 0;
    4074                 :            : 
    4075 [ +  - ][ +  - ]:     461848 :   for (map<string,functiondecl*>::iterator it = s.functions.begin(); it != s.functions.end(); it++)
                 [ +  + ]
    4076                 :            :         {
    4077         [ +  - ]:     458433 :           assert_no_interrupts();
    4078                 :            : 
    4079         [ +  - ]:     458433 :           functiondecl* fd = it->second;
    4080                 :     458433 :           ti.current_probe = 0;
    4081                 :     458433 :           ti.current_function = fd;
    4082                 :     458433 :           ti.t = pe_unknown;
    4083         [ +  - ]:     458433 :           fd->body->visit (& ti);
    4084                 :            :           // NB: we don't have to assert a known type for
    4085                 :            :           // functions here, to permit a "void" function.
    4086                 :            :           // The translator phase will omit the "retvalue".
    4087                 :            :           //
    4088                 :            :           // if (fd->type == pe_unknown)
    4089                 :            :           //   ti.unresolved (fd->tok);
    4090         [ +  + ]:     470522 :           for (unsigned i=0; i < fd->locals.size(); ++i)
    4091         [ +  - ]:      12089 :             ti.check_local (fd->locals[i]);
    4092                 :            :         }
    4093                 :            : 
    4094         [ +  + ]:     582690 :       for (unsigned j=0; j<s.probes.size(); j++)
    4095                 :            :         {
    4096         [ +  - ]:     579301 :           assert_no_interrupts();
    4097                 :            : 
    4098                 :     579301 :           derived_probe* pn = s.probes[j];
    4099                 :     579301 :           ti.current_function = 0;
    4100                 :     579301 :           ti.current_probe = pn;
    4101                 :     579301 :           ti.t = pe_unknown;
    4102         [ +  + ]:     579301 :           pn->body->visit (& ti);
    4103         [ +  + ]:    1091368 :           for (unsigned i=0; i < pn->locals.size(); ++i)
    4104         [ +  - ]:     512093 :             ti.check_local (pn->locals[i]);
    4105                 :            : 
    4106         [ +  - ]:     579275 :           probe_point* pp = pn->sole_location();
    4107         [ +  + ]:     579275 :           if (pp->condition)
    4108                 :            :             {
    4109                 :         32 :               ti.current_function = 0;
    4110                 :         32 :               ti.current_probe = 0;
    4111                 :         32 :               ti.t = pe_long; // NB: expected type
    4112         [ +  - ]:         32 :               pp->condition->visit (& ti);
    4113                 :            :             }
    4114                 :            :         }
    4115                 :            : 
    4116         [ +  + ]:      25507 :       for (unsigned j=0; j<s.globals.size(); j++)
    4117                 :            :         {
    4118                 :      22119 :           vardecl* gd = s.globals[j];
    4119         [ +  + ]:      22119 :           if (gd->type == pe_unknown)
    4120         [ +  - ]:       3842 :             ti.unresolved (gd->tok);
    4121 [ +  + ][ +  + ]:      22119 :           if(gd->arity == 0 && gd->wrap == true)
    4122                 :            :             {
    4123 [ +  - ][ +  - ]:          1 :               throw semantic_error (_("wrapping not supported for scalars"), gd->tok);
    4124                 :            :             }
    4125                 :            :         }
    4126                 :            : 
    4127         [ +  + ]:       3388 :       if (ti.num_newly_resolved == 0) // converged
    4128                 :            :         {
    4129         [ +  + ]:       1246 :           if (ti.num_still_unresolved == 0)
    4130                 :       1181 :             break; // successfully
    4131         [ +  + ]:         65 :           else if (! ti.assert_resolvability)
    4132                 :         33 :             ti.assert_resolvability = true; // last pass, with error msgs
    4133                 :            :           else
    4134                 :            :             { // unsuccessful conclusion
    4135                 :         32 :               rc ++;
    4136                 :         32 :               break;
    4137                 :            :             }
    4138                 :            :         }
    4139                 :            :     }
    4140                 :            : 
    4141 [ +  - ][ +  - ]:       1240 :   return rc + s.num_errors();
    4142                 :            : }
    4143                 :            : 
    4144                 :            : 
    4145                 :            : 
    4146                 :       1240 : typeresolution_info::typeresolution_info (systemtap_session& s):
    4147                 :            :   session(s), num_newly_resolved(0), num_still_unresolved(0),
    4148                 :            :   assert_resolvability(false), current_function(0), current_probe(0),
    4149 [ +  - ][ +  - ]:       1240 :   t(pe_unknown)
    4150                 :            : {
    4151                 :       1240 : }
    4152                 :            : 
    4153                 :            : 
    4154                 :            : void
    4155                 :     759430 : typeresolution_info::visit_literal_number (literal_number* e)
    4156                 :            : {
    4157         [ -  + ]:     759430 :   assert (e->type == pe_long);
    4158 [ +  + ][ +  + ]:     759430 :   if ((t == e->type) || (t == pe_unknown))
    4159                 :     759430 :     return;
    4160                 :            : 
    4161                 :          4 :   mismatch (e->tok, e->type, t);
    4162                 :            : }
    4163                 :            : 
    4164                 :            : 
    4165                 :            : void
    4166                 :     392280 : typeresolution_info::visit_literal_string (literal_string* e)
    4167                 :            : {
    4168         [ -  + ]:     392280 :   assert (e->type == pe_string);
    4169 [ +  + ][ +  + ]:     392280 :   if ((t == e->type) || (t == pe_unknown))
    4170                 :     392280 :     return;
    4171                 :            : 
    4172                 :         23 :   mismatch (e->tok, e->type, t);
    4173                 :            : }
    4174                 :            : 
    4175                 :            : 
    4176                 :            : void
    4177                 :       5810 : typeresolution_info::visit_logical_or_expr (logical_or_expr *e)
    4178                 :            : {
    4179                 :       5810 :   visit_binary_expression (e);
    4180                 :       5810 : }
    4181                 :            : 
    4182                 :            : 
    4183                 :            : void
    4184                 :       7996 : typeresolution_info::visit_logical_and_expr (logical_and_expr *e)
    4185                 :            : {
    4186                 :       7996 :   visit_binary_expression (e);
    4187                 :       7996 : }
    4188                 :            : 
    4189                 :            : void
    4190                 :         92 : typeresolution_info::visit_regex_query (regex_query *e)
    4191                 :            : {
    4192                 :            :   // NB: result of regex query is an integer!
    4193 [ +  - ][ -  + ]:         92 :   if (t == pe_stats || t == pe_string)
    4194                 :          0 :     invalid (e->tok, t);
    4195                 :            : 
    4196                 :         92 :   t = pe_string;
    4197                 :         92 :   e->left->visit (this);
    4198                 :         92 :   t = pe_string;
    4199                 :         92 :   e->right->visit (this); // parser ensures this is a literal known at compile time
    4200                 :            : 
    4201         [ +  + ]:         92 :   if (e->type == pe_unknown)
    4202                 :            :     {
    4203                 :         45 :       e->type = pe_long;
    4204                 :         45 :       resolved (e->tok, e->type);
    4205                 :            :     }
    4206                 :         92 : }
    4207                 :            : 
    4208                 :            : 
    4209                 :            : void
    4210                 :     353420 : typeresolution_info::visit_comparison (comparison *e)
    4211                 :            : {
    4212                 :            :   // NB: result of any comparison is an integer!
    4213 [ +  - ][ -  + ]:     353420 :   if (t == pe_stats || t == pe_string)
    4214                 :          0 :     invalid (e->tok, t);
    4215                 :            : 
    4216                 :     353420 :   t = (e->right->type != pe_unknown) ? e->right->type : pe_unknown;
    4217                 :     353420 :   e->left->visit (this);
    4218                 :     353420 :   t = (e->left->type != pe_unknown) ? e->left->type : pe_unknown;
    4219                 :     353420 :   e->right->visit (this);
    4220                 :            : 
    4221 [ +  + ][ +  + ]:     353420 :   if (e->left->type != pe_unknown &&
                 [ -  + ]
    4222                 :            :       e->right->type != pe_unknown &&
    4223                 :            :       e->left->type != e->right->type)
    4224                 :          0 :     mismatch (e->tok, e->left->type, e->right->type);
    4225                 :            : 
    4226         [ +  + ]:     353420 :   if (e->type == pe_unknown)
    4227                 :            :     {
    4228                 :      79276 :       e->type = pe_long;
    4229                 :      79276 :       resolved (e->tok, e->type);
    4230                 :            :     }
    4231                 :     353420 : }
    4232                 :            : 
    4233                 :            : 
    4234                 :            : void
    4235                 :      32804 : typeresolution_info::visit_concatenation (concatenation *e)
    4236                 :            : {
    4237 [ +  + ][ -  + ]:      32804 :   if (t != pe_unknown && t != pe_string)
    4238                 :          0 :     invalid (e->tok, t);
    4239                 :            : 
    4240                 :      32804 :   t = pe_string;
    4241                 :      32804 :   e->left->visit (this);
    4242                 :      32804 :   t = pe_string;
    4243                 :      32804 :   e->right->visit (this);
    4244                 :            : 
    4245         [ +  + ]:      32804 :   if (e->type == pe_unknown)
    4246                 :            :     {
    4247                 :       7431 :       e->type = pe_string;
    4248                 :       7431 :       resolved (e->tok, e->type);
    4249                 :            :     }
    4250                 :      32804 : }
    4251                 :            : 
    4252                 :            : 
    4253                 :            : void
    4254                 :     843008 : typeresolution_info::visit_assignment (assignment *e)
    4255                 :            : {
    4256         [ -  + ]:     843008 :   if (t == pe_stats)
    4257                 :          0 :     invalid (e->tok, t);
    4258                 :            : 
    4259         [ +  + ]:     843008 :   if (e->op == "<<<") // stats aggregation
    4260                 :            :     {
    4261         [ -  + ]:      41855 :       if (t == pe_string)
    4262                 :          0 :         invalid (e->tok, t);
    4263                 :            : 
    4264                 :      41855 :       t = pe_stats;
    4265                 :      41855 :       e->left->visit (this);
    4266                 :      41855 :       t = pe_long;
    4267                 :      41855 :       e->right->visit (this);
    4268 [ +  + ][ -  + ]:      41852 :       if (e->type == pe_unknown ||
    4269                 :            :           e->type == pe_stats)
    4270                 :            :         {
    4271                 :      11415 :           e->type = pe_long;
    4272                 :      11415 :           resolved (e->tok, e->type);
    4273                 :            :         }
    4274                 :            :     }
    4275                 :            : 
    4276         [ -  + ]:     801153 :   else if (e->left->type == pe_stats)
    4277                 :          0 :     invalid (e->left->tok, e->left->type);
    4278                 :            : 
    4279         [ -  + ]:     801153 :   else if (e->right->type == pe_stats)
    4280                 :          0 :     invalid (e->right->tok, e->right->type);
    4281                 :            : 
    4282   [ +  +  +  +  :    7964372 :   else if (e->op == "+=" || // numeric only
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
              + ][ +  + ]
    4283                 :     798714 :            e->op == "-=" ||
    4284                 :     798609 :            e->op == "*=" ||
    4285                 :     798573 :            e->op == "/=" ||
    4286                 :     798559 :            e->op == "%=" ||
    4287                 :     798544 :            e->op == "&=" ||
    4288                 :     792567 :            e->op == "^=" ||
    4289                 :     792560 :            e->op == "|=" ||
    4290                 :     792553 :            e->op == "<<=" ||
    4291                 :     792540 :            e->op == ">>=" ||
    4292                 :            :            false)
    4293                 :            :     {
    4294                 :       8620 :       visit_binary_expression (e);
    4295                 :            :     }
    4296 [ +  + ][ +  + ]:     792533 :   else if (e->op == ".=" || // string only
    4297                 :            :            false)
    4298                 :            :     {
    4299 [ +  - ][ -  + ]:       1131 :       if (t == pe_long || t == pe_stats)
    4300                 :          0 :         invalid (e->tok, t);
    4301                 :            : 
    4302                 :       1131 :       t = pe_string;
    4303                 :       1131 :       e->left->visit (this);
    4304                 :       1131 :       t = pe_string;
    4305                 :       1131 :       e->right->visit (this);
    4306         [ +  + ]:       1131 :       if (e->type == pe_unknown)
    4307                 :            :         {
    4308                 :        191 :           e->type = pe_string;
    4309                 :        191 :           resolved (e->tok, e->type);
    4310                 :            :         }
    4311                 :            :     }
    4312         [ +  - ]:     791402 :   else if (e->op == "=") // overloaded = for string & numeric operands
    4313                 :            :     {
    4314                 :            :       // logic similar to ternary_expression
    4315                 :     791402 :       exp_type sub_type = t;
    4316                 :            : 
    4317                 :            :       // Infer types across the l/r values
    4318 [ +  + ][ +  + ]:     791402 :       if (sub_type == pe_unknown && e->type != pe_unknown)
    4319                 :     529655 :         sub_type = e->type;
    4320                 :            : 
    4321                 :            :       t = (sub_type != pe_unknown) ? sub_type :
    4322                 :            :         (e->right->type != pe_unknown) ? e->right->type :
    4323         [ +  + ]:     791402 :         pe_unknown;
    4324                 :     791402 :       e->left->visit (this);
    4325                 :            :       t = (sub_type != pe_unknown) ? sub_type :
    4326                 :            :         (e->left->type != pe_unknown) ? e->left->type :
    4327         [ +  + ]:     791396 :         pe_unknown;
    4328                 :     791396 :       e->right->visit (this);
    4329                 :            : 
    4330 [ +  + ][ +  + ]:     791220 :       if ((sub_type != pe_unknown) && (e->type == pe_unknown))
    4331                 :            :         {
    4332                 :         85 :           e->type = sub_type;
    4333                 :         85 :           resolved (e->tok, e->type);
    4334                 :            :         }
    4335 [ +  + ][ +  + ]:     791220 :       if ((sub_type == pe_unknown) && (e->left->type != pe_unknown))
    4336                 :            :         {
    4337                 :     170691 :           e->type = e->left->type;
    4338                 :     170691 :           resolved (e->tok, e->type);
    4339                 :            :         }
    4340                 :            : 
    4341 [ +  + ][ +  - ]:     791220 :       if (e->left->type != pe_unknown &&
                 [ -  + ]
    4342                 :            :           e->right->type != pe_unknown &&
    4343                 :            :           e->left->type != e->right->type)
    4344                 :          0 :         mismatch (e->tok, e->left->type, e->right->type);
    4345                 :            : 
    4346                 :            :     }
    4347                 :            :   else
    4348 [ #  # ][ #  # ]:          0 :     throw semantic_error (_("unsupported assignment operator ") + e->op);
    4349                 :     842823 : }
    4350                 :            : 
    4351                 :            : 
    4352                 :            : void
    4353                 :      33161 : typeresolution_info::visit_embedded_expr (embedded_expr *e)
    4354                 :            : {
    4355         [ +  + ]:      33161 :   if (e->type == pe_unknown)
    4356                 :            :     {
    4357         [ +  + ]:       7854 :       if (e->code.find ("/* string */") != string::npos)
    4358                 :        692 :         e->type = pe_string;
    4359                 :            :       else // if (e->code.find ("/* long */") != string::npos)
    4360                 :       7162 :         e->type = pe_long;
    4361                 :            : 
    4362                 :       7854 :       resolved (e->tok, e->type);
    4363                 :            :     }
    4364                 :      33161 : }
    4365                 :            : 
    4366                 :            : 
    4367                 :            : void
    4368                 :      68119 : typeresolution_info::visit_binary_expression (binary_expression* e)
    4369                 :            : {
    4370 [ +  - ][ -  + ]:      68119 :   if (t == pe_stats || t == pe_string)
    4371                 :          0 :     invalid (e->tok, t);
    4372                 :            : 
    4373                 :      68119 :   t = pe_long;
    4374                 :      68119 :   e->left->visit (this);
    4375                 :      68119 :   t = pe_long;
    4376                 :      68119 :   e->right->visit (this);
    4377                 :            : 
    4378 [ +  + ][ +  - ]:      68116 :   if (e->left->type != pe_unknown &&
                 [ +  + ]
    4379                 :            :       e->right->type != pe_unknown &&
    4380                 :            :       e->left->type != e->right->type)
    4381                 :          5 :     mismatch (e->tok, e->left->type, e->right->type);
    4382                 :            : 
    4383         [ +  + ]:      68116 :   if (e->type == pe_unknown)
    4384                 :            :     {
    4385                 :      15694 :       e->type = pe_long;
    4386                 :      15694 :       resolved (e->tok, e->type);
    4387                 :            :     }
    4388                 :      68116 : }
    4389                 :            : 
    4390                 :            : 
    4391                 :            : void
    4392                 :       7861 : typeresolution_info::visit_pre_crement (pre_crement *e)
    4393                 :            : {
    4394                 :       7861 :   visit_unary_expression (e);
    4395                 :       7861 : }
    4396                 :            : 
    4397                 :            : 
    4398                 :            : void
    4399                 :     194989 : typeresolution_info::visit_post_crement (post_crement *e)
    4400                 :            : {
    4401                 :     194989 :   visit_unary_expression (e);
    4402                 :     194989 : }
    4403                 :            : 
    4404                 :            : 
    4405                 :            : void
    4406                 :     214235 : typeresolution_info::visit_unary_expression (unary_expression* e)
    4407                 :            : {
    4408 [ +  - ][ -  + ]:     214235 :   if (t == pe_stats || t == pe_string)
    4409                 :          0 :     invalid (e->tok, t);
    4410                 :            : 
    4411                 :     214235 :   t = pe_long;
    4412                 :     214235 :   e->operand->visit (this);
    4413                 :            : 
    4414         [ +  + ]:     214235 :   if (e->type == pe_unknown)
    4415                 :            :     {
    4416                 :      47818 :       e->type = pe_long;
    4417                 :      47818 :       resolved (e->tok, e->type);
    4418                 :            :     }
    4419                 :     214235 : }
    4420                 :            : 
    4421                 :            : 
    4422                 :            : void
    4423                 :       1678 : typeresolution_info::visit_ternary_expression (ternary_expression* e)
    4424                 :            : {
    4425                 :       1678 :   exp_type sub_type = t;
    4426                 :            : 
    4427                 :       1678 :   t = pe_long;
    4428                 :       1678 :   e->cond->visit (this);
    4429                 :            : 
    4430                 :            :   // Infer types across the true/false arms of the ternary expression.
    4431                 :            : 
    4432 [ +  + ][ +  + ]:       1678 :   if (sub_type == pe_unknown && e->type != pe_unknown)
    4433                 :         28 :     sub_type = e->type;
    4434                 :       1678 :   t = sub_type;
    4435                 :       1678 :   e->truevalue->visit (this);
    4436                 :       1678 :   t = sub_type;
    4437                 :       1678 :   e->falsevalue->visit (this);
    4438                 :            : 
    4439 [ +  + ][ -  + ]:       1678 :   if ((sub_type == pe_unknown) && (e->type != pe_unknown))
    4440                 :            :     ; // already resolved
    4441 [ +  + ][ +  + ]:       1678 :   else if ((sub_type != pe_unknown) && (e->type == pe_unknown))
    4442                 :            :     {
    4443                 :        150 :       e->type = sub_type;
    4444                 :        150 :       resolved (e->tok, e->type);
    4445                 :            :     }
    4446 [ +  + ][ +  + ]:       1528 :   else if ((sub_type == pe_unknown) && (e->truevalue->type != pe_unknown))
    4447                 :            :     {
    4448                 :        250 :       e->type = e->truevalue->type;
    4449                 :        250 :       resolved (e->tok, e->type);
    4450                 :            :     }
    4451 [ +  + ][ +  - ]:       1278 :   else if ((sub_type == pe_unknown) && (e->falsevalue->type != pe_unknown))
    4452                 :            :     {
    4453                 :          1 :       e->type = e->falsevalue->type;
    4454                 :          1 :       resolved (e->tok, e->type);
    4455                 :            :     }
    4456         [ -  + ]:       1277 :   else if (e->type != sub_type)
    4457                 :          0 :     mismatch (e->tok, sub_type, e->type);
    4458                 :       1678 : }
    4459                 :            : 
    4460                 :            : 
    4461                 :            : template <class Referrer, class Referent>
    4462                 :    4080470 : void resolve_2types (Referrer* referrer, Referent* referent,
    4463                 :            :                     typeresolution_info* r, exp_type t, bool accept_unknown = false)
    4464                 :            : {
    4465                 :    4080470 :   exp_type& re_type = referrer->type;
    4466                 :    4080470 :   const token* re_tok = referrer->tok;
    4467                 :    4080470 :   exp_type& te_type = referent->type;
    4468                 :    4080470 :   const token* te_tok = referent->tok;
    4469                 :            : 
    4470 [ +  + ][ +  + ]:    4080470 :   if (t != pe_unknown && re_type == t && re_type == te_type)
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
                 [ +  + ]
    4471                 :            :     ; // do nothing: all three e->types in agreement
    4472 [ +  + ][ +  + ]:    1111490 :   else if (t == pe_unknown && re_type != pe_unknown && re_type == te_type)
         [ +  - ][ +  + ]
         [ +  + ][ +  - ]
         [ +  + ][ +  + ]
                 [ +  + ]
    4473                 :            :     ; // do nothing: two known e->types in agreement
    4474 [ +  + ][ -  + ]:    1076897 :   else if (re_type != pe_unknown && te_type != pe_unknown && re_type != te_type)
         [ #  # ][ +  + ]
         [ +  + ][ +  - ]
         [ +  + ][ +  + ]
                 [ +  - ]
    4475                 :         35 :     r->mismatch (re_tok, re_type, te_type);
    4476 [ +  + ][ +  - ]:    1076862 :   else if (re_type != pe_unknown && t != pe_unknown && re_type != t)
         [ -  + ][ +  + ]
         [ +  - ][ -  + ]
         [ +  + ][ +  + ]
                 [ -  + ]
    4477                 :          0 :     r->mismatch (re_tok, re_type, t);
    4478 [ +  + ][ +  + ]:    1076862 :   else if (te_type != pe_unknown && t != pe_unknown && te_type != t)
         [ +  + ][ +  + ]
         [ +  + ][ -  + ]
         [ +  + ][ +  + ]
                 [ +  + ]
    4479                 :         22 :     r->mismatch (te_tok, te_type, t);
    4480 [ +  + ][ +  + ]:    1076840 :   else if (re_type == pe_unknown && t != pe_unknown)
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
    4481                 :            :     {
    4482                 :            :       // propagate from upstream
    4483                 :     668751 :       re_type = t;
    4484                 :     668751 :       r->resolved (re_tok, re_type);
    4485                 :            :       // catch re_type/te_type mismatch later
    4486                 :            :     }
    4487 [ +  + ][ +  + ]:     408089 :   else if (re_type == pe_unknown && te_type != pe_unknown)
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
    4488                 :            :     {
    4489                 :            :       // propagate from referent
    4490                 :     112186 :       re_type = te_type;
    4491                 :     112186 :       r->resolved (re_tok, re_type);
    4492                 :            :       // catch re_type/t mismatch later
    4493                 :            :     }
    4494 [ +  + ][ +  - ]:     295903 :   else if (re_type != pe_unknown && te_type == pe_unknown)
         [ +  + ][ +  - ]
         [ +  + ][ +  - ]
    4495                 :            :     {
    4496                 :            :       // propagate to referent
    4497                 :     116842 :       te_type = re_type;
    4498                 :     116842 :       r->resolved (te_tok, te_type);
    4499                 :            :       // catch re_type/t mismatch later
    4500                 :            :     }
    4501 [ -  + ][ +  - ]:     179061 :   else if (! accept_unknown)
                 [ +  - ]
    4502                 :     132961 :     r->unresolved (re_tok);
    4503                 :    4080470 : }
    4504                 :            : 
    4505                 :            : 
    4506                 :            : void
    4507                 :    2361415 : typeresolution_info::visit_symbol (symbol* e)
    4508                 :            : {
    4509         [ -  + ]:    2361415 :   assert (e->referent != 0);
    4510                 :    2361415 :   resolve_2types (e, e->referent, this, t);
    4511                 :    2361415 : }
    4512                 :            : 
    4513                 :            : 
    4514                 :            : void
    4515                 :        206 : typeresolution_info::visit_target_symbol (target_symbol* e)
    4516                 :            : {
    4517                 :            :   // This occurs only if a target symbol was not resolved over in
    4518                 :            :   // tapset.cxx land, that error was properly suppressed, and the
    4519                 :            :   // later unused-expression-elimination pass didn't get rid of it
    4520                 :            :   // either.  So we have a target symbol that is believed to be of
    4521                 :            :   // genuine use, yet unresolved by the provider.
    4522                 :            : 
    4523         [ -  + ]:        206 :   if (session.verbose > 2)
    4524                 :            :     {
    4525                 :          0 :       clog << _("Resolution problem with ");
    4526         [ #  # ]:          0 :       if (current_function)
    4527                 :            :         {
    4528                 :          0 :           clog << "function " << current_function->name << endl;
    4529                 :          0 :           current_function->body->print (clog);
    4530                 :          0 :           clog << endl;
    4531                 :            :         }
    4532         [ #  # ]:          0 :       else if (current_probe)
    4533                 :            :         {
    4534                 :          0 :           clog << "probe " << *current_probe->sole_location() << endl;
    4535                 :          0 :           current_probe->body->print (clog);
    4536                 :          0 :           clog << endl;
    4537                 :            :         }
    4538                 :            :       else
    4539                 :            :         //TRANSLATORS: simply saying not an issue with a probe or function
    4540                 :          0 :         clog << _("other") << endl;
    4541                 :            :     }
    4542                 :            : 
    4543         [ +  + ]:        206 :   if (e->saved_conversion_error)
    4544         [ +  - ]:        205 :     throw (* (e->saved_conversion_error));
    4545                 :            :   else
    4546 [ +  - ][ +  - ]:          1 :     throw semantic_error(_("unresolved target-symbol expression"), e->tok);
    4547                 :            : }
    4548                 :            : 
    4549                 :            : 
    4550                 :            : void
    4551                 :          0 : typeresolution_info::visit_defined_op (defined_op* e)
    4552                 :            : {
    4553 [ #  # ][ #  # ]:          0 :   throw semantic_error(_("unexpected @defined"), e->tok);
    4554                 :            : }
    4555                 :            : 
    4556                 :            : 
    4557                 :            : void
    4558                 :          3 : typeresolution_info::visit_entry_op (entry_op* e)
    4559                 :            : {
    4560 [ +  - ][ +  - ]:          3 :   throw semantic_error(_("@entry is only valid in .return probes"), e->tok);
    4561                 :            : }
    4562                 :            : 
    4563                 :            : 
    4564                 :            : void
    4565                 :          0 : typeresolution_info::visit_cast_op (cast_op* e)
    4566                 :            : {
    4567                 :            :   // Like target_symbol, a cast_op shouldn't survive this far
    4568                 :            :   // unless it was not resolved and its value is really needed.
    4569         [ #  # ]:          0 :   if (e->saved_conversion_error)
    4570         [ #  # ]:          0 :     throw (* (e->saved_conversion_error));
    4571                 :            :   else
    4572                 :          0 :     throw semantic_error(_F("type definition '%s' not found in '%s'",
    4573 [ #  # ][ #  # ]:          0 :                             e->type_name.c_str(), e->module.c_str()), e->tok);
         [ #  # ][ #  # ]
    4574                 :            : }
    4575                 :            : 
    4576                 :            : 
    4577                 :            : void
    4578                 :          4 : typeresolution_info::visit_perf_op (perf_op* e)
    4579                 :            : {
    4580                 :            :   // A perf_op should already be resolved
    4581 [ +  - ][ -  + ]:          4 :   if (t == pe_stats || t == pe_string)
    4582                 :          0 :     invalid (e->tok, t);
    4583                 :            : 
    4584                 :          4 :   e->type = pe_long;
    4585                 :            : 
    4586                 :            :   // (There is no real need to visit our operand - by parser
    4587                 :            :   // construction, it's always a string literal, with its type already
    4588                 :            :   // set.)
    4589                 :          4 :   t = pe_string;
    4590                 :          4 :   e->operand->visit (this);
    4591                 :          4 : }
    4592                 :            : 
    4593                 :            : 
    4594                 :            : void
    4595                 :     350429 : typeresolution_info::visit_arrayindex (arrayindex* e)
    4596                 :            : {
    4597                 :            : 
    4598                 :     350429 :   symbol *array = NULL;
    4599                 :     350429 :   hist_op *hist = NULL;
    4600         [ +  - ]:     350429 :   classify_indexable(e->base, array, hist);
    4601                 :            : 
    4602                 :            :   // Every hist_op has type [int]:int, that is to say, every hist_op
    4603                 :            :   // is a pseudo-one-dimensional integer array type indexed by
    4604                 :            :   // integers (bucket numbers).
    4605                 :            : 
    4606         [ +  + ]:     350429 :   if (hist)
    4607                 :            :     {
    4608         [ -  + ]:         82 :       if (e->indexes.size() != 1)
    4609         [ #  # ]:          0 :         unresolved (e->tok);
    4610                 :         82 :       t = pe_long;
    4611         [ +  - ]:         82 :       e->indexes[0]->visit (this);
    4612         [ -  + ]:         82 :       if (e->indexes[0]->type != pe_long)
    4613         [ #  # ]:          0 :         unresolved (e->tok);
    4614         [ +  - ]:         82 :       hist->visit (this);
    4615         [ +  + ]:         82 :       if (e->type != pe_long)
    4616                 :            :         {
    4617                 :         26 :           e->type = pe_long;
    4618         [ +  - ]:         26 :           resolved (e->tok, pe_long);
    4619                 :            :         }
    4620                 :     350429 :       return;
    4621                 :            :     }
    4622                 :            : 
    4623                 :            :   // Now we are left with "normal" map inference and index checking.
    4624                 :            : 
    4625         [ -  + ]:     350347 :   assert (array);
    4626         [ -  + ]:     350347 :   assert (array->referent != 0);
    4627         [ +  - ]:     350347 :   resolve_2types (e, array->referent, this, t);
    4628                 :            : 
    4629                 :            :   // now resolve the array indexes
    4630                 :            : 
    4631                 :            :   // if (e->referent->index_types.size() == 0)
    4632                 :            :   //   // redesignate referent as array
    4633                 :            :   //   e->referent->set_arity (e->indexes.size ());
    4634                 :            : 
    4635         [ -  + ]:     350347 :   if (e->indexes.size() != array->referent->index_types.size())
    4636         [ #  # ]:          0 :     unresolved (e->tok); // symbol resolution should prevent this
    4637         [ +  + ]:     787908 :   else for (unsigned i=0; i<e->indexes.size(); i++)
    4638                 :            :     {
    4639                 :     437479 :       expression* ee = e->indexes[i];
    4640                 :     437479 :       exp_type& ft = array->referent->index_types [i];
    4641                 :     437479 :       t = ft;
    4642         [ +  - ]:     437479 :       ee->visit (this);
    4643                 :     437479 :       exp_type at = ee->type;
    4644                 :            : 
    4645 [ +  + ][ +  + ]:     437479 :       if ((at == pe_string || at == pe_long) && ft == pe_unknown)
                 [ +  + ]
    4646                 :            :         {
    4647                 :            :           // propagate to formal type
    4648                 :       4571 :           ft = at;
    4649         [ +  - ]:       4571 :           resolved (array->referent->tok, ft);
    4650                 :            :           // uses array decl as there is no token for "formal type"
    4651                 :            :         }
    4652         [ +  + ]:     437479 :       if (at == pe_stats)
    4653         [ +  - ]:          3 :         invalid (ee->tok, at);
    4654         [ -  + ]:     437479 :       if (ft == pe_stats)
    4655         [ #  # ]:          0 :         invalid (ee->tok, ft);
    4656 [ +  + ][ +  + ]:     437479 :       if (at != pe_unknown && ft != pe_unknown && ft != at)
                 [ +  + ]
    4657         [ +  - ]:          4 :         mismatch (e->tok, at, ft);
    4658         [ +  + ]:     437479 :       if (at == pe_unknown)
    4659         [ +  - ]:      20702 :           unresolved (ee->tok);
    4660                 :            :     }
    4661                 :            : }
    4662                 :            : 
    4663                 :            : 
    4664                 :            : void
    4665                 :    1368035 : typeresolution_info::visit_functioncall (functioncall* e)
    4666                 :            : {
    4667         [ -  + ]:    1368035 :   assert (e->referent != 0);
    4668                 :            : 
    4669                 :    1368035 :   resolve_2types (e, e->referent, this, t, true); // accept unknown type
    4670                 :            : 
    4671         [ -  + ]:    1368035 :   if (e->type == pe_stats)
    4672                 :          0 :     invalid (e->tok, e->type);
    4673                 :            : 
    4674                 :            :   // now resolve the function parameters
    4675         [ -  + ]:    1368035 :   if (e->args.size() != e->referent->formal_args.size())
    4676                 :          0 :     unresolved (e->tok); // symbol resolution should prevent this
    4677         [ +  + ]:    1893418 :   else for (unsigned i=0; i<e->args.size(); i++)
    4678                 :            :     {
    4679                 :     525497 :       expression* ee = e->args[i];
    4680                 :     525497 :       exp_type& ft = e->referent->formal_args[i]->type;
    4681                 :     525497 :       const token* fe_tok = e->referent->formal_args[i]->tok;
    4682                 :     525497 :       t = ft;
    4683                 :     525497 :       ee->visit (this);
    4684                 :     525383 :       exp_type at = ee->type;
    4685                 :            : 
    4686 [ +  + ][ +  + ]:     525383 :       if (((at == pe_string) || (at == pe_long)) && ft == pe_unknown)
                 [ +  + ]
    4687                 :            :         {
    4688                 :            :           // propagate to formal arg
    4689                 :       2101 :           ft = at;
    4690                 :       2101 :           resolved (e->referent->formal_args[i]->tok, ft);
    4691                 :            :         }
    4692         [ +  + ]:     525383 :       if (at == pe_stats)
    4693                 :          4 :         invalid (e->tok, at);
    4694         [ +  + ]:     525383 :       if (ft == pe_stats)
    4695                 :          7 :         invalid (fe_tok, ft);
    4696 [ +  + ][ +  - ]:     525383 :       if (at != pe_unknown && ft != pe_unknown && ft != at)
                 [ -  + ]
    4697                 :          0 :         mismatch (e->tok, at, ft);
    4698         [ +  + ]:     525383 :       if (at == pe_unknown)
    4699                 :       4511 :         unresolved (e->tok);
    4700                 :            :     }
    4701                 :    1367921 : }
    4702                 :            : 
    4703                 :            : 
    4704                 :            : void
    4705                 :     492907 : typeresolution_info::visit_block (block* e)
    4706                 :            : {
    4707         [ +  + ]:    2234779 :   for (unsigned i=0; i<e->statements.size(); i++)
    4708                 :            :     {
    4709                 :            :       try
    4710                 :            :         {
    4711                 :    1741872 :           t = pe_unknown;
    4712         [ +  + ]:    1741872 :           e->statements[i]->visit (this);
    4713                 :            :         }
    4714         [ -  + ]:        366 :       catch (const semantic_error& e)
    4715                 :            :         {
    4716         [ -  + ]:        183 :           session.print_error (e);
    4717                 :            :         }
    4718                 :            :     }
    4719                 :     492907 : }
    4720                 :            : 
    4721                 :            : 
    4722                 :            : void
    4723                 :       8401 : typeresolution_info::visit_try_block (try_block* e)
    4724                 :            : {
    4725         [ +  - ]:       8401 :   if (e->try_block)
    4726                 :       8401 :     e->try_block->visit (this);
    4727         [ +  + ]:       8401 :   if (e->catch_error_var)
    4728                 :            :     {
    4729                 :         13 :       t = pe_string;
    4730                 :         13 :       e->catch_error_var->visit (this);
    4731                 :            :     }
    4732         [ +  + ]:       8401 :   if (e->catch_block)
    4733                 :       8369 :     e->catch_block->visit (this);
    4734                 :       8401 : }
    4735                 :            : 
    4736                 :            : 
    4737                 :            : void
    4738                 :     425868 : typeresolution_info::visit_embeddedcode (embeddedcode* s)
    4739                 :            : {
    4740                 :            :   // PR11573.  If we have survived thus far with a piece of embedded
    4741                 :            :   // code that requires uprobes, we need to track this.
    4742                 :            :   //
    4743                 :            :   // This is an odd place for this check, as opposed
    4744                 :            :   // to a separate 'optimization' pass, or c_unparser::visit_embeddedcode
    4745                 :            :   // over yonder in pass 3.  However, we want to do it during pass 2 so
    4746                 :            :   // that cached sessions also get the uprobes treatment.
    4747 [ +  + ][ +  + ]:     425868 :   if (!session.need_uprobes && s->code.find("/* pragma:uprobes */") != string::npos)
                 [ +  + ]
    4748                 :            :     {
    4749         [ -  + ]:          5 :       if (session.verbose > 2)
    4750                 :          0 :         clog << _("Activating uprobes support because /* pragma:uprobes */ seen.") << endl;
    4751                 :          5 :       session.need_uprobes = true;
    4752                 :            :     }
    4753                 :     425868 : }
    4754                 :            : 
    4755                 :            : 
    4756                 :            : void
    4757                 :     646733 : typeresolution_info::visit_if_statement (if_statement* e)
    4758                 :            : {
    4759                 :     646733 :   t = pe_long;
    4760                 :     646733 :   e->condition->visit (this);
    4761                 :            : 
    4762                 :     646733 :   t = pe_unknown;
    4763                 :     646733 :   e->thenblock->visit (this);
    4764                 :            : 
    4765         [ +  + ]:     646733 :   if (e->elseblock)
    4766                 :            :     {
    4767                 :     105789 :       t = pe_unknown;
    4768                 :     105789 :       e->elseblock->visit (this);
    4769                 :            :     }
    4770                 :     646733 : }
    4771                 :            : 
    4772                 :            : 
    4773                 :            : void
    4774                 :       2484 : typeresolution_info::visit_for_loop (for_loop* e)
    4775                 :            : {
    4776                 :       2484 :   t = pe_unknown;
    4777         [ +  + ]:       2484 :   if (e->init) e->init->visit (this);
    4778                 :       2484 :   t = pe_long;
    4779                 :       2484 :   e->cond->visit (this);
    4780                 :       2484 :   t = pe_unknown;
    4781         [ +  + ]:       2484 :   if (e->incr) e->incr->visit (this);
    4782                 :       2484 :   t = pe_unknown;
    4783                 :       2484 :   e->block->visit (this);
    4784                 :       2484 : }
    4785                 :            : 
    4786                 :            : 
    4787                 :            : void
    4788                 :       3860 : typeresolution_info::visit_foreach_loop (foreach_loop* e)
    4789                 :            : {
    4790                 :            :   // See also visit_arrayindex.
    4791                 :            :   // This is different in that, being a statement, we can't assign
    4792                 :            :   // a type to the outer array, only propagate to/from the indexes
    4793                 :            : 
    4794                 :            :   // if (e->referent->index_types.size() == 0)
    4795                 :            :   //   // redesignate referent as array
    4796                 :            :   //   e->referent->set_arity (e->indexes.size ());
    4797                 :            : 
    4798                 :       3860 :   exp_type wanted_value = pe_unknown;
    4799                 :       3860 :   symbol *array = NULL;
    4800                 :       3860 :   hist_op *hist = NULL;
    4801         [ +  - ]:       3860 :   classify_indexable(e->base, array, hist);
    4802                 :            : 
    4803         [ +  + ]:       3860 :   if (hist)
    4804                 :            :     {
    4805         [ -  + ]:         29 :       if (e->indexes.size() != 1)
    4806         [ #  # ]:          0 :         unresolved (e->tok);
    4807                 :         29 :       t = pe_long;
    4808         [ +  - ]:         29 :       e->indexes[0]->visit (this);
    4809         [ -  + ]:         29 :       if (e->indexes[0]->type != pe_long)
    4810         [ #  # ]:          0 :         unresolved (e->tok);
    4811         [ +  - ]:         29 :       hist->visit (this);
    4812                 :         29 :       wanted_value = pe_long;
    4813                 :            :     }
    4814                 :            :   else
    4815                 :            :     {
    4816         [ -  + ]:       3831 :       assert (array);
    4817         [ -  + ]:       3831 :       if (e->indexes.size() != array->referent->index_types.size())
    4818         [ #  # ]:          0 :         unresolved (e->tok); // symbol resolution should prevent this
    4819         [ +  + ]:      16146 :       else for (unsigned i=0; i<e->indexes.size(); i++)
    4820                 :            :         {
    4821                 :      12315 :           expression* ee = e->indexes[i];
    4822                 :      12315 :           exp_type& ft = array->referent->index_types [i];
    4823                 :      12315 :           t = ft;
    4824         [ +  - ]:      12315 :           ee->visit (this);
    4825                 :      12315 :           exp_type at = ee->type;
    4826                 :            : 
    4827 [ +  + ][ +  + ]:      12315 :           if ((at == pe_string || at == pe_long) && ft == pe_unknown)
                 [ +  + ]
    4828                 :            :             {
    4829                 :            :               // propagate to formal type
    4830                 :         14 :               ft = at;
    4831         [ +  - ]:         14 :               resolved (array->referent->tok, ft);
    4832                 :            :               // uses array decl as there is no token for "formal type"
    4833                 :            :             }
    4834         [ -  + ]:      12315 :           if (at == pe_stats)
    4835         [ #  # ]:          0 :             invalid (ee->tok, at);
    4836         [ -  + ]:      12315 :           if (ft == pe_stats)
    4837         [ #  # ]:          0 :             invalid (ee->tok, ft);
    4838 [ +  + ][ +  - ]:      12315 :           if (at != pe_unknown && ft != pe_unknown && ft != at)
                 [ -  + ]
    4839         [ #  # ]:          0 :             mismatch (e->tok, at, ft);
    4840         [ +  + ]:      12315 :           if (at == pe_unknown)
    4841         [ +  - ]:        275 :             unresolved (ee->tok);
    4842                 :            :         }
    4843                 :       3831 :       t = pe_unknown;
    4844         [ +  - ]:       3831 :       array->visit (this);
    4845                 :       3831 :       wanted_value = array->type;
    4846                 :            :     }
    4847                 :            : 
    4848         [ +  + ]:       3860 :   if (e->value)
    4849                 :            :     {
    4850         [ +  + ]:       2139 :       if (wanted_value == pe_stats)
    4851         [ +  - ]:          3 :         invalid(e->value->tok, wanted_value);
    4852         [ +  + ]:       2136 :       else if (wanted_value != pe_unknown)
    4853         [ +  - ]:       2130 :         check_arg_type(wanted_value, e->value);
    4854                 :            :       else
    4855                 :            :         {
    4856                 :          6 :           t = pe_unknown;
    4857         [ +  - ]:          6 :           e->value->visit (this);
    4858                 :            :         }
    4859                 :            :     }
    4860                 :            : 
    4861                 :            :   /* Prevent @sum etc. aggregate sorting on non-statistics arrays. */
    4862         [ +  + ]:       3860 :   if (wanted_value != pe_unknown)
    4863 [ +  + ][ +  + ]:       3532 :     if (e->sort_aggr != sc_none && wanted_value != pe_stats)
    4864         [ +  - ]:          3 :       invalid (array->tok, wanted_value);
    4865                 :            : 
    4866         [ +  + ]:       3860 :   if (e->limit)
    4867                 :            :     {
    4868                 :        213 :       t = pe_long;
    4869         [ +  - ]:        213 :       e->limit->visit (this);
    4870                 :            :     }
    4871                 :            : 
    4872                 :       3860 :   t = pe_unknown;
    4873         [ +  - ]:       3860 :   e->block->visit (this);
    4874                 :       3860 : }
    4875                 :            : 
    4876                 :            : 
    4877                 :            : void
    4878                 :     265535 : typeresolution_info::visit_null_statement (null_statement*)
    4879                 :            : {
    4880                 :     265535 : }
    4881                 :            : 
    4882                 :            : 
    4883                 :            : void
    4884                 :    1519764 : typeresolution_info::visit_expr_statement (expr_statement* e)
    4885                 :            : {
    4886                 :    1519764 :   t = pe_unknown;
    4887                 :    1519764 :   e->value->visit (this);
    4888                 :    1519555 : }
    4889                 :            : 
    4890                 :            : 
    4891         [ -  + ]:      15733 : struct delete_statement_typeresolution_info:
    4892                 :            :   public throwing_visitor
    4893                 :            : {
    4894                 :            :   typeresolution_info *parent;
    4895                 :      15733 :   delete_statement_typeresolution_info (typeresolution_info *p):
    4896                 :      15733 :     throwing_visitor (_("invalid operand of delete expression")),
    4897 [ +  - ][ +  - ]:      15733 :     parent (p)
                 [ +  - ]
    4898                 :      15733 :   {}
    4899                 :            : 
    4900                 :      15060 :   void visit_arrayindex (arrayindex* e)
    4901                 :            :   {
    4902                 :      15060 :     parent->visit_arrayindex (e);
    4903                 :      15060 :   }
    4904                 :            : 
    4905                 :        673 :   void visit_symbol (symbol* e)
    4906                 :            :   {
    4907                 :        673 :     exp_type ignored = pe_unknown;
    4908         [ -  + ]:        673 :     assert (e->referent != 0);
    4909                 :        673 :     resolve_2types (e, e->referent, parent, ignored);
    4910                 :        673 :   }
    4911                 :            : };
    4912                 :            : 
    4913                 :            : 
    4914                 :            : void
    4915                 :      15733 : typeresolution_info::visit_delete_statement (delete_statement* e)
    4916                 :            : {
    4917         [ +  - ]:      15733 :   delete_statement_typeresolution_info di (this);
    4918                 :      15733 :   t = pe_unknown;
    4919 [ +  - ][ +  - ]:      15733 :   e->value->visit (&di);
    4920                 :      15733 : }
    4921                 :            : 
    4922                 :            : 
    4923                 :            : void
    4924                 :      16831 : typeresolution_info::visit_next_statement (next_statement*)
    4925                 :            : {
    4926                 :      16831 : }
    4927                 :            : 
    4928                 :            : 
    4929                 :            : void
    4930                 :       1009 : typeresolution_info::visit_break_statement (break_statement*)
    4931                 :            : {
    4932                 :       1009 : }
    4933                 :            : 
    4934                 :            : 
    4935                 :            : void
    4936                 :        248 : typeresolution_info::visit_continue_statement (continue_statement*)
    4937                 :            : {
    4938                 :        248 : }
    4939                 :            : 
    4940                 :            : 
    4941                 :            : void
    4942                 :       1877 : typeresolution_info::visit_array_in (array_in* e)
    4943                 :            : {
    4944                 :            :   // all unary operators only work on numerics
    4945                 :       1877 :   exp_type t1 = t;
    4946                 :       1877 :   t = pe_unknown; // array value can be anything
    4947                 :       1877 :   e->operand->visit (this);
    4948                 :            : 
    4949 [ +  + ][ -  + ]:       1877 :   if (t1 == pe_unknown && e->type != pe_unknown)
    4950                 :            :     ; // already resolved
    4951 [ +  - ][ -  + ]:       1877 :   else if (t1 == pe_string || t1 == pe_stats)
    4952                 :          0 :     mismatch (e->tok, t1, pe_long);
    4953         [ +  + ]:       1877 :   else if (e->type == pe_unknown)
    4954                 :            :     {
    4955                 :        456 :       e->type = pe_long;
    4956                 :        456 :       resolved (e->tok, e->type);
    4957                 :            :     }
    4958                 :       1877 : }
    4959                 :            : 
    4960                 :            : 
    4961                 :            : void
    4962                 :     158954 : typeresolution_info::visit_return_statement (return_statement* e)
    4963                 :            : {
    4964                 :            :   // This is like symbol, where the referent is
    4965                 :            :   // the return value of the function.
    4966                 :            : 
    4967                 :            :   // translation pass will print error
    4968         [ -  + ]:     158954 :   if (current_function == 0)
    4969                 :     158954 :     return;
    4970                 :            : 
    4971                 :     158954 :   exp_type& e_type = current_function->type;
    4972                 :     158954 :   t = current_function->type;
    4973                 :     158954 :   e->value->visit (this);
    4974                 :            : 
    4975 [ +  + ][ +  + ]:     158954 :   if (e_type != pe_unknown && e->value->type != pe_unknown
                 [ -  + ]
    4976                 :            :       && e_type != e->value->type)
    4977                 :          0 :     mismatch (current_function->tok, e_type, e->value->type);
    4978 [ +  + ][ +  + ]:     158954 :   if (e_type == pe_unknown &&
                 [ +  + ]
    4979                 :            :       (e->value->type == pe_long || e->value->type == pe_string))
    4980                 :            :     {
    4981                 :            :       // propagate non-statistics from value
    4982                 :       3655 :       e_type = e->value->type;
    4983                 :       3655 :       resolved (current_function->tok, e->value->type);
    4984                 :            :     }
    4985         [ -  + ]:     158954 :   if (e->value->type == pe_stats)
    4986                 :          0 :     invalid (e->value->tok, e->value->type);
    4987                 :            : }
    4988                 :            : 
    4989                 :            : void
    4990                 :     603189 : typeresolution_info::visit_print_format (print_format* e)
    4991                 :            : {
    4992                 :     603189 :   size_t unresolved_args = 0;
    4993                 :            : 
    4994         [ +  + ]:     603189 :   if (e->hist)
    4995                 :            :     {
    4996                 :        318 :       e->hist->visit(this);
    4997                 :            :     }
    4998                 :            : 
    4999         [ +  + ]:     602871 :   else if (e->print_with_format)
    5000                 :            :     {
    5001                 :            :       // If there's a format string, we can do both inference *and*
    5002                 :            :       // checking.
    5003                 :            : 
    5004                 :            :       // First we extract the subsequence of formatting components
    5005                 :            :       // which are conversions (not just literal string components)
    5006                 :            : 
    5007                 :     547038 :       unsigned expected_num_args = 0;
    5008         [ +  - ]:     547038 :       std::vector<print_format::format_component> components;
    5009         [ +  + ]:    2793944 :       for (size_t i = 0; i < e->components.size(); ++i)
    5010                 :            :         {
    5011         [ -  + ]:    2246906 :           if (e->components[i].type == print_format::conv_unspecified)
    5012                 :          0 :             throw semantic_error (_("Unspecified conversion in print operator format string"),
    5013 [ #  # ][ #  # ]:          0 :                                   e->tok);
    5014         [ +  + ]:    2246906 :           else if (e->components[i].type == print_format::conv_literal)
    5015                 :    1053880 :             continue;
    5016         [ +  - ]:    1193026 :           components.push_back(e->components[i]);
    5017                 :    1193026 :           ++expected_num_args;
    5018         [ +  + ]:    1193026 :           if (e->components[i].widthtype == print_format::width_dynamic)
    5019                 :        152 :             ++expected_num_args;
    5020         [ +  + ]:    1193026 :           if (e->components[i].prectype == print_format::prec_dynamic)
    5021                 :        132 :             ++expected_num_args;
    5022                 :            :         }
    5023                 :            : 
    5024                 :            :       // Then we check that the number of conversions and the number
    5025                 :            :       // of args agree.
    5026                 :            : 
    5027         [ -  + ]:     547038 :       if (expected_num_args != e->args.size())
    5028                 :          0 :         throw semantic_error (_("Wrong number of args to formatted print operator"),
    5029 [ #  # ][ #  # ]:          0 :                               e->tok);
    5030                 :            : 
    5031                 :            :       // Then we check that the types of the conversions match the types
    5032                 :            :       // of the args.
    5033                 :     547038 :       unsigned argno = 0;
    5034         [ +  + ]:    1740051 :       for (size_t i = 0; i < components.size(); ++i)
    5035                 :            :         {
    5036                 :            :           // Check the dynamic width, if specified
    5037         [ +  + ]:    1193018 :           if (components[i].widthtype == print_format::width_dynamic)
    5038                 :            :             {
    5039         [ +  - ]:        152 :               check_arg_type (pe_long, e->args[argno]);
    5040                 :        152 :               ++argno;
    5041                 :            :             }
    5042                 :            : 
    5043                 :            :           // Check the dynamic precision, if specified
    5044         [ +  + ]:    1193018 :           if (components[i].prectype == print_format::prec_dynamic)
    5045                 :            :             {
    5046         [ +  - ]:        132 :               check_arg_type (pe_long, e->args[argno]);
    5047                 :        132 :               ++argno;
    5048                 :            :             }
    5049                 :            : 
    5050                 :    1193018 :           exp_type wanted = pe_unknown;
    5051                 :            : 
    5052   [ -  +  +  - ]:    1193018 :           switch (components[i].type)
    5053                 :            :             {
    5054                 :            :             case print_format::conv_unspecified:
    5055                 :            :             case print_format::conv_literal:
    5056                 :          0 :               assert (false);
    5057                 :            :               break;
    5058                 :            : 
    5059                 :            :             case print_format::conv_pointer:
    5060                 :            :             case print_format::conv_number:
    5061                 :            :             case print_format::conv_binary:
    5062                 :            :             case print_format::conv_char:
    5063                 :            :             case print_format::conv_memory:
    5064                 :            :             case print_format::conv_memory_hex:
    5065                 :     444753 :               wanted = pe_long;
    5066                 :     444753 :               break;
    5067                 :            : 
    5068                 :            :             case print_format::conv_string:
    5069                 :     748265 :               wanted = pe_string;
    5070                 :     748265 :               break;
    5071                 :            :             }
    5072                 :            : 
    5073         [ -  + ]:    1193018 :           assert (wanted != pe_unknown);
    5074         [ +  + ]:    1193018 :           check_arg_type (wanted, e->args[argno]);
    5075                 :    1193013 :           ++argno;
    5076         [ +  - ]:     547038 :         }
    5077                 :            :     }
    5078                 :            :   else
    5079                 :            :     {
    5080                 :            :       // Without a format string, the best we can do is require that
    5081                 :            :       // each argument resolve to a concrete type.
    5082         [ +  + ]:     113436 :       for (size_t i = 0; i < e->args.size(); ++i)
    5083                 :            :         {
    5084                 :      57622 :           t = pe_unknown;
    5085                 :      57622 :           e->args[i]->visit (this);
    5086         [ +  + ]:      57603 :           if (e->args[i]->type == pe_unknown)
    5087                 :            :             {
    5088                 :       2157 :               unresolved (e->args[i]->tok);
    5089                 :       2157 :               ++unresolved_args;
    5090                 :            :             }
    5091                 :            :         }
    5092                 :            :     }
    5093                 :            : 
    5094         [ +  + ]:     603165 :   if (unresolved_args == 0)
    5095                 :            :     {
    5096         [ +  + ]:     601039 :       if (e->type == pe_unknown)
    5097                 :            :         {
    5098         [ +  + ]:     136554 :           if (e->print_to_stream)
    5099                 :     107098 :             e->type = pe_long;
    5100                 :            :           else
    5101                 :      29456 :             e->type = pe_string;
    5102                 :     136554 :           resolved (e->tok, e->type);
    5103                 :            :         }
    5104                 :            :     }
    5105                 :            :   else
    5106                 :            :     {
    5107                 :       2126 :       e->type = pe_unknown;
    5108                 :       2126 :       unresolved (e->tok);
    5109                 :            :     }
    5110                 :     603165 : }
    5111                 :            : 
    5112                 :            : 
    5113                 :            : void
    5114                 :       5419 : typeresolution_info::visit_stat_op (stat_op* e)
    5115                 :            : {
    5116                 :       5419 :   t = pe_stats;
    5117                 :       5419 :   e->stat->visit (this);
    5118         [ +  + ]:       5419 :   if (e->type == pe_unknown)
    5119                 :            :     {
    5120                 :        570 :       e->type = pe_long;
    5121                 :        570 :       resolved (e->tok, e->type);
    5122                 :            :     }
    5123         [ -  + ]:       4849 :   else if (e->type != pe_long)
    5124                 :          0 :     mismatch (e->tok, e->type, pe_long);
    5125                 :       5419 : }
    5126                 :            : 
    5127                 :            : void
    5128                 :        429 : typeresolution_info::visit_hist_op (hist_op* e)
    5129                 :            : {
    5130                 :        429 :   t = pe_stats;
    5131                 :        429 :   e->stat->visit (this);
    5132                 :        429 : }
    5133                 :            : 
    5134                 :            : 
    5135                 :            : void
    5136                 :    1195432 : typeresolution_info::check_arg_type (exp_type wanted, expression* arg)
    5137                 :            : {
    5138                 :    1195432 :   t = wanted;
    5139                 :    1195432 :   arg->visit (this);
    5140                 :            : 
    5141         [ +  + ]:    1195427 :   if (arg->type == pe_unknown)
    5142                 :            :     {
    5143                 :          1 :       arg->type = wanted;
    5144                 :          1 :       resolved (arg->tok, wanted);
    5145                 :            :     }
    5146         [ -  + ]:    1195426 :   else if (arg->type != wanted)
    5147                 :            :     {
    5148                 :          0 :       mismatch (arg->tok, arg->type, wanted);
    5149                 :            :     }
    5150                 :    1195427 : }
    5151                 :            : 
    5152                 :            : 
    5153                 :            : void
    5154                 :     524182 : typeresolution_info::check_local (vardecl* v)
    5155                 :            : {
    5156         [ -  + ]:     524182 :   if (v->arity != 0)
    5157                 :            :     {
    5158                 :          0 :       num_still_unresolved ++;
    5159         [ #  # ]:          0 :       if (assert_resolvability)
    5160                 :            :         session.print_error
    5161 [ #  # ][ #  # ]:          0 :           (semantic_error (_("array locals not supported, missing global declaration? "), v->tok));
         [ #  # ][ #  # ]
    5162                 :            :     }
    5163                 :            : 
    5164         [ +  + ]:     524182 :   if (v->type == pe_unknown)
    5165                 :     118106 :     unresolved (v->tok);
    5166         [ +  + ]:     406076 :   else if (v->type == pe_stats)
    5167                 :            :     {
    5168                 :          9 :       num_still_unresolved ++;
    5169         [ +  + ]:          9 :       if (assert_resolvability)
    5170                 :            :         session.print_error
    5171 [ +  - ][ +  - ]:          3 :           (semantic_error (_("stat locals not supported, missing global declaration? "), v->tok));
         [ +  - ][ +  - ]
    5172                 :            :     }
    5173 [ +  + ][ -  + ]:     406067 :   else if (!(v->type == pe_long || v->type == pe_string))
    5174                 :          0 :     invalid (v->tok, v->type);
    5175                 :     524182 : }
    5176                 :            : 
    5177                 :            : 
    5178                 :            : void
    5179                 :     284680 : typeresolution_info::unresolved (const token* tok)
    5180                 :            : {
    5181                 :     284680 :   num_still_unresolved ++;
    5182                 :            : 
    5183         [ +  + ]:     284680 :   if (assert_resolvability)
    5184                 :            :     {
    5185         [ +  - ]:         44 :       stringstream msg;
    5186         [ +  - ]:         44 :       msg << _("unresolved type ");
    5187 [ +  - ][ +  - ]:         44 :       session.print_error (semantic_error (msg.str(), tok));
         [ +  - ][ +  - ]
                 [ +  - ]
    5188                 :            :     }
    5189                 :     284680 : }
    5190                 :            : 
    5191                 :            : 
    5192                 :            : void
    5193                 :         20 : typeresolution_info::invalid (const token* tok, exp_type pe)
    5194                 :            : {
    5195                 :         20 :   num_still_unresolved ++;
    5196                 :            : 
    5197         [ +  + ]:         20 :   if (assert_resolvability)
    5198                 :            :     {
    5199         [ +  - ]:          6 :       stringstream msg;
    5200 [ +  - ][ -  + ]:          6 :       if (tok && tok->type == tok_operator)
    5201         [ #  # ]:          0 :         msg << _("invalid operator");
    5202                 :            :       else
    5203 [ +  - ][ +  - ]:          6 :         msg << _("invalid type ") << pe;
    5204 [ +  - ][ +  - ]:          6 :       session.print_error (semantic_error (msg.str(), tok));
         [ +  - ][ +  - ]
                 [ +  - ]
    5205                 :            :     }
    5206                 :         20 : }
    5207                 :            : 
    5208                 :            : 
    5209                 :            : void
    5210                 :         93 : typeresolution_info::mismatch (const token* tok, exp_type t1, exp_type t2)
    5211                 :            : {
    5212                 :         93 :   bool tok_resolved = false;
    5213                 :            :   size_t i;
    5214                 :         93 :   semantic_error* err1 = 0;
    5215                 :         93 :   num_still_unresolved ++;
    5216                 :            : 
    5217                 :            :   //BZ 9719: for improving type mismatch messages, a semantic error is
    5218                 :            :   //generated with the token where type was first resolved. All such 
    5219                 :            :   //resolved tokens, stored in a vector, are matched against their 
    5220                 :            :   //content. If an error for the matching token hasn't been printed out
    5221                 :            :   //already, it is and the token pushed in another printed_toks vector
    5222                 :            : 
    5223         [ +  + ]:         93 :   if (assert_resolvability)
    5224                 :            :     {
    5225         [ +  - ]:         26 :       stringstream msg;
    5226         [ +  + ]:        168 :       for (i=0; i<resolved_toks.size(); i++)
    5227                 :            :         {
    5228 [ +  - ][ +  + ]:        158 :           if (resolved_toks[i]->content == tok->content)
    5229                 :            :             {
    5230                 :         16 :               tok_resolved = true;
    5231                 :         16 :               break;
    5232                 :            :             }
    5233                 :            :         }
    5234         [ +  + ]:         26 :       if (!tok_resolved)
    5235                 :            :         {
    5236 [ +  - ][ +  - ]:         20 :           msg << _F("type mismatch (%s vs. %s)",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    5237         [ +  - ]:         10 :                     lex_cast(t1).c_str(), lex_cast(t2).c_str());
    5238                 :            :         }
    5239                 :            :       else
    5240                 :            :         {
    5241                 :         16 :           bool tok_printed = false;
    5242         [ +  + ]:         17 :           for (size_t j=0; j<printed_toks.size(); j++)
    5243                 :            :             {
    5244         [ +  + ]:          4 :               if (printed_toks[j] == resolved_toks[i])
    5245                 :            :                 {
    5246                 :          3 :                   tok_printed = true;
    5247                 :          3 :                   break;
    5248                 :            :                 }
    5249                 :            :             }
    5250 [ +  - ][ +  - ]:         32 :           msg << _F("type mismatch (%s vs. %s)",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    5251         [ +  - ]:         16 :                     lex_cast(t1).c_str(), lex_cast(t2).c_str());
    5252         [ +  + ]:         16 :           if (!tok_printed)
    5253                 :            :             {
    5254                 :            :               //error for possible mismatch in the earlier resolved token
    5255         [ +  - ]:         13 :               printed_toks.push_back (resolved_toks[i]);
    5256         [ +  - ]:         13 :               stringstream type_msg;
    5257 [ +  - ][ +  - ]:         13 :               type_msg << _F("type was first inferred here (%s)", lex_cast(t2).c_str());
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    5258 [ +  - ][ +  - ]:         13 :               err1 = new semantic_error (type_msg.str(), resolved_toks[i]);
         [ +  - ][ +  - ]
                 [ +  - ]
    5259                 :            :             }
    5260                 :            :         }
    5261 [ +  - ][ +  - ]:         26 :       semantic_error err (msg.str(), tok);
                 [ +  - ]
    5262                 :         26 :       err.chain = err1;
    5263 [ +  - ][ +  - ]:         26 :       session.print_error (err);
    5264                 :            :     }
    5265                 :         93 : }
    5266                 :            : 
    5267                 :            : 
    5268                 :            : void
    5269                 :    1386628 : typeresolution_info::resolved (const token* tok, exp_type)
    5270                 :            : {
    5271                 :    1386628 :   resolved_toks.push_back (tok);
    5272                 :    1386628 :   num_newly_resolved ++;
    5273 [ +  - ][ +  - ]:    1393870 : }
    5274                 :            : 
    5275                 :            : /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */

Generated by: LCOV version 1.9