109
100
return curr_arg_bindings.lookup (a);
112
bool PCE_SingleArg::check_derived (CClassInfo *cls, CFunctionInfo *func,
113
PointCutContext &context, Binding &binding, Condition &cond) {
103
bool PCE_SingleArg::check_derived_class (JPL_Class &cls,
104
PointCutContext &context, Binding &binding, Condition &cond) {
114
106
Condition unused;
115
107
bool do_subclasses = true;
116
for (unsigned i = 0; i < cls->DerivedClasses (); i++) {
117
CClassInfo *derived = cls->DerivedClass (i);
119
for (unsigned f = 0; f < derived->Functions (); f++) {
120
if (!func->hasSameNameAndArgs (derived->Function (f)))
122
JoinPointLoc *func_loc = context.scopes ().lookup (
123
TrackerDog::unique_object (derived->Function (f)));
124
if (func_loc && arg (0)->evaluate (*func_loc, context, binding, unused))
129
JoinPointLoc *class_loc = context.scopes ().lookup (derived);
131
arg (0)->evaluate (*class_loc, context, binding, unused)) {
132
if (context.in_that () || context.in_target ()) {
133
cond.matches (derived);
134
do_subclasses = false; // don't check subclasses, but siblings
140
if (do_subclasses && check_derived (derived, func, context, binding, cond))
108
const set<int> &derived_classes = cls.derived_class_ids ();
109
for (set<int>::const_iterator i = derived_classes.begin ();
110
i != derived_classes.end (); ++i) {
111
JPL_Class *derived = (JPL_Class*)cls.map (*i);
112
if (arg (0)->evaluate (*derived, context, binding, unused)) {
113
if (context.in_that () || context.in_target ()) {
114
cond.matches (*derived);
115
do_subclasses = false; // don't check subclasses, but
121
if (do_subclasses && check_derived_class (*derived, context,
143
125
return !do_subclasses;
146
bool PCE_SingleArg::check_base (CClassInfo *cls, CFunctionInfo *func,
147
PointCutContext &context, Binding &binding, Condition &cond) {
149
for (unsigned f = 0; f < cls->Functions (); f++) {
150
if (!func->hasSameNameAndArgs (cls->Function (f)))
128
bool PCE_SingleArg::check_derived_func (JPL_Class &cls, JPL_Function &func,
129
PointCutContext &context, Binding &binding, Condition &cond) {
131
bool do_subclasses = true;
132
const set<int> &derived_classes = cls.derived_class_ids ();
133
for (set<int>::const_iterator i = derived_classes.begin ();
134
i != derived_classes.end (); ++i) {
135
JPL_Class *derived = (JPL_Class*)cls.map (*i);
137
const JPL_Name::CList &children = derived->children ();
138
for (JPL_Name::CList::const_iterator i = children.begin ();
139
i != children.end (); ++i) {
140
if ((*i)->type () != JoinPointLoc::Function)
152
JoinPointLoc *func_loc = context.scopes ().lookup (
153
TrackerDog::unique_object (cls->Function (f)));
154
if (func_loc && arg (0)->evaluate (*func_loc, context, binding, cond))
142
JPL_Function &curr = *(JPL_Function*)*i;
143
if (!func.has_same_name_and_args (curr))
145
if (arg (0)->evaluate (curr, context, binding, cond))
159
JoinPointLoc *class_loc = context.scopes ().lookup (cls);
160
if (class_loc && arg (0)->evaluate (*class_loc, context, binding, cond))
163
for (unsigned i = 0; i < cls->BaseClasses (); i++) {
164
if (check_base (cls->BaseClass (i)->Class (), func, context, binding, cond))
149
if (do_subclasses && check_derived_func (*derived, func, context,
153
return !do_subclasses;
157
bool PCE_SingleArg::check_base_class (JPL_Class &cls,
158
PointCutContext &context, Binding &binding, Condition &cond) {
159
if (arg (0)->evaluate (cls, context, binding, cond)) {
162
const set<int> &bases = cls.base_class_ids ();
163
for (set<int>::const_iterator i = bases.begin (); i != bases.end (); ++i) {
164
JPL_Class *base = (JPL_Class*)cls.map (*i);
165
if (check_base_class (*base, context, binding, cond))
171
bool PCE_SingleArg::check_base_func (JPL_Class &cls, JPL_Function &func,
172
PointCutContext &context, Binding &binding, Condition &cond) {
173
const JPL_Name::CList &children = cls.children ();
174
for (JPL_Name::CList::const_iterator i = children.begin ();
175
i != children.end (); ++i) {
176
if ((*i)->type () != JoinPointLoc::Function)
178
JPL_Function &curr = *(JPL_Function*)*i;
179
if (!func.has_same_name_and_args (curr))
181
if (arg (0)->evaluate (curr, context, binding, cond))
185
const set<int> &bases = cls.base_class_ids ();
186
for (set<int>::const_iterator i = bases.begin (); i != bases.end (); ++i) {
187
JPL_Class *base = (JPL_Class*)cls.map (*i);
188
if (check_base_func (*base, func, context, binding, cond))
194
bool PCE_SingleArg::check_scopes (JPL_Name *scope,
195
PointCutContext &context, Binding &binding, Condition &cond) {
197
// TODO: at the moment the evaluation only matches classes.
198
// later namespaces should also be accepted, e.g. within("Puma")
199
if (arg (0)->evaluate (*scope, context, binding, cond))
201
scope = (JPL_Name*)scope->parent ();
171
207
PCE_Type PCE_Classes::type () const {
190
227
void PCE_Base::semantics (ErrorStream &err, PointCutContext &context) {
191
228
check_arg_types (err, "base", PCE_NAME);
192
229
sem_args (err, context);
230
_possible_types = (JoinPointLoc::join_point_type)arg (0)->possible_types ();
195
233
bool PCE_Base::evaluate (JoinPointLoc &jpl, PointCutContext &context,
196
234
Binding &binding, Condition &cond) {
235
if (!(jpl.type () & (int)_possible_types))
197
238
if (jpl.type () & (JoinPointLoc::Class | JoinPointLoc::Aspect)) {
198
CClassInfo *cls = ((JPL_Class&)jpl).class_info ();
199
239
// the class is a base of the argument class(es) if one of its derived
200
240
// classes is described by the argument
201
return check_derived (cls, 0, context, binding, cond);
204
CFunctionInfo *func = ((JPL_Function&)jpl).func_info ();
205
CClassInfo *cls = cscope (func);
206
return cls && check_derived (cls, func, context, binding, cond);
241
return check_derived_class ((JPL_Class&)jpl, context, binding, cond);
243
else if ((jpl.type () == JoinPointLoc::Function)) {
244
JPL_Function &func = (JPL_Function&)jpl;
245
if (func.parent ()->type () & (JoinPointLoc::Class | JoinPointLoc::Aspect)) {
246
JPL_Class &cls = *(JPL_Class*)func.parent ();
247
return check_derived_func (cls, func, context, binding, cond);
210
253
PCE_Type PCE_Derived::type () const {
214
257
void PCE_Derived::semantics (ErrorStream &err, PointCutContext &context) {
215
258
check_arg_types (err, "derived", PCE_NAME);
216
259
sem_args (err, context);
260
_possible_types = (JoinPointLoc::join_point_type)arg (0)->possible_types ();
219
263
bool PCE_Derived::evaluate (JoinPointLoc &jpl, PointCutContext &context,
220
264
Binding &binding, Condition &cond) {
265
if (!(jpl.type () & (int)_possible_types))
221
268
if (jpl.type () & (JoinPointLoc::Class | JoinPointLoc::Aspect)) {
222
CClassInfo *cls = ((JPL_Class&)jpl).class_info ();
223
269
// the class is derived of the argument class(es) if the class itself or
224
270
// one of its base classes is described by the argument
225
return check_base (cls, 0, context, binding, cond);
228
CFunctionInfo *func = ((JPL_Function&)jpl).func_info ();
229
CClassInfo *cls = cscope (func);
230
return cls && check_base (cls, func, context, binding, cond);
271
return check_base_class ((JPL_Class&)jpl, context, binding, cond);
273
else if ((jpl.type () == JoinPointLoc::Function)) {
274
JPL_Function &func = (JPL_Function&)jpl;
275
if (func.parent ()->type () & (JoinPointLoc::Class | JoinPointLoc::Aspect)) {
276
JPL_Class *cls = (JPL_Class*)func.parent ();
277
return check_base_func (*cls, func, context, binding, cond);
234
283
PCE_Type PCE_Within::type () const {
238
287
void PCE_Within::semantics (ErrorStream &err, PointCutContext &context) {
239
288
check_arg_types (err, "within", PCE_NAME);
240
289
sem_args (err, context);
290
_possible_types = JoinPointLoc::Code;
243
293
bool PCE_Within::evaluate (JoinPointLoc &jpl, PointCutContext &context,
244
294
Binding &binding, Condition &cond) {
245
if (jpl.type () == JoinPointLoc::MethodCall &&
246
((JPL_MethodCall&)jpl).is_pseudo ()) {
296
// 'within' matches only code join points
297
if (!(jpl.type () & (int)JoinPointLoc::Code))
299
JPL_Code &jpl_code = (JPL_Code&)jpl;
301
// accept pseudo method calls
302
if (jpl_code.type () == JoinPointLoc::MethodCall &&
303
((JPL_MethodCall&)jpl_code).is_pseudo ()) {
247
304
context.pseudo_true (true);
251
// TODO: here I should better use the virtual that_type() function
253
switch (jpl.type ()) {
254
case JoinPointLoc::Method:
255
func = ((JPL_Method&)jpl).func_info (); break;
256
case JoinPointLoc::Construction:
257
func = ((JPL_Construction&)jpl).func_info (); break;
258
case JoinPointLoc::Destruction:
259
func = ((JPL_Destruction&)jpl).func_info (); break;
260
case JoinPointLoc::MethodCall:
261
func = ((JPL_MethodCall&)jpl).caller (); break;
263
return false; // should not happen
266
if (jpl.type () != JoinPointLoc::Method &&
267
jpl.type () != JoinPointLoc::Construction &&
268
jpl.type () != JoinPointLoc::Destruction) {
269
// only within("aClass") returns methods
270
JoinPointLoc *func_loc = context.scopes ().lookup (func);
271
if (func_loc && arg (0)->evaluate (*func_loc, context, binding, cond))
275
CClassInfo *cls = cscope (func);
277
// only member functions are relevant for within("aClass")
278
JoinPointLoc *class_loc = context.scopes ().lookup (cls);
279
if (class_loc && arg (0)->evaluate (*class_loc, context, binding, cond))
308
JPL_Name *scope = jpl_code.lexical_scope ();
309
if (scope->type () == JoinPointLoc::Function) {
310
JPL_Function *func = (JPL_Function*)scope;
311
if (func->is_constructor () || func->is_destructor ())
312
scope = func->parent ();
314
return check_scopes (scope, context, binding, cond);
285
317
PCE_Type PCE_Execution::type () const {
298
331
if (jpl.type () != JoinPointLoc::Method)
301
// get the class and function object
302
CFunctionInfo *that_func = ((JPL_Method&)jpl).func_info ();
303
CClassInfo *that_class = cscope (that_func);
305
// if the function is not part of the project it is not considered to
306
// be an execution join point
307
if (!context.in_project (that_func))
311
// check if the class, which is the scope of the current exec join point
312
// is described by the argument
313
JoinPointLoc *class_loc = context.scopes ().lookup (that_class);
314
if (class_loc && arg (0)->evaluate (*class_loc, context, binding, cond))
318
// check if the exec join point's function name is described by the argument
319
JoinPointLoc *func_loc = context.scopes ().lookup (that_func);
320
if (func_loc && arg (0)->evaluate (*func_loc, context, binding, cond))
334
// check if the executed function's name matches the argument
335
JPL_Function *function = ((JPL_Method&)jpl).function ();
336
if (arg (0)->evaluate (*function, context, binding, cond))
339
// otherwise check the scope of the function and all its parent scopes
340
JPL_Name *scope = ((JPL_Code&)jpl).lexical_scope ();
341
return check_scopes (scope, context, binding, cond);
327
344
PCE_Type PCE_Call::type () const {
331
348
void PCE_Call::semantics (ErrorStream &err, PointCutContext &context) {
332
349
check_arg_types (err, "call", PCE_NAME);
333
350
sem_args (err, context);
351
_possible_types = JoinPointLoc::MethodCall;
336
354
bool PCE_Call::evaluate (JoinPointLoc &jpl, PointCutContext &context,
337
355
Binding &binding, Condition &cond) {
338
356
if (jpl.type () != JoinPointLoc::MethodCall)
341
CFunctionInfo *target_func = ((JPL_MethodCall&)jpl).called ();
342
CClassInfo *target_class = cscope (target_func);
345
// check if the target class is described by the argument
346
JoinPointLoc *class_loc = context.scopes ().lookup (target_class);
347
if (class_loc && arg (0)->evaluate (*class_loc, context, binding, cond))
351
// check if the target function name is described by the argument
352
JoinPointLoc *func_loc = context.scopes ().lookup (target_func);
353
if (func_loc && arg (0)->evaluate (*func_loc, context, binding, cond))
359
// check if the called function's name matches the argument
360
JPL_Function *target_function = ((JPL_MethodCall&)jpl).target_function ();
361
if (arg (0)->evaluate (*target_function, context, binding, cond))
364
// otherwise check the scope of the function and all its parent scopes
365
JPL_Name *scope = target_function->parent ();
366
return scope && check_scopes (scope, context, binding, cond);
365
374
void PCE_Construction::semantics (ErrorStream &err, PointCutContext &context) {
366
375
check_arg_types (err, "construction", PCE_NAME);
367
376
sem_args (err, context);
377
_possible_types = JoinPointLoc::Construction;
370
380
bool PCE_Construction::evaluate (JoinPointLoc &jpl, PointCutContext &context,
371
381
Binding &binding, Condition &cond) {
372
382
if (jpl.type () != JoinPointLoc::Construction)
374
CFunctionInfo *func = ((JPL_Construction&)jpl).func_info ();
375
CClassInfo *cls = cscope (func);
376
if (cls) { // TODO: this is because unions yield 0 here. Handle them!
377
JoinPointLoc *class_loc = context.scopes ().lookup (cls);
378
if (class_loc && arg (0)->evaluate (*class_loc, context, binding, cond))
384
JPL_Name *scope = ((JPL_Construction&)jpl).lexical_scope ();
385
return arg (0)->evaluate (*scope, context, binding, cond);
384
388
PCE_Type PCE_Destruction::type () const {
414
413
context.enter_that ();
415
414
sem_args (err, context);
416
415
context.leave_that ();
416
_possible_types = JoinPointLoc::Code;
419
419
bool PCE_That::evaluate (JoinPointLoc &jpl, PointCutContext &context,
420
420
Binding &binding, Condition &cond) {
421
// 'that' matches only code join points
422
if (!(jpl.type () & (int)JoinPointLoc::Code))
424
JPL_Code &jpl_code = (JPL_Code&)jpl;
421
426
if (jpl.type () == JoinPointLoc::MethodCall &&
422
427
((JPL_MethodCall&)jpl).is_pseudo ()) {
423
428
context.pseudo_true (true);
427
// TODO: use a virtual JoinPointLoc method instead of this...
428
CFunctionInfo *that_func = 0;
429
if (jpl.type () == JoinPointLoc::Method)
430
that_func = ((JPL_Method&)jpl).func_info ();
431
else if (jpl.type () == JoinPointLoc::Construction)
432
that_func = ((JPL_Construction&)jpl).func_info ();
433
else if (jpl.type () == JoinPointLoc::Destruction)
434
that_func = ((JPL_Destruction&)jpl).func_info ();
435
else if (jpl.type () == JoinPointLoc::MethodCall)
436
that_func = ((JPL_MethodCall&)jpl).caller ();
440
CClassInfo *that_class = cscope (that_func);
442
// if the function is not part of the project, this is no real join point
443
if (!context.in_project (that_func))
446
// if this is not a member function return false
447
if (!that_class || that_func->isStaticMethod ())
432
// get the function that is executed when the join point is reached
433
JPL_Name *parent = jpl_code.parent ();
434
if (!parent->type () == JoinPointLoc::Function)
436
JPL_Function *jpl_function = (JPL_Function*)parent;
438
// static member functions and non-member functions don't have a 'this' pointer
439
if (jpl_function->is_non_member () || jpl_function->is_static_member ())
442
// get the class of which the function is a member
443
JPL_Class *class_loc = (JPL_Class*)jpl_function->parent ();
450
445
context.enter_that ();
451
446
binding._this = (CArgumentInfo *)0;
453
448
// if any of the class' base classes matches the argument the current class
454
449
// is definitely an object of the required type
455
if (!check_base (that_class, 0, context, binding, cond)) {
450
if (!check_base_class (*class_loc, context, binding, cond)) {
456
451
// in a construction or destruction the object has exactly the type
457
452
// of the constructor/destructor scope => no run-time check
458
if (jpl.type () == JoinPointLoc::Construction ||
459
jpl.type () == JoinPointLoc::Destruction) {
453
if (jpl_function->is_constructor () || jpl_function->is_destructor ()) {
460
454
context.leave_that ();
464
458
// create a 'that' condition with a mangled name
465
stringstream mangled, cond_name;
466
arg (0)->mangle_type_check (mangled);
468
Naming::type_check_func (cond_name, that_class, mangled.str ().data ());
470
// cout << "cond name: " << cond_name.str ().data () << endl;
471
cond.that (cond_name.str ().data ());
459
stringstream mangled_check;
460
arg (0)->mangle_type_check (mangled_check);
461
cond.that (class_loc, mangled_check.str ());
473
463
// find the derived classes that match the argument
474
check_derived (that_class, 0, context, binding, cond);
464
check_derived_class (*class_loc, context, binding, cond);
476
466
context.leave_that ();
493
484
// only calls have a target at the moment
494
485
if (jpl.type () != JoinPointLoc::MethodCall)
497
487
JPL_MethodCall &jpl_call = (JPL_MethodCall&)jpl;
498
CFunctionInfo *source_func = jpl_call.is_pseudo () ? 0 : jpl_call.caller ();
499
CFunctionInfo *target_func = ((JPL_MethodCall&)jpl).called ();
500
CClassInfo *target_class = cscope (target_func);
502
// if the caller function is not part of the project, the call is not
503
// considered to be a call join point
504
if (source_func && !context.in_project (source_func))
507
// if this is not a member function return false
508
if (!target_class || target_func->isStaticMethod ())
489
JPL_Function *target_function = jpl_call.target_function ();
491
// only non-static member functions are relevant here
492
// TODO: how to handle explicit destructor calls?
493
if (!target_function->is_non_static_member ())
496
// get the class of which the function is a member
497
JPL_Class *class_loc = (JPL_Class*)target_function->parent ();
511
499
context.enter_target ();
512
500
binding._target = (CArgumentInfo *)0;
513
501
// if any of the class' base classes matches the argument the current class
514
502
// is definitely an object of the required type
515
if (!check_base (target_class, 0, context, binding, cond)) {
503
if (!check_base_class (*class_loc, context, binding, cond)) {
516
504
// create a 'that' condition with a mangled name
517
stringstream mangled, cond_name;
518
arg (0)->mangle_type_check (mangled);
520
Naming::type_check_func (cond_name, target_class, mangled.str ().data ());
522
cond.target (cond_name.str ().data ());
505
stringstream mangled_check;
506
arg (0)->mangle_type_check (mangled_check);
507
cond.target (class_loc, mangled_check.str ());
524
509
// find the derived classes that match the argument
525
check_derived (target_class, 0, context, binding, cond);
510
check_derived_class (*class_loc, context, binding, cond);
527
512
context.leave_target ();
589
575
arg (i)->semantics (err, context);
591
577
context.set_arg (saved_arg);
578
_possible_types = JoinPointLoc::Code;
594
581
bool PCE_Args::evaluate (JoinPointLoc &jpl, PointCutContext &context,
595
582
Binding &binding, Condition &cond) {
596
CFunctionInfo *func = 0;
597
if (jpl.type () == JoinPointLoc::Method)
598
func = ((JPL_Method&)jpl).func_info ();
599
else if (jpl.type () == JoinPointLoc::Construction)
600
func = ((JPL_Construction&)jpl).func_info ();
601
else if (jpl.type () == JoinPointLoc::Destruction)
602
func = ((JPL_Destruction&)jpl).func_info ();
603
else if (jpl.type () == JoinPointLoc::MethodCall)
604
func = ((JPL_MethodCall&)jpl).called ();
606
return false; // other join points are not considered, yet.
584
// ignore all non-code join points
585
if (!(jpl.type () & (int)JoinPointLoc::Code))
608
587
JPL_Code *jpl_code = (JPL_Code*)&jpl;
610
589
// check if the number of arguments is ok -> not compatible ("...")
904
902
void PCE_Match::semantics (ErrorStream &err, PointCutContext &context) {
905
_match_expr.parse (err, node ()->token ()->location (), _dstr);
903
_match_expr.parse (err, node ()->token ()->location (), _str.c_str ());
904
if (_match_expr.is_function ())
905
_possible_types = JoinPointLoc::Function;
906
else if (_match_expr.is_type ())
907
_possible_types = (JoinPointLoc::join_point_type)
908
(JoinPointLoc::Class|JoinPointLoc::Aspect);
910
_possible_types = JoinPointLoc::None;
908
913
bool PCE_Match::evaluate (JoinPointLoc &jpl, PointCutContext &context,
909
914
Binding &binding, Condition &cond) {
910
assert ((jpl.type () & JoinPointLoc::Name) != 0);
911
915
assert (!_match_expr.error ());
913
JPL_Name &jpl_name = (JPL_Name&)jpl;
914
if ((jpl.type () == JoinPointLoc::Function && _match_expr.is_function ()) ||
915
((jpl.type () & (JoinPointLoc::Class | JoinPointLoc::Aspect |
916
JoinPointLoc::Type)) && _match_expr.is_type ()))
917
return _match_expr.matches (jpl_name.type_info (), jpl_name.obj_info ());
917
if (jpl.type () == JoinPointLoc::Type) {
918
if (_match_expr.is_type ()) {
919
JPL_Type &jpl_type = (JPL_Type&)jpl;
920
return _match_expr.matches ((MatchSignature &)jpl_type.match_signature ());
924
else if ((jpl.type () & JoinPointLoc::Name) != 0) {
925
JPL_Name &jpl_name = (JPL_Name&)jpl;
926
if ((jpl.type () == JoinPointLoc::Function && _match_expr.is_function ()) ||
927
((jpl.type () & (JoinPointLoc::Class | JoinPointLoc::Aspect) &&
928
_match_expr.is_type ()))) {
929
return _match_expr.matches ((MatchSignature &)jpl_name.match_signature ());
921
// if ((_filter.method () && jpl.type () != JoinPointLoc::Function) ||
922
// (!_filter.method () && jpl.type () == JoinPointLoc::Function))
923
// old_result = false;
925
// old_result = ((JPL_Name&)jpl).matches (_dstr, _filter);
927
//// if (old_result != new_result) {
928
//// cout << (old_result == new_result ? "same" : "diff ")
929
//// << old_result << " " << new_result << " " << _dstr
930
//// << ": " << jpl.signature () << endl;
933
// return old_result;
936
936
void PCE_Match::mangle_type_check (ostream &out) {
937
const char *str = _dstr;
937
const char *str = _str.c_str ();
940
940
case ':' : out << "___S___"; break;