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
16 * Szabo, Janos Zoltan – initial implementation
17 * Zalanyi, Balazs Andor
19 ******************************************************************************/
20 #include "Attributes.hh"
22 #include "../CompilerError.hh"
25 #include "TtcnTemplate.hh"
29 // ==== Qualifier ====
31 Qualifier
* Qualifier::clone() const
33 return new Qualifier(*this);
36 const Identifier
* Qualifier::get_identifier(size_t p_index
) const
38 FieldOrArrayRef
* ref
= get_ref(p_index
);
39 return (ref
->get_type()==FieldOrArrayRef::FIELD_REF
) ?
44 Qualifier
* Qualifier::get_qualifier_without_first_id() const
46 Qualifier
* temp
= this->clone();
51 string
Qualifier::get_stringRepr() const
54 append_stringRepr(str_repr
);
55 if (str_repr
[0]=='.') str_repr
.replace(0, 1, ""); // remove leading dot if present
59 void Qualifier::dump(unsigned level
) const
61 const string
& rep
= get_stringRepr();
62 DEBUG(level
, "(%s)", rep
.c_str());
65 // ==== Qualifiers ====
67 Qualifiers::~Qualifiers()
69 for(size_t i
= 0; i
< qualifiers
.size(); i
++)
76 Qualifiers::Qualifiers(const Qualifiers
& p
)
79 for(size_t i
= 0; i
< p
.get_nof_qualifiers(); i
++)
81 qualifiers
.add(p
.get_qualifier(i
)->clone());
85 void Qualifiers::add_qualifier(Qualifier
* p_qualifier
)
87 if(p_qualifier
->get_nof_identifiers() > 0)
88 qualifiers
.add(p_qualifier
);
93 void Qualifiers::delete_qualifier(size_t p_index
)
95 delete qualifiers
[p_index
];
96 qualifiers
.replace(p_index
,1,NULL
);
99 const Qualifier
* Qualifiers::get_qualifier(size_t p_index
) const
101 return qualifiers
[p_index
];
104 Qualifiers
* Qualifiers::clone() const
106 return new Qualifiers(*this);
109 void Qualifiers::set_fullname(const string
& p_fullname
)
111 Node::set_fullname(p_fullname
);
112 for(size_t i
= 0; i
< qualifiers
.size(); i
++)
114 qualifiers
[i
]->set_fullname(p_fullname
+ ".<qualifier "
115 + Int2string(i
) + ">");
119 bool Qualifiers::has_qualifier(Qualifier
* p_qualifier
) const
124 for(size_t i
= 0; i
< qualifiers
.size() && !result
; i
++)
126 if(qualifiers
[i
]->get_nof_identifiers()
127 ==p_qualifier
->get_nof_identifiers())
131 while(index
< p_qualifier
->get_nof_identifiers() && same
)
133 same
= (*qualifiers
[i
]->get_identifier(index
)
134 == *p_qualifier
->get_identifier(index
));
144 void Qualifiers::dump(unsigned level
) const
146 DEBUG(level
, "has %lu qualifiers",
147 (unsigned long)get_nof_qualifiers());
148 for(size_t i
= 0; i
< qualifiers
.size(); i
++)
149 qualifiers
[i
]->dump(level
);
152 // ==== ErroneousDescriptor ====
154 ErroneousDescriptor::~ErroneousDescriptor()
156 for (size_t i
=0; i
<descr_m
.size(); i
++) delete descr_m
.get_nth_elem(i
);
158 for (size_t i
=0; i
<values_m
.size(); i
++) delete values_m
.get_nth_elem(i
);
162 // ==== ErroneousAttributeSpec ====
164 ErroneousAttributeSpec::ErroneousAttributeSpec(bool p_is_raw
, indicator_t p_indicator
, TemplateInstance
* p_tmpl_inst
, bool p_has_all_keyword
):
165 is_raw(p_is_raw
), has_all_keyword(p_has_all_keyword
), indicator(p_indicator
),
166 tmpl_inst(p_tmpl_inst
), type(0), value(0)
168 if (!tmpl_inst
) FATAL_ERROR("ErroneousAttributeSpec::ErroneousAttributeSpec()");
171 ErroneousAttributeSpec::ErroneousAttributeSpec(const ErroneousAttributeSpec
& p
)
172 : Node(p
), Location(p
), is_raw(p
.is_raw
), has_all_keyword(p
.has_all_keyword
),
173 indicator(p
.indicator
), type(0), value(0)
175 tmpl_inst
= p
.tmpl_inst
? tmpl_inst
->clone() : 0;
178 ErroneousAttributeSpec::~ErroneousAttributeSpec()
184 ErroneousAttributeSpec
* ErroneousAttributeSpec::clone() const
186 return new ErroneousAttributeSpec(*this);
189 void ErroneousAttributeSpec::set_fullname(const string
& p_fullname
)
191 Node::set_fullname(p_fullname
);
192 tmpl_inst
->set_fullname(p_fullname
+".<template_instance>");
195 void ErroneousAttributeSpec::set_my_scope(Scope
*p_scope
)
197 tmpl_inst
->set_my_scope(p_scope
);
200 void ErroneousAttributeSpec::dump(unsigned level
) const
202 DEBUG(level
, "raw: %s", is_raw
? "yes" : "no");
203 DEBUG(level
, "indicator:");
206 DEBUG(level
+1, "before");
209 DEBUG(level
+1, "value");
212 DEBUG(level
+1, "after");
215 DEBUG(level
+1, "<invalid>");
218 FATAL_ERROR("ErroneousAttributeSpec::dump()");
220 DEBUG(level
, "template instance:");
221 tmpl_inst
->dump(level
+1);
224 bool ErroneousAttributeSpec::get_is_omit() const
226 return (tmpl_inst
->get_Template()->get_templatetype()==Template::OMIT_VALUE
);
229 void ErroneousAttributeSpec::chk()
231 if (get_is_omit()) { // special case, no type needed
232 if ((indicator
==I_BEFORE
)||(indicator
==I_AFTER
)) {
233 if (!has_all_keyword
) {
235 "Keyword `all' is expected after `omit' when omitting all fields %s the specified field",
236 get_indicator_str(indicator
));
239 if (has_all_keyword
) {
241 "Unexpected `all' keyword after `omit' when omitting one field");
247 if (has_all_keyword
) {
249 "Unexpected `all' keyword after the in-line template");
252 // determine the type of the tmpl_inst
253 type
= tmpl_inst
->get_expr_governor(Type::EXPECTED_TEMPLATE
);
255 tmpl_inst
->get_Template()->set_lowerid_to_ref();
256 type
= tmpl_inst
->get_expr_governor(Type::EXPECTED_TEMPLATE
);
259 tmpl_inst
->error("Cannot determine the type of the in-line template");
263 Type
* type_last
= type
->get_type_refd_last();
264 if (!type_last
|| type_last
->get_typetype()==Type::T_ERROR
) {
269 switch (type_last
->get_typetype_ttcn3()) {
276 tmpl_inst
->error("An in-line template of type `%s' cannot be used as a `raw' erroneous value",
277 type_last
->get_typename().c_str());
281 if (tmpl_inst
->get_DerivedRef()) {
282 tmpl_inst
->error("Reference to a constant value was expected instead of an in-line modified template");
287 Template
* templ
= tmpl_inst
->get_Template();
289 if (templ
->is_Value()) {
290 value
= templ
->get_Value();
291 value
->set_my_governor(type
);
292 type
->chk_this_value_ref(value
);
293 type
->chk_this_value(value
, 0, Type::EXPECTED_CONSTANT
,
294 INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
, SUB_CHK
);
295 //{ FIXME: make this work
296 // ReferenceChain refch(type, "While checking embedded recursions");
297 // value->chk_recursions(refch);
299 value
->set_code_section(GovernedSimple::CS_PRE_INIT
);
301 tmpl_inst
->error("A specific value without matching symbols was expected");
307 const char* ErroneousAttributeSpec::get_indicator_str(indicator_t i
)
310 case I_BEFORE
: return "before";
311 case I_VALUE
: return "value";
312 case I_AFTER
: return "after";
313 default: FATAL_ERROR("ErroneousAttributeSpec::get_indicator_str()");
318 char* ErroneousAttributeSpec::generate_code_str(char *str
, char *& def
, string genname
, const bool embedded
)
320 if (get_is_omit()) return str
;
321 if (!type
) FATAL_ERROR("ErroneousAttributeSpec::generate_code_str()");
322 if (!value
) FATAL_ERROR("ErroneousAttributeSpec::generate_code_str()");
323 if (first_genname
.empty()) { // this is the first use
324 str
= mputprintf(str
, "%s%s %s;\n", split_to_slices
&& !embedded
? "" : "static ",
325 type
->get_genname_value(value
->get_my_scope()).c_str(), genname
.c_str());
326 first_genname
= genname
;
327 if (split_to_slices
&& !embedded
) {
328 def
= mputprintf(def
, "extern %s %s;\n",
329 type
->get_genname_value(value
->get_my_scope()).c_str(), genname
.c_str());
332 str
= mputprintf(str
, "%s%s& %s = %s;\n", split_to_slices
&& !embedded
? "" : "static ",
333 type
->get_genname_value(value
->get_my_scope()).c_str(),
334 genname
.c_str(), first_genname
.c_str());
339 char* ErroneousAttributeSpec::generate_code_init_str(char *str
, string genname
)
341 if (get_is_omit()) return str
;
342 if (!type
) FATAL_ERROR("ErroneousAttributeSpec::generate_code_init_str()");
343 if (!value
) FATAL_ERROR("ErroneousAttributeSpec::generate_code_init_str()");
344 str
= value
->generate_code_init(str
, genname
.c_str());
348 string
ErroneousAttributeSpec::get_typedescriptor_str()
350 if (get_is_omit() || is_raw
) return string("NULL");
351 if (!type
) FATAL_ERROR("ErroneousAttributeSpec::get_typedescriptor_str()");
352 if (!value
) FATAL_ERROR("ErroneousAttributeSpec::generate_code_ti_str()");
353 return ( "&" + type
->get_genname_typedescriptor(value
->get_my_scope()) + "_descr_" );
356 void ErroneousAttributeSpec::chk_recursions(ReferenceChain
& refch
)
360 value
->chk_recursions(refch
);
365 // ==== ErroneousValues ====
367 char* ErroneousValues::generate_code_embedded_str(char *str
, char *& def
, string genname
, const bool embedded
)
369 if (before
) str
= generate_code_embedded_str(str
, def
, genname
+"_before", before
, embedded
);
370 if (value
) str
= generate_code_embedded_str(str
, def
, genname
+"_value", value
, embedded
);
371 if (after
) str
= generate_code_embedded_str(str
, def
, genname
+"_after", after
, embedded
);
375 char* ErroneousValues::generate_code_embedded_str(char *str
, char *& def
, string genname
, ErroneousAttributeSpec
* attr_spec
, const bool embedded
)
377 str
= attr_spec
->generate_code_str(str
, def
, genname
+"_errval", embedded
);
378 str
= mputprintf(str
, "%sErroneous_value_t %s = { %s, %s, %s };\n", split_to_slices
&& !embedded
? "" : "static ", genname
.c_str(),
379 attr_spec
->get_is_raw() ? "true" : "false",
380 attr_spec
->get_is_omit() ? "NULL" : ("&"+genname
+"_errval").c_str(),
381 attr_spec
->get_typedescriptor_str().c_str());
382 if (split_to_slices
&& !embedded
) {
383 def
= mputprintf(def
, "extern Erroneous_value_t %s;\n", genname
.c_str());
388 char* ErroneousValues::generate_code_init_str(char *str
, string genname
)
390 if (before
) str
= before
->generate_code_init_str(str
, genname
+"_before_errval");
391 if (value
) str
= value
->generate_code_init_str(str
, genname
+"_value_errval");
392 if (after
) str
= after
->generate_code_init_str(str
, genname
+"_after_errval");
396 char* ErroneousValues::generate_code_struct_str(char *str
, string genname
, int field_index
)
398 str
= mputprintf(str
, "{ %d, %s, %s, %s, %s }", field_index
,
399 ("\""+field_name
+"\"").c_str(),
400 before
? ("&"+genname
+"_before").c_str() : "NULL",
401 value
? ("&"+genname
+"_value").c_str() : "NULL",
402 after
? ("&"+genname
+"_after").c_str() : "NULL");
406 void ErroneousValues::chk_recursions(ReferenceChain
& refch
)
408 if (before
) before
->chk_recursions(refch
);
409 if (value
) value
->chk_recursions(refch
);
410 if (after
) after
->chk_recursions(refch
);
413 // ==== ErroneousDescriptor ====
415 char* ErroneousDescriptor::generate_code_embedded_str(char *str
, char *& def
, string genname
, const bool embedded
)
418 for (size_t i
=0; i
<values_m
.size(); i
++) {
419 str
= values_m
.get_nth_elem(i
)->generate_code_embedded_str(str
, def
, genname
+"_v"+Int2string((int)values_m
.get_nth_key(i
)), embedded
);
421 // embedded descriptors
422 for (size_t i
=0; i
<descr_m
.size(); i
++) {
423 str
= descr_m
.get_nth_elem(i
)->generate_code_embedded_str(str
, def
, genname
+"_d"+Int2string((int)descr_m
.get_nth_key(i
)), embedded
);
426 if (values_m
.size()>0) {
427 str
= mputprintf(str
, "%sErroneous_values_t %s_valsvec[%d] = { ", split_to_slices
&& !embedded
? "" : "static ", genname
.c_str(), (int)values_m
.size());
428 for (size_t i
=0; i
<values_m
.size(); i
++) {
429 if (i
>0) str
= mputstr(str
, ", ");
430 int key_i
= (int)values_m
.get_nth_key(i
);
431 str
= values_m
.get_nth_elem(i
)->generate_code_struct_str(str
, genname
+"_v"+Int2string(key_i
), key_i
);
433 str
= mputstr(str
, " };\n");
434 if (split_to_slices
&& !embedded
) {
435 def
= mputprintf(def
, "extern Erroneous_values_t %s_valsvec[%d];\n", genname
.c_str(), (int)values_m
.size());
438 // embedded descriptor vector
439 if (descr_m
.size()>0) {
440 str
= mputprintf(str
, "%sErroneous_descriptor_t %s_embvec[%d] = { ", split_to_slices
&& !embedded
? "" : "static ", genname
.c_str(), (int)descr_m
.size());
441 for (size_t i
=0; i
<descr_m
.size(); i
++) {
442 if (i
>0) str
= mputstr(str
, ", ");
443 int key_i
= (int)descr_m
.get_nth_key(i
);
444 str
= descr_m
.get_nth_elem(i
)->generate_code_struct_str(str
, def
, genname
+"_d"+Int2string(key_i
), key_i
);
446 str
= mputstr(str
, " };\n");
447 if (split_to_slices
&& !embedded
) {
448 def
= mputprintf(def
, "extern Erroneous_descriptor_t %s_embvec[%d];\n", genname
.c_str(), (int)descr_m
.size());
454 char* ErroneousDescriptor::generate_code_init_str(char *str
, string genname
)
456 for (size_t i
=0; i
<values_m
.size(); i
++) {
457 str
= values_m
.get_nth_elem(i
)->generate_code_init_str(str
, genname
+"_v"+Int2string((int)values_m
.get_nth_key(i
)));
459 for (size_t i
=0; i
<descr_m
.size(); i
++) {
460 str
= descr_m
.get_nth_elem(i
)->generate_code_init_str(str
, genname
+"_d"+Int2string((int)descr_m
.get_nth_key(i
)));
465 char* ErroneousDescriptor::generate_code_struct_str(char *str
, char *& def
, string genname
, int field_index
)
467 string genname_values_vec
= genname
+ "_valsvec";
468 string genname_embedded_vec
= genname
+ "_embvec";
469 str
= mputprintf(str
, "{ %d, %d, %s, %d, %s, %d, %s, %d, %s }",
471 omit_before
, (omit_before
==-1)?"NULL":("\""+omit_before_name
+"\"").c_str(),
472 omit_after
, (omit_after
==-1)?"NULL":("\""+omit_after_name
+"\"").c_str(),
473 (int)values_m
.size(), (values_m
.size()>0) ? genname_values_vec
.c_str(): "NULL",
474 (int)descr_m
.size(), (descr_m
.size()>0) ? genname_embedded_vec
.c_str(): "NULL");
478 void ErroneousDescriptor::chk_recursions(ReferenceChain
& refch
)
480 for (size_t i
=0; i
<values_m
.size(); i
++) {
481 values_m
.get_nth_elem(i
)->chk_recursions(refch
);
484 for (size_t i
=0; i
<descr_m
.size(); i
++) {
485 descr_m
.get_nth_elem(i
)->chk_recursions(refch
);
489 char* ErroneousDescriptor::generate_code_str(char *str
, char *& def
, string genname
, const bool embedded
)
491 genname
+= "_err_descr";
492 str
= generate_code_embedded_str(str
, def
, genname
, embedded
);
493 str
= mputprintf(str
, "%sErroneous_descriptor_t %s = ", split_to_slices
&& !embedded
? "" : "static ", genname
.c_str());
494 str
= generate_code_struct_str(str
, def
, genname
, -1);
495 str
= mputstr(str
, ";\n");
496 if (split_to_slices
&& !embedded
) {
497 def
= mputprintf(def
, "extern Erroneous_descriptor_t %s;\n", genname
.c_str());
502 // ==== ErroneousAttributes ====
504 ErroneousAttributes::ErroneousAttributes(Type
* p_type
):
505 type(p_type
), err_descr_tree(NULL
)
507 if (!type
) FATAL_ERROR("ErroneousAttributes::ErroneousAttributes()");
510 ErroneousAttributes::~ErroneousAttributes()
512 for (size_t i
=0; i
<spec_vec
.size(); i
++) {
516 if (err_descr_tree
) delete err_descr_tree
;
519 ErroneousAttributes::ErroneousAttributes(const ErroneousAttributes
& p
)
520 : Node(p
), type(p
.type
), err_descr_tree(NULL
)
524 ErroneousAttributes
* ErroneousAttributes::clone() const
526 return new ErroneousAttributes(*this);
529 void ErroneousAttributes::set_fullname(const string
& p_fullname
)
531 Node::set_fullname(p_fullname
);
532 for (size_t i
=0; i
<spec_vec
.size(); i
++) {
533 spec_vec
[i
]->set_fullname(p_fullname
+".<erroneous_attr_spec_"+Int2string(i
)+">");
537 void ErroneousAttributes::dump(unsigned level
) const
539 DEBUG(level
, "erroneous attributes:");
540 for (size_t i
=0; i
<spec_vec
.size(); i
++) {
541 spec_vec
[i
]->dump(level
+1);
545 void ErroneousAttributes::add_spec(ErroneousAttributeSpec
* err_attr_spec
)
547 if (!err_attr_spec
) FATAL_ERROR("ErroneousAttributes::add_spec()");
548 spec_vec
.add(err_attr_spec
);
551 void ErroneousAttributes::add_pair(const Qualifier
* qualifier
, ErroneousAttributeSpec
* err_attr_spec
)
553 if (!qualifier
|| !err_attr_spec
) FATAL_ERROR("ErroneousAttributes::add()");
555 f
.qualifier
= qualifier
;
556 f
.err_attr
= err_attr_spec
;
560 void ErroneousAttributes::chk()
562 // check that encodings of erroneous type and templateinstance type match
563 for (size_t i
=0; i
<spec_vec
.size(); i
++) {
564 ErroneousAttributeSpec
* act_attr
= spec_vec
[i
];
565 Type
* ti_type
= act_attr
->get_type();
566 if ((act_attr
->get_indicator()!=ErroneousAttributeSpec::I_INVALID
) && ti_type
) {
567 if (act_attr
->get_is_raw()) {
568 switch (ti_type
->get_typetype_ttcn3()) {
570 if (!type
->has_encoding(Type::CT_PER
) && !type
->has_encoding(Type::CT_RAW
)) {
571 act_attr
->error("A `raw' %s value was used for erroneous type `%s' which has no RAW or PER encodings.",
572 ti_type
->get_typename().c_str(), type
->get_typename().c_str());
576 if (!type
->has_encoding(Type::CT_TEXT
) && !type
->has_encoding(Type::CT_XER
) &&
577 !type
->has_encoding(Type::CT_JSON
)) {
578 act_attr
->error("A `raw' %s value was used for erroneous type `%s' which has no TEXT, XER or JSON encodings.",
579 ti_type
->get_typename().c_str(), type
->get_typename().c_str());
583 if (!type
->has_encoding(Type::CT_XER
) && !type
->has_encoding(Type::CT_JSON
)) {
584 act_attr
->error("A `raw' %s value was used for erroneous type `%s' which has no XER or JSON encoding.",
585 ti_type
->get_typename().c_str(), type
->get_typename().c_str());
592 // the two types must have at least one common encoding
593 if (!((type
->has_encoding(Type::CT_BER
)&&ti_type
->has_encoding(Type::CT_BER
)) ||
594 (type
->has_encoding(Type::CT_PER
)&&ti_type
->has_encoding(Type::CT_PER
)) ||
595 (type
->has_encoding(Type::CT_RAW
)&&ti_type
->has_encoding(Type::CT_RAW
)) ||
596 (type
->has_encoding(Type::CT_TEXT
)&&ti_type
->has_encoding(Type::CT_TEXT
)) ||
597 (type
->has_encoding(Type::CT_XER
)&&ti_type
->has_encoding(Type::CT_XER
)) ||
598 (type
->has_encoding(Type::CT_JSON
)&&ti_type
->has_encoding(Type::CT_JSON
)))) {
599 act_attr
->error("Type `%s' and type `%s' have no common encoding",
600 ti_type
->get_typename().c_str(), type
->get_typename().c_str());
606 // for every erroneous field calculate the corresponding index and type arrays
607 // for example: x[5].z -> [3,5,2] and [MyRec,MyRecOf,MyUnion]
608 // MyRec.x field has index 3, etc.
609 for (size_t i
=0; i
<field_array
.size(); i
++) {
610 bool b
= type
->get_subrefs_as_array(field_array
[i
].qualifier
, field_array
[i
].subrefs_array
, field_array
[i
].type_array
);
611 if (!b
) FATAL_ERROR("ErroneousAttributes::chk()");
613 // check the qualifiers and build the tree
614 err_descr_tree
= build_descr_tree(field_array
);
617 ErroneousDescriptor
* ErroneousAttributes::build_descr_tree(dynamic_array
<field_err_t
>& fld_array
)
619 ErroneousDescriptor
* err_descr
= new ErroneousDescriptor();
620 const Qualifier
* omit_before_qual
= NULL
, * omit_after_qual
= NULL
;
621 map
< size_t, dynamic_array
<field_err_t
> > embedded_fld_array_m
; // used for recursive calls
622 for (size_t i
=0; i
<fld_array
.size(); i
++) {
623 field_err_t
& act_field_err
= fld_array
[i
];
624 ErroneousAttributeSpec::indicator_t act_indicator
= act_field_err
.err_attr
->get_indicator();
625 bool is_omit
= act_field_err
.err_attr
->get_is_omit();
626 if (act_field_err
.subrefs_array
.size()<1) FATAL_ERROR("ErroneousAttributes::build_descr_tree()");
627 size_t fld_idx
= act_field_err
.subrefs_array
[0];
628 if (omit_before_qual
&& (err_descr
->omit_before
!=-1) && (err_descr
->omit_before
>(int)fld_idx
)) {
629 act_field_err
.qualifier
->error(
630 "Field `%s' cannot be referenced because all fields before field `%s' have been omitted",
631 act_field_err
.qualifier
->get_stringRepr().c_str(), omit_before_qual
->get_stringRepr().c_str());
634 if (omit_after_qual
&& (err_descr
->omit_after
!=-1) && (err_descr
->omit_after
<(int)fld_idx
)) {
635 act_field_err
.qualifier
->error(
636 "Field `%s' cannot be referenced because all fields after field `%s' have been omitted",
637 act_field_err
.qualifier
->get_stringRepr().c_str(), omit_after_qual
->get_stringRepr().c_str());
640 if (act_field_err
.subrefs_array
.size()==1) { // erroneous value
641 if (act_field_err
.type_array
.size()!=1) FATAL_ERROR("ErroneousAttributes::build_descr_tree()");
642 if ((act_field_err
.type_array
[0]->get_typetype()==Type::T_SET_A
) &&
643 is_omit
&& (act_indicator
!=ErroneousAttributeSpec::I_VALUE
)) {
644 act_field_err
.qualifier
->error(
645 "Cannot omit all fields %s `%s' which is a field of an ASN.1 SET type",
646 ErroneousAttributeSpec::get_indicator_str(act_indicator
), act_field_err
.qualifier
->get_stringRepr().c_str());
647 act_field_err
.qualifier
->note(
648 "The order of fields in ASN.1 SET types changes depending on tagging (see X.690 9.3). "
649 "Fields can be omitted individually, independently of the field order which depends on tagging");
652 switch (act_field_err
.type_array
[0]->get_typetype_ttcn3()) {
653 case Type::T_CHOICE_T
:
654 if (act_indicator
!=ErroneousAttributeSpec::I_VALUE
) {
655 act_field_err
.qualifier
->error(
656 "Indicator `%s' cannot be used with reference `%s' which points to a field of a union type",
657 ErroneousAttributeSpec::get_indicator_str(act_indicator
), act_field_err
.qualifier
->get_stringRepr().c_str());
663 if (is_omit
&& (act_indicator
==ErroneousAttributeSpec::I_AFTER
) &&
664 (fld_idx
==act_field_err
.type_array
[0]->get_nof_comps()-1)) {
665 act_field_err
.qualifier
->error(
666 "There is nothing to omit after the last field (%s) of a record/set type",
667 act_field_err
.qualifier
->get_stringRepr().c_str());
673 if (is_omit
&& (act_indicator
==ErroneousAttributeSpec::I_BEFORE
) &&
675 act_field_err
.qualifier
->error(
676 "There is nothing to omit before the first field (%s)",
677 act_field_err
.qualifier
->get_stringRepr().c_str());
684 // check for duplicate value+indicator
685 if (err_descr
->values_m
.has_key(fld_idx
)) {
686 ErroneousValues
* evs
= err_descr
->values_m
[fld_idx
];
687 if ( (evs
->before
&& (act_indicator
==ErroneousAttributeSpec::I_BEFORE
)) ||
688 (evs
->value
&& (act_indicator
==ErroneousAttributeSpec::I_VALUE
)) ||
689 (evs
->after
&& (act_indicator
==ErroneousAttributeSpec::I_AFTER
)) ) {
690 act_field_err
.qualifier
->error(
691 "Duplicate reference to field `%s' with indicator `%s'",
692 act_field_err
.qualifier
->get_stringRepr().c_str(), ErroneousAttributeSpec::get_indicator_str(act_indicator
));
696 // when overwriting a value check if embedded values were used
697 if ((act_indicator
==ErroneousAttributeSpec::I_VALUE
) && embedded_fld_array_m
.has_key(fld_idx
)) {
698 act_field_err
.qualifier
->error(
699 "Reference to field `%s' with indicator `value' would invalidate previously specified erroneous data",
700 act_field_err
.qualifier
->get_stringRepr().c_str());
703 // if before/after omit then check that no references to omitted regions and no duplication of omit before/after rule
704 if ((act_indicator
==ErroneousAttributeSpec::I_BEFORE
) && is_omit
) {
705 if (omit_before_qual
&& (err_descr
->omit_before
!=-1)) {
706 act_field_err
.qualifier
->error(
707 "Duplicate rule for omitting all fields before the specified field. Used on field `%s' but previously already used on field `%s'",
708 act_field_err
.qualifier
->get_stringRepr().c_str(), omit_before_qual
->get_stringRepr().c_str());
711 bool is_invalid
= false;
712 for (size_t j
=0; j
<err_descr
->values_m
.size(); j
++) {
713 if (err_descr
->values_m
.get_nth_key(j
)<fld_idx
) {
719 for (size_t j
=0; j
<embedded_fld_array_m
.size(); j
++) {
720 if (embedded_fld_array_m
.get_nth_key(j
)<fld_idx
) {
727 act_field_err
.qualifier
->error(
728 "Omitting fields before field `%s' would invalidate previously specified erroneous data",
729 act_field_err
.qualifier
->get_stringRepr().c_str());
732 // save valid omit before data
733 omit_before_qual
= act_field_err
.qualifier
;
734 err_descr
->omit_before
= fld_idx
;
735 err_descr
->omit_before_name
= omit_before_qual
->get_stringRepr();
738 if ((act_indicator
==ErroneousAttributeSpec::I_AFTER
) && is_omit
) {
739 if (omit_after_qual
&& (err_descr
->omit_after
!=-1)) {
740 act_field_err
.qualifier
->error(
741 "Duplicate rule for omitting all fields after the specified field. Used on field `%s' but previously already used on field `%s'",
742 act_field_err
.qualifier
->get_stringRepr().c_str(), omit_after_qual
->get_stringRepr().c_str());
745 bool is_invalid
= false;
746 for (size_t j
=0; j
<err_descr
->values_m
.size(); j
++) {
747 if (err_descr
->values_m
.get_nth_key(j
)>fld_idx
) {
753 for (size_t j
=0; j
<embedded_fld_array_m
.size(); j
++) {
754 if (embedded_fld_array_m
.get_nth_key(j
)>fld_idx
) {
761 act_field_err
.qualifier
->error(
762 "Omitting fields after field `%s' would invalidate previously specified erroneous data",
763 act_field_err
.qualifier
->get_stringRepr().c_str());
766 // save valid omit after data
767 omit_after_qual
= act_field_err
.qualifier
;
768 err_descr
->omit_after
= fld_idx
;
769 err_descr
->omit_after_name
= omit_after_qual
->get_stringRepr();
772 // if not before/after omit then save this into values_m
773 bool has_key
= err_descr
->values_m
.has_key(fld_idx
);
774 ErroneousValues
* evs
= has_key
? err_descr
->values_m
[fld_idx
] : new ErroneousValues(act_field_err
.qualifier
->get_stringRepr());
775 switch (act_indicator
) {
776 case ErroneousAttributeSpec::I_BEFORE
: evs
->before
= act_field_err
.err_attr
; break;
777 case ErroneousAttributeSpec::I_VALUE
: evs
->value
= act_field_err
.err_attr
; break;
778 case ErroneousAttributeSpec::I_AFTER
: evs
->after
= act_field_err
.err_attr
; break;
779 default: FATAL_ERROR("ErroneousAttributes::build_descr_tree()");
782 err_descr
->values_m
.add(fld_idx
, evs
);
784 } else { // embedded err.value
785 if ((err_descr
->values_m
.has_key(fld_idx
)) && (err_descr
->values_m
[fld_idx
]->value
)) {
786 act_field_err
.qualifier
->error(
787 "Field `%s' is embedded into a field which was previously overwritten or omitted",
788 act_field_err
.qualifier
->get_stringRepr().c_str());
791 // add the embedded field to the map
792 bool has_idx
= embedded_fld_array_m
.has_key(fld_idx
);
793 dynamic_array
<field_err_t
>* emb_fld_array
= has_idx
? embedded_fld_array_m
[fld_idx
] : new dynamic_array
<field_err_t
>();
794 field_err_t emb_field_err
= act_field_err
;
795 emb_field_err
.subrefs_array
.remove(0); // remove the first reference
796 emb_field_err
.type_array
.remove(0);
797 emb_fld_array
->add(emb_field_err
);
799 embedded_fld_array_m
.add(fld_idx
, emb_fld_array
);
803 // recursive calls to create embedded descriptors
804 for (size_t i
=0; i
<embedded_fld_array_m
.size(); i
++) {
805 dynamic_array
<field_err_t
>* emb_fld_array
= embedded_fld_array_m
.get_nth_elem(i
);
806 err_descr
->descr_m
.add(embedded_fld_array_m
.get_nth_key(i
), build_descr_tree(*emb_fld_array
));
807 delete emb_fld_array
;
809 embedded_fld_array_m
.clear();
813 // ==== AttributeSpec ====
815 AttributeSpec
* AttributeSpec::clone() const
817 return new AttributeSpec(*this);
820 void AttributeSpec::set_fullname(const string
& p_fullname
)
822 Node::set_fullname(p_fullname
);
825 void AttributeSpec::dump(unsigned level
) const
827 DEBUG(level
,"spec: %s", spec
.c_str());
830 // ==== SingleWithAttrib ====
832 SingleWithAttrib::SingleWithAttrib(const SingleWithAttrib
& p
)
833 : Node(p
), Location(p
), attribKeyword(p
.attribKeyword
),
834 hasOverride(p
.hasOverride
)
836 attribQualifiers
= p
.attribQualifiers
? p
.attribQualifiers
->clone() : 0;
837 attribSpec
= p
.attribSpec
->clone();
840 SingleWithAttrib::SingleWithAttrib(
841 attribtype_t p_attribKeyword
, bool p_hasOverride
,
842 Qualifiers
*p_attribQualifiers
, AttributeSpec
* p_attribSpec
)
843 : Node(), Location(), attribKeyword(p_attribKeyword
),
844 hasOverride(p_hasOverride
), attribQualifiers(p_attribQualifiers
),
845 attribSpec(p_attribSpec
)
848 FATAL_ERROR("SingleWithAttrib::SingleWithAttrib()");
851 SingleWithAttrib::~SingleWithAttrib()
853 delete attribQualifiers
;
857 SingleWithAttrib
* SingleWithAttrib::clone() const
859 return new SingleWithAttrib(*this);
862 void SingleWithAttrib::set_fullname(const string
& p_fullname
)
864 Node::set_fullname(p_fullname
);
866 attribQualifiers
->set_fullname(p_fullname
+ ".<attribute qualifiers>");
867 attribSpec
->set_fullname(p_fullname
+ ".<attribute specification>");
870 void SingleWithAttrib::dump(unsigned level
) const
872 DEBUG(level
,"attribute");
873 switch(attribKeyword
)
876 DEBUG(level
+ 1,"keyword: encode");
879 DEBUG(level
+ 1,"keyword: variant");
882 DEBUG(level
+ 1,"keyword: display");
885 DEBUG(level
+ 1,"keyword: extension");
888 DEBUG(level
+ 1,"keyword: optional");
891 DEBUG(level
+1, "keyword: erroneous");
894 DEBUG(level
+1, "invalid keyword");
897 FATAL_ERROR("SingleWithAttrib::dump()");
900 DEBUG(level
+ 1, hasOverride
? "has override" : "hasn't got override");
903 attribSpec
->dump(level
+ 1);
905 attribQualifiers
->dump(level
+ 1);
908 // ==== MultiWithAttrib ====
910 MultiWithAttrib::MultiWithAttrib(const MultiWithAttrib
& p
)
911 : Node(p
), Location(p
)
913 for(size_t i
= 0; i
< p
.get_nof_elements(); i
++)
915 elements
.add(p
.get_element(i
)->clone());
919 MultiWithAttrib
* MultiWithAttrib::clone() const
921 return new MultiWithAttrib(*this);
924 void MultiWithAttrib::set_fullname(const string
& p_fullname
)
926 Node::set_fullname(p_fullname
);
927 for(size_t i
= 0; i
< elements
.size(); i
++)
929 elements
[i
]->set_fullname(p_fullname
+ ".<singlewithattribute "
930 + Int2string(i
) + ">");
934 MultiWithAttrib::~MultiWithAttrib()
936 for(size_t i
= 0; i
< elements
.size(); i
++)
943 const SingleWithAttrib
* MultiWithAttrib::get_element(size_t p_index
) const
945 return elements
[p_index
];
948 SingleWithAttrib
* MultiWithAttrib::get_element_for_modification(
951 return elements
[p_index
];
954 void MultiWithAttrib::delete_element(size_t p_index
)
956 delete elements
[p_index
];
957 elements
.replace(p_index
,1,NULL
);
960 void MultiWithAttrib::dump(unsigned level
) const
962 DEBUG(level
,"with attrib parameters (%lu pcs)",
963 (unsigned long) elements
.size());
964 for(size_t i
= 0; i
< elements
.size(); i
++)
966 elements
[i
]->dump(level
+ 1);
970 // ==== WithAttribPath ====
972 WithAttribPath::WithAttribPath(const WithAttribPath
& p
)
973 : Node(p
), had_global_variants(false), attributes_checked(false),
974 cached(false), s_o_encode(false), parent(p
.parent
)
976 m_w_attrib
= p
.m_w_attrib
? p
.m_w_attrib
->clone() : 0;
979 WithAttribPath::~WithAttribPath()
985 WithAttribPath
* WithAttribPath::clone() const
987 return new WithAttribPath(*this);
990 void WithAttribPath::set_fullname(const string
& p_fullname
)
992 Node::set_fullname(p_fullname
);
993 if (m_w_attrib
) m_w_attrib
->set_fullname(p_fullname
994 + ".<multiwithattribute>");
997 void WithAttribPath::chk_no_qualif()
999 if(attributes_checked
)
1005 const SingleWithAttrib
*swa
;
1006 for(int i
= m_w_attrib
->get_nof_elements() - 1; i
>= 0; i
--)
1008 swa
= m_w_attrib
->get_element(i
);
1009 if( swa
->get_attribQualifiers()
1010 && swa
->get_attribQualifiers()->get_nof_qualifiers() != 0)
1012 swa
->error("field qualifiers are only allowed"
1013 " for record, set and union types");
1014 m_w_attrib
->delete_element(i
);
1018 attributes_checked
= true;
1021 void WithAttribPath::dump(unsigned int level
) const
1023 DEBUG(level
, "WithAttribPath");
1024 if (!m_w_attrib
) return;
1025 DEBUG(level
+1, "%lu elements",
1026 (unsigned long)m_w_attrib
->get_nof_elements());
1027 for (size_t i
=0; i
< m_w_attrib
->get_nof_elements(); ++i
) {
1028 const SingleWithAttrib
* a
= m_w_attrib
->get_element(i
);
1035 * Checks whether there is inconsistency among global attributes or not.
1036 * Only the last encode can have effect so we can throw out the others.
1037 * This is because encode is not an attribute, but a "context".
1038 * If there is an overriding variant/display/extension then the
1039 * following attributes from the same type should be omitted.
1041 void WithAttribPath::chk_global_attrib(bool erroneous_allowed
)
1046 if (!erroneous_allowed
) {
1047 for(size_t i
= m_w_attrib
->get_nof_elements(); i
> 0; i
--) {
1048 const SingleWithAttrib
* const temp_attrib
=
1049 m_w_attrib
->get_element(i
-1);
1050 if (temp_attrib
->get_attribKeyword()==SingleWithAttrib::AT_ERRONEOUS
) {
1051 temp_attrib
->error("The `erroneous' attribute can be used only on "
1052 "template and constant definitions");
1057 bool has_encode
= false;
1058 bool has_override_variant
= false;
1059 bool has_override_display
= false;
1060 bool has_override_extension
= false;
1061 bool has_override_optional
= false;
1062 for(size_t i
= m_w_attrib
->get_nof_elements(); i
> 0; i
--)
1064 const SingleWithAttrib
* const temp_attrib
=
1065 m_w_attrib
->get_element(i
-1);
1066 switch(temp_attrib
->get_attribKeyword())
1068 case SingleWithAttrib::AT_ENCODE
:
1072 temp_attrib
->warning("Only the last encode "
1073 "of the with statement will have effect");
1074 m_w_attrib
->delete_element(i
-1);
1080 case SingleWithAttrib::AT_ERRONEOUS
:
1082 if (temp_attrib
->has_override()) {
1083 temp_attrib
->error("Override cannot be used with erroneous");
1092 for(size_t i
= 0; i
< m_w_attrib
->get_nof_elements();)
1094 const SingleWithAttrib
* const temp_attrib
= m_w_attrib
->get_element(i
);
1095 switch(temp_attrib
->get_attribKeyword())
1097 case SingleWithAttrib::AT_VARIANT
:
1099 if(has_override_variant
)
1101 temp_attrib
->warning("Only the first override"
1102 " variant of the with statement will have effect");
1103 m_w_attrib
->delete_element(i
);
1105 if(temp_attrib
->has_override())
1106 has_override_variant
= true;
1111 case SingleWithAttrib::AT_DISPLAY
:
1113 if(has_override_display
)
1115 temp_attrib
->warning("Only the first override"
1116 " display of the with statement will have effect");
1117 m_w_attrib
->delete_element(i
);
1119 if(temp_attrib
->has_override())
1120 has_override_display
= true;
1125 case SingleWithAttrib::AT_EXTENSION
:
1127 if(has_override_extension
)
1129 temp_attrib
->warning("Only the first override"
1130 " extension of the with statement will have effect");
1131 m_w_attrib
->delete_element(i
);
1133 if(temp_attrib
->has_override())
1134 has_override_extension
= true;
1139 case SingleWithAttrib::AT_OPTIONAL
:
1141 if ("implicit omit" != temp_attrib
->get_attribSpec().get_spec() &&
1142 "explicit omit" != temp_attrib
->get_attribSpec().get_spec()) {
1143 temp_attrib
->error("Value of optional attribute can only be "
1144 "either 'explicit omit' or 'implicit omit' not '%s'",
1145 temp_attrib
->get_attribSpec().get_spec().c_str());
1147 if(has_override_optional
)
1149 temp_attrib
->warning("Only the first override"
1150 " optional of the with statement will have effect");
1151 m_w_attrib
->delete_element(i
);
1153 if(temp_attrib
->has_override())
1154 has_override_optional
= true;
1166 void WithAttribPath::set_with_attr(MultiWithAttrib
* p_m_w_attr
)
1168 if(m_w_attrib
) FATAL_ERROR("WithAttribPath::set_with_attr()");
1169 m_w_attrib
= p_m_w_attr
;
1170 attributes_checked
= false;
1174 * Finds the real attributes checking the inherited ones with its own.
1175 * Only qualifierless attributes are handled.
1176 * The stepped_over_encode is needed because it can happen that we
1177 * override an encode and later (inner) find variants without encode.
1178 * As those were the overridden encode's variants we can not add them to
1181 void WithAttribPath::qualifierless_attrib_finder(
1182 vector
<SingleWithAttrib
>& p_result
,
1183 bool& stepped_over_encode
)
1187 for(size_t i
= 0; i
< cache
.size(); i
++)
1189 p_result
.add(cache
[i
]);
1191 stepped_over_encode
= s_o_encode
;
1196 parent
->qualifierless_attrib_finder(p_result
,stepped_over_encode
);
1198 stepped_over_encode
= false;
1202 // These two refer only to the attributes of this type
1203 int self_encode_index
= -1; // the index of the "encode" attribute
1204 bool self_has_variant
= false; // flag for the presence of a "variant"
1205 // The following refer to all the attributes, including those collected
1206 // from the parent and all the ancestors.
1207 bool par_has_override_encode
= false;
1208 bool par_has_encode
= false;
1209 // True if there is an encode attribute in the local attribute list,
1210 // it differs from the parents encode
1211 // and the parent does not overwrite it.
1212 bool new_local_encode_context
= false;
1213 bool par_has_override_variant
= false;
1214 bool par_has_override_display
= false;
1215 bool par_has_override_extension
= false;
1216 bool par_has_override_optional
= false;
1218 //checking the owned attributes
1219 const SingleWithAttrib
* act_single
;
1220 const Qualifiers
* act_qualifiers
;
1221 const size_t m_w_attrib_nof_elements
= m_w_attrib
->get_nof_elements();
1222 for(size_t i
= 0; i
< m_w_attrib_nof_elements
;i
++)
1224 act_single
= m_w_attrib
->get_element(i
);
1225 act_qualifiers
= act_single
->get_attribQualifiers();
1228 if(!act_qualifiers
|| act_qualifiers
->get_nof_qualifiers() == 0)
1230 switch(act_single
->get_attribKeyword())
1232 case SingleWithAttrib::AT_ENCODE
:
1233 self_encode_index
= i
;
1236 case SingleWithAttrib::AT_VARIANT
: {
1237 // Ignore JSON variants, these should not produce warnings
1238 const string
& spec
= act_single
->get_attribSpec().get_spec();
1240 while (i2
< spec
.size()) {
1241 if (spec
[i2
] != ' ' && spec
[i2
] != '\t') {
1246 if (i2
== spec
.size() || spec
.find("JSON", i2
) != i2
) {
1247 self_has_variant
= true;
1251 case SingleWithAttrib::AT_DISPLAY
:
1252 case SingleWithAttrib::AT_EXTENSION
:
1253 case SingleWithAttrib::AT_OPTIONAL
:
1254 case SingleWithAttrib::AT_ERRONEOUS
:
1255 case SingleWithAttrib::AT_INVALID
:
1259 FATAL_ERROR("WithAttribPath::attrib_finder()");
1264 // Here p_result contains attributes collected from outer scopes only.
1265 size_t p_result_size
= p_result
.size();
1266 // gather information on the attributes collected from the parents
1267 for(size_t i
= 0; i
< p_result_size
; i
++)
1269 act_single
= p_result
[i
];
1271 switch(act_single
->get_attribKeyword())
1273 case SingleWithAttrib::AT_ENCODE
:
1274 par_has_encode
= true;
1275 par_has_override_encode
|= act_single
->has_override();
1276 if(self_encode_index
!= -1)
1278 // We also have an encode. See if they differ.
1279 new_local_encode_context
= (act_single
->get_attribSpec().get_spec()
1280 != m_w_attrib
->get_element(self_encode_index
)->
1281 get_attribSpec().get_spec());
1285 case SingleWithAttrib::AT_VARIANT
:
1286 par_has_override_variant
|= act_single
->has_override();
1288 case SingleWithAttrib::AT_DISPLAY
:
1289 par_has_override_display
|= act_single
->has_override();
1291 case SingleWithAttrib::AT_EXTENSION
:
1292 par_has_override_extension
|= act_single
->has_override();
1294 case SingleWithAttrib::AT_OPTIONAL
:
1295 par_has_override_optional
|= act_single
->has_override();
1297 case SingleWithAttrib::AT_ERRONEOUS
:
1298 case SingleWithAttrib::AT_INVALID
:
1302 FATAL_ERROR("WithAttribPath::attrib_finder()");
1306 if(!par_has_encode
&& self_encode_index
== -1 && self_has_variant
)
1308 // There is no encode, but there is at least one variant.
1309 // Find them and issue warnings.
1310 for(size_t i
= 0; i
< m_w_attrib_nof_elements
; i
++)
1312 act_single
= m_w_attrib
->get_element(i
);
1313 if(act_single
->get_attribKeyword() == SingleWithAttrib::AT_VARIANT
)
1314 act_single
->warning("This variant does not belong to an encode");
1318 // If we have an encode (self_encode_index != -1) and it differs from
1319 // the outer encode (new_local_encode_context) and the outer wasn't
1320 // an "override encode" (!par_has_override_encode),
1321 // remove the outer encode and all the variants that belong to it.
1322 for(size_t i
= p_result
.size(); i
> 0; i
--)
1324 switch(p_result
[i
-1]->get_attribKeyword())
1326 case SingleWithAttrib::AT_ENCODE
:
1327 case SingleWithAttrib::AT_VARIANT
:
1328 if (self_encode_index
!= -1 && new_local_encode_context
1329 && !par_has_override_encode
)
1330 p_result
.replace(i
-1,1,NULL
);
1332 case SingleWithAttrib::AT_DISPLAY
:
1333 case SingleWithAttrib::AT_EXTENSION
:
1334 case SingleWithAttrib::AT_OPTIONAL
:
1335 case SingleWithAttrib::AT_ERRONEOUS
:
1336 case SingleWithAttrib::AT_INVALID
:
1341 //adding the right ones from the local attributes
1342 for(size_t i
= 0; i
< m_w_attrib_nof_elements
; i
++)
1344 act_single
= m_w_attrib
->get_element(i
);
1345 act_qualifiers
= act_single
->get_attribQualifiers();
1346 if(!act_qualifiers
|| act_qualifiers
->get_nof_qualifiers() == 0)
1348 switch(act_single
->get_attribKeyword())
1350 case SingleWithAttrib::AT_ENCODE
:
1351 if((par_has_encode
&& !par_has_override_encode
1352 && new_local_encode_context
)
1353 || (!par_has_encode
))
1355 p_result
.add_front(m_w_attrib
->get_element_for_modification(i
));
1356 stepped_over_encode
= false;
1357 }else if(new_local_encode_context
){
1358 //par_has_encode && par_has_override_encode
1359 stepped_over_encode
= true;
1361 stepped_over_encode
= false;
1364 case SingleWithAttrib::AT_VARIANT
:
1365 if((!par_has_encode
&& !par_has_override_variant
)
1366 || (par_has_encode
&& self_encode_index
== -1
1367 && !stepped_over_encode
&& !par_has_override_variant
)
1368 || (par_has_encode
&& self_encode_index
!= -1
1369 && !par_has_override_encode
&& !par_has_override_variant
)
1370 || (!par_has_encode
&& self_encode_index
!= -1))
1371 p_result
.add(m_w_attrib
->get_element_for_modification(i
));
1373 case SingleWithAttrib::AT_DISPLAY
:
1374 if(!par_has_override_display
)
1375 p_result
.add(m_w_attrib
->get_element_for_modification(i
));
1377 case SingleWithAttrib::AT_EXTENSION
:
1378 if(!par_has_override_extension
)
1379 p_result
.add(m_w_attrib
->get_element_for_modification(i
));
1381 case SingleWithAttrib::AT_OPTIONAL
:
1382 if (!par_has_override_optional
)
1383 p_result
.add(m_w_attrib
->get_element_for_modification(i
));
1385 case SingleWithAttrib::AT_ERRONEOUS
:
1386 case SingleWithAttrib::AT_INVALID
:
1396 * Be very cautious this function gives back only the qualifierless attributes.
1397 * Because of types giving back all the attribs, so that they are already
1398 * in their final encode context would mean that attributes coming from
1399 * the parent path would need to be cloned and qualified as many times
1400 * as many components the type has.
1402 const vector
<SingleWithAttrib
>& WithAttribPath::get_real_attrib()
1405 qualifierless_attrib_finder(cache
,s_o_encode
);
1411 bool WithAttribPath::has_attribs()
1413 if (had_global_variants
) return true;
1414 else if (get_real_attrib().size() > 0) return true;
1415 else if (m_w_attrib
) {
1416 for (size_t i
= 0; i
< m_w_attrib
->get_nof_elements(); i
++) {
1417 const Qualifiers
*qualifiers
=
1418 m_w_attrib
->get_element(i
)->get_attribQualifiers();
1419 if (qualifiers
&& qualifiers
->get_nof_qualifiers() > 0) return true;