393
369
ti->addDeducedArg (DeducedArg (i));
394
370
for (unsigned i = 0; i < base_candidate->DeducedArgs (); i++)
395
371
ti->addInstantiationArg (base_candidate->DeducedArg (i));
396
if (! instance->TemplateParamInfo ()) {
397
TemplateInfo ()->addPseudoInstance (instance);
402
void CCInstantiation::createInstance () {
372
TemplateInfo ()->addInstance (instance);
376
void CCInstantiation::setupFromPseudoInstance (CTemplateInstance* instinfo, CStructure* scope) {
377
instance = instinfo->Object ();
378
current_scope = (scope && scope == instance) ? scope->Parent ()->Structure () : scope;
379
CObjectInfo* defobj = instinfo->Template ()->ObjectInfo ()->DefObject ();
380
base_candidate->initialize (instinfo->PointOfInstantiation (), defobj, defobj->Template ());
381
for (unsigned i = 0; i < instinfo->DeducedArgs (); i++)
382
base_candidate->addDeducedArg (instinfo->DeducedArg (i));
386
bool CCInstantiation::instantiate (CTemplateInstance* instinfo, CStructure* instscope) {
403
387
CTranslationUnit *tu;
404
388
CStructure *scope;
405
389
CProject *project;
393
// setup from the pseudo instance information to
394
// reset the correct instantiation information
395
setupFromPseudoInstance (instinfo, instscope);
397
// check maximal instantiation depth
398
if (maxInstDepthReached ()) {
399
First ().forgetDeducedArgs ();
409
404
// increase instantiation depth
410
405
TemplateInfo ()->increaseDepth ();
412
scope = makeScope ();
407
scope = instance->TemplateParamInfo () ? makeScope () : instance->Scope ()->Structure ();
413
408
fct_inst = (ObjectInfo ()->FunctionInfo ());
414
409
project = ObjectInfo ()->SemDB ()->Project ();
415
unit = new CUnit (err);
410
unit = new TemplateInstanceUnit (err, getPoiToken()->unit(), instinfo);
411
unit->scanner ().configure (project->config ());
416
412
unit->name (scope->Name ());
418
414
// create code for the template instance
475
First ().forgetDeducedArgs ();
480
bool CCInstantiation::maxInstDepthReached () {
481
// ISO says not more than 17
482
unsigned max_depth = 17;
483
// maximum set by user?
484
const ConfOption *opt = TemplateInfo ()->SemDB ()->Project ()->config ().Option ("--template-depth");
485
if (opt && opt->Arguments () > 0) {
486
max_depth = strtol (opt->Argument (0), NULL, 10);
488
if (TemplateInfo ()->Depth () > max_depth) {
489
CTemplateInstance* topinst = 0;
490
Unit* unit = getPoiToken()->unit ();
491
while (unit->isTemplateInstance ()) {
492
TemplateInstanceUnit* tiunit = (TemplateInstanceUnit*)unit;
493
topinst = tiunit->TemplateInstance ();
494
unit = tiunit->ContainingUnit ();
496
if (topinst && topinst->Object()) {
497
err << getPoiToken(topinst)->location ()
498
<< "In instantiation of `" << *topinst->Object()->TypeInfo()
499
<< "':" << endMessage;
501
err << sev_error << getPoiToken()->location ()
502
<< "maximum instantiation depth ("
503
<< max_depth << ") reached" << endMessage;
510
Token* CCInstantiation::getPoiToken(CTemplateInstance* ti) {
513
CTree* poi = ti->PointOfInstantiation();
516
} while (! tok && (poi = poi->Parent()));
519
tok = First().getPointOfInstantiationToken();
473
525
void CCInstantiation::insertInstance (CObjectInfo *info) {
474
if (! info || ! info->TemplateInstance ())
478
for (unsigned i = 0; i < DeducedArgs (); i++)
479
instance->TemplateInstance ()->addDeducedArg (DeducedArg (i));
480
for (unsigned i = 0; i < base_candidate->DeducedArgs (); i++)
481
instance->TemplateInstance ()->addInstantiationArg (base_candidate->DeducedArg (i));
482
if (last_instance && last_instance != instance)
483
instance->NextObject (last_instance);
484
instance->TemplateInstance ()->PointOfInstantiation (getSimpleName (),
486
instance->TemplateInstance ()->Template (TemplateInfo ());
487
instance->TemplateInstance ()->TranslationUnit (trans_unit);
488
TemplateInfo ()->addInstance (instance);
526
if (info && info->TemplateInstance ()) {
528
if (last_instance && last_instance != instance)
529
instance->NextObject (last_instance);
530
instance->TemplateInstance ()->TranslationUnit (trans_unit);
492
535
void CCInstantiation::removeInstance () {
496
TemplateInfo ()->removeInstance (instance);
497
instance->TemplateInstance ()->clearDeducedArgs ();
498
instance->TemplateInstance ()->PointOfInstantiation (0, 0);
499
instance->TemplateInstance ()->TranslationUnit (0);
540
CStructure *CCInstantiation::makeScope () {
543
// create namespace name
544
std::ostringstream sname;
545
sname << "%" << ObjectInfo ()->Name ();
546
base_candidate->printArgumentList (sname);
548
scope = TemplateInfo ()->Parent ()->newNamespace ();
549
scope->NamespaceInfo ()->aroundInstantiation (true);
550
scope->Name (sname.str ().c_str ());
551
scope->TypeInfo (&CTYPE_UNDEFINED);
552
scope->SemDB (ObjectInfo ()->SemDB ());
553
scope->SourceInfo ()->FileInfo (ObjectInfo ()->SourceInfo ()->FileInfo ());
554
scope->SourceInfo ()->StartToken (PointOfInstantiation ()->token_node ());
559
void CCInstantiation::listParameters (CUnit &unit, CTemplateInfo *ti) {
560
CTemplateParamInfo *tp;
561
CT_TypeParamDecl *tpd;
562
CT_NonTypeParamDecl *ntpd;
565
for (unsigned i = 0; i < ti->Parameters (); ++i) {
569
tp = ti->Parameter (i);
572
if (*tp->Name () == '%') {
573
sprintf(anonymous, "__puma_%s", name+1);
576
if (tp->isTypeParam ()) {
577
tpd = (CT_TypeParamDecl*)tp->Tree ();
578
copyTree (unit, tpd, findPrivateName (tpd->Name ()), name);
580
ntpd = (CT_NonTypeParamDecl*)tp->Tree ();
581
copyTree (unit, ntpd, findPrivateName (ntpd->Declarator ()), name);
504
587
void CCInstantiation::fillUnit (CUnit &unit) {
588
CTemplateParamInfo *param, *tp;
505
589
DeducedArgument *arg;
506
CTemplateParamInfo *param;
507
590
CTree *default_arg;
509
std::ostringstream psname;
511
psname << "__puma_" << m_ScopeNameCounter;
512
m_ScopeNameCounter++;
513
593
for (unsigned i = 0; i < DeducedArgs (); i++) {
514
594
arg = DeducedArg (i);
515
595
param = arg->TemplateParam ();
516
// unnamed and template template parameters are special,
517
// nothing needs to be generated
518
if (! param || param->isTemplate () || ! param->Name () ||
519
*param->Name () == '%')
599
// get the name of the parameter, generate one
600
// if the parameter is anonymous
602
const char* name = param->Name ();
604
sprintf(anonymous, "__puma_%s", name+1);
608
// deduced template-template argument
609
if (param->isTemplate ()) {
610
ti = param->TemplateTemplate ();
611
unit << "template< ";
612
listParameters(unit, param->TemplateTemplate ());
613
unit << " > struct " << name;
614
unit << " {\n typedef ";
615
if (arg->isDefaultArg () && arg->TemplateArg ()) {
616
copyTree (unit, arg->TemplateArg (), arg->TemplateArg ()->end_token ());
617
} else if (arg->Type ()) {
618
arg->Type ()->TypeText (unit, 0, true);
621
for (unsigned j = 0; j < ti->Parameters (); ++j) {
625
tp = ti->Parameter (j);
626
if (*tp->Name () != '%') {
629
unit << "__puma_" << tp->Name ()+1;
632
unit << "> __puma_redirect;\n};\n" << endu;
522
633
// deduced type argument
523
if (param->isTypeParam ()) {
634
} else if (param->isTypeParam ()) {
524
635
// default template argument
525
if (arg->isDefaultArg ()) {
636
if (arg->isDefaultArg () && arg->TemplateArg ()) {
526
637
unit << "typedef ";
527
638
default_arg = arg->TemplateArg ();
528
genArgType (unit, default_arg, findPrivateName (default_arg), param->Name ());
639
copyTree (unit, default_arg, findPrivateName (default_arg), name);
529
640
unit << ";\n" << endu;
530
641
} else if (arg->Type ()) {
531
unit << "namespace " << psname.str () << " {\n";
532
642
unit << "typedef ";
533
arg->Type ()->TypeText (unit, param->Name (), true);
534
unit << ";\n}\n" << "using " << psname.str () << "::"
535
<< param->Name () << ";\n" << endu;
643
arg->Type ()->TypeText (unit, name, true);
644
unit << ";\n" << endu;
537
646
// deduced non-type argument
539
648
unit << "static ";
540
type = param->ValueType ();
541
if (! type->isConst ()) {
542
// turn it into a const type
543
type = new CTypeQualified (type->Duplicate (), true, false, false);
544
type->TypeText (unit, param->Name (), true);
547
type->TypeText (unit, param->Name (), true);
649
CT_NonTypeParamDecl* decl = (CT_NonTypeParamDecl*)param->Tree ();
650
copyTree (unit, decl->DeclSpecs (), 0, name);
652
copyTree (unit, decl->Declarator (), findName (decl->Declarator ()), name,
653
param->ValueType () && ! param->ValueType ()->isConst ());
549
654
// default template argument
550
if (arg->isDefaultArg ()) {
655
if (arg->isDefaultArg () && arg->TemplateArg ()) {
552
copyTree (unit, arg->TemplateArg ());
657
copyTree (unit, arg->TemplateArg (), arg->TemplateArg ()->end_token ());
553
658
} else if (arg->Value ()) {
554
659
unit << " = " << *(arg->Value ());
556
661
unit << ";\n" << endu;
560
665
// check for a template parameter in the class name -> desturbs
561
666
Array<CTree*> desturbing;
562
667
if (ObjectInfo ()->Tree ()->NodeName () == CT_ClassDef::NodeId ()) {
566
671
CT_MembList *members = clsdef->Members ();
567
672
if (members) { // normally true, but in case of parse errors (?) ...
568
673
for (int i = 0; i < members->Entries (); i++) {
569
if (members->Entry (i)->NodeName () == CT_FctDef::NodeId ()) {
570
CT_FctDef *fctdef = (CT_FctDef*)members->Entry (i);
571
CT_SimpleName *nm =((CT_Declarator*)fctdef->Declarator ())->Name ();
572
if (nm->NodeName () == CT_TemplateName::NodeId ())
573
desturbing.append (((CT_TemplateName*)nm)->Arguments ());
674
if (members->Entry (i)->NodeName () == CT_FctDef::NodeId ()) {
675
CT_FctDef *fctdef = (CT_FctDef*)members->Entry (i);
676
CT_SimpleName *nm =((CT_Declarator*)fctdef->Declarator ())->Name ();
677
if (nm->NodeName () == CT_TemplateName::NodeId ())
678
desturbing.append (((CT_TemplateName*)nm)->Arguments ());
579
684
// copy the object declaration without the template header
580
685
if (TemplateInfo ()->Tree ()) {
581
copyTree (unit, TemplateInfo ()->Tree ()->Declaration (), false, &desturbing);
686
CTree* decl = TemplateInfo ()->Tree ()->Declaration ();
687
copyTree (unit, decl, decl->end_token(), &desturbing);
584
690
unit << "\n" << endu;
586
692
if (TRACE_INSTANCE_CODE) {
587
cout << "\ninstantiation unit: " << unit.name () << endl;
694
if (PointOfInstantiation ()) {
695
cout << getPoiToken()->location () << ": ";
697
cout << unit.name ();
698
if (instance && instance->Scope () && instance->Scope ()->Scope ()) {
699
cout << ": instantiated in scope " << instance->Scope ()->Scope ()->QualName (true);
702
if (TemplateInfo ()->Tree () && TemplateInfo ()->Tree ()->token () && TemplateInfo ()->ObjectInfo ()) {
703
cout << TemplateInfo ()->Tree ()->token ()->location () << ": instantiation of template "
704
<< TemplateInfo ()->ObjectInfo ()->QualName (true) << endl;
588
706
cout << "-------------------" << endl;
589
707
unit.print (cout);
590
cout << "\n-------------------\n" << endl;
708
cout << "-------------------\n" << endl;
595
void CCInstantiation::genArgType (CUnit &unit, CTree *tree, CTree *pname, const char *name) {
596
// replace private name with name of the current template parameter
713
void CCInstantiation::copyTree (CUnit &unit, CTree *tree, CTree *sn, const char *name, bool make_const) {
714
// replace name with name of the current template parameter
719
if (sn->NodeName () == CT_PrivateName::NodeId ())
599
721
// replace template template parameter by its deduced value
600
722
} else if (tree->NodeName () == CT_SimpleName::NodeId ()) {
601
replaceName (unit, (CT_SimpleName*)tree, true);
723
replaceName (unit, (CT_SimpleName*)tree, 0);
604
726
} else if (tree->NodeName () == CT_Token::NodeId ()) {
606
unit << tree->token ()->text () << " ";
727
Token* t = tree->token ();
730
Token* next = t->unit()->next(t);
731
if (next && (next->is_whitespace() || next->is_comment()))
732
unit << (next->is_whitespace() ? next->text() : " ");
609
738
for (unsigned i = 0; i < (unsigned)tree->Sons (); i++) {
610
genArgType (unit, tree->Son (i), pname, name);
739
copyTree (unit, tree->Son (i), sn, name, make_const);
742
if (tree->NodeName () == CT_TemplateName::NodeId ()) {
743
extendTemplateName (unit, (CT_TemplateName*)tree);
615
void CCInstantiation::copyTree (CUnit &unit, CTree *tree, bool gen_spaces,
616
Array<CTree*> *desturbing) {
617
// first check if this subtree is desturbing and should
748
void CCInstantiation::copyTree (CUnit &unit, CTree *tree, Token* end_token, Array<CTree*> *desturbing) {
749
// first check if this subtree is disturbing and should
618
750
// be omitted in the generated unit
620
752
for (int i = 0; i < desturbing->length (); i++)
621
753
if (desturbing->lookup (i) == tree)
622
754
return; // prune here
624
756
// replace template template parameter by its deduced value
625
757
if (tree->NodeName () == CT_SimpleName::NodeId ()) {
626
replaceName (unit, (CT_SimpleName*)tree, gen_spaces);
758
replaceName (unit, (CT_SimpleName*)tree, end_token);
629
761
} else if (tree->NodeName () == CT_Token::NodeId ()) {
630
if (tree->token ()) {
631
unit << tree->token ()->text () << " ";
762
Token* t = tree->token ();
765
if (t != end_token) {
766
Token* next = t->unit()->next(t);
767
if (next && (next->is_whitespace() || next->is_comment()))
768
unit << (next->is_whitespace() ? next->text() : " ");
635
for (unsigned i = 0; i < (unsigned)tree->Sons (); i++)
636
copyTree (unit, tree->Son (i), gen_spaces, desturbing);
638
// function bodies might be error nodes, because they were skipped
639
// ==> replace by ';'
640
776
if (tree->NodeName () == CT_FctDef::NodeId ()) {
641
if (((CT_FctDef*)tree)->Body ()->NodeName () == CT_Error::NodeId ()) {
648
void CCInstantiation::replaceName (CUnit &unit, CT_SimpleName *name, bool gen_spaces) {
777
body = ((CT_FctDef*)tree)->Body ();
780
for (unsigned i = 0; i < (unsigned)tree->Sons (); i++) {
781
CTree* son = tree->Son (i);
782
if (body && body == son) {
783
if (body->NodeName () == CT_Error::NodeId ()) {
784
// if function body is error node => replace by ';'
787
// don't instantiate function body, instantiated on demand
792
copyTree (unit, tree->Son (i), end_token, desturbing);
795
if (tree->NodeName () == CT_TemplateName::NodeId ()) {
796
extendTemplateName (unit, (CT_TemplateName*)tree);
801
void CCInstantiation::extendTemplateName (CUnit &unit, CT_TemplateName *name) {
802
CObjectInfo *info = name->TemplateName ()->Object ();
804
// is template template parameter?
805
CTemplateParamInfo *pinfo = info->TemplateParamInfo ();
806
if (pinfo && pinfo->isTemplate ()) {
807
// which template parameter is it?
808
int pos = First ().getPosition (pinfo);
810
// extend the template name
811
unit << "::__puma_redirect ";
818
void CCInstantiation::replaceName (CUnit &unit, CT_SimpleName *name, Token *end_token) {
649
819
bool replaced = false;
651
821
CObjectInfo *info = name->Object ();
655
825
if (pinfo && pinfo->isTemplate ()) {
656
826
// which template parameter is it?
657
827
int pos = First ().getPosition (pinfo);
828
if (pos != -1 && name->Parent ()->NodeName () != CT_TemplateName::NodeId ()) {
659
829
// get deduced argument for this parameter and insert it here
660
830
DeducedArgument *darg = DeducedArg (pos);
661
831
if (darg->TemplateArg ()) {
662
copyTree (unit, darg->TemplateArg (), gen_spaces);
832
copyTree (unit, darg->TemplateArg (), end_token);
665
replaced = dumpDeducedArg (darg, unit);
835
replaced = darg->Type() || darg->Value();
836
unit << *darg << " ";
670
841
// not replaced, so copy it as it is
671
842
if (! replaced) {
672
copyTree (unit, name->token_node (), gen_spaces);
677
CStructure *CCInstantiation::makeScope () {
680
// create namespace name
681
std::ostringstream sname;
682
sname << "%" << ObjectInfo ()->Name ();
683
listArguments (*base_candidate, sname);
685
// if (current_scope)
686
// scope = current_scope->newNamespace ();
688
scope = TemplateInfo ()->Parent ()->newNamespace ();
689
scope->NamespaceInfo ()->aroundInstantiation (true);
690
scope->Name (sname.str ().c_str ());
691
scope->TypeInfo (&CTYPE_UNDEFINED);
692
scope->SemDB (ObjectInfo ()->SemDB ());
693
scope->SourceInfo ()->FileInfo (ObjectInfo ()->SourceInfo ()->FileInfo ());
694
scope->SourceInfo ()->StartToken (PointOfInstantiation ()->token_node ());
699
void CCInstantiation::listArguments (InstantiationCandidate &cand, std::ostringstream &out) {
701
for (unsigned i = 0; i < cand.DeducedArgs (); i++) {
702
DeducedArgument *arg = cand.DeducedArg (i);
703
// do not list default arguments
704
if (arg->isDefaultArg ())
708
dumpDeducedArg (arg, out);
714
bool CCInstantiation::dumpDeducedArg (DeducedArgument *arg, std::ostringstream &out) {
716
arg->Type ()->TypeText (out);
717
} else if (arg->Value ()) {
718
out << *(arg->Value ());
726
CT_SimpleName *CCInstantiation::getSimpleName () {
727
if (PointOfInstantiation ()->NodeName () == CT_SimpleName::NodeId () ||
728
PointOfInstantiation ()->NodeName () == CT_QualName::NodeId () ||
729
PointOfInstantiation ()->NodeName () == CT_RootQualName::NodeId () ||
730
PointOfInstantiation ()->NodeName () == CT_TemplateName::NodeId () ||
731
PointOfInstantiation ()->NodeName () == CT_OperatorName::NodeId () ||
732
PointOfInstantiation ()->NodeName () == CT_SpecialName::NodeId () ||
733
PointOfInstantiation ()->NodeName () == CT_PrivateName::NodeId () ||
734
PointOfInstantiation ()->NodeName () == CT_DestructorName::NodeId () ||
735
PointOfInstantiation ()->NodeName () == CT_ConversionName::NodeId ())
736
return (CT_SimpleName*)PointOfInstantiation ();
737
return (CT_SimpleName*)0;
843
for (unsigned i = 0; i < (unsigned)name->Sons (); i++) {
844
copyTree (unit, name->Son (i), end_token);