1 /******************************************************************************
2 * Copyright (c) 2000-2016 Ericsson Telecom AB
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
13 ******************************************************************************/
14 #include "CompType.hh"
16 #include "ttcn3/AST_ttcn3.hh"
17 #include "ttcn3/Attributes.hh"
19 // implemented in comptype_attrib_la.l
20 extern void parseExtendsCompTypeRefList(Ttcn::AttributeSpec
const& attrib
,
21 Common::CompTypeRefList
*& attr_comp_refs
);
25 // =================================
26 // ===== ComponentTypeBody
27 // =================================
29 ComponentTypeBody::~ComponentTypeBody()
31 for(size_t i
= 0; i
< def_v
.size(); i
++) delete def_v
[i
];
34 delete attr_extends_refs
;
40 ComponentTypeBody
*ComponentTypeBody::clone() const
42 FATAL_ERROR("ComponentTypeBody::clone()");
45 void ComponentTypeBody::set_fullname(const string
& p_fullname
)
47 Scope::set_fullname(p_fullname
);
48 for(size_t i
= 0; i
< def_v
.size(); i
++) {
49 Ttcn::Definition
*def
= def_v
[i
];
50 def
->set_fullname(p_fullname
+ "." + def
->get_id().get_dispname());
53 extends_refs
->set_fullname(p_fullname
+".<extends>");
54 if (attr_extends_refs
)
55 attr_extends_refs
->set_fullname(get_fullname()+".<extends attribute>");
58 void ComponentTypeBody::set_my_scope(Scope
*p_scope
)
60 set_parent_scope(p_scope
);
61 if (extends_refs
) extends_refs
->set_my_scope(p_scope
);
62 if (attr_extends_refs
) attr_extends_refs
->set_my_scope(p_scope
);
65 void ComponentTypeBody::add_extends(CompTypeRefList
*p_crl
)
67 if (extends_refs
|| !p_crl
|| check_state
!=CHECK_INITIAL
)
68 FATAL_ERROR("ComponentTypeBody::add_extends()");
72 bool ComponentTypeBody::is_compatible(ComponentTypeBody
*other
)
74 if (other
==this) return true;
76 other
->chk(CHECK_EXTENDS
);
77 // a component with no definitions is compatible with all components
78 if (def_v
.size()==0 && !extends_refs
&& !attr_extends_refs
) return true;
79 return other
->compatible_m
.has_key(this);
82 void ComponentTypeBody::add_ass(Ttcn::Definition
*p_ass
)
84 if (check_state
!=CHECK_INITIAL
|| !p_ass
)
85 FATAL_ERROR("ComponentTypeBody::add_ass()");
86 p_ass
->set_my_scope(this);
90 bool ComponentTypeBody::has_local_ass_withId(const Identifier
& p_id
)
93 return all_defs_m
.has_key(p_id
.get_name());
96 Assignment
* ComponentTypeBody::get_local_ass_byId(const Identifier
& p_id
)
99 return all_defs_m
[p_id
.get_name()];
102 size_t ComponentTypeBody::get_nof_asss()
105 return all_defs_m
.size();
108 bool ComponentTypeBody::has_ass_withId(const Identifier
& p_id
)
110 if (has_local_ass_withId(p_id
)) return true;
111 else if (parent_scope
) return parent_scope
->has_ass_withId(p_id
);
115 Assignment
* ComponentTypeBody::get_ass_byIndex(size_t p_i
)
118 return all_defs_m
.get_nth_elem(p_i
);
121 bool ComponentTypeBody::is_own_assignment(const Assignment
* p_ass
)
123 for(size_t i
= 0; i
< def_v
.size(); i
++) {
124 if (def_v
[i
] == p_ass
) return true;
129 Assignment
* ComponentTypeBody::get_ass_bySRef(Ref_simple
*p_ref
)
131 if (!p_ref
|| !parent_scope
)
132 FATAL_ERROR("ComponentTypeBody::get_ass_bySRef()");
133 if (!p_ref
->get_modid()) {
134 const Identifier
*id
= p_ref
->get_id();
135 if (id
&& has_local_ass_withId(*id
)) {
136 Assignment
* ass
= get_local_ass_byId(*id
);
137 if (!ass
) FATAL_ERROR("ComponentTypeBody::get_ass_bySRef()");
139 for(size_t i
= 0; i
< def_v
.size(); i
++) {
140 if (def_v
[i
] == ass
) return ass
;
143 if (ass
->get_visibility() == PUBLIC
) {
147 p_ref
->error("The member definition `%s' in component type `%s'"
148 " is not visible in this scope", id
->get_dispname().c_str(),
149 comp_id
->get_dispname().c_str());
153 return parent_scope
->get_ass_bySRef(p_ref
);
156 void ComponentTypeBody::dump(unsigned level
) const
159 DEBUG(level
, "Extends references:");
160 extends_refs
->dump(level
+1);
162 DEBUG(level
, "Definitions: (%lu pcs.)", (unsigned long) def_v
.size());
163 for(size_t i
= 0; i
< def_v
.size(); i
++) def_v
[i
]->dump(level
+ 1);
164 if (attr_extends_refs
) {
165 DEBUG(level
, "Extends attribute references:");
166 attr_extends_refs
->dump(level
+1);
170 // read out the contents of the with attribute extension,
171 // parse it to the the attr_extends_refs member variable,
172 // collects all extends components from all attributes along the attrib path
173 void ComponentTypeBody::chk_extends_attr()
175 if (check_state
>=CHECK_WITHATTRIB
) return;
176 check_state
= CHECK_WITHATTRIB
;
177 Ttcn::WithAttribPath
* w_attrib_path
= my_type
->get_attrib_path();
180 vector
<Ttcn::SingleWithAttrib
> const &real_attribs
=
181 w_attrib_path
->get_real_attrib();
182 for (size_t i
= 0; i
< real_attribs
.size(); i
++)
184 Ttcn::SingleWithAttrib
*act_attr
= real_attribs
[i
];
185 if (act_attr
->get_attribKeyword()==Ttcn::SingleWithAttrib::AT_EXTENSION
)
186 parseExtendsCompTypeRefList(act_attr
->get_attribSpec(),
190 if (attr_extends_refs
)
192 attr_extends_refs
->set_fullname(get_fullname()+".<extends attribute>");
193 attr_extends_refs
->set_my_scope(parent_scope
);
197 void ComponentTypeBody::chk_recursion(ReferenceChain
& refch
)
199 if (refch
.add(get_fullname())) {
200 if (extends_refs
) extends_refs
->chk_recursion(refch
);
201 if (attr_extends_refs
) attr_extends_refs
->chk_recursion(refch
);
205 // contained components must already be checked,
206 // having valid compatible_m maps
207 void ComponentTypeBody::init_compatibility(CompTypeRefList
*crl
,
208 bool is_standard_extends
)
210 for (size_t i
= 0; i
< crl
->get_nof_comps(); i
++)
212 ComponentTypeBody
*cb
= crl
->get_nth_comp_body(i
);
213 if (!compatible_m
.has_key(cb
))
214 compatible_m
.add(cb
, is_standard_extends
? cb
: NULL
);
215 // compatible with all components which are compatible with the compatible
217 for (size_t j
= 0; j
< cb
->compatible_m
.size(); j
++)
219 ComponentTypeBody
*ccb
= cb
->compatible_m
.get_nth_key(j
);
220 ComponentTypeBody
*ccbval
= cb
->compatible_m
.get_nth_elem(j
);
221 if (!compatible_m
.has_key(ccb
))
222 compatible_m
.add(ccb
, is_standard_extends
? ccbval
: NULL
);
227 void ComponentTypeBody::chk_extends()
229 if (check_state
>=CHECK_EXTENDS
) return;
230 check_state
= CHECK_EXTENDS
;
231 // check the references in component extends parts (keyword and attribute)
232 if (extends_refs
) extends_refs
->chk(CHECK_EXTENDS
);
233 if (attr_extends_refs
) attr_extends_refs
->chk(CHECK_EXTENDS
);
234 // check for circular reference chains
235 ReferenceChain
refch(this, "While checking component type extensions");
236 chk_recursion(refch
);
237 // build compatibility map for faster is_compatible() and generate_code()
238 // contained components must already have valid compatible_m map
239 // keys used in is_compatible(), values used in generate_code()
240 if (extends_refs
) init_compatibility(extends_refs
, true);
241 if (attr_extends_refs
) init_compatibility(attr_extends_refs
, false);
244 void ComponentTypeBody::collect_defs_from_standard_extends()
246 Assignments
*module_defs
= parent_scope
->get_scope_asss();
247 for (size_t i
= 0; i
< extends_refs
->get_nof_comps(); i
++) {
248 ComponentTypeBody
*parent
= extends_refs
->get_nth_comp_body(i
);
249 // iterate through all definitions of the parent
250 // parent is already checked (has it's inherited defs included)
251 for (size_t j
= 0; j
< parent
->all_defs_m
.size(); j
++) {
252 Ttcn::Definition
*def
= parent
->all_defs_m
.get_nth_elem(j
);
253 const Identifier
& id
= def
->get_id();
254 const string
& name
= id
.get_name();
255 if (all_defs_m
.has_key(name
)) {
256 Ttcn::Definition
*my_def
= all_defs_m
[name
];
258 // it is not the same definition inherited on two paths
259 const char *dispname_str
= id
.get_dispname().c_str();
260 if (my_def
->get_my_scope() == this) {
261 my_def
->error("Local definition `%s' collides with definition "
262 "inherited from component type `%s'", dispname_str
,
263 def
->get_my_scope()->get_fullname().c_str());
264 def
->note("Inherited definition of `%s' is here", dispname_str
);
266 error("Definition `%s' inherited from component type `%s' "
267 "collides with definition inherited from `%s'", dispname_str
,
268 def
->get_my_scope()->get_fullname().c_str(),
269 my_def
->get_my_scope()->get_fullname().c_str());
270 def
->note("Definition of `%s' in `%s' is here", dispname_str
,
271 def
->get_my_scope()->get_fullname().c_str());
272 my_def
->note("Definition of `%s' in `%s' is here", dispname_str
,
273 my_def
->get_my_scope()->get_fullname().c_str());
277 all_defs_m
.add(name
, def
);
278 if (def
->get_my_scope()->get_scope_mod() !=
279 module_defs
->get_scope_mod()) {
280 // def comes from another module
281 if (module_defs
->has_local_ass_withId(id
)) {
282 const char *dispname_str
= id
.get_dispname().c_str();
283 error("The name of inherited definition `%s' is not unique in "
284 "the scope hierarchy", dispname_str
);
285 module_defs
->get_local_ass_byId(id
)->note("Symbol `%s' is "
286 "already defined here in a higher scope unit", dispname_str
);
287 def
->note("Definition `%s' inherited from component type `%s' "
288 "is here", dispname_str
,
289 def
->get_my_scope()->get_fullname().c_str());
290 } else if (module_defs
->is_valid_moduleid(id
)) {
291 def
->warning("Inherited definition with name `%s' hides a "
292 "module identifier", id
.get_dispname().c_str());
300 void ComponentTypeBody::collect_defs_from_attribute_extends()
302 for (size_t i
= 0; i
< attr_extends_refs
->get_nof_comps(); i
++) {
303 ComponentTypeBody
*parent
= attr_extends_refs
->get_nth_comp_body(i
);
304 // iterate through all definitions of the parent
305 // parent is already checked (has it's inherited defs included)
306 for (size_t j
= 0; j
< parent
->all_defs_m
.size(); j
++) {
307 Ttcn::Definition
*def
= parent
->all_defs_m
.get_nth_elem(j
);
308 const Identifier
& id
= def
->get_id();
309 const char *dispname_str
= id
.get_dispname().c_str();
310 const string
& name
= id
.get_name();
311 // the definition to be imported must be already in the all_defs_m map
312 // and must belong to owner (not be inherited)
313 // orig_defs_map contains backed up own definitions
314 if (all_defs_m
.has_key(name
)) {
315 Ttcn::Definition
*my_def
= all_defs_m
[name
];
316 if (my_def
->get_my_scope() == this) {
317 // my_def is a local definition
318 if (orig_defs_m
.has_key(name
)) FATAL_ERROR( \
319 "ComponentTypeBody::collect_defs_from_attribute_extends()");
320 orig_defs_m
.add(name
, my_def
); // backup for init
321 all_defs_m
[name
] = def
; // point to inherited def
323 // my_def comes from another component type
324 // exclude case when the same definition is inherited on different
325 // paths, there must be a local definition
326 if (def
!=my_def
|| !orig_defs_m
.has_key(name
)) {
327 error("Definition `%s' inherited from component type `%s' "
328 "collides with definition inherited from `%s'", dispname_str
,
329 def
->get_my_scope()->get_fullname().c_str(),
330 my_def
->get_my_scope()->get_fullname().c_str());
331 def
->note("Definition of `%s' in `%s' is here",
332 dispname_str
, def
->get_my_scope()->get_fullname().c_str());
333 my_def
->note("Definition of `%s' in `%s' is here",
334 dispname_str
, my_def
->get_my_scope()->get_fullname().c_str());
335 if (orig_defs_m
.has_key(name
)) {
336 // the same definition is also present locally
337 orig_defs_m
[name
]->note("Local definition of `%s' is here",
343 error("Missing local definition of `%s', which was inherited from "
344 "component type `%s'", dispname_str
,
345 def
->get_my_scope()->get_fullname().c_str());
346 def
->note("Inherited definition of `%s' is here", dispname_str
);
352 void ComponentTypeBody::chk_defs_uniq()
354 if (check_state
>=CHECK_DEFUNIQ
) return;
355 check_state
= CHECK_DEFUNIQ
;
356 if (extends_refs
) extends_refs
->chk(CHECK_DEFUNIQ
);
357 if (attr_extends_refs
) attr_extends_refs
->chk(CHECK_DEFUNIQ
);
358 size_t nof_defs
= def_v
.size();
360 Error_Context
cntxt(this, "While checking uniqueness of component "
361 "element definitions");
362 Assignments
*module_defs
= parent_scope
->get_scope_asss();
363 // add own definitions to all_def_m
364 for (size_t i
= 0; i
< nof_defs
; i
++) {
365 Ttcn::Definition
*def
= def_v
[i
];
366 const Identifier
& id
= def
->get_id();
367 const string
& name
= id
.get_name();
368 if (all_defs_m
.has_key(name
)) {
369 const char *dispname_str
= id
.get_dispname().c_str();
370 def
->error("Duplicate definition with name `%s'", dispname_str
);
371 all_defs_m
[name
]->note("Previous definition of `%s' is here",
374 all_defs_m
.add(name
, def
);
375 if (module_defs
->has_local_ass_withId(id
)) {
376 const char *dispname_str
= id
.get_dispname().c_str();
377 def
->error("Component element name `%s' is not unique in the "
378 "scope hierarchy", dispname_str
);
379 module_defs
->get_local_ass_byId(id
)->note("Symbol `%s' is "
380 "already defined here in a higher scope unit", dispname_str
);
381 } else if (module_defs
->is_valid_moduleid(id
)) {
382 def
->warning("Definition with name `%s' hides a module identifier",
383 id
.get_dispname().c_str());
388 if (extends_refs
|| attr_extends_refs
) {
389 // collect all inherited definitions
390 Error_Context
cntxt(this, "While checking uniqueness of inherited "
391 "component element definitions");
392 if (extends_refs
) collect_defs_from_standard_extends();
393 if (attr_extends_refs
) collect_defs_from_attribute_extends();
397 void ComponentTypeBody::chk_my_defs()
399 if (check_state
>=CHECK_OWNDEFS
) return;
400 check_state
= CHECK_OWNDEFS
;
401 Error_Context
cntxt(this, "In component element definitions");
402 for (size_t i
= 0; i
< def_v
.size(); i
++) def_v
[i
]->chk();
405 void ComponentTypeBody::chk_attr_ext_defs()
407 if (check_state
>=CHECK_EXTDEFS
) return;
408 check_state
= CHECK_EXTDEFS
;
409 size_t nof_inherited_defs
= orig_defs_m
.size();
410 if (nof_inherited_defs
> 0) {
411 Error_Context
cntxt(this, "While checking whether the local and "
412 "inherited component element definitions are identical");
413 // for definitions inherited with attribute extends check if
414 // local and inherited definitions are identical
415 for (size_t i
= 0; i
< nof_inherited_defs
; i
++) {
416 const string
& key
= orig_defs_m
.get_nth_key(i
);
417 Ttcn::Definition
*original_def
= orig_defs_m
.get_nth_elem(i
);
418 Ttcn::Definition
*inherited_def
= all_defs_m
[key
];
419 if (!original_def
->chk_identical(inherited_def
))
420 all_defs_m
[key
] = original_def
;
425 void ComponentTypeBody::chk(check_state_t required_check_state
)
427 if (checking
|| check_state
==CHECK_FINAL
) return;
433 if (required_check_state
==CHECK_WITHATTRIB
) break;
435 case CHECK_WITHATTRIB
:
437 if (required_check_state
==CHECK_EXTENDS
) break;
441 if (required_check_state
==CHECK_DEFUNIQ
) break;
445 if (required_check_state
==CHECK_OWNDEFS
) break;
449 if (required_check_state
==CHECK_EXTDEFS
) break;
452 check_state
= CHECK_FINAL
;
457 FATAL_ERROR("ComponentTypeBody::chk()");
462 void ComponentTypeBody::set_genname(const string
& prefix
)
464 for (size_t i
= 0; i
< def_v
.size(); i
++) {
465 Ttcn::Definition
*def
= def_v
[i
];
466 def
->set_genname(prefix
+ def
->get_id().get_name());
471 void ComponentTypeBody::generate_code(output_struct
* target
)
473 if (check_state
!= CHECK_FINAL
|| !comp_id
)
474 FATAL_ERROR("ComponentTypeBody::generate_code()");
475 // beginning of block in init_comp
476 target
->functions
.init_comp
= mputprintf(target
->functions
.init_comp
,
477 "if (!strcmp(component_type, \"%s\")) {\n",
478 comp_id
->get_dispname().c_str());
480 // call init_comp for all components which are compatible
481 // with this component along standard extends paths
483 bool has_base_comps
= false;
484 for (size_t i
= 0; i
< compatible_m
.size(); i
++) {
485 ComponentTypeBody
*cb
= compatible_m
.get_nth_elem(i
);
486 // recursive initialization is needed if the component type is
487 // inherited using the standard "extends" mechanism and the component
488 // type has its own definitions
489 if (cb
&& cb
->def_v
.size() > 0) {
490 if (!has_base_comps
) {
491 target
->functions
.init_comp
= mputstr(target
->functions
.init_comp
,
492 "if (init_base_comps) {\n");
493 has_base_comps
= true;
495 const char *ct_dispname_str
= cb
->get_id()->get_dispname().c_str();
496 Module
*ct_mod
= cb
->get_scope_mod_gen();
497 if (ct_mod
== get_scope_mod_gen()) {
498 // the other component type is in the same module
499 // call the initializer function recursively
500 target
->functions
.init_comp
= mputprintf(
501 target
->functions
.init_comp
, "init_comp_type(\"%s\", FALSE);\n",
504 // the other component type is imported from another module
505 // use the module list for initialization
506 target
->functions
.init_comp
= mputprintf(
507 target
->functions
.init_comp
,
508 "Module_List::initialize_component(\"%s\", \"%s\", FALSE);\n",
509 ct_mod
->get_modid().get_dispname().c_str(), ct_dispname_str
);
513 if (has_base_comps
) {
514 // closing of the if() above
515 target
->functions
.init_comp
= mputstr(target
->functions
.init_comp
,
520 // code generation for embedded definitions
521 size_t nof_defs
= def_v
.size();
522 for (size_t i
= 0; i
< nof_defs
; i
++) {
523 Ttcn::Definition
*def
= def_v
[i
];
524 const string
& name
= def
->get_id().get_name();
525 if (orig_defs_m
.has_key(name
)) {
526 // def is hidden by an inherited definiton
527 // only an initializer shall be generated
528 target
->functions
.init_comp
= def
->generate_code_init_comp(
529 target
->functions
.init_comp
, all_defs_m
[name
]);
531 // def is a normal (non-inherited) definition
532 def
->generate_code(target
, true);
536 // end of block in init_comp
537 target
->functions
.init_comp
= mputstr(target
->functions
.init_comp
,
542 char *ComponentTypeBody::generate_code_comptype_name(char *str
)
545 FATAL_ERROR("ComponentTypeBody::generate_code_comtype_name()");
546 return mputprintf(str
, "\"%s\", \"%s\"",
547 parent_scope
->get_scope_mod_gen()->get_modid().get_dispname().c_str(),
548 comp_id
->get_dispname().c_str());
551 void ComponentTypeBody::set_parent_path(Ttcn::WithAttribPath
* p_path
) {
552 for (size_t i
= 0; i
< def_v
.size(); i
++)
553 def_v
[i
]->set_parent_path(p_path
);
556 // =================================
557 // ===== CompTypeRefList
558 // =================================
560 CompTypeRefList::~CompTypeRefList()
562 for (size_t i
=0; i
<comp_ref_v
.size(); i
++) delete comp_ref_v
[i
];
568 CompTypeRefList
*CompTypeRefList::clone() const
570 FATAL_ERROR("CompTypeRefList::clone()");
573 void CompTypeRefList::add_ref(Ttcn::Reference
*p_ref
)
575 if (!p_ref
|| checked
) FATAL_ERROR("CompTypeRefList::add_ref()");
576 comp_ref_v
.add(p_ref
);
579 void CompTypeRefList::dump(unsigned level
) const
581 for(size_t i
= 0; i
< comp_ref_v
.size(); i
++) comp_ref_v
[i
]->dump(level
+1);
584 void CompTypeRefList::set_fullname(const string
& p_fullname
)
586 Node::set_fullname(p_fullname
);
587 for (size_t i
=0; i
<comp_ref_v
.size(); i
++)
588 comp_ref_v
[i
]->set_fullname(p_fullname
+ ".<ref" + Int2string(i
+1) + ">");
591 void CompTypeRefList::chk_uniq()
595 for (size_t i
= 0; i
< comp_ref_v
.size(); i
++)
597 Ttcn::Reference
*ref
= comp_ref_v
[i
];
598 Type
*type
= ref
->chk_comptype_ref();
601 // add the component body to the map or error if it's duplicate
602 ComponentTypeBody
*cb
= type
->get_CompBody();
605 if (comp_body_m
.has_key(cb
))
607 const string
& type_name
= type
->get_typename();
608 const char *name
= type_name
.c_str();
609 ref
->error("Duplicate reference to component with name `%s'", name
);
610 comp_body_m
[cb
]->note("Previous reference to `%s' is here", name
);
614 // map and vector must always have same content
615 comp_body_m
.add(cb
, ref
);
623 void CompTypeRefList::chk(ComponentTypeBody::check_state_t
624 required_check_state
)
627 for (size_t i
=0; i
<comp_body_v
.size(); i
++)
628 comp_body_v
[i
]->chk(required_check_state
);
631 void CompTypeRefList::chk_recursion(ReferenceChain
& refch
)
633 for (size_t i
= 0; i
< comp_body_v
.size(); i
++) {
635 comp_body_v
[i
]->chk_recursion(refch
);
640 void CompTypeRefList::set_my_scope(Scope
*p_scope
)
642 for (size_t i
=0; i
<comp_ref_v
.size(); i
++)
643 comp_ref_v
[i
]->set_my_scope(p_scope
);
646 size_t CompTypeRefList::get_nof_comps()
648 if (!checked
) chk_uniq();
649 return comp_body_v
.size();
652 ComponentTypeBody
*CompTypeRefList::get_nth_comp_body(size_t i
)
654 if (!checked
) chk_uniq();
655 return comp_body_v
[i
];
658 Ttcn::Reference
*CompTypeRefList::get_nth_comp_ref(size_t i
)
660 if (!checked
) chk_uniq();
661 return comp_body_m
[comp_body_v
[i
]];
664 bool CompTypeRefList::has_comp_body(ComponentTypeBody
*cb
)
666 if (!checked
) chk_uniq();
667 return comp_body_m
.has_key(cb
);
670 } /* namespace Common */