148
140
_code_weaver.commit ();
142
// prepare the project model
143
jpm.setup_phase1((FileUnit*)unit, _code_weaver.primary_len());
145
// fill the model while parsing the AOP elements of the language in phase 1
150
146
_vm << "Parsing ..." << endvm;
151
// parse the translation unit, but ignore function bodies
152
unsigned options = _parser.Options ();
153
_parser.Options (options | CCParser::SKIP_FCT_BODY);
154
tunit = _parser.parse (*unit, _project);
155
_parser.Options (options);
156
// do semantic analysis of expressions
157
_sem_visitor.run (tunit->tree ());
159
if (_err.severity () >= sev_error)
162
// tunit->unit ()->print(cout);
163
// CPrintVisitor printer;
164
// printer.print (tunit->tree (), cout);
166
// Some debugging code:
167
// tunit->unit ()->print(cout);
168
// CPrintVisitor printer;
169
// printer.print (tunit->tree (), cout);
170
// tunit->db ().Dump (cout, 2);
172
// create the phase 1 join point model
173
_vm << "Setting up join point model 1 ..." << endvm;
175
int tunit_len = _code_weaver.primary_end ()->location().line() -
176
_code_weaver.primary_start()->location().line() + 1;
177
jpm.setup_phase1 (*tunit, tunit_len);
147
Phase1 phase1 (jpm, *unit, _project, _code_weaver);
149
// cout << "Project Model after Phase1" << endl;
180
152
// set up the project repository
181
153
_repo.setup (jpm.tunit_file());
183
_vm << "Setting Aspect Access Privileges ..." << endvm;
184
aspect_privileges (jpm);
186
_vm << "Weaving Introductions ..." << endvm;
187
introductions (*tunit, jpm);
189
_vm << "Weaving Advice Declarations ..." << endvm;
192
_vm << "Weaving Singleton Aspects ..." << endvm;
193
singleton_aspects (*tunit);
195
// _vm << "Slice/Intro Includes ..." << endvm;
196
// _code_weaver.slice_includes (_project, _primary_start);
155
// generate a string with aspect forward declarations
156
_vm << "Weaving Aspects Forward Declarations ..." << endvm;
157
determine_aspect_fwd_decls (jpm);
158
_code_weaver.insert (_code_weaver.weave_pos ((Token*)unit->first (), WeavePos::WP_BEFORE),
198
161
_vm << "Committing" << endvm;
199
162
_code_weaver.commit ();
165
// Some debugging code:
166
// unit->print(cout);
201
168
// _vm << "Stage1 save!" << endvm;
202
169
// _project.save();
203
170
// _vm << " done." << endvm;
215
182
bool Transformer::phase2 (Unit *unit, CTranslationUnit *tunit1,
183
ModelBuilder &jpm, IncludeGraph &ig) {
219
186
static Profiler::Data data (__PRETTY_FUNCTION__, NULL);
220
187
Profiler::ClockTicks start = Profiler::rdtsc ();
223
IncludeGraph ig (_project);
190
Plan plan (_err, jpm);
227
192
_vm << "Preparing introductions ..." << endvm;
228
Plan plan (_err, jpm);
229
193
PointCutContext context (jpm);
230
PointCutEvaluator eval (_err, context);
232
// get all aspects from the plan (in some order)
233
const Plan::AspectContainer &aspects = plan.aspect_infos ();
234
for (Plan::AspectContainer::const_iterator i = aspects.begin ();
235
i != aspects.end (); ++i) {
238
ACM_Aspect &jpl_aspect = i->loc ();
239
context.concrete_aspect (jpl_aspect);
241
// add introductions to plan
242
list<ACM_Introduction*> intros;
243
collect_intros (jpl_aspect, intros);
245
for (list<ACM_Introduction*>::iterator i = intros.begin ();
246
i != intros.end (); ++i) {
247
IntroductionInfo *ii = plan.addIntroduction (jpl_aspect, **i);
248
ii->pointcut_expr () =
249
eval.create (TI_PointcutExpr::of(*(*i)->get_expr ())->tree(), JPT_Name);
250
if (!(ii->pointcut_expr()->possible_types() & JPT_Class)) {
251
_err << sev_warning << TI_Introduction::of(ii->intro ())->loc()
252
<< "pointcut expression for introduction can't match class"
257
// add order advices to plan
258
list<ACM_Order*> orders;
259
collect_orders (jpl_aspect, orders);
261
for (list<ACM_Order*>::iterator i = orders.begin ();
262
i != orders.end (); ++i) {
263
OrderInfo *oi = plan.addOrder (jpl_aspect, **i);
264
oi->analyze_exprs (eval);
265
if (!getenv ("ACNEWREPO")) {
270
JPL_Aspect &jpl_aspect = i->loc ();
271
context.concrete_aspect (jpl_aspect);
273
// add introductions to plan
274
list<JPL_Introduction*> intros;
275
jpl_aspect.collect_intros (intros);
277
for (list<JPL_Introduction*>::iterator i = intros.begin ();
278
i != intros.end (); ++i) {
279
IntroductionInfo *ii = plan.addIntroduction (jpl_aspect, **i);
280
ii->pointcut_expr() = eval.create ((*i)->expr (), JoinPointLoc::Name);
281
if (!(ii->pointcut_expr()->possible_types() & JoinPointLoc::Class)) {
282
_err << sev_warning << TI_Introduction::of(ii->intro ())->loc()
283
<< "pointcut expression for introduction can't match class"
288
// add order advices to plan
289
list<JPL_Order*> orders;
290
jpl_aspect.collect_orders (orders);
292
for (list<JPL_Order*>::iterator i = orders.begin ();
293
i != orders.end (); ++i) {
294
OrderInfo *oi = plan.addOrder (jpl_aspect, **i);
295
oi->analyze_exprs (eval);
296
if (!getenv ("ACNEWREPO")) {
195
// perform semantic analysis of all pointcut expressions used for introductions
196
const list<IntroductionInfo*> &intros = plan.introduction_infos ();
197
for (list<IntroductionInfo*>::const_iterator i = intros.begin ();
198
i != intros.end (); ++i) {
199
IntroductionInfo *intro_info = *i;
200
ACM_Introduction &intro = intro_info->intro();
201
context.concrete_aspect(intro_info->aspect());
202
context.pct_func (intro.get_pointcut());
203
intro_info->pointcut_expr()->semantics(_err, context);
204
if (!(intro_info->pointcut_expr()->possible_types() & JPT_Class)) {
206
<< Location (Filename (filename (intro).c_str ()), line (intro))
207
<< "pointcut expression for introduction can't match class"
212
// ... and also for the pointcut expressions in order advice
213
const list<OrderInfo*> &orders = plan.order_infos ();
214
for (list<OrderInfo*>::const_iterator i = orders.begin ();
215
i != orders.end (); ++i) {
217
context.concrete_aspect (oi->aspect());
218
oi->analyze_exprs (_err, context);
219
if (getenv ("ACOLDREPO")) {
303
224
_vm << "Parsing again ..." << endvm;
587
501
for (ProjectModel::Selection::iterator i = classes.begin ();
588
502
i != classes.end (); ++i) {
589
503
ACM_Class &cls = *(ACM_Class*)*i;
590
// get the weaving plan of this intro
591
JPP_Class *plan = (JPP_Class*)cls.plan ();
592
// collect the intros into this class
594
set<ACM_Introduction*> intros;
595
for (int b = 0; b < plan->baseIntros (); b++)
596
intros.insert (plan->baseIntro (b));
597
for (int o = 0; o < plan->otherIntros (); o++)
598
intros.insert (plan->otherIntro (o));
599
// now update the repository with the intro information
600
for (set<ACM_Introduction*>::iterator intro_iter = intros.begin ();
601
intro_iter != intros.end (); ++intro_iter) {
602
_repo.update (**intro_iter, cls);
607
ModelBuilder::Selection intros;
608
jpm1.select (JoinPointLoc::Introduction, intros);
609
for (JoinPointModel::Selection::iterator i = intros.begin ();
610
i != intros.end (); ++i) {
611
JPL_Introduction &intro = *(JPL_Introduction*)*i;
612
_repo.consider (intro);
614
ModelBuilder::Selection classes;
615
jpm1.select ((JoinPointLoc::join_point_type)(JoinPointLoc::Class|
616
JoinPointLoc::Aspect), classes);
617
for (JoinPointModel::Selection::iterator i = classes.begin ();
618
i != classes.end (); ++i) {
619
JPL_Class &cls = *(JPL_Class*)*i;
620
// get the weaving plan of this intro
621
JPP_Class *plan = (JPP_Class*)cls.plan ();
622
// collect the intros into this class
624
set<JPL_Introduction*> intros;
625
for (int b = 0; b < plan->baseIntros (); b++)
626
intros.insert (plan->baseIntro (b));
627
for (int o = 0; o < plan->otherIntros (); o++)
628
intros.insert (plan->otherIntro (o));
629
// now update the repository with the intro information
630
for (set<JPL_Introduction*>::iterator intro_iter = intros.begin ();
631
intro_iter != intros.end (); ++intro_iter) {
632
_repo.update (**intro_iter, cls);
640
static bool needs_friend_injection (ModelBuilder &jpm, CRecord *rec) {
641
static Filename anon("<anonymous unit>");
642
CSemDatabase *semdb = jpm.get_db();
644
// no need for template instances; the templates already get the friend injection
645
if (rec->isTemplateInstance())
647
// only defined classes can get an injection
648
if (!rec->isDefined ())
650
// code introduced by ac++ (in an anonymous unit) is not modified here
651
if (rec->Tree()->token ()->location().filename() == anon)
653
// nested classes in template instances should also not be modified to avoid double injection
654
if (jpm.inside_template_instance(rec))
656
// the class has to belong to the project
657
Unit *unit = (Unit*)rec->Tree ()->token ()->belonging_to ();
658
if (!semdb->Project ()->isBelow (unit))
664
void Transformer::aspect_privileges (ModelBuilder &jpm) {
665
// TODO: move this into phase 2 parse; introduce classes don't
666
// get the friend injection yet!
668
// get all aspects from the join point model
670
ProjectModel::Selection all_aspects;
671
jpm.select (JPT_Aspect, all_aspects);
673
// remember that these aspects should become friend of all classes
674
list<CClassInfo*> friends;
675
for (ProjectModel::Selection::iterator iter = all_aspects.begin ();
676
iter != all_aspects.end (); ++iter) {
677
ACM_Aspect &jpl = (ACM_Aspect&)**iter;
678
friends.push_back (((TI_Aspect*)jpl.transform_info ())->ClassInfo());
681
JoinPointModel::Selection all_aspects;
682
jpm.select (JoinPointLoc::Aspect, all_aspects);
684
// remember that these aspects should become friend of all classes
685
list<CClassInfo*> friends;
686
for (JoinPointModel::Selection::iterator iter = all_aspects.begin ();
687
iter != all_aspects.end (); ++iter) {
688
JPL_Aspect &jpl = (JPL_Aspect&)**iter;
689
friends.push_back (((TI_Aspect*)jpl.transform_info ())->ClassInfo());
693
if (!friends.empty ()) {
694
CSemDatabase *semdb = jpm.get_db();
695
// handle struct and classes
696
for (unsigned i = 0; i < semdb->ClassInfos(); i++) {
697
CClassInfo *ci = semdb->ClassInfo(i);
699
if (needs_friend_injection (jpm, ci)) {
700
// perform the code transformation
701
_code_weaver.declare_friends (ci, friends);
705
for (unsigned i = 0; i < semdb->UnionInfos(); i++) {
706
CUnionInfo *ui = semdb->UnionInfo(i);
708
if (needs_friend_injection (jpm, ui)) {
709
// perform the code transformation
710
_code_weaver.declare_friends (ui, friends);
717
void Transformer::cleanup (CTranslationUnit &tunit) {
718
CSemDatabase &db = tunit.db ();
720
// replace keyword "aspect" with "class" and remove advice
721
for (int a = 0; a < db.AspectInfos (); a++) {
722
ACAspectInfo *acai = db.AspectInfo (a);
724
// remove advice declarations
725
for (int adv = 0; adv < acai->AdviceNodes (); adv++)
726
_code_weaver.kill (acai->AdviceNode (adv));
728
_code_weaver.to_class (acai);
504
// skip this class if it has no plan yet
505
if (!cls.has_plan ())
507
// collect the intros into this class
508
set<ACM_Introduction*> intros; // a 'set', because the same intro might add a base class and a member
509
typedef ACM_Container<ACM_BaseIntro, true> BContainer;
510
BContainer bintros = cls.get_plan()->get_base_intros();
511
for (BContainer::iterator i = bintros.begin (); i != bintros.end (); ++i)
512
intros.insert ((*i)->get_intro());
513
typedef ACM_Container<ACM_MemberIntro, true> MContainer;
514
MContainer mintros = cls.get_plan()->get_member_intros();
515
for (MContainer::iterator i = mintros.begin (); i != mintros.end (); ++i)
516
intros.insert ((*i)->get_intro());
517
// now update the repository with the intro information
518
for (set<ACM_Introduction*>::iterator intro_iter = intros.begin ();
519
intro_iter != intros.end (); ++intro_iter) {
520
_repo.update (**intro_iter, cls);
526
void Transformer::cleanup (ModelBuilder &jpm) {
731
528
// delete all pointcut definitions that are left
732
for (int p = 0; p < db.PointcutInfos (); p++)
733
_code_weaver.kill (db.PointcutInfo (p)->def_node ());
737
void Transformer::introductions (CTranslationUnit &tunit,
740
// remove the introductions from the code
742
ProjectModel::Selection intros;
743
jpm.select (JPT_Introduction, intros);
744
for (ProjectModel::Selection::iterator i = intros.begin ();
745
i != intros.end (); ++i) {
746
ACM_Introduction &intro = *(ACM_Introduction*)*i;
747
_code_weaver.kill (TI_Introduction::of (intro)->tree ());
750
ModelBuilder::Selection intros;
751
jpm.select (JoinPointLoc::Introduction, intros);
752
for (JoinPointModel::Selection::iterator i = intros.begin ();
753
i != intros.end (); ++i) {
754
JPL_Introduction &intro = *(JPL_Introduction*)*i;
755
_code_weaver.kill (TI_Introduction::of (intro)->tree ());
759
// now delete all slice definitions
760
CSemDatabase &db = tunit.db ();
761
for (int s = 0; s < db.SliceInfos (); s++) {
762
ACSliceInfo *acsi = db.SliceInfo (s);
764
for (int sm = 0; sm < acsi->members (); sm++) {
765
CT_Intro *member = acsi->member (sm);
766
_code_weaver.kill (member);
768
// now the main definition
769
if (!acsi->in_advice ())
770
_code_weaver.kill (acsi->def_node ());
774
void Transformer::orderings (CTranslationUnit &tunit, Plan& plan,
775
ModelBuilder &jpm, bool purge) {
777
// let the plan object calculate the right order
780
// remove the introductions from the code
782
// Iterate through order advice declarations
784
ProjectModel::Selection orders;
785
jpm.select (JPT_Order, orders);
786
for (ProjectModel::Selection::iterator i = orders.begin ();
787
i != orders.end (); ++i) {
788
ACM_Order &order = *(ACM_Order*)*i;
790
ModelBuilder::Selection orders;
791
jpm.select (JoinPointLoc::Order, orders);
792
for (JoinPointModel::Selection::iterator i = orders.begin ();
793
i != orders.end (); ++i) {
794
JPL_Order &order = *(JPL_Order*)*i;
796
TI_Order &ti = *TI_Order::of (order);
797
_code_weaver.kill (ti.tree ());
803
void Transformer::advice (CTranslationUnit &tunit)
805
CSemDatabase &db = tunit.db ();
806
for (int a = 0; a < db.AspectInfos (); a++)
808
ACAspectInfo *ai = db.AspectInfo (a);
811
// handle all advice of this aspect
812
for (int i = 0; i < ai->AdviceNodes (); i++) {
813
CT_AdviceDecl *ad = ai->AdviceNode (i);
814
CFunctionInfo *advice_func = ((CT_FctDef*)ad->Decl ())->Object ()->
817
// handle only real advice here
818
if (strncmp (advice_func->Name (), "%a", 2) != 0)
821
// don't handle inherited advice here. This is done in the base class
822
if (advice_func->BaseObject ())
825
_vm << ai->ClassInfo ()->QualName () << "::"
826
<< advice_func->Name () << endvm;
828
_code_weaver.declare_function (advice_func, ad); // first phase
837
void Transformer::singleton_aspects (CTranslationUnit &tunit) {
838
CSemDatabase &db = tunit.db ();
839
for (int a = 0; a < db.AspectInfos (); a++) {
840
ACAspectInfo *ai = db.AspectInfo (a);
842
if (ai->is_abstract ())
845
_code_weaver.singleton (ai);
529
ProjectModel::Selection pointcuts;
530
jpm.select (JPT_Pointcut, pointcuts);
531
for (ProjectModel::Selection::iterator i = pointcuts.begin ();
532
i != pointcuts.end (); ++i) {
533
ACM_Pointcut &pct = *(ACM_Pointcut*)*i;
534
// delete all non-anonymous pointcut definitions
535
if (TI_Pointcut::of (pct)->func_info())
536
_code_weaver.kill (((CT_InitDeclarator*)TI_Pointcut::of (pct)->tree())->ObjDecl());
849
541
void Transformer::insert_bypass_class (ModelBuilder &jpm) {
850
set<Token*> blacklist; // see comments below
851
// Iterate through classes and structs, what about unions?
542
_code_weaver.bypass_info_clear();
544
// Iterate over classes and structs, what about unions?
853
545
ProjectModel::Selection all_classes;
854
546
jpm.select ((JoinPointType)(JPT_Class|JPT_Aspect), all_classes);
855
547
for (ProjectModel::Selection::iterator i = all_classes.begin ();
856
548
i != all_classes.end (); ++i) {
857
549
ACM_Class *cls = (ACM_Class*)*i;
859
ModelBuilder::Selection all_classes;
860
jpm.select ((JoinPointLoc::join_point_type)(JoinPointLoc::Class|
861
JoinPointLoc::Aspect), all_classes);
862
for (JoinPointModel::Selection::iterator i = all_classes.begin ();
863
i != all_classes.end (); ++i) {
864
JPL_Class *cls = (JPL_Class*)*i;
866
CClassInfo *ci = TI_Class::of (*cls)->class_info();
867
Token *token = ci->DefObject ()->Tree ()->token();
868
if (blacklist.find (token) == blacklist.end ()) {
869
// handle all classes that are not on the blacklist
870
_code_weaver.insert_bypass_class (ci);
872
// put a class in the backlist if is defined inside a template instance
873
// -> it can appear more than once in the model!
874
if (jpm.inside_template_instance (ci)) {
875
blacklist.insert (token);
551
// handle all classes that are not on the blacklist
552
if (!_code_weaver.bypass_in_blacklist(cls)) {
553
_code_weaver.bypass_insert (cls);
1251
853
_vm << "Call Join Points" << endvm;
1253
855
for (int i = 0; i < plan.call_jp_plans (); i++) {
1254
JPP_Code &jp_plan = plan.call_jp_plan (i);
1256
856
ACM_Call &jp_loc = plan.call_jp_loc (i);
1257
857
_vm << signature (jp_loc) << endvm;
1259
JPL_MethodCall &jp_loc = plan.call_jp_loc (i);
1260
_vm << jp_loc.signature () << endvm;
1263
859
// handle call joinpoint itself
1264
_code_weaver.call_join_point (&jp_loc, jp_plan);
860
_code_weaver.call_join_point (&jp_loc);
1268
864
_vm << "Execution Join Points" << endvm;
1270
866
for (int i = 0; i < plan.exec_jp_plans (); i++) {
1271
JPP_Code &jp_plan = plan.exec_jp_plan (i);
1273
867
ACM_Execution &jp_loc = plan.exec_jp_loc (i);
1274
868
_vm << signature (jp_loc) << endvm;
1276
JPL_Method &jp_loc = plan.exec_jp_loc (i);
1277
_vm << jp_loc.signature () << endvm;
1280
870
// handle exec joinpoint itself
1281
_code_weaver.exec_join_point (&jp_loc, jp_plan);
871
_code_weaver.exec_join_point (&jp_loc);
1285
875
_vm << "Construction Join Points" << endvm;
1287
877
for (int i = 0; i < plan.cons_jp_plans (); i++) {
1288
JPP_Code &jp_plan = plan.cons_jp_plan (i);
1290
878
ACM_Construction &jp_loc = plan.cons_jp_loc (i);
1291
879
_vm << signature (jp_loc) << endvm;
1293
JPL_Construction &jp_loc = plan.cons_jp_loc (i);
1294
_vm << jp_loc.signature () << endvm;
1297
881
// handle construction joinpoint itself
1298
_code_weaver.cons_join_point (&jp_loc, jp_plan);
882
_code_weaver.cons_join_point (&jp_loc);
1302
886
_vm << "Destruction Join Points" << endvm;
1304
888
for (int i = 0; i < plan.dest_jp_plans (); i++) {
1305
JPP_Code &jp_plan = plan.dest_jp_plan (i);
1307
889
ACM_Destruction &jp_loc = plan.dest_jp_loc (i);
1308
890
_vm << signature (jp_loc) << endvm;
1310
JPL_Destruction &jp_loc = plan.dest_jp_loc (i);
1311
_vm << jp_loc.signature () << endvm;
1314
892
// handle destruction joinpoint itself
1315
_code_weaver.dest_join_point (&jp_loc, jp_plan);
893
_code_weaver.dest_join_point (&jp_loc);
1327
905
data._calls = 1;
909
// add references to the introduced elements to the plan
910
void Transformer::link_members (ACM_Class &jpl) {
911
if (!jpl.has_plan ())
914
ACM_ClassPlan *plan = jpl.get_plan ();
916
typedef ACM_Container<ACM_Any, true> Container;
917
Container &children = jpl.get_children();
918
typedef ACM_Container<ACM_MemberIntro, true> Container2;
919
Container2 &member_intros = plan->get_member_intros();
920
for (Container::iterator i = children.begin (); i != children.end (); ++i) {
922
if (any->type_val() == JPT_Class) {
923
ACM_Class *cls = (ACM_Class*)any;
924
Unit *u = (Unit*)TI_Class::of(*cls)->obj_info()->Tree()->token()->belonging_to();
925
if (IntroductionUnit::cast(u)) {
926
ACM_Introduction *intro = IntroductionUnit::cast(u)->intro();
927
for (Container2::iterator mi = member_intros.begin ();
928
mi != member_intros.end(); ++mi)
929
if ((*mi)->get_intro() == intro)
930
(*mi)->get_members().insert(cls);
933
else if (any->type_val() == JPT_Function) {
934
ACM_Function *func = (ACM_Function*)any;
935
if (func->get_builtin())
937
Unit *u = (Unit*)TI_Function::of(*func)->obj_info()->Tree()->token()->belonging_to();
938
if (IntroductionUnit::cast(u)) {
939
ACM_Introduction *intro = IntroductionUnit::cast(u)->intro();
940
for (Container2::iterator mi = member_intros.begin ();
941
mi != member_intros.end(); ++mi)
942
if ((*mi)->get_intro() == intro)
943
(*mi)->get_members().insert(func);
949
// add references to the introduced elements to the plan
950
void Transformer::link_bases (ACM_Class &jpl) {
951
if (!jpl.has_plan ())
954
ACM_ClassPlan *plan = jpl.get_plan ();
955
CClassInfo *ci = TI_Class::of(jpl)->class_info();
957
typedef ACM_Container<ACM_Class, false> Container;
958
Container &bases = jpl.get_bases();
959
typedef ACM_Container<ACM_BaseIntro, true> Container2;
960
Container2 &base_intros = plan->get_base_intros();
961
for (Container::iterator i = bases.begin (); i != bases.end (); ++i) {
963
// find the base class info in Puma's semantic data structure
964
for (unsigned b = 0; b < ci->BaseClasses(); b++) {
965
if (ci->BaseClass(b)->Class() != TI_Class::of (*cls)->class_info())
967
Unit *u = (Unit*)ci->BaseClass(b)->Tree()->token()->belonging_to();
968
if (IntroductionUnit::cast(u)) {
969
ACM_Introduction *intro = IntroductionUnit::cast(u)->intro();
970
for (Container2::iterator bi = base_intros.begin ();
971
bi != base_intros.end(); ++bi) {
972
if ((*bi)->get_intro () == intro) {
973
(*bi)->get_bases().insert(cls);