~ubuntu-branches/ubuntu/maverick/aspectc++/maverick

« back to all changes in this revision

Viewing changes to AspectC++/PointCutExpr.cc

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler
  • Date: 2008-04-10 17:40:52 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20080410174052-xdnsm7oi8hauyyf1
Tags: 1.0pre4~svn.20080409+dfsg-3
Fix another missing include, this time in Ag++/StdSystem.cc

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
#include "PointCutExpr.h"
21
21
#include "PointCutContext.h"
22
22
#include "Binding.h"
23
 
#include "Naming.h"
24
23
#include "MatchExpr.h"
25
 
#include "TrackerDog.h"
26
24
 
27
25
// PUMA includes
28
26
#include "Puma/ErrorStream.h"
37
35
#include <sstream>
38
36
using std::stringstream;
39
37
using std::endl;
40
 
using std::ends;
41
 
 
42
 
static CClassInfo *cscope(CObjectInfo *obj) {
43
 
  if (obj->QualifiedScope ())
44
 
    return obj->QualifiedScope ()->ClassInfo ();
45
 
  return obj->Scope ()->ClassInfo ();
46
 
}
47
38
 
48
39
void PointCutExpr::sem_args (ErrorStream &err, PointCutContext &context) {
49
40
  // recursively do a semantic analysis of child nodes
109
100
  return curr_arg_bindings.lookup (a);
110
101
}
111
102
 
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) {
 
105
    
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);
118
 
    if (func) {
119
 
      for (unsigned f = 0; f < derived->Functions (); f++) {
120
 
        if (!func->hasSameNameAndArgs (derived->Function (f)))
121
 
          continue;
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))
125
 
                return true;
126
 
      }
127
 
    }
128
 
    else {
129
 
      JoinPointLoc *class_loc = context.scopes ().lookup (derived);
130
 
      if (class_loc &&
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
135
 
        }
136
 
        else
137
 
          return true;
138
 
      }
139
 
    }
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
 
116
                               // siblings
 
117
      }
 
118
      else
 
119
        return true;
 
120
    }
 
121
    if (do_subclasses && check_derived_class (*derived, context,
 
122
        binding, cond))
141
123
      return true;
142
124
  }
143
125
  return !do_subclasses;
144
126
}
145
127
 
146
 
bool PCE_SingleArg::check_base (CClassInfo *cls, CFunctionInfo *func,
147
 
                                PointCutContext &context, Binding &binding, Condition &cond) {
148
 
  if (func) {
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) {
 
130
  Condition unused;
 
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);
 
136
 
 
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)
151
141
        continue;
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))
155
 
            return true;
 
142
      JPL_Function &curr = *(JPL_Function*)*i;
 
143
      if (!func.has_same_name_and_args (curr))
 
144
         continue;
 
145
      if (arg (0)->evaluate (curr, context, binding, cond))
 
146
        return true;
156
147
    }
157
 
  }
158
 
  else {
159
 
    JoinPointLoc *class_loc = context.scopes ().lookup (cls);
160
 
    if (class_loc && arg (0)->evaluate (*class_loc, context, binding, cond))
161
 
      return true;
162
 
  }
163
 
  for (unsigned i = 0; i < cls->BaseClasses (); i++) {
164
 
    if (check_base (cls->BaseClass (i)->Class (), func, context, binding, cond))
165
 
      return true;
166
 
  }
167
 
  return false;
168
 
}
169
 
 
 
148
 
 
149
    if (do_subclasses && check_derived_func (*derived, func, context, 
 
150
      binding, cond))
 
151
      return true;
 
152
  }
 
153
  return !do_subclasses;
 
154
}
 
155
 
 
156
 
 
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)) {
 
160
    return true;
 
161
  }
 
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))
 
166
      return true;
 
167
  }
 
168
  return false;
 
169
}
 
170
 
 
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)
 
177
      continue;
 
178
    JPL_Function &curr = *(JPL_Function*)*i;
 
179
    if (!func.has_same_name_and_args (curr))
 
180
       continue;
 
181
    if (arg (0)->evaluate (curr, context, binding, cond))
 
182
      return true;
 
183
  }
 
184
 
 
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))
 
189
      return true;
 
190
  }
 
191
  return false;
 
192
}
 
193
 
 
194
bool PCE_SingleArg::check_scopes (JPL_Name *scope,
 
195
        PointCutContext &context, Binding &binding, Condition &cond) {
 
196
  do {
 
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))
 
200
      return true;
 
201
    scope = (JPL_Name*)scope->parent ();
 
202
  } while (scope);
 
203
 
 
204
  return false;
 
205
}
170
206
 
171
207
PCE_Type PCE_Classes::type () const {
172
208
  return PCE_NAME;
175
211
void PCE_Classes::semantics (ErrorStream &err, PointCutContext &context) {
176
212
  check_arg_types (err, "classes", PCE_NAME);
177
213
  sem_args (err, context);
 
214
  _possible_types = JoinPointLoc::Class;
178
215
}
179
216
 
180
217
bool PCE_Classes::evaluate (JoinPointLoc &jpl, PointCutContext &context,
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 ();
193
231
}
194
232
 
195
233
bool PCE_Base::evaluate (JoinPointLoc &jpl, PointCutContext &context,
196
234
                         Binding &binding, Condition &cond) {
 
235
  if (!(jpl.type () & (int)_possible_types))
 
236
    return false;
 
237
    
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);
202
 
  }
203
 
  else {
204
 
    CFunctionInfo *func = ((JPL_Function&)jpl).func_info ();
205
 
    CClassInfo *cls = cscope (func);
206
 
    return cls && check_derived (cls, func, context, binding, cond);
207
 
  }
 
241
    return check_derived_class ((JPL_Class&)jpl, context, binding, cond);
 
242
  }
 
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);
 
248
    }
 
249
  }
 
250
  return false;
208
251
}
209
252
 
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 ();
217
261
}
218
262
 
219
263
bool PCE_Derived::evaluate (JoinPointLoc &jpl, PointCutContext &context,
220
264
                            Binding &binding, Condition &cond) {
 
265
  if (!(jpl.type () & (int)_possible_types))
 
266
    return false;
 
267
    
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);
226
 
  }
227
 
  else {
228
 
    CFunctionInfo *func = ((JPL_Function&)jpl).func_info ();
229
 
    CClassInfo *cls = cscope (func);
230
 
    return cls && check_base (cls, func, context, binding, cond);
231
 
  }
 
271
    return check_base_class ((JPL_Class&)jpl, context, binding, cond);
 
272
  }
 
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);
 
278
    }
 
279
  }
 
280
  return false;
232
281
}
233
282
 
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;
241
291
}
242
292
 
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 ()) {
 
295
 
 
296
  // 'within' matches only code join points
 
297
  if (!(jpl.type () & (int)JoinPointLoc::Code))
 
298
    return false;
 
299
  JPL_Code &jpl_code = (JPL_Code&)jpl;
 
300
    
 
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);
248
305
    return true;
249
306
  }
250
307
 
251
 
  // TODO: here I should better use the virtual that_type() function
252
 
  CFunctionInfo *func;
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;
262
 
  default:
263
 
    return false; // should not happen
264
 
  }
265
 
  
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))
272
 
      return true;
273
 
  }
274
 
 
275
 
  CClassInfo *cls = cscope (func);
276
 
  if (cls) {
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))
280
 
      return true;
281
 
  }
282
 
  return false;
 
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 ();
 
313
  }
 
314
  return check_scopes (scope, context, binding, cond);
283
315
}
284
316
 
285
317
PCE_Type PCE_Execution::type () const {
290
322
                               PointCutContext &context) {
291
323
  check_arg_types (err, "execution", PCE_NAME);
292
324
  sem_args (err, context);
 
325
  _possible_types = JoinPointLoc::Method;
293
326
}
294
327
 
295
328
bool PCE_Execution::evaluate (JoinPointLoc &jpl, PointCutContext &context,
298
331
  if (jpl.type () != JoinPointLoc::Method)
299
332
    return false;
300
333
 
301
 
  // get the class and function object
302
 
  CFunctionInfo *that_func = ((JPL_Method&)jpl).func_info ();
303
 
  CClassInfo *that_class = cscope (that_func);
304
 
 
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))
308
 
    return false;
309
 
 
310
 
  if (that_class) {
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))
315
 
      return true;
316
 
  }
317
 
 
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))
321
337
    return true;
322
338
 
323
 
  // no match!
324
 
  return false;
 
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);
325
342
}
326
343
 
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;
334
352
}
335
353
 
336
354
bool PCE_Call::evaluate (JoinPointLoc &jpl, PointCutContext &context,
337
355
                         Binding &binding, Condition &cond) {
338
356
  if (jpl.type () != JoinPointLoc::MethodCall)
339
357
    return false;
340
 
    
341
 
  CFunctionInfo *target_func = ((JPL_MethodCall&)jpl).called ();
342
 
  CClassInfo *target_class = cscope (target_func);
343
 
 
344
 
  if (target_class) {
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))
348
 
      return true;
349
 
  }
350
 
 
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))
 
358
 
 
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))
354
362
    return true;
355
363
 
356
 
  // no match!
357
 
  return false;
 
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);
358
367
}
359
368
 
360
369
 
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;
368
378
}
369
379
 
370
380
bool PCE_Construction::evaluate (JoinPointLoc &jpl, PointCutContext &context,
371
381
                                 Binding &binding, Condition &cond) {
372
382
  if (jpl.type () != JoinPointLoc::Construction)
373
383
    return false;
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))
379
 
      return true;
380
 
  }
381
 
  return false;
 
384
  JPL_Name *scope = ((JPL_Construction&)jpl).lexical_scope ();
 
385
  return arg (0)->evaluate (*scope, context, binding, cond);
382
386
}
383
387
 
384
388
PCE_Type PCE_Destruction::type () const {
388
392
void PCE_Destruction::semantics (ErrorStream &err, PointCutContext &context) {
389
393
  check_arg_types (err, "destruction", PCE_NAME);
390
394
  sem_args (err, context);
 
395
  _possible_types = JoinPointLoc::Destruction;
391
396
}
392
397
 
393
398
bool PCE_Destruction::evaluate (JoinPointLoc &jpl, PointCutContext &context,
394
399
                                Binding &binding, Condition &cond) {
395
400
  if (jpl.type () != JoinPointLoc::Destruction)
396
401
    return false;
397
 
  CFunctionInfo *func = ((JPL_Destruction&)jpl).func_info ();
398
 
  CClassInfo *cls = cscope (func);
399
 
  if (cls) { // TODO: this is because unions yield 0 here. Handle them!
400
 
    JoinPointLoc *class_loc = context.scopes ().lookup (cls);
401
 
    if (class_loc && arg (0)->evaluate (*class_loc, context, binding, cond))
402
 
      return true;
403
 
  }
404
 
  return false;
 
402
  JPL_Name *scope = ((JPL_Destruction&)jpl).lexical_scope ();
 
403
  return arg (0)->evaluate (*scope, context, binding, cond);
405
404
}
406
405
 
407
406
 
414
413
  context.enter_that ();
415
414
  sem_args (err, context);
416
415
  context.leave_that ();
 
416
  _possible_types = JoinPointLoc::Code;
417
417
}
418
418
 
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))
 
423
    return false;
 
424
  JPL_Code &jpl_code = (JPL_Code&)jpl;
 
425
 
421
426
  if (jpl.type () == JoinPointLoc::MethodCall &&
422
427
      ((JPL_MethodCall&)jpl).is_pseudo ()) {
423
428
    context.pseudo_true (true);
424
429
    return true;
425
430
  }
426
 
    
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 ();
437
 
  else
438
 
    return false;
439
 
 
440
 
  CClassInfo *that_class = cscope (that_func);
441
 
 
442
 
  // if the function is not part of the project, this is no real join point
443
 
  if (!context.in_project (that_func))
444
 
    return false;
445
 
    
446
 
  // if this is not a member function return false
447
 
  if (!that_class || that_func->isStaticMethod ())
448
 
    return false;
 
431
 
 
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)
 
435
    return false;
 
436
  JPL_Function *jpl_function = (JPL_Function*)parent;
 
437
 
 
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 ())
 
440
    return false;
 
441
 
 
442
  // get the class of which the function is a member
 
443
  JPL_Class *class_loc = (JPL_Class*)jpl_function->parent ();
449
444
  
450
445
  context.enter_that ();
451
446
  binding._this = (CArgumentInfo *)0;
452
447
 
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 ();
461
455
      return false;
462
456
    }
463
457
      
464
458
    // create a 'that' condition with a mangled name
465
 
    stringstream mangled, cond_name;
466
 
    arg (0)->mangle_type_check (mangled);
467
 
    mangled << ends;
468
 
    Naming::type_check_func (cond_name, that_class, mangled.str ().data ());
469
 
    cond_name << ends;
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 ());
472
462
 
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);
475
465
  }
476
466
  context.leave_that ();
477
467
  return true;
486
476
  context.enter_target ();
487
477
  sem_args (err, context);
488
478
  context.leave_target ();
 
479
  _possible_types = JoinPointLoc::MethodCall;
489
480
}
490
481
 
491
482
bool PCE_Target::evaluate (JoinPointLoc &jpl, PointCutContext &context,
493
484
  // only calls have a target at the moment
494
485
  if (jpl.type () != JoinPointLoc::MethodCall)
495
486
    return false;
496
 
    
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);
501
 
 
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))
505
 
    return false;
506
 
  
507
 
  // if this is not a member function return false
508
 
  if (!target_class || target_func->isStaticMethod ())
509
 
    return false;
 
488
 
 
489
  JPL_Function *target_function = jpl_call.target_function ();
 
490
 
 
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 ())
 
494
    return false;
 
495
 
 
496
  // get the class of which the function is a member
 
497
  JPL_Class *class_loc = (JPL_Class*)target_function->parent ();
510
498
  
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);
519
 
    mangled << ends;
520
 
    Naming::type_check_func (cond_name, target_class, mangled.str ().data ());
521
 
    cond_name << ends;
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 ());
523
508
 
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);
526
511
  }
527
512
  context.leave_target ();
528
513
  return true;
536
521
  check_arg_types (err, "cflow", PCE_CODE);
537
522
  sem_args (err, context);
538
523
  // evaluate the argument pointcut
539
 
  JoinPointLocList::Selection all;
540
 
  context.world ().select (JoinPointLoc::Code, all);
541
 
  for (JoinPointLocList::Selection::iterator iter = all.begin ();
 
524
  JoinPointModel::Selection all;
 
525
  context.jpm ().select (JoinPointLoc::Code, all);
 
526
  for (JoinPointModel::Selection::iterator iter = all.begin ();
542
527
       iter != all.end (); ++iter) {
543
528
    JoinPointLoc &jpl = **iter;
544
529
    Binding cflow_binding;
561
546
    }
562
547
  }
563
548
  _index = context.cflow (this); // remember this node in the context
 
549
  _possible_types = JoinPointLoc::Code;
564
550
}
565
551
 
566
552
bool PCE_CFlow::evaluate (JoinPointLoc &jpl, PointCutContext &context,
589
575
      arg (i)->semantics (err, context);
590
576
  }
591
577
  context.set_arg (saved_arg);
 
578
  _possible_types = JoinPointLoc::Code;
592
579
}
593
580
 
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 ();
605
 
  else
606
 
    return false; // other join points are not considered, yet.
607
 
  
 
583
 
 
584
  // ignore all non-code join points
 
585
  if (!(jpl.type () & (int)JoinPointLoc::Code))
 
586
    return false;
608
587
  JPL_Code *jpl_code = (JPL_Code*)&jpl;
609
588
    
610
589
  // check if the number of arguments is ok -> not compatible ("...")
636
615
  context.enter_result ();
637
616
  sem_args (err, context);
638
617
  context.leave_result ();
 
618
  _possible_types = (JoinPointLoc::join_point_type)
 
619
    (JoinPointLoc::Method|JoinPointLoc::MethodCall);
639
620
}
640
621
 
641
622
bool PCE_Result::evaluate (JoinPointLoc &jpl, PointCutContext &context,
642
623
                           Binding &binding, Condition &cond) {
643
 
  CFunctionInfo *func = 0;
644
 
  if (jpl.type () == JoinPointLoc::Method)
645
 
    func = ((JPL_Method&)jpl).func_info ();
646
 
  else if (jpl.type () == JoinPointLoc::MethodCall)
647
 
    func = ((JPL_MethodCall&)jpl).called ();
648
 
  else
649
 
    return false; // other join points are not considered, yet.
 
624
 
 
625
  // only execution and call join points have a result
 
626
  if (jpl.type () != JoinPointLoc::Method &&
 
627
      jpl.type () != JoinPointLoc::MethodCall)
 
628
    return false;
650
629
  
651
630
  JPL_Code *jpl_code = (JPL_Code*)&jpl;
652
631
  JPL_Type &type_loc = (JPL_Type&)jpl_code->result_type ();
666
645
void PCE_Or::semantics (ErrorStream &err, PointCutContext &context) {
667
646
  check_arg_types_equal (err, "||");
668
647
  sem_args (err, context);
 
648
  _possible_types = (JoinPointLoc::join_point_type)
 
649
    (arg(0)->possible_types () | arg(1)->possible_types ());
669
650
}
670
651
 
671
652
bool PCE_Or::evaluate (JoinPointLoc &jpl, PointCutContext &context,
701
682
void PCE_And::semantics (ErrorStream &err, PointCutContext &context) {
702
683
  check_arg_types_equal (err, "&&");
703
684
  sem_args (err, context);
 
685
  _possible_types = (JoinPointLoc::join_point_type)
 
686
    (arg(0)->possible_types () & arg(1)->possible_types ());
704
687
}
705
688
 
706
689
bool PCE_And::evaluate (JoinPointLoc &jpl, PointCutContext &context,
736
719
void PCE_Not::semantics (ErrorStream &err, PointCutContext &context) {
737
720
  check_arg_types (err, "!", type ());
738
721
  sem_args (err, context);
 
722
  if (type () == PCE_NAME)
 
723
    _possible_types = JoinPointLoc::Name;
 
724
  else if (type () == PCE_CODE)
 
725
    _possible_types = JoinPointLoc::Code;
 
726
  else
 
727
    _possible_types = JoinPointLoc::None;
739
728
}
740
729
 
741
730
bool PCE_Not::evaluate (JoinPointLoc &jpl, PointCutContext &context,
807
796
  context.arg_bindings ().pop ();
808
797
 
809
798
  context.func (saved_func); // restore old function pointer
 
799
  
 
800
  _possible_types = (JoinPointLoc::join_point_type)arg(0)->possible_types ();
810
801
}
811
802
 
812
803
bool PCE_Named::evaluate (JoinPointLoc &jpl, PointCutContext &context,
847
838
    _bound_to = CV_ARG;
848
839
    _arg = context.get_arg ();
849
840
  }
 
841
  if (_bound_to == CV_ARG || _bound_to == CV_RESULT)
 
842
    _possible_types = JoinPointLoc::Type;
 
843
  else if (_bound_to == CV_TARGET || _bound_to == CV_THAT)
 
844
    _possible_types = (JoinPointLoc::join_point_type)
 
845
      (JoinPointLoc::Class|JoinPointLoc::Aspect);
 
846
  else
 
847
    _possible_types = JoinPointLoc::None;
850
848
}
851
849
 
852
850
bool PCE_ContextVar::evaluate (JoinPointLoc &jpl, PointCutContext &context,
860
858
  // determine the current type
861
859
  CTypeInfo *curr_type = 0;
862
860
  if (jpl.type () == JoinPointLoc::Type)
863
 
    curr_type = ((JPL_Type&)jpl).type_info ();
 
861
    curr_type = TI_Type::of ((JPL_Type&)jpl)->type_info ();
864
862
  else if (jpl.type () == JoinPointLoc::Class ||
865
863
           jpl.type () == JoinPointLoc::Aspect)
866
 
    curr_type = ((JPL_Class&)jpl).class_info ()->TypeInfo ();
 
864
    curr_type = ((TI_Class*)((JPL_Class&)jpl).transform_info ())->class_info ()->TypeInfo ();
867
865
 
868
866
  assert (curr_type);
869
867
  if (!curr_type)
902
900
}
903
901
 
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);
 
909
  else
 
910
    _possible_types = JoinPointLoc::None;
906
911
}
907
912
 
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 ());
912
916
  
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 ());
918
 
    
 
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 ());
 
921
    }
 
922
    return false;    
 
923
  }
 
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 ());
 
930
    }
 
931
    return false;
 
932
  }
919
933
  return false;
920
 
//  bool old_result;        
921
 
//  if ((_filter.method () && jpl.type () != JoinPointLoc::Function) ||
922
 
//      (!_filter.method () && jpl.type () == JoinPointLoc::Function))
923
 
//    old_result = false;
924
 
//  else {          
925
 
//    old_result = ((JPL_Name&)jpl).matches (_dstr, _filter);
926
 
//    
927
 
////    if (old_result != new_result) {
928
 
////      cout << (old_result == new_result ? "same" : "diff ") 
929
 
////           << old_result << " " << new_result << " " << _dstr
930
 
////           << ": " << jpl.signature () << endl;
931
 
////    }
932
 
//  }
933
 
//  return old_result;
934
934
}
935
935
 
936
936
void PCE_Match::mangle_type_check (ostream &out) {
937
 
  const char *str = _dstr;
 
937
  const char *str = _str.c_str ();
938
938
  while (*str) {
939
939
    switch (*str) {
940
940
      case ':' : out << "___S___"; break;