xref: /trunk/main/autodoc/source/ary/cpp/usedtype.cxx (revision d291ea28)
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