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 23 #include <precomp.h> 24 #include "ca_ce.hxx" 25 26 27 // NOT FULLY DEFINED SERVICES 28 #include <ary/qualiname.hxx> 29 #include <ary/cpp/inpcontx.hxx> 30 #include <ary/cpp/c_namesp.hxx> 31 #include <ary/cpp/c_class.hxx> 32 #include <ary/cpp/c_enum.hxx> 33 #include <ary/cpp/c_enuval.hxx> 34 #include <ary/cpp/c_funct.hxx> 35 #include <ary/cpp/c_tydef.hxx> 36 #include <ary/cpp/c_type.hxx> 37 #include <ary/cpp/c_vari.hxx> 38 #include <ary/cpp/cp_type.hxx> 39 #include <ary/loc/loc_file.hxx> 40 #include <ary/getncast.hxx> 41 42 43 44 45 46 47 namespace 48 { 49 50 String Get_NewAnonymousNamespaceName(); 51 String Get_NewAnonymousName( 52 char i_start ); 53 54 55 } // anonymous namespace 56 57 58 59 60 namespace ary 61 { 62 namespace cpp 63 { 64 65 66 // KORR_FUTURE 67 // What about namespace visibility ? 68 // Perhaps handle all/some visibility transfer only after parse is complete. 69 void 70 transfer_visibility( const Class * i_owner, 71 CodeEntity & o_child ) 72 { 73 if ( i_owner != 0 ? NOT i_owner->IsVisible() : false ) 74 o_child.Set_InVisible(); 75 } 76 77 inline const TypePilot & 78 CeAdmin::Types() const 79 { 80 csv_assert(pTypes != 0); 81 return *pTypes; 82 } 83 84 85 86 87 88 89 CeAdmin::CeAdmin(RepositoryPartition & io_myReposyPartition) 90 : aStorage(), 91 pTypes(0), 92 pCppRepositoryPartition(&io_myReposyPartition) 93 { 94 } 95 96 void 97 CeAdmin::Set_Related(const TypePilot & i_types) 98 { 99 pTypes = &i_types; 100 } 101 102 CeAdmin::~CeAdmin() 103 { 104 } 105 106 Namespace & 107 CeAdmin::CheckIn_Namespace( const InputContext & i_context, 108 const String & i_localName ) 109 { 110 const String 111 local_name = NOT i_localName.empty() 112 ? i_localName 113 : Get_NewAnonymousNamespaceName(); 114 Namespace & 115 rParent = i_context.CurNamespace(); 116 Namespace * 117 ret = rParent.Search_LocalNamespace(local_name); 118 if ( ret == 0 ) 119 { 120 ret = &Create_Namespace(rParent, local_name); 121 } 122 return *ret; 123 } 124 125 Class & 126 CeAdmin::Store_Class( const InputContext & i_context, 127 const String & i_localName, 128 E_ClassKey i_eClassKey ) 129 { 130 const String 131 local_name = i_localName.empty() 132 ? Get_NewAnonymousName( i_eClassKey == CK_class 133 ? 'c' 134 : i_eClassKey == CK_struct 135 ? 's' 136 : 'u' ) 137 : i_localName; 138 139 Class & 140 ret = * new Class( local_name, 141 i_context.CurOwner().CeId(), 142 i_context.CurProtection(), 143 i_context.CurFile().LeId(), 144 i_eClassKey ); 145 aStorage.Store_Type(ret); 146 i_context.CurOwner().Add_Class(local_name, ret.CeId()); 147 transfer_visibility(i_context.CurClass(), ret); 148 149 return ret; 150 } 151 152 Enum & 153 CeAdmin::Store_Enum( const InputContext & i_context, 154 const String & i_localName ) 155 { 156 const String 157 local_name = i_localName.empty() 158 ? Get_NewAnonymousName('e') 159 : i_localName; 160 Enum & 161 ret = * new Enum( local_name, 162 i_context.CurOwner().CeId(), 163 i_context.CurProtection(), 164 i_context.CurFile().LeId() ); 165 aStorage.Store_Type(ret); 166 i_context.CurOwner().Add_Enum(local_name, ret.CeId()); 167 transfer_visibility(i_context.CurClass(), ret); 168 169 return ret; 170 } 171 172 Typedef & 173 CeAdmin::Store_Typedef( const InputContext& i_context, 174 const String & i_localName, 175 Type_id i_referredType ) 176 { 177 Typedef & 178 ret = * new Typedef( i_localName, 179 i_context.CurOwner().CeId(), 180 i_context.CurProtection(), 181 i_context.CurFile().LeId(), 182 i_referredType ); 183 aStorage.Store_Type(ret); 184 i_context.CurOwner().Add_Typedef(i_localName, ret.CeId()); 185 transfer_visibility(i_context.CurClass(), ret); 186 187 return ret; 188 } 189 190 Function * 191 CeAdmin::Store_Operation( const InputContext & i_context, 192 const String & i_localName, 193 Type_id i_returnType, 194 const std::vector<S_Parameter> & i_parameters, 195 E_Virtuality i_virtuality, 196 E_ConVol i_conVol, 197 FunctionFlags i_flags, 198 bool i_throwExists, 199 const std::vector<Type_id> & i_exceptions ) 200 { 201 Function & 202 ret = * new Function( i_localName, 203 i_context.CurOwner().CeId(), 204 i_context.CurProtection(), 205 i_context.CurFile().LeId(), 206 i_returnType, 207 i_parameters, 208 i_conVol, 209 i_virtuality, 210 i_flags, 211 i_throwExists, 212 i_exceptions ); 213 214 // Check for double declaration: 215 Ce_id 216 nAlreadyExistingFunction(0); 217 switch ( lhf_CheckAndHandle_DuplicateOperation( 218 nAlreadyExistingFunction, 219 i_context, 220 ret) ) 221 { 222 case df_discard_new: 223 delete &ret; 224 return 0; 225 case df_replace: 226 csv_assert(nAlreadyExistingFunction.IsValid()); 227 aStorage.Replace_Entity( 228 nAlreadyExistingFunction, 229 ret ); 230 break; 231 case df_no: 232 aStorage.Store_Operation(ret); // Now it has a valid id. 233 i_context.CurOwner().Add_Operation( i_localName, ret.CeId(), i_flags.IsStaticMember() ); 234 break; 235 default: 236 csv_assert(false); 237 } 238 239 transfer_visibility(i_context.CurClass(), ret); 240 if ( i_context.CurProtection() != PROTECT_global ) 241 { 242 Class * 243 pClass = i_context.CurClass(); 244 if ( pClass != 0 AND i_virtuality != VIRTUAL_none) 245 { 246 pClass->UpdateVirtuality(i_virtuality); 247 } 248 } 249 250 return &ret; 251 } 252 253 Variable & 254 CeAdmin::Store_Variable( const InputContext& i_context, 255 const String & i_localName, 256 Type_id i_type, 257 VariableFlags i_flags, 258 const String & i_arraySize, 259 const String & i_initValue ) 260 { 261 Variable & 262 ret = * new Variable( i_localName, 263 i_context.CurOwner().CeId(), 264 i_context.CurProtection(), 265 i_context.CurFile().LeId(), 266 i_type, 267 i_flags, 268 i_arraySize, 269 i_initValue ); 270 271 bool 272 is_const = Types().Find_Type(i_type).IsConst(); 273 aStorage.Store_Datum(ret); 274 i_context.CurOwner().Add_Variable( 275 i_localName, 276 ret.CeId(), 277 is_const, 278 i_flags.IsStaticMember() ); 279 transfer_visibility(i_context.CurClass(), ret); 280 281 return ret; 282 } 283 284 EnumValue & 285 CeAdmin::Store_EnumValue( const InputContext & i_context, 286 const String & i_localName, 287 const String & i_initValue ) 288 { 289 Enum * 290 parent = i_context.CurEnum(); 291 csv_assert( parent != 0 ); 292 293 EnumValue & 294 ret = * new EnumValue( i_localName, 295 parent->CeId(), 296 i_initValue ); 297 aStorage.Store_Datum(ret); 298 parent->Add_Value(ret.CeId()); 299 300 // KORR also for current enum: 301 transfer_visibility(i_context.CurClass(), ret); 302 303 return ret; 304 } 305 306 const Namespace & 307 CeAdmin::GlobalNamespace() const 308 { 309 return ary_cast<Namespace>( aStorage[predefined::ce_GlobalNamespace] ); 310 } 311 312 const CodeEntity & 313 CeAdmin::Find_Ce(Ce_id i_id) const 314 { 315 return aStorage[i_id]; 316 } 317 318 const CodeEntity * 319 CeAdmin::Search_Ce(Ce_id i_id) const 320 { 321 return aStorage.Exists(i_id) 322 ? & aStorage[i_id] 323 : (const CodeEntity*)(0); 324 } 325 326 const CodeEntity * 327 CeAdmin::Search_CeAbsolute( const CodeEntity & i_curScope, 328 const QualifiedName & i_rSearchedName ) const 329 { 330 const symtree::Node<CeNode_Traits> * 331 cur_node = CeNode_Traits::NodeOf_(i_curScope); 332 csv_assert(cur_node != 0); 333 334 Ce_id 335 ret(0); 336 cur_node->SearchUp( ret, 337 i_rSearchedName.first_namespace(), 338 i_rSearchedName.end_namespace(), 339 i_rSearchedName.LocalName() ); 340 return Search_Ce(ret); 341 } 342 343 const CodeEntity * 344 CeAdmin::Search_CeLocal( const String & i_localName, 345 bool i_bIsFunction, 346 const Namespace & i_rCurNamespace, 347 const Class * i_pCurClass ) const 348 { 349 // KORR_FUTURE 350 // See if this is correct. 351 352 Ce_id 353 ret(0); 354 355 if ( NOT i_bIsFunction ) 356 { 357 CesResultList 358 type_instances = aStorage.TypeIndex().SearchAll(i_localName); 359 CesResultList 360 data_instances = aStorage.DataIndex().SearchAll(i_localName); 361 Ce_id 362 ret1 = Search_MatchingInstance( 363 type_instances, 364 (i_pCurClass 365 ? i_pCurClass->CeId() 366 : i_rCurNamespace.CeId()) 367 ); 368 Ce_id 369 ret2 = Search_MatchingInstance( 370 data_instances, 371 (i_pCurClass 372 ? i_pCurClass->CeId() 373 : i_rCurNamespace.CeId()) 374 ); 375 if (NOT ret2.IsValid()) 376 ret = ret1; 377 else if (NOT ret1.IsValid()) 378 ret = ret2; 379 } 380 else 381 { 382 CesResultList 383 function_instances = aStorage.OperationIndex().SearchAll(i_localName); 384 if ( function_instances.size() == 1 ) 385 ret = *function_instances.begin(); 386 else 387 { 388 ret = Search_MatchingInstance( 389 function_instances, 390 (i_pCurClass 391 ? i_pCurClass->CeId() 392 : i_rCurNamespace.CeId()) 393 ); 394 } 395 } 396 397 if ( ret.IsValid() ) 398 return & Find_Ce(ret); 399 400 return 0; 401 } 402 403 void 404 CeAdmin::Get_QualifiedName( StreamStr & o_rOut, 405 const String & i_localName, 406 Ce_id i_nOwner, 407 const char * i_sDelimiter ) const 408 { 409 if ( i_localName.empty() OR NOT i_nOwner.IsValid() ) 410 return; 411 412 const CodeEntity * 413 pOwner = & Find_Ce( i_nOwner ); 414 if ( is_type<Enum>(*pOwner) ) 415 pOwner = &Find_Ce( Ce_id(pOwner->Owner()) ); 416 417 Get_QualifiedName( o_rOut, 418 pOwner->LocalName(), 419 Ce_id(pOwner->Owner()), 420 i_sDelimiter ); 421 o_rOut 422 << i_sDelimiter 423 << i_localName; 424 } 425 426 void 427 CeAdmin::Get_SignatureText( StreamStr & o_rOut, 428 const OperationSignature & i_signature, 429 const StringVector * i_sParameterNames ) const 430 { 431 OperationSignature::ParameterTypeList::const_iterator 432 it = i_signature.Parameters().begin(); 433 OperationSignature::ParameterTypeList::const_iterator 434 it_end = i_signature.Parameters().end(); 435 436 const StringVector aDummy; 437 StringVector::const_iterator 438 itName = i_sParameterNames != 0 439 ? i_sParameterNames->begin() 440 : aDummy.begin(); 441 StringVector::const_iterator 442 itName_end = i_sParameterNames != 0 443 ? i_sParameterNames->end() 444 : aDummy.end(); 445 446 bool 447 bEmpty = (it == it_end); 448 if (NOT bEmpty) 449 { 450 o_rOut << "( "; 451 Types().Get_TypeText(o_rOut, *it); 452 if (itName != itName_end) 453 o_rOut << " " << (*itName); 454 455 for ( ++it; it != it_end; ++it ) 456 { 457 o_rOut << ", "; 458 Types().Get_TypeText(o_rOut, *it); 459 if (itName != itName_end) 460 { 461 ++itName; 462 if (itName != itName_end) 463 o_rOut << " " << (*itName); 464 } 465 } 466 o_rOut << " )"; 467 } 468 else 469 { 470 o_rOut << "( )"; 471 } 472 473 if ( intt(i_signature.ConVol()) & intt(ary::cpp::CONVOL_const) ) 474 o_rOut << " const"; 475 if ( intt(i_signature.ConVol()) & intt(ary::cpp::CONVOL_volatile) ) 476 o_rOut << " volatile"; 477 } 478 479 CesResultList 480 CeAdmin::Search_TypeName(const String & i_sName) const 481 { 482 return aStorage.TypeIndex().SearchAll(i_sName); 483 } 484 485 Namespace & 486 CeAdmin::GlobalNamespace() 487 { 488 return ary_cast<Namespace>( aStorage[predefined::ce_GlobalNamespace] ); 489 } 490 491 CeAdmin::E_DuplicateFunction 492 CeAdmin::lhf_CheckAndHandle_DuplicateOperation( 493 Ce_id & o_existentFunction, 494 const InputContext & i_context, 495 const Function & i_newFunction ) 496 { 497 if (i_context.CurProtection() != PROTECT_global) 498 { 499 // Assume, there will be no duplicates within the same class. 500 501 // KORR_FUTURE 502 // Assumption may be wrong in case of #defines providing different 503 // versions for different compilers. 504 return df_no; 505 } 506 507 std::vector<Ce_id> 508 aOperationsWithSameName; 509 i_context.CurNamespace().Search_LocalOperations( 510 aOperationsWithSameName, 511 i_newFunction.LocalName() ); 512 513 for ( std::vector<Ce_id>::const_iterator 514 it = aOperationsWithSameName.begin(); 515 it != aOperationsWithSameName.end(); 516 ++it ) 517 { 518 const Function & 519 rFunction = ary_cast<Function>(aStorage[*it]); 520 if ( rFunction.LocalName() == i_newFunction.LocalName() 521 AND rFunction.Signature() == i_newFunction.Signature() ) 522 { 523 if (NOT rFunction.IsIdentical(i_newFunction)) 524 { 525 // KORR_FUTURE Make this more detailed. 526 Cerr() << "Non identical function with same signature " 527 << "found: " 528 << i_context.CurNamespace().LocalName() 529 << "::" 530 << i_newFunction.LocalName() 531 << "(..)" 532 << Endl(); 533 } 534 o_existentFunction = rFunction.CeId(); 535 if (rFunction.Docu().Data() == 0) 536 return df_replace; 537 else 538 return df_discard_new; 539 } 540 } // end for 541 542 return df_no; 543 } 544 545 Namespace & 546 CeAdmin::Create_Namespace( Namespace & o_parent, 547 const String & i_localName ) 548 { 549 DYN Namespace & 550 ret = *new Namespace(i_localName, o_parent); 551 aStorage.Store_Entity(ret); 552 o_parent.Add_LocalNamespace(ret); 553 return ret; 554 } 555 556 Ce_id 557 CeAdmin::Search_MatchingInstance( CesResultList i_list, 558 Ce_id i_owner ) const 559 { 560 // KORR 561 // Multiple results? 562 563 for ( CesList::const_iterator it = i_list.begin(); 564 it != i_list.end(); 565 ++it ) 566 { 567 const CodeEntity & 568 ce = aStorage[*it]; 569 if ( ce.Owner() == i_owner) 570 { 571 return *it; 572 } 573 } 574 return Ce_id(0); 575 } 576 577 578 579 } // namespace cpp 580 } // namespace ary 581 582 583 584 namespace 585 { 586 587 uintt G_nLastFreeAnonymousNamespaceNr = 0; 588 uintt G_nLastFreeAnonymousEntityNr = 0; 589 590 String 591 Get_NewAnonymousNamespaceName() 592 { 593 StreamLock 594 sl(100); 595 return String( sl() 596 << "namespace_anonymous_" 597 << ++G_nLastFreeAnonymousNamespaceNr 598 << csv::c_str ); 599 600 } 601 602 String 603 Get_NewAnonymousName(char i_cStart) 604 { 605 StreamLock 606 sl(100); 607 return String( sl() 608 << i_cStart 609 << "_Anonymous__" 610 << ++G_nLastFreeAnonymousEntityNr 611 << c_str ); 612 } 613 614 615 616 } // namespace anonymous 617