]> sourceware.org Git - systemtap.git/blame - elaborate.cxx
2005-08-09 Martin Hunt <hunt@redhat.com>
[systemtap.git] / elaborate.cxx
CommitLineData
2b066ec1 1// elaboration functions
69c68955
FCE
2// Copyright (C) 2005 Red Hat Inc.
3//
4// This file is part of systemtap, and is free software. You can
5// redistribute it and/or modify it under the terms of the GNU General
6// Public License (GPL); either version 2, or (at your option) any
7// later version.
2b066ec1
FCE
8
9#include "config.h"
10#include "elaborate.h"
11#include "parse.h"
20c6c071 12#include "tapsets.h"
2b066ec1
FCE
13
14extern "C" {
15#include <sys/utsname.h>
16}
17
2b066ec1 18#include <algorithm>
67c0a579
GH
19#include <fstream>
20#include <map>
21#include <set>
22#include <vector>
2b066ec1 23
2b066ec1
FCE
24using namespace std;
25
26
27// ------------------------------------------------------------------------
28
29
30derived_probe::derived_probe (probe *p):
31 base (p)
32{
77de5e9e
GH
33 if (p)
34 {
35 this->locations = p->locations;
36 this->tok = p->tok;
37 this->body = deep_copy_visitor::deep_copy(p->body);
38 }
2b066ec1
FCE
39}
40
41
42derived_probe::derived_probe (probe *p, probe_point *l):
43 base (p)
44{
45 this->locations.push_back (l);
77de5e9e
GH
46 if (p)
47 {
48 this->tok = p->tok;
49 this->body = deep_copy_visitor::deep_copy(p->body);
50 }
2b066ec1
FCE
51}
52
20c6c071
GH
53// ------------------------------------------------------------------------
54
55// Members of match_key.
56
57match_key::match_key(string const & n)
58 : name(n),
59 have_parameter(false),
60 parameter_type(tok_junk)
61{
62}
63
64match_key::match_key(probe_point::component const & c)
65 : name(c.functor),
66 have_parameter(c.arg != NULL),
67 parameter_type(c.arg ? c.arg->tok->type : tok_junk)
68{
69}
70
71match_key &
72match_key::with_number()
73{
74 have_parameter = true;
75 parameter_type = tok_number;
76 return *this;
77}
78
79match_key &
80match_key::with_string()
81{
82 have_parameter = true;
83 parameter_type = tok_string;
84 return *this;
85}
86
87string
88match_key::str() const
89{
90 if (have_parameter)
91 switch (parameter_type)
92 {
93 case tok_string: return name + "(string)";
94 case tok_number: return name + "(number)";
95 default: return name + "(...)";
96 }
97 return name;
98}
99
100bool
101match_key::operator<(match_key const & other) const
102{
103 return ((name < other.name)
104
105 || (name == name
106 && have_parameter < other.have_parameter)
107
108 || (name == name
109 && have_parameter == other.have_parameter
110 && parameter_type < other.parameter_type));
111}
2b066ec1
FCE
112
113// ------------------------------------------------------------------------
20c6c071
GH
114// Members of match_node
115// ------------------------------------------------------------------------
116
117match_node::match_node()
118 : end(NULL)
119{}
120
121match_node *
122match_node::bind(match_key const & k)
123{
124 map<match_key, match_node *>::const_iterator i = sub.find(k);
125 if (i != sub.end())
126 return i->second;
127 match_node * n = new match_node();
128 sub.insert(make_pair(k, n));
129 return n;
130}
131
132void
133match_node::bind(derived_probe_builder * e)
134{
135 if (end)
136 throw semantic_error("already have a pattern ending");
137 end = e;
138}
139
140match_node *
141match_node::bind(string const & k)
142{
143 return bind(match_key(k));
144}
145
146match_node *
147match_node::bind_str(string const & k)
148{
149 return bind(match_key(k).with_string());
150}
151
152match_node *
153match_node::bind_num(string const & k)
154{
155 return bind(match_key(k).with_number());
156}
157
158derived_probe_builder *
159match_node::find_builder(vector<probe_point::component *> const & components,
160 unsigned pos,
161 vector< pair<string, literal *> > & parameters)
162{
163 assert(pos <= components.size());
164 if (pos == components.size())
165 {
166 // Probe_point ends here. We match iff we have
167 // an "end" entry here. If we don't, it'll be null.
168 return end;
169 }
170 else
171 {
172 // Probe_point contains a component here. We match iff there's
173 // an entry in the sub table, and its value matches the rest
174 // of the probe_point.
175 match_key k(*components[pos]);
f4b28491 176 if (0) // session.verbose
20c6c071
GH
177 clog << "searching for component " << k.str() << endl;
178 map<match_key, match_node *>::const_iterator i = sub.find(k);
179 if (i == sub.end())
180 {
f4b28491 181 if (0) // session.verbose
20c6c071
GH
182 clog << "no match found" << endl;
183 return NULL;
184 }
185 else
186 {
f4b28491 187 if (0) // session.verbose
20c6c071
GH
188 clog << "matched " << k.str() << endl;
189 derived_probe_builder * builder = NULL;
190 if (k.have_parameter)
191 {
192 assert(components[pos]->arg);
193 parameters.push_back(make_pair(components[pos]->functor,
194 components[pos]->arg));
195 }
196 else
197 {
198 // store a "null parameter" for any component we run into, anyways
199 literal_string *empty = NULL;
200 parameters.push_back(make_pair(components[pos]->functor, empty));
201 }
202 builder = i->second->find_builder(components, pos+1, parameters);
203 if (k.have_parameter && !builder)
204 parameters.pop_back();
205 return builder;
206 }
207 }
208}
209
210
211static void
212param_vec_to_map(vector< pair<string, literal *> > const & param_vec,
213 map<string, literal *> & param_map)
214{
215 for (vector< pair<string, literal *> >::const_iterator i = param_vec.begin();
216 i != param_vec.end(); ++i)
217 {
218 param_map[i->first] = i->second;
219 }
220}
221
222// ------------------------------------------------------------------------
223// Alias probes
224// ------------------------------------------------------------------------
225
226struct
227alias_expansion_builder
228 : public derived_probe_builder
229{
230 probe_alias * alias;
231
232 alias_expansion_builder(probe_alias * a)
233 : alias(a)
234 {}
235
5227f1ea
GH
236 virtual void build(systemtap_session & sess,
237 probe * use,
20c6c071
GH
238 probe_point * location,
239 std::map<std::string, literal *> const & parameters,
240 vector<probe *> & results_to_expand_further,
241 vector<derived_probe *> & finished_results)
242 {
243 // We're going to build a new probe and wrap it up in an
244 // alias_expansion_probe so that the expansion loop recognizer it as
245 // such and re-expands its expansion.
246
247 probe * n = new probe();
248 n->body = new block();
249
250 // The new probe gets the location list of the alias,
251 n->locations = alias->locations;
252
253 // the token location of the use,
254 n->tok = use->tok;
255
5227f1ea
GH
256 // and statements representing the concatenation of the alias'
257 // body with the use's.
258 //
259 // NB: locals are *not* copied forward, from either alias or
260 // use. The expansion should have its locals re-inferred since
261 // there's concatenated code here and we only want one vardecl per
262 // resulting variable.
263
85365d1b
GH
264 for (unsigned i = 0; i < alias->body->statements.size(); ++i)
265 {
266 statement *s = deep_copy_visitor::deep_copy(alias->body->statements[i]);
267 n->body->statements.push_back(s);
268 }
269
270 for (unsigned i = 0; i < use->body->statements.size(); ++i)
271 {
272 statement *s = deep_copy_visitor::deep_copy(use->body->statements[i]);
273 n->body->statements.push_back(s);
274 }
20c6c071
GH
275
276 results_to_expand_further.push_back(n);
277 }
278};
279
280
281// ------------------------------------------------------------------------
282// Pattern matching
283// ------------------------------------------------------------------------
284
285
286// Register all the aliases we've seen in library files, and the user
287// file, as patterns.
288
289void
290systemtap_session::register_library_aliases()
291{
292 vector<stapfile*> files(library_files);
293 files.push_back(user_file);
294
295 for (unsigned f = 0; f < files.size(); ++f)
296 {
297 stapfile * file = files[f];
298 for (unsigned a = 0; a < file->aliases.size(); ++a)
299 {
300 probe_alias * alias = file->aliases[a];
301 for (unsigned n = 0; n < alias->alias_names.size(); ++n)
302 {
303 probe_point * name = alias->alias_names[n];
304 if (verbose)
305 {
306 clog << "registering probe alias ";
307 for (unsigned c = 0; c < name->components.size(); ++c)
308 clog << (c > 0 ? "." : "") << name->components[c]->functor;
309 clog << endl;
310 }
311 match_node * n = pattern_root;
312 for (unsigned c = 0; c < name->components.size(); ++c)
313 {
314 probe_point::component * comp = name->components[c];
315 // XXX: alias parameters
316 if (comp->arg)
317 throw semantic_error("alias component "
318 + comp->functor
319 + " contains illegal parameter");
320 n = n->bind(comp->functor);
321 }
322 n->bind(new alias_expansion_builder(alias));
323 }
324 }
325 }
326}
327
328
5227f1ea
GH
329static unsigned max_recursion = 100;
330
331struct
332recursion_guard
333{
334 unsigned & i;
335 recursion_guard(unsigned & i) : i(i)
336 {
337 if (i > max_recursion)
338 throw semantic_error("recursion limit reached");
339 ++i;
340 }
341 ~recursion_guard()
342 {
343 --i;
344 }
345};
346
20c6c071
GH
347// The match-and-expand loop.
348void
349symresolution_info::derive_probes (match_node * root,
350 probe *p, vector<derived_probe*>& dps)
351{
5227f1ea
GH
352 static unsigned depth=0;
353 recursion_guard guard(depth);
354
20c6c071
GH
355 for (unsigned i = 0; i < p->locations.size(); ++i)
356 {
357 probe_point *loc = p->locations[i];
358 vector< pair<string, literal *> > param_vec;
359 map<string, literal *> param_map;
360 vector<probe *> re_expand;
361
fe3d01fa
FCE
362 try
363 {
364 derived_probe_builder * builder =
365 root->find_builder(loc->components, 0, param_vec);
366
367 if (!builder)
368 throw semantic_error ("no match for probe point family");
369
370 param_vec_to_map(param_vec, param_map);
371
372 unsigned num_atbegin = dps.size();
373 builder->build(session, p, loc, param_map, re_expand, dps);
374
375 // Recursively expand any further-expanding results
376 if (!re_expand.empty())
377 {
378 for (unsigned j = 0; j < re_expand.size(); ++j)
379 derive_probes(root, re_expand[j], dps);
380 }
381
382 unsigned num_atend = dps.size();
383 if (num_atbegin == num_atend) // nothing new derived!
384 throw semantic_error ("no match for probe point");
385 }
386 catch (const semantic_error& e)
387 {
388 session.print_error (e);
389 cerr << " while: resolving probe point " << *loc << endl;
390 }
20c6c071
GH
391 }
392}
393
394// ------------------------------------------------------------------------
67c0a579
GH
395//
396// Map usage checks
397//
398
399class lvalue_aware_traversing_visitor
400 : public traversing_visitor
401{
402 unsigned lval_depth;
403public:
404
405 lvalue_aware_traversing_visitor() : lval_depth(0) {}
406
407 bool is_in_lvalue()
408 {
409 return lval_depth > 0;
410 }
411
412 virtual void visit_pre_crement (pre_crement* e)
413 {
414 ++lval_depth;
415 e->operand->visit (this);
416 --lval_depth;
417 }
418
419 virtual void visit_post_crement (post_crement* e)
420 {
421 ++lval_depth;
422 e->operand->visit (this);
423 --lval_depth;
424 }
425
426 virtual void visit_assignment (assignment* e)
427 {
428 ++lval_depth;
429 e->left->visit (this);
430 --lval_depth;
431 e->right->visit (this);
432 }
433
434 virtual void visit_delete_statement (delete_statement* s)
435 {
436 ++lval_depth;
437 s->value->visit (this);
438 --lval_depth;
439 }
440
441};
442
443
444struct mutated_map_collector
445 : public lvalue_aware_traversing_visitor
446{
447 set<vardecl *> * mutated_maps;
448
449 mutated_map_collector(set<vardecl *> * mm)
450 : mutated_maps (mm)
451 {}
452
453 void visit_arrayindex (arrayindex *e)
454 {
455 if (is_in_lvalue())
456 mutated_maps->insert(e->referent);
457 }
458};
459
460
461struct no_map_mutation_during_iteration_check
462 : public lvalue_aware_traversing_visitor
463{
464 systemtap_session & session;
465 map<functiondecl *,set<vardecl *> *> & function_mutates_maps;
466 vector<vardecl *> maps_being_iterated;
467
468 no_map_mutation_during_iteration_check
469 (systemtap_session & sess,
470 map<functiondecl *,set<vardecl *> *> & fmm)
471 : session(sess), function_mutates_maps (fmm)
472 {}
473
474 void visit_arrayindex (arrayindex *e)
475 {
476 if (is_in_lvalue())
477 {
478 for (unsigned i = 0; i < maps_being_iterated.size(); ++i)
479 {
480 vardecl *m = maps_being_iterated[i];
481 if (m == e->referent)
482 {
483 string err = ("map '" + m->name +
484 "' modified during 'foreach' iteration");
485 session.print_error (semantic_error (err, e->tok));
486 }
487 }
488 }
489 }
490
491 void visit_functioncall (functioncall* e)
492 {
493 map<functiondecl *,set<vardecl *> *>::const_iterator i
494 = function_mutates_maps.find (e->referent);
495
496 if (i != function_mutates_maps.end())
497 {
498 for (unsigned j = 0; j < maps_being_iterated.size(); ++j)
499 {
500 vardecl *m = maps_being_iterated[j];
501 if (i->second->find (m) != i->second->end())
502 {
503 string err = ("function call modifies map '" + m->name +
504 "' during 'foreach' iteration");
505 session.print_error (semantic_error (err, e->tok));
506 }
507 }
508 }
509
510 for (unsigned i=0; i<e->args.size(); i++)
511 e->args[i]->visit (this);
512 }
513
514 void visit_foreach_loop(foreach_loop* s)
515 {
516 maps_being_iterated.push_back (s->base_referent);
517 for (unsigned i=0; i<s->indexes.size(); i++)
518 s->indexes[i]->visit (this);
519 s->block->visit (this);
520 maps_being_iterated.pop_back();
521 }
522};
20c6c071 523
2b066ec1 524
67c0a579
GH
525static int
526semantic_pass_maps (systemtap_session & sess)
527{
528
529 map<functiondecl *, set<vardecl *> *> fmm;
530 no_map_mutation_during_iteration_check chk(sess, fmm);
531
532 for (unsigned i = 0; i < sess.functions.size(); ++i)
533 {
534 functiondecl * fn = sess.functions[i];
535 if (fn->body)
536 {
537 set<vardecl *> * m = new set<vardecl *>();
538 mutated_map_collector mc (m);
539 fn->body->visit (&mc);
540 fmm[fn] = m;
541 }
542 }
543
544 for (unsigned i = 0; i < sess.functions.size(); ++i)
545 {
546 if (sess.functions[i]->body)
547 sess.functions[i]->body->visit (&chk);
548 }
549
550 for (unsigned i = 0; i < sess.probes.size(); ++i)
551 {
552 if (sess.probes[i]->body)
553 sess.probes[i]->body->visit (&chk);
554 }
555
556 return sess.num_errors;
557}
558
559// ------------------------------------------------------------------------
560
2b066ec1
FCE
561
562static int semantic_pass_symbols (systemtap_session&);
563static int semantic_pass_types (systemtap_session&);
67c0a579 564static int semantic_pass_maps (systemtap_session&);
2b066ec1
FCE
565
566
567
568// Link up symbols to their declarations. Set the session's
569// files/probes/functions/globals vectors from the transitively
570// reached set of stapfiles in s.library_files, starting from
20c6c071 571// s.user_file. Perform automatic tapset inclusion and probe
2b066ec1
FCE
572// alias expansion.
573static int
574semantic_pass_symbols (systemtap_session& s)
575{
576 symresolution_info sym (s);
577
578 // NB: s.files can grow during this iteration, so size() can
579 // return gradually increasing numbers.
580 s.files.push_back (s.user_file);
581 for (unsigned i = 0; i < s.files.size(); i++)
582 {
583 stapfile* dome = s.files[i];
584
585 // Pass 1: add globals and functions to systemtap-session master list,
586 // so the find_* functions find them
587
588 for (unsigned i=0; i<dome->globals.size(); i++)
589 s.globals.push_back (dome->globals[i]);
590
591 for (unsigned i=0; i<dome->functions.size(); i++)
592 s.functions.push_back (dome->functions[i]);
593
54dfabe9
FCE
594 for (unsigned i=0; i<dome->embeds.size(); i++)
595 s.embeds.push_back (dome->embeds[i]);
596
2b066ec1
FCE
597 // Pass 2: process functions
598
599 for (unsigned i=0; i<dome->functions.size(); i++)
600 {
601 functiondecl* fd = dome->functions[i];
602
603 try
604 {
8a43522c
GH
605 sym.current_function = fd;
606 sym.current_probe = 0;
607 fd->body->visit (& sym);
2b066ec1
FCE
608 }
609 catch (const semantic_error& e)
610 {
611 s.print_error (e);
612 }
613 }
614
5227f1ea
GH
615 // Pass 3: derive probes and resolve any further symbols in the
616 // derived results.
2b066ec1
FCE
617
618 for (unsigned i=0; i<dome->probes.size(); i++)
619 {
620 probe* p = dome->probes [i];
621 vector<derived_probe*> dps;
622
fe3d01fa
FCE
623 // much magic happens here: probe alias expansion,
624 // provider identification
625 sym.derive_probes (s.pattern_root, p, dps);
2b066ec1
FCE
626
627 for (unsigned j=0; j<dps.size(); j++)
628 {
629 derived_probe* dp = dps[j];
630 s.probes.push_back (dp);
631
632 try
633 {
634 sym.current_function = 0;
5227f1ea 635 sym.current_probe = dp;
2b066ec1
FCE
636 dp->body->visit (& sym);
637 }
638 catch (const semantic_error& e)
639 {
640 s.print_error (e);
641 }
642 }
643 }
644 }
fe3d01fa 645
2b066ec1
FCE
646 return s.num_errors; // all those print_error calls
647}
648
649
650
651int
652semantic_pass (systemtap_session& s)
653{
20c6c071 654 s.register_library_aliases();
f8220a7b 655 register_standard_tapsets(s);
20c6c071 656
2b066ec1
FCE
657 int rc = semantic_pass_symbols (s);
658 if (rc == 0) rc = semantic_pass_types (s);
67c0a579 659 if (rc == 0) rc = semantic_pass_maps (s);
2b066ec1
FCE
660 return rc;
661}
662
663
664// ------------------------------------------------------------------------
665
666
667systemtap_session::systemtap_session ():
20c6c071 668 pattern_root(new match_node),
2b066ec1
FCE
669 user_file (0), op (0), up (0), num_errors (0)
670{
671}
672
673
674void
675systemtap_session::print_error (const semantic_error& e)
676{
d8067b24
FCE
677 cerr << "semantic error: " << e.what ();
678 if (e.tok1 || e.tok2)
679 cerr << ": ";
2b066ec1
FCE
680 if (e.tok1) cerr << *e.tok1;
681 cerr << e.msg2;
682 if (e.tok2) cerr << *e.tok2;
683 cerr << endl;
684 num_errors ++;
685}
686
687
688// ------------------------------------------------------------------------
689// semantic processing: symbol resolution
690
691
692symresolution_info::symresolution_info (systemtap_session& s):
5227f1ea 693 session (s), current_function (0), current_probe (0)
2b066ec1
FCE
694{
695}
696
697
698void
699symresolution_info::visit_block (block* e)
700{
701 for (unsigned i=0; i<e->statements.size(); i++)
702 {
703 try
704 {
705 e->statements[i]->visit (this);
706 }
707 catch (const semantic_error& e)
708 {
709 session.print_error (e);
710 }
711 }
712}
713
714
69c68955
FCE
715void
716symresolution_info::visit_foreach_loop (foreach_loop* e)
717{
718 for (unsigned i=0; i<e->indexes.size(); i++)
719 e->indexes[i]->visit (this);
720
721 if (e->base_referent)
722 return;
723
313b2f74 724 vardecl* d = find_var (e->base, e->indexes.size ());
69c68955
FCE
725 if (d)
726 e->base_referent = d;
727 else
728 throw semantic_error ("unresolved global array " + e->base, e->tok);
729
730 e->block->visit (this);
731}
732
d98d459c
GH
733struct
734delete_statement_symresolution_info:
735 public traversing_visitor
736{
737 symresolution_info *parent;
738
739 delete_statement_symresolution_info (symresolution_info *p):
740 parent(p)
741 {}
742
743 void visit_arrayindex (arrayindex* e)
744 {
745 parent->visit_arrayindex (e);
746 }
747 void visit_functioncall (functioncall* e)
748 {
749 parent->visit_functioncall (e);
750 }
751
752 void visit_symbol (symbol* e)
753 {
754 if (e->referent)
755 return;
756
757 vardecl* d = parent->find_var (e->name, -1);
758 if (d)
759 e->referent = d;
760 else
761 throw semantic_error ("unresolved array in delete statement", e->tok);
762 }
763};
764
765void
766symresolution_info::visit_delete_statement (delete_statement* s)
767{
768 delete_statement_symresolution_info di (this);
769 s->value->visit (&di);
770}
771
69c68955 772
2b066ec1
FCE
773void
774symresolution_info::visit_symbol (symbol* e)
775{
776 if (e->referent)
777 return;
778
313b2f74 779 vardecl* d = find_var (e->name, 0);
2b066ec1
FCE
780 if (d)
781 e->referent = d;
782 else
783 {
784 // new local
785 vardecl* v = new vardecl;
786 v->name = e->name;
787 v->tok = e->tok;
788 if (current_function)
789 current_function->locals.push_back (v);
790 else if (current_probe)
791 current_probe->locals.push_back (v);
792 else
ce10591c
FCE
793 // must not happen
794 throw semantic_error ("no current probe/function", e->tok);
2b066ec1
FCE
795 e->referent = v;
796 }
797}
798
799
800void
801symresolution_info::visit_arrayindex (arrayindex* e)
802{
803 for (unsigned i=0; i<e->indexes.size(); i++)
804 e->indexes[i]->visit (this);
805
806 if (e->referent)
807 return;
808
313b2f74 809 vardecl* d = find_var (e->base, e->indexes.size ());
2b066ec1
FCE
810 if (d)
811 e->referent = d;
812 else
313b2f74
GH
813 {
814 // new local
815 vardecl* v = new vardecl;
816 v->set_arity(e->indexes.size());
817 v->name = e->base;
818 v->tok = e->tok;
819 if (current_function)
820 current_function->locals.push_back (v);
821 else if (current_probe)
822 current_probe->locals.push_back (v);
823 else
824 // must not happen
825 throw semantic_error ("no current probe/function", e->tok);
826 e->referent = v;
827 }
2b066ec1
FCE
828}
829
830
831void
832symresolution_info::visit_functioncall (functioncall* e)
833{
834 for (unsigned i=0; i<e->args.size(); i++)
835 e->args[i]->visit (this);
836
837 if (e->referent)
838 return;
839
840 functiondecl* d = find_function (e->function, e->args.size ());
841 if (d)
842 e->referent = d;
843 else
844 throw semantic_error ("unresolved function call", e->tok);
845}
846
847
848vardecl*
d98d459c 849symresolution_info::find_var (const string& name, int arity)
2b066ec1 850{
313b2f74 851
2b066ec1
FCE
852 // search locals
853 vector<vardecl*>& locals = (current_function ?
854 current_function->locals :
5227f1ea 855 current_probe->locals);
6deb8173 856
313b2f74 857
2b066ec1 858 for (unsigned i=0; i<locals.size(); i++)
313b2f74
GH
859 if (locals[i]->name == name
860 && locals[i]->compatible_arity(arity))
8846477c 861 {
313b2f74 862 locals[i]->set_arity (arity);
8846477c
FCE
863 return locals[i];
864 }
2b066ec1 865
313b2f74
GH
866 // search function formal parameters (for scalars)
867 if (arity == 0 && current_function)
2b066ec1
FCE
868 for (unsigned i=0; i<current_function->formal_args.size(); i++)
869 if (current_function->formal_args[i]->name == name)
8846477c
FCE
870 {
871 // NB: no need to check arity here: formal args always scalar
872 current_function->formal_args[i]->set_arity (0);
873 return current_function->formal_args[i];
874 }
2b066ec1 875
313b2f74 876 // search processed globals
2b066ec1 877 for (unsigned i=0; i<session.globals.size(); i++)
313b2f74 878 if (session.globals[i]->name == name
d98d459c 879 && session.globals[i]->compatible_arity(arity))
8846477c 880 {
313b2f74 881 session.globals[i]->set_arity (arity);
8846477c
FCE
882 return session.globals[i];
883 }
d98d459c 884
2b066ec1
FCE
885 // search library globals
886 for (unsigned i=0; i<session.library_files.size(); i++)
887 {
888 stapfile* f = session.library_files[i];
889 for (unsigned j=0; j<f->globals.size(); j++)
84e5ea0f
FCE
890 {
891 vardecl* g = f->globals[j];
892 if (g->name == name && g->compatible_arity (arity))
893 {
d98d459c 894 g->set_arity (arity);
84e5ea0f
FCE
895
896 // put library into the queue if not already there
897 if (find (session.files.begin(), session.files.end(), f)
898 == session.files.end())
899 session.files.push_back (f);
900
901 return g;
902 }
903 }
2b066ec1
FCE
904 }
905
906 // search builtins that become locals
907 // XXX: need to invent a proper formalism for this
313b2f74 908 if (arity == 0 && (name == "$pid" || name == "$tid"))
2b066ec1
FCE
909 {
910 vardecl_builtin* vb = new vardecl_builtin;
911 vb->name = name;
912 vb->type = pe_long;
913
914 // XXX: need a better way to synthesize tokens
915 token* t = new token;
916 t->type = tok_identifier;
917 t->content = name;
918 t->location.file = "<builtin>";
919 vb->tok = t;
920
921 locals.push_back (vb);
922 return vb;
923 }
924
925 return 0;
2b066ec1
FCE
926}
927
928
2b066ec1
FCE
929functiondecl*
930symresolution_info::find_function (const string& name, unsigned arity)
931{
932 for (unsigned j = 0; j < session.functions.size(); j++)
933 {
934 functiondecl* fd = session.functions[j];
935 if (fd->name == name &&
936 fd->formal_args.size() == arity)
937 return fd;
938 }
939
940 // search library globals
941 for (unsigned i=0; i<session.library_files.size(); i++)
942 {
943 stapfile* f = session.library_files[i];
944 for (unsigned j=0; j<f->functions.size(); j++)
945 if (f->functions[j]->name == name &&
946 f->functions[j]->formal_args.size() == arity)
947 {
948 // put library into the queue if not already there
949 if (0) // session.verbose_resolution
950 cerr << " function " << name << " "
951 << "is defined from " << f->name << endl;
952
953 if (find (session.files.begin(), session.files.end(), f)
954 == session.files.end())
955 session.files.push_back (f);
956 // else .. print different message?
957
958 return f->functions[j];
959 }
960 }
961
962 return 0;
2b066ec1
FCE
963}
964
965
966// ------------------------------------------------------------------------
967// type resolution
968
969
970static int
971semantic_pass_types (systemtap_session& s)
972{
973 int rc = 0;
974
975 // next pass: type inference
976 unsigned iterations = 0;
977 typeresolution_info ti (s);
978
979 ti.assert_resolvability = false;
980 // XXX: maybe convert to exception-based error signalling
981 while (1)
982 {
983 iterations ++;
984 // cerr << "Type resolution, iteration " << iterations << endl;
985 ti.num_newly_resolved = 0;
986 ti.num_still_unresolved = 0;
987
988 for (unsigned j=0; j<s.functions.size(); j++)
989 {
990 functiondecl* fn = s.functions[j];
8a43522c
GH
991 ti.current_function = fn;
992 ti.t = pe_unknown;
993 fn->body->visit (& ti);
994 // NB: we don't have to assert a known type for
995 // functions here, to permit a "void" function.
996 // The translator phase will omit the "retvalue".
997 //
998 // if (fn->type == pe_unknown)
999 // ti.unresolved (fn->tok);
2b066ec1
FCE
1000 }
1001
1002 for (unsigned j=0; j<s.probes.size(); j++)
1003 {
1004 derived_probe* pn = s.probes[j];
1005 ti.current_function = 0;
1006 ti.t = pe_unknown;
1007 pn->body->visit (& ti);
1008 }
1009
1010 for (unsigned j=0; j<s.globals.size(); j++)
1011 {
1012 vardecl* gd = s.globals[j];
1013 if (gd->type == pe_unknown)
1014 ti.unresolved (gd->tok);
1015 }
1016
1017 if (ti.num_newly_resolved == 0) // converged
1018 if (ti.num_still_unresolved == 0)
1019 break; // successfully
1020 else if (! ti.assert_resolvability)
1021 ti.assert_resolvability = true; // last pass, with error msgs
1022 else
1023 { // unsuccessful conclusion
1024 rc ++;
1025 break;
1026 }
1027 }
1028
1029 return rc + s.num_errors;
1030}
1031
1032
1033void
1034typeresolution_info::visit_literal_number (literal_number* e)
1035{
1036 assert (e->type == pe_long);
1037 if ((t == e->type) || (t == pe_unknown))
1038 return;
1039
1040 mismatch (e->tok, e->type, t);
1041}
1042
1043
1044void
1045typeresolution_info::visit_literal_string (literal_string* e)
1046{
1047 assert (e->type == pe_string);
1048 if ((t == e->type) || (t == pe_unknown))
1049 return;
1050
1051 mismatch (e->tok, e->type, t);
1052}
1053
1054
1055void
1056typeresolution_info::visit_logical_or_expr (logical_or_expr *e)
1057{
1058 visit_binary_expression (e);
1059}
1060
1061
1062void
1063typeresolution_info::visit_logical_and_expr (logical_and_expr *e)
1064{
1065 visit_binary_expression (e);
1066}
1067
1068
1069void
1070typeresolution_info::visit_comparison (comparison *e)
1071{
d5d7c2cc 1072 // NB: result of any comparison is an integer!
553d27a5
FCE
1073 if (t == pe_stats || t == pe_string)
1074 invalid (e->tok, t);
1075
1076 t = (e->right->type != pe_unknown) ? e->right->type : pe_unknown;
1077 e->left->visit (this);
1078 t = (e->left->type != pe_unknown) ? e->left->type : pe_unknown;
1079 e->right->visit (this);
1080
1081 if (e->left->type != pe_unknown &&
1082 e->right->type != pe_unknown &&
1083 e->left->type != e->right->type)
1084 mismatch (e->tok, e->left->type, e->right->type);
1085
1086 if (e->type == pe_unknown)
1087 {
1088 e->type = pe_long;
1089 resolved (e->tok, e->type);
1090 }
2b066ec1
FCE
1091}
1092
1093
1094void
1095typeresolution_info::visit_concatenation (concatenation *e)
1096{
553d27a5
FCE
1097 if (t != pe_unknown && t != pe_string)
1098 invalid (e->tok, t);
1099
1100 t = pe_string;
1101 e->left->visit (this);
1102 t = pe_string;
1103 e->right->visit (this);
1104
1105 if (e->type == pe_unknown)
1106 {
1107 e->type = pe_string;
1108 resolved (e->tok, e->type);
1109 }
2b066ec1
FCE
1110}
1111
1112
2b066ec1
FCE
1113void
1114typeresolution_info::visit_assignment (assignment *e)
1115{
553d27a5
FCE
1116 if (t == pe_stats)
1117 invalid (e->tok, t);
2b066ec1 1118
2b066ec1
FCE
1119 if (e->op == "<<<") // stats aggregation
1120 {
553d27a5
FCE
1121 if (t == pe_string)
1122 invalid (e->tok, t);
1123
2b066ec1
FCE
1124 t = pe_stats;
1125 e->left->visit (this);
1126 t = pe_long;
1127 e->right->visit (this);
553d27a5 1128 if (e->type == pe_unknown)
2b066ec1
FCE
1129 {
1130 e->type = pe_long;
1131 resolved (e->tok, e->type);
1132 }
1133 }
553d27a5 1134 else if (e->op == "+=" || // numeric only
d5d7c2cc
FCE
1135 e->op == "-=" ||
1136 e->op == "*=" ||
1137 e->op == "/=" ||
1138 e->op == "%=" ||
1139 e->op == "&=" ||
1140 e->op == "^=" ||
1141 e->op == "|=" ||
1142 e->op == "<<=" ||
1143 e->op == ">>=" ||
553d27a5 1144 false)
2b066ec1 1145 {
553d27a5 1146 visit_binary_expression (e);
2b066ec1 1147 }
d5d7c2cc
FCE
1148 else if (e->op == ".=" || // string only
1149 false)
1150 {
1151 if (t == pe_long || t == pe_stats)
1152 invalid (e->tok, t);
1153
1154 t = pe_string;
1155 e->left->visit (this);
1156 t = pe_string;
1157 e->right->visit (this);
1158 if (e->type == pe_unknown)
1159 {
1160 e->type = pe_string;
1161 resolved (e->tok, e->type);
1162 }
1163 }
1164 else if (e->op == "=") // overloaded = for string & numeric operands
2b066ec1 1165 {
553d27a5 1166 // logic similar to ternary_expression
2b066ec1 1167 exp_type sub_type = t;
553d27a5
FCE
1168
1169 // Infer types across the l/r values
1170 if (sub_type == pe_unknown && e->type != pe_unknown)
2b066ec1 1171 sub_type = e->type;
553d27a5
FCE
1172
1173 t = (sub_type != pe_unknown) ? sub_type :
1174 (e->right->type != pe_unknown) ? e->right->type :
1175 pe_unknown;
2b066ec1 1176 e->left->visit (this);
553d27a5
FCE
1177 t = (sub_type != pe_unknown) ? sub_type :
1178 (e->left->type != pe_unknown) ? e->left->type :
1179 pe_unknown;
2b066ec1 1180 e->right->visit (this);
553d27a5
FCE
1181
1182 if ((sub_type != pe_unknown) && (e->type == pe_unknown))
2b066ec1
FCE
1183 {
1184 e->type = sub_type;
1185 resolved (e->tok, e->type);
1186 }
553d27a5 1187 if ((sub_type == pe_unknown) && (e->left->type != pe_unknown))
2b066ec1
FCE
1188 {
1189 e->type = e->left->type;
1190 resolved (e->tok, e->type);
1191 }
553d27a5
FCE
1192
1193 if (e->left->type != pe_unknown &&
1194 e->right->type != pe_unknown &&
1195 e->left->type != e->right->type)
1196 mismatch (e->tok, e->left->type, e->right->type);
1197 }
d5d7c2cc
FCE
1198 else
1199 throw semantic_error ("unsupported assignment operator " + e->op);
553d27a5
FCE
1200}
1201
1202
1203void
1204typeresolution_info::visit_binary_expression (binary_expression* e)
1205{
1206 if (t == pe_stats || t == pe_string)
1207 invalid (e->tok, t);
1208
1209 t = pe_long;
1210 e->left->visit (this);
1211 t = pe_long;
1212 e->right->visit (this);
1213
1214 if (e->left->type != pe_unknown &&
1215 e->right->type != pe_unknown &&
1216 e->left->type != e->right->type)
1217 mismatch (e->tok, e->left->type, e->right->type);
1218
1219 if (e->type == pe_unknown)
1220 {
1221 e->type = pe_long;
1222 resolved (e->tok, e->type);
2b066ec1
FCE
1223 }
1224}
1225
1226
1227void
1228typeresolution_info::visit_pre_crement (pre_crement *e)
1229{
1230 visit_unary_expression (e);
1231}
1232
1233
1234void
1235typeresolution_info::visit_post_crement (post_crement *e)
1236{
1237 visit_unary_expression (e);
1238}
1239
1240
1241void
1242typeresolution_info::visit_unary_expression (unary_expression* e)
1243{
553d27a5
FCE
1244 if (t == pe_stats || t == pe_string)
1245 invalid (e->tok, t);
1246
2b066ec1
FCE
1247 t = pe_long;
1248 e->operand->visit (this);
1249
553d27a5 1250 if (e->type == pe_unknown)
2b066ec1
FCE
1251 {
1252 e->type = pe_long;
1253 resolved (e->tok, e->type);
1254 }
1255}
1256
1257
2b066ec1
FCE
1258void
1259typeresolution_info::visit_ternary_expression (ternary_expression* e)
1260{
1261 exp_type sub_type = t;
1262
1263 t = pe_long;
1264 e->cond->visit (this);
1265
553d27a5 1266 // Infer types across the true/false arms of the ternary expression.
2b066ec1
FCE
1267
1268 if (sub_type == pe_unknown && e->type != pe_unknown)
1269 sub_type = e->type;
1270 t = sub_type;
1271 e->truevalue->visit (this);
1272 t = sub_type;
1273 e->falsevalue->visit (this);
1274
1275 if ((sub_type == pe_unknown) && (e->type != pe_unknown))
1276 ; // already resolved
1277 else if ((sub_type != pe_unknown) && (e->type == pe_unknown))
1278 {
1279 e->type = sub_type;
1280 resolved (e->tok, e->type);
1281 }
1282 else if ((sub_type == pe_unknown) && (e->truevalue->type != pe_unknown))
1283 {
1284 e->type = e->truevalue->type;
1285 resolved (e->tok, e->type);
1286 }
1287 else if ((sub_type == pe_unknown) && (e->falsevalue->type != pe_unknown))
1288 {
1289 e->type = e->falsevalue->type;
1290 resolved (e->tok, e->type);
1291 }
1292 else if (e->type != sub_type)
1293 mismatch (e->tok, sub_type, e->type);
1294}
1295
1296
1297template <class Referrer, class Referent>
1298void resolve_2types (Referrer* referrer, Referent* referent,
1299 typeresolution_info* r, exp_type t)
1300{
1301 exp_type& re_type = referrer->type;
1302 const token* re_tok = referrer->tok;
1303 exp_type& te_type = referent->type;
1304 const token* te_tok = referent->tok;
1305
1306 if (t != pe_unknown && re_type == t && re_type == te_type)
1307 ; // do nothing: all three e->types in agreement
1308 else if (t == pe_unknown && re_type != pe_unknown && re_type == te_type)
1309 ; // do nothing: two known e->types in agreement
1310 else if (re_type != pe_unknown && te_type != pe_unknown && re_type != te_type)
1311 r->mismatch (re_tok, re_type, te_type);
1312 else if (re_type != pe_unknown && t != pe_unknown && re_type != t)
1313 r->mismatch (re_tok, re_type, t);
1314 else if (te_type != pe_unknown && t != pe_unknown && te_type != t)
1315 r->mismatch (te_tok, te_type, t);
1316 else if (re_type == pe_unknown && t != pe_unknown)
1317 {
1318 // propagate from upstream
1319 re_type = t;
1320 r->resolved (re_tok, re_type);
1321 // catch re_type/te_type mismatch later
1322 }
1323 else if (re_type == pe_unknown && te_type != pe_unknown)
1324 {
1325 // propagate from referent
1326 re_type = te_type;
1327 r->resolved (re_tok, re_type);
1328 // catch re_type/t mismatch later
1329 }
1330 else if (re_type != pe_unknown && te_type == pe_unknown)
1331 {
1332 // propagate to referent
1333 te_type = re_type;
1334 r->resolved (te_tok, te_type);
1335 // catch re_type/t mismatch later
1336 }
1337 else
1338 r->unresolved (re_tok);
1339}
1340
1341
1342void
1343typeresolution_info::visit_symbol (symbol* e)
1344{
1345 assert (e->referent != 0);
1346
1347 if (e->referent->arity > 0)
1348 unresolved (e->tok); // symbol resolution should not permit this
1349 // XXX: but consider "delete <array>;" and similar constructs
1350 else
1351 resolve_2types (e, e->referent, this, t);
1352}
1353
1354
1355void
1356typeresolution_info::visit_arrayindex (arrayindex* e)
1357{
1358 assert (e->referent != 0);
1359
1360 resolve_2types (e, e->referent, this, t);
1361
1362 // now resolve the array indexes
69c68955
FCE
1363
1364 // if (e->referent->index_types.size() == 0)
1365 // // redesignate referent as array
1366 // e->referent->set_arity (e->indexes.size ());
2b066ec1
FCE
1367
1368 if (e->indexes.size() != e->referent->index_types.size())
1369 unresolved (e->tok); // symbol resolution should prevent this
1370 else for (unsigned i=0; i<e->indexes.size(); i++)
1371 {
1372 expression* ee = e->indexes[i];
1373 exp_type& ft = e->referent->index_types [i];
1374 t = ft;
1375 ee->visit (this);
1376 exp_type at = ee->type;
1377
1378 if ((at == pe_string || at == pe_long) && ft == pe_unknown)
1379 {
1380 // propagate to formal type
1381 ft = at;
1382 resolved (e->referent->tok, ft);
1383 // uses array decl as there is no token for "formal type"
1384 }
1385 if (at == pe_stats)
1386 invalid (ee->tok, at);
1387 if (ft == pe_stats)
1388 invalid (ee->tok, ft);
1389 if (at != pe_unknown && ft != pe_unknown && ft != at)
1390 mismatch (e->tok, at, ft);
1391 if (at == pe_unknown)
313b2f74 1392 unresolved (ee->tok);
2b066ec1
FCE
1393 }
1394}
1395
1396
1397void
1398typeresolution_info::visit_functioncall (functioncall* e)
1399{
1400 assert (e->referent != 0);
1401
1402 resolve_2types (e, e->referent, this, t);
1403
1404 if (e->type == pe_stats)
1405 invalid (e->tok, e->type);
1406
1407 // XXX: but what about functions that return no value,
1408 // and are used only as an expression-statement for side effects?
1409
1410 // now resolve the function parameters
1411 if (e->args.size() != e->referent->formal_args.size())
1412 unresolved (e->tok); // symbol resolution should prevent this
1413 else for (unsigned i=0; i<e->args.size(); i++)
1414 {
1415 expression* ee = e->args[i];
1416 exp_type& ft = e->referent->formal_args[i]->type;
1417 const token* fe_tok = e->referent->formal_args[i]->tok;
1418 t = ft;
1419 ee->visit (this);
1420 exp_type at = ee->type;
1421
1422 if (((at == pe_string) || (at == pe_long)) && ft == pe_unknown)
1423 {
1424 // propagate to formal arg
1425 ft = at;
1426 resolved (e->referent->formal_args[i]->tok, ft);
1427 }
1428 if (at == pe_stats)
1429 invalid (e->tok, at);
1430 if (ft == pe_stats)
1431 invalid (fe_tok, ft);
1432 if (at != pe_unknown && ft != pe_unknown && ft != at)
1433 mismatch (e->tok, at, ft);
1434 if (at == pe_unknown)
1435 unresolved (e->tok);
1436 }
1437}
1438
1439
1440void
1441typeresolution_info::visit_block (block* e)
1442{
1443 for (unsigned i=0; i<e->statements.size(); i++)
1444 {
1445 try
1446 {
1447 t = pe_unknown;
1448 e->statements[i]->visit (this);
1449 }
1450 catch (const semantic_error& e)
1451 {
1452 session.print_error (e);
1453 }
1454 }
1455}
1456
1457
54dfabe9
FCE
1458void
1459typeresolution_info::visit_embeddedcode (embeddedcode* e)
1460{
1461}
1462
1463
2b066ec1
FCE
1464void
1465typeresolution_info::visit_if_statement (if_statement* e)
1466{
1467 t = pe_long;
1468 e->condition->visit (this);
1469
1470 t = pe_unknown;
1471 e->thenblock->visit (this);
1472
1473 if (e->elseblock)
1474 {
1475 t = pe_unknown;
1476 e->elseblock->visit (this);
1477 }
1478}
1479
1480
1481void
1482typeresolution_info::visit_for_loop (for_loop* e)
1483{
1484 t = pe_unknown;
1485 e->init->visit (this);
1486 t = pe_long;
1487 e->cond->visit (this);
1488 t = pe_unknown;
1489 e->incr->visit (this);
1490 t = pe_unknown;
1491 e->block->visit (this);
1492}
1493
1494
69c68955
FCE
1495void
1496typeresolution_info::visit_foreach_loop (foreach_loop* e)
1497{
1498 // See also visit_arrayindex.
1499 // This is different in that, being a statement, we can't assign
1500 // a type to the outer array, only propagate to/from the indexes
1501
1502 // if (e->referent->index_types.size() == 0)
1503 // // redesignate referent as array
1504 // e->referent->set_arity (e->indexes.size ());
1505
1506 if (e->indexes.size() != e->base_referent->index_types.size())
1507 unresolved (e->tok); // symbol resolution should prevent this
1508 else for (unsigned i=0; i<e->indexes.size(); i++)
1509 {
1510 expression* ee = e->indexes[i];
1511 exp_type& ft = e->base_referent->index_types [i];
1512 t = ft;
1513 ee->visit (this);
1514 exp_type at = ee->type;
1515
1516 if ((at == pe_string || at == pe_long) && ft == pe_unknown)
1517 {
1518 // propagate to formal type
1519 ft = at;
1520 resolved (e->base_referent->tok, ft);
1521 // uses array decl as there is no token for "formal type"
1522 }
1523 if (at == pe_stats)
1524 invalid (ee->tok, at);
1525 if (ft == pe_stats)
1526 invalid (ee->tok, ft);
1527 if (at != pe_unknown && ft != pe_unknown && ft != at)
1528 mismatch (e->tok, at, ft);
1529 if (at == pe_unknown)
1530 unresolved (ee->tok);
1531 }
1532
1533 t = pe_unknown;
1534 e->block->visit (this);
1535}
1536
1537
2b066ec1
FCE
1538void
1539typeresolution_info::visit_null_statement (null_statement* e)
1540{
1541}
1542
1543
1544void
1545typeresolution_info::visit_expr_statement (expr_statement* e)
1546{
1547 t = pe_unknown;
1548 e->value->visit (this);
1549}
1550
1551
d98d459c
GH
1552struct delete_statement_typeresolution_info:
1553 public throwing_visitor
1554{
1555 typeresolution_info *parent;
1556 delete_statement_typeresolution_info (typeresolution_info *p):
1557 throwing_visitor ("invalid operand of delete expression"),
1558 parent (p)
1559 {}
1560
1561 void visit_arrayindex (arrayindex* e)
1562 {
1563 parent->visit_arrayindex (e);
1564 }
1565
1566 void visit_symbol (symbol* e)
1567 {
1568 exp_type ignored = pe_unknown;
1569 assert (e->referent != 0);
1570 resolve_2types (e, e->referent, parent, ignored);
1571 }
1572};
1573
1574
2b066ec1
FCE
1575void
1576typeresolution_info::visit_delete_statement (delete_statement* e)
1577{
d98d459c
GH
1578 delete_statement_typeresolution_info di (this);
1579 t = pe_unknown;
1580 e->value->visit (&di);
2b066ec1
FCE
1581}
1582
1583
f3c26ea5
FCE
1584void
1585typeresolution_info::visit_next_statement (next_statement* s)
1586{
1587}
1588
1589
1590void
1591typeresolution_info::visit_break_statement (break_statement* s)
1592{
1593}
1594
1595
1596void
1597typeresolution_info::visit_continue_statement (continue_statement* s)
1598{
1599}
1600
1601
2b066ec1
FCE
1602void
1603typeresolution_info::visit_array_in (array_in* e)
1604{
ce10591c
FCE
1605 // all unary operators only work on numerics
1606 exp_type t1 = t;
1607 t = pe_unknown; // array value can be anything
1608 e->operand->visit (this);
1609
1610 if (t1 == pe_unknown && e->type != pe_unknown)
1611 ; // already resolved
1612 else if (t1 == pe_string || t1 == pe_stats)
1613 mismatch (e->tok, t1, pe_long);
1614 else if (e->type == pe_unknown)
1615 {
1616 e->type = pe_long;
1617 resolved (e->tok, e->type);
1618 }
2b066ec1
FCE
1619}
1620
1621
1622void
1623typeresolution_info::visit_return_statement (return_statement* e)
1624{
1625 // This is like symbol, where the referent is
1626 // the return value of the function.
1627
22f46231 1628 // translation pass will print error
2b066ec1 1629 if (current_function == 0)
22f46231 1630 return;
2b066ec1
FCE
1631
1632 exp_type& e_type = current_function->type;
1633 t = current_function->type;
1634 e->value->visit (this);
1635
1636 if (e_type != pe_unknown && e->value->type != pe_unknown
1637 && e_type != e->value->type)
1638 mismatch (current_function->tok, e_type, e->value->type);
1639 if (e_type == pe_unknown &&
1640 (e->value->type == pe_long || e->value->type == pe_string))
1641 {
1642 // propagate non-statistics from value
1643 e_type = e->value->type;
1644 resolved (current_function->tok, e->value->type);
1645 }
1646 if (e->value->type == pe_stats)
1647 invalid (e->value->tok, e->value->type);
1648}
1649
1650
1651void
1652typeresolution_info::unresolved (const token* tok)
1653{
1654 num_still_unresolved ++;
1655
1656 if (assert_resolvability)
1657 {
1658 cerr << "error: unresolved type for ";
1659 if (tok)
1660 cerr << *tok;
1661 else
1662 cerr << "a token";
1663 cerr << endl;
1664 }
1665}
1666
1667
1668void
1669typeresolution_info::invalid (const token* tok, exp_type pe)
1670{
1671 num_still_unresolved ++;
1672
1673 if (assert_resolvability)
1674 {
1675 cerr << "error: invalid type " << pe << " for ";
1676 if (tok)
1677 cerr << *tok;
1678 else
1679 cerr << "a token";
1680 cerr << endl;
1681 }
1682}
1683
1684
1685void
1686typeresolution_info::mismatch (const token* tok, exp_type t1, exp_type t2)
1687{
1688 num_still_unresolved ++;
1689
1690 if (assert_resolvability)
1691 {
1692 cerr << "error: type mismatch for ";
1693 if (tok)
1694 cerr << *tok;
1695 else
1696 cerr << "a token";
1697 cerr << ": " << t1 << " vs. " << t2 << endl;
1698 }
1699}
1700
1701
1702void
1703typeresolution_info::resolved (const token* tok, exp_type t)
1704{
1705 num_newly_resolved ++;
1706 // cerr << "resolved " << *e->tok << " type " << t << endl;
1707}
1708
This page took 0.204322 seconds and 5 git commands to generate.