1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22 #include <precomp.h>
23 #include <ary/cpp/usedtype.hxx>
24
25
26 // NOT FULLY DEFINED SERVICES
27 #include <cosv/tpl/tpltools.hxx>
28 #include <ary/symtreenode.hxx>
29 #include <ary/cpp/c_ce.hxx>
30 #include <ary/cpp/c_class.hxx>
31 #include <ary/cpp/c_namesp.hxx>
32 #include <ary/cpp/c_slntry.hxx>
33 #include <ary/cpp/c_tydef.hxx>
34 #include <ary/cpp/c_traits.hxx>
35 #include <ary/cpp/c_types4cpp.hxx>
36 #include <ary/cpp/c_gate.hxx>
37 #include <ary/cpp/cp_ce.hxx>
38 #include <ary/cpp/cp_type.hxx>
39 #include <ary/doc/d_oldcppdocu.hxx>
40 #include <ary/getncast.hxx>
41 #include "tplparam.hxx"
42
43
44
45 namespace
46 {
47
48 using namespace ::ary::cpp;
49 typedef std::vector< ary::cpp::E_ConVol > PtrLevelVector;
50
51
52 inline bool
result2bool(intt i_nResult)53 result2bool( intt i_nResult )
54 { return i_nResult < 0; }
55
56
57 intt compare_PtrLevelVector(
58 const PtrLevelVector &
59 i_r1,
60 const PtrLevelVector &
61 i_r2 );
62 inline intt
compare_ConVol(E_ConVol i_e1,E_ConVol i_e2)63 compare_ConVol( E_ConVol i_e1,
64 E_ConVol i_e2 )
65 { return intt(i_e1) - intt(i_e2); }
66
67 inline intt
compare_bool(bool i_b1,bool i_b2)68 compare_bool( bool i_b1,
69 bool i_b2 )
70 { return i_b1 == i_b2
71 ? 0
72 : i_b1
73 ? -1
74 : +1; }
75 inline intt
compare_Specialisation(E_TypeSpecialisation i_e1,E_TypeSpecialisation i_e2)76 compare_Specialisation( E_TypeSpecialisation i_e1,
77 E_TypeSpecialisation i_e2 )
78 { return intt(i_e1) - intt(i_e2); }
79
80 inline bool
is_const(E_ConVol i_eCV)81 is_const( E_ConVol i_eCV )
82 { return ( intt(i_eCV) & intt(CONVOL_const) ) != 0; }
83
84 inline bool
is_volatile(E_ConVol i_eCV)85 is_volatile( E_ConVol i_eCV )
86 { return ( intt(i_eCV) & intt(CONVOL_volatile) ) != 0; }
87
88
89 intt
compare_PtrLevelVector(const PtrLevelVector & i_r1,const PtrLevelVector & i_r2)90 compare_PtrLevelVector( const PtrLevelVector & i_r1,
91 const PtrLevelVector & i_r2 )
92 {
93 intt nResult = i_r1.size() - i_r2.size();
94 if ( nResult != 0 )
95 return nResult;
96
97 PtrLevelVector::const_iterator it1 = i_r1.begin();
98 PtrLevelVector::const_iterator it1End = i_r1.end();
99 PtrLevelVector::const_iterator it2 = i_r2.begin();
100
101 for ( ; it1 != it1End; ++it1, ++it2 )
102 {
103 nResult = compare_ConVol(*it1, *it2);
104 if ( nResult != 0 )
105 return nResult;
106 }
107
108 return 0;
109 }
110
111
112 } // anonymous namespace
113
114
115
116
117 namespace ary
118 {
119 namespace cpp
120 {
121
122 typedef symtree::Node<CeNode_Traits> CeNode;
123 typedef ut::NameChain::const_iterator nc_iter;
124
125 Ce_id CheckForRelatedCe_inNode(
126 const CeNode & i_node,
127 const StringVector& i_qualification,
128 const String & i_name );
129
130
UsedType(Ce_id i_scope)131 UsedType::UsedType(Ce_id i_scope )
132 : aPath(),
133 aPtrLevels(),
134 eConVol_Type(CONVOL_none),
135 bIsReference(false),
136 bIsAbsolute(false),
137 bRefers2BuiltInType(false),
138 eTypeSpecialisation(TYSP_none),
139 nRelatedCe(0),
140 nScope(i_scope)
141 {
142 }
143
~UsedType()144 UsedType::~UsedType()
145 {
146 }
147
148
149 bool
operator <(const UsedType & i_rType) const150 UsedType::operator<( const UsedType & i_rType ) const
151 {
152 intt nResult = compare_bool( bIsAbsolute, i_rType.bIsAbsolute );
153 if ( nResult != 0 )
154 return result2bool(nResult);
155
156 nResult = static_cast<intt>(nScope.Value())
157 -
158 static_cast<intt>(i_rType.nScope.Value());
159 if ( nResult != 0 )
160 return result2bool(nResult);
161
162 nResult = aPath.Compare( i_rType.aPath );
163 if ( nResult != 0 )
164 return result2bool(nResult);
165
166 nResult = compare_ConVol( eConVol_Type, i_rType.eConVol_Type );
167 if ( nResult != 0 )
168 return result2bool(nResult);
169
170 nResult = compare_PtrLevelVector( aPtrLevels, i_rType.aPtrLevels );
171 if ( nResult != 0 )
172 return result2bool(nResult);
173
174 nResult = compare_bool( bIsReference, i_rType.bIsReference );
175 if ( nResult != 0 )
176 return result2bool(nResult);
177
178 nResult = compare_Specialisation( eTypeSpecialisation, i_rType.eTypeSpecialisation );
179 if ( nResult != 0 )
180 return result2bool(nResult);
181
182 return false;
183 }
184
185 void
Set_Absolute()186 UsedType::Set_Absolute()
187 {
188 bIsAbsolute = true;
189 }
190
191 void
Add_NameSegment(const char * i_sSeg)192 UsedType::Add_NameSegment( const char * i_sSeg )
193 {
194 aPath.Add_Segment(i_sSeg);
195 }
196
197 ut::List_TplParameter &
Enter_Template()198 UsedType::Enter_Template()
199 {
200 return aPath.Templatize_LastSegment();
201 }
202
203 void
Set_Unsigned()204 UsedType::Set_Unsigned()
205 {
206 eTypeSpecialisation = TYSP_unsigned;
207 }
208
209 void
Set_Signed()210 UsedType::Set_Signed()
211 {
212 eTypeSpecialisation = TYSP_signed;
213 }
214
215 void
Set_BuiltIn(const char * i_sType)216 UsedType::Set_BuiltIn( const char * i_sType )
217 {
218 aPath.Add_Segment(i_sType);
219 bRefers2BuiltInType = true;
220 }
221
222 void
Set_Const()223 UsedType::Set_Const()
224 {
225 if (PtrLevel() == 0)
226 eConVol_Type = E_ConVol(eConVol_Type | CONVOL_const);
227 else
228 aPtrLevels.back() = E_ConVol(aPtrLevels.back() | CONVOL_const);
229 }
230
231 void
Set_Volatile()232 UsedType::Set_Volatile()
233 {
234 if (PtrLevel() == 0)
235 eConVol_Type = E_ConVol(eConVol_Type | CONVOL_volatile);
236 else
237 aPtrLevels.back() = E_ConVol(aPtrLevels.back() | CONVOL_volatile);
238 }
239
240 void
Add_PtrLevel()241 UsedType::Add_PtrLevel()
242 {
243 aPtrLevels.push_back(CONVOL_none);
244 }
245
246 void
Set_Reference()247 UsedType::Set_Reference()
248 {
249 bIsReference = true;
250 }
251
252 inline bool
IsInternal(const ary::cpp::CodeEntity & i_ce)253 IsInternal(const ary::cpp::CodeEntity & i_ce)
254 {
255 const ary::doc::OldCppDocu *
256 docu = dynamic_cast< const ary::doc::OldCppDocu* >(i_ce.Docu().Data());
257 if (docu != 0)
258 return docu->IsInternal();
259 return false;
260 }
261
262
263 void
Connect2Ce(const CePilot & i_ces)264 UsedType::Connect2Ce( const CePilot & i_ces)
265 {
266 StringVector
267 qualification;
268 String
269 name;
270 Get_NameParts(qualification, name);
271
272 for ( const CeNode * scope_node = CeNode_Traits::NodeOf_(
273 i_ces.Find_Ce(nScope));
274 scope_node != 0;
275 scope_node = scope_node->Parent() )
276 {
277 nRelatedCe = CheckForRelatedCe_inNode(*scope_node, qualification, name);
278 if ( nRelatedCe.IsValid() )
279 {
280 if ( IsInternal(i_ces.Find_Ce(nRelatedCe)) )
281 nRelatedCe = Ce_id(0);
282 return;
283 }
284 } // end for
285 }
286
287 void
Connect2CeOnlyKnownViaBaseClass(const Gate & i_gate)288 UsedType::Connect2CeOnlyKnownViaBaseClass(const Gate & i_gate)
289 {
290 csv_assert(nScope.IsValid());
291 CesResultList
292 instances = i_gate.Ces().Search_TypeName( LocalName() );
293
294 // If there are no matches, or only one match that was already
295 // accepted, all work is done.
296 if ( (nRelatedCe.IsValid() AND instances.size() == 1)
297 OR instances.size() == 0 )
298 return;
299
300 StringVector
301 qualification;
302 String
303 name;
304 Get_NameParts(qualification, name);
305
306 const CodeEntity &
307 scopece = i_gate.Ces().Find_Ce(nScope);
308
309 // Else search for declaration in own class and then in base classes.
310 // These would be of higher priority than those in parent namespaces.
311 Ce_id
312 foundce = RecursiveSearchCe_InBaseClassesOf(
313 scopece, qualification, name, i_gate);
314 if (foundce.IsValid())
315 nRelatedCe = foundce;
316
317 if ( nRelatedCe.IsValid() AND IsInternal(i_gate.Ces().Find_Ce(nRelatedCe)) )
318 {
319 nRelatedCe = Ce_id(0);
320 }
321 }
322
323 bool
IsBuiltInType() const324 UsedType::IsBuiltInType() const
325 {
326 return bRefers2BuiltInType
327 AND aPtrLevels.size() == 0
328 AND NOT bIsReference
329 AND eConVol_Type == ary::cpp::CONVOL_none;
330 }
331
332 const String &
LocalName() const333 UsedType::LocalName() const
334 {
335 return aPath.LastSegment();
336 }
337
338 E_TypeSpecialisation
TypeSpecialisation() const339 UsedType::TypeSpecialisation() const
340 {
341 return eTypeSpecialisation;
342 }
343
344 void
do_Accept(csv::ProcessorIfc & io_processor) const345 UsedType::do_Accept(csv::ProcessorIfc & io_processor) const
346 {
347 csv::CheckedCall(io_processor,*this);
348 }
349
350 ary::ClassId
get_AryClass() const351 UsedType::get_AryClass() const
352 {
353 return class_id;
354 }
355
356 Rid
inq_RelatedCe() const357 UsedType::inq_RelatedCe() const
358 {
359 return nRelatedCe.Value();
360 }
361
362 bool
inq_IsConst() const363 UsedType::inq_IsConst() const
364 {
365 if ( is_const(eConVol_Type) )
366 return true;
367 for ( PtrLevelVector::const_iterator it = aPtrLevels.begin();
368 it != aPtrLevels.end();
369 ++it )
370 {
371 if ( is_const(*it) )
372 return true;
373 }
374
375 return false;
376 }
377
378 void
inq_Get_Text(StreamStr & o_rPreName,StreamStr & o_rName,StreamStr & o_rPostName,const Gate & i_rGate) const379 UsedType::inq_Get_Text( StreamStr & o_rPreName,
380 StreamStr & o_rName,
381 StreamStr & o_rPostName,
382 const Gate & i_rGate ) const
383 {
384 if ( is_const(eConVol_Type) )
385 o_rPreName << "const ";
386 if ( is_volatile(eConVol_Type) )
387 o_rPreName << "volatile ";
388 if ( bIsAbsolute )
389 o_rPreName << "::";
390
391 aPath.Get_Text( o_rPreName, o_rName, o_rPostName, i_rGate );
392
393 for ( PtrLevelVector::const_iterator it = aPtrLevels.begin();
394 it != aPtrLevels.end();
395 ++it )
396 {
397 o_rPostName << " *";
398 if ( is_const(*it) )
399 o_rPostName << " const";
400 if ( is_volatile(*it) )
401 o_rPostName << " volatile";
402 }
403 if ( bIsReference )
404 o_rPostName << " &";
405 }
406
407 Ce_id
RecursiveSearchCe_InBaseClassesOf(const CodeEntity & i_mayBeClass,const StringVector & i_myQualification,const String & i_myName,const Gate & i_gate) const408 UsedType::RecursiveSearchCe_InBaseClassesOf( const CodeEntity & i_mayBeClass,
409 const StringVector & i_myQualification,
410 const String & i_myName,
411 const Gate & i_gate ) const
412 {
413 // Find in this class?
414 const CeNode *
415 basenode = CeNode_Traits::NodeOf_(i_mayBeClass);
416 if (basenode == 0)
417 return Ce_id(0);
418 Ce_id
419 found = CheckForRelatedCe_inNode(*basenode, i_myQualification, i_myName);
420 if (found.IsValid())
421 return found;
422
423
424 const Class *
425 cl = ary_cast<Class>(&i_mayBeClass);
426 if (cl == 0)
427 return Ce_id(0);
428
429 for ( List_Bases::const_iterator it = cl->BaseClasses().begin();
430 it != cl->BaseClasses().end();
431 ++it )
432 {
433 csv_assert((*it).nId.IsValid());
434 Ce_id
435 base = i_gate.Types().Find_Type((*it).nId).RelatedCe();
436 while (base.IsValid() AND is_type<Typedef>(i_gate.Ces().Find_Ce(base)) )
437 {
438 base = i_gate.Types().Find_Type(
439 ary_cast<Typedef>(i_gate.Ces().Find_Ce(base))
440 .DescribingType() )
441 .RelatedCe();
442 }
443
444 if (base.IsValid())
445 {
446 const CodeEntity &
447 basece = i_gate.Ces().Find_Ce(base);
448 found = RecursiveSearchCe_InBaseClassesOf(
449 basece, i_myQualification, i_myName, i_gate);
450 if (found.IsValid())
451 return found;
452 }
453 } // end for
454
455 return Ce_id(0);
456 }
457
458
459 void
Get_NameParts(StringVector & o_qualification,String & o_name)460 UsedType::Get_NameParts( StringVector & o_qualification,
461 String & o_name )
462 {
463 nc_iter nit = aPath.begin();
464 nc_iter nit_end = aPath.end();
465 csv_assert(nit != nit_end); // Each UsedType has to have a local name.
466
467 --nit_end;
468 o_name = (*nit_end).Name();
469 for ( ;
470 nit != nit_end;
471 ++nit )
472 {
473 o_qualification.push_back( (*nit).Name() );
474 }
475 }
476
477 Ce_id
CheckForRelatedCe_inNode(const CeNode & i_node,const StringVector & i_qualification,const String & i_name)478 CheckForRelatedCe_inNode( const CeNode & i_node,
479 const StringVector & i_qualification,
480 const String & i_name )
481 {
482 if (i_qualification.size() > 0)
483 {
484 Ce_id
485 ret(0);
486 i_node.SearchBelow( ret,
487 i_qualification.begin(),
488 i_qualification.end(),
489 i_name );
490 return ret;
491 }
492 else
493 {
494 return i_node.Search(i_name);
495 }
496 }
497
498
499 namespace ut
500 {
501
List_TplParameter()502 List_TplParameter::List_TplParameter()
503 : aTplParameters()
504 {
505 }
506
~List_TplParameter()507 List_TplParameter::~List_TplParameter()
508 {
509 csv::erase_container_of_heap_ptrs(aTplParameters);
510 }
511
512 void
AddParam_Type(Type_id i_nType)513 List_TplParameter::AddParam_Type( Type_id i_nType )
514 {
515 aTplParameters.push_back( new TplParameter_Type(i_nType) );
516 }
517
518 void
Get_Text(StreamStr & o_rOut,const ary::cpp::Gate & i_rGate) const519 List_TplParameter::Get_Text( StreamStr & o_rOut,
520 const ary::cpp::Gate & i_rGate ) const
521 {
522 Vector_TplArgument::const_iterator it = aTplParameters.begin();
523 Vector_TplArgument::const_iterator itEnd = aTplParameters.end();
524
525 if ( it == itEnd )
526 {
527 o_rOut << "<>";
528 return;
529 }
530
531 o_rOut << "< ";
532
533 (*it)->Get_Text( o_rOut, i_rGate );
534
535 for ( ++it; it != itEnd; ++it )
536 {
537 o_rOut << ", ";
538 (*it)->Get_Text( o_rOut, i_rGate );
539 }
540
541 o_rOut << " >";
542 }
543
544 intt
Compare(const List_TplParameter & i_rOther) const545 List_TplParameter::Compare( const List_TplParameter & i_rOther ) const
546 {
547 intt nResult = intt(aTplParameters.size()) - intt(i_rOther.aTplParameters.size());
548
549 if (nResult != 0)
550 return nResult;
551
552 Vector_TplArgument::const_iterator it1 = aTplParameters.begin();
553 Vector_TplArgument::const_iterator it1End = aTplParameters.end();
554 Vector_TplArgument::const_iterator it2 = i_rOther.aTplParameters.begin();
555
556 for ( ; it1 != it1End; ++it1, ++it2 )
557 {
558 nResult = (*it1)->Compare( *(*it2) );
559 if (nResult != 0)
560 return nResult;
561 }
562
563 return 0;
564 }
565
566
567 } // namespace ut
568 } // namespace cpp
569 } // namespace ary
570