1------------------------------------------------------------------------------ 2-- -- 3-- GNAT COMPILER COMPONENTS -- 4-- -- 5-- E X P _ I M G V -- 6-- -- 7-- B o d y -- 8-- -- 9-- Copyright (C) 2001-2018, Free Software Foundation, Inc. -- 10-- -- 11-- GNAT is free software; you can redistribute it and/or modify it under -- 12-- terms of the GNU General Public License as published by the Free Soft- -- 13-- ware Foundation; either version 3, or (at your option) any later ver- -- 14-- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- 15-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- 16-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -- 17-- for more details. You should have received a copy of the GNU General -- 18-- Public License distributed with GNAT; see file COPYING3. If not, go to -- 19-- http://www.gnu.org/licenses for a complete copy of the license. -- 20-- -- 21-- GNAT was originally developed by the GNAT team at New York University. -- 22-- Extensive contributions were provided by Ada Core Technologies Inc. -- 23-- -- 24------------------------------------------------------------------------------ 25 26with Atree; use Atree; 27with Casing; use Casing; 28with Checks; use Checks; 29with Einfo; use Einfo; 30with Exp_Util; use Exp_Util; 31with Lib; use Lib; 32with Namet; use Namet; 33with Nmake; use Nmake; 34with Nlists; use Nlists; 35with Opt; use Opt; 36with Rtsfind; use Rtsfind; 37with Sem_Aux; use Sem_Aux; 38with Sem_Res; use Sem_Res; 39with Sem_Util; use Sem_Util; 40with Sinfo; use Sinfo; 41with Snames; use Snames; 42with Stand; use Stand; 43with Stringt; use Stringt; 44with Tbuild; use Tbuild; 45with Ttypes; use Ttypes; 46with Uintp; use Uintp; 47with Urealp; use Urealp; 48 49package body Exp_Imgv is 50 51 function Has_Decimal_Small (E : Entity_Id) return Boolean; 52 -- Applies to all entities. True for a Decimal_Fixed_Point_Type, or an 53 -- Ordinary_Fixed_Point_Type with a small that is a negative power of ten. 54 -- Shouldn't this be in einfo.adb or sem_aux.adb??? 55 56 procedure Rewrite_Object_Image 57 (N : Node_Id; 58 Pref : Entity_Id; 59 Attr_Name : Name_Id; 60 Str_Typ : Entity_Id); 61 -- AI12-00124: Rewrite attribute 'Image when it is applied to an object 62 -- reference as an attribute applied to a type. N denotes the node to be 63 -- rewritten, Pref denotes the prefix of the 'Image attribute, and Name 64 -- and Str_Typ specify which specific string type and 'Image attribute to 65 -- apply (e.g. Name_Wide_Image and Standard_Wide_String). 66 67 ------------------------------------ 68 -- Build_Enumeration_Image_Tables -- 69 ------------------------------------ 70 71 procedure Build_Enumeration_Image_Tables (E : Entity_Id; N : Node_Id) is 72 Loc : constant Source_Ptr := Sloc (E); 73 Str : String_Id; 74 Ind : List_Id; 75 Lit : Entity_Id; 76 Nlit : Nat; 77 Len : Nat; 78 Estr : Entity_Id; 79 Eind : Entity_Id; 80 Ityp : Node_Id; 81 82 begin 83 -- Nothing to do for other than a root enumeration type 84 85 if E /= Root_Type (E) then 86 return; 87 88 -- Nothing to do if pragma Discard_Names applies 89 90 elsif Discard_Names (E) then 91 return; 92 end if; 93 94 -- Otherwise tables need constructing 95 96 Start_String; 97 Ind := New_List; 98 Lit := First_Literal (E); 99 Len := 1; 100 Nlit := 0; 101 102 loop 103 Append_To (Ind, 104 Make_Integer_Literal (Loc, UI_From_Int (Len))); 105 106 exit when No (Lit); 107 Nlit := Nlit + 1; 108 109 Get_Unqualified_Decoded_Name_String (Chars (Lit)); 110 111 if Name_Buffer (1) /= ''' then 112 Set_Casing (All_Upper_Case); 113 end if; 114 115 Store_String_Chars (Name_Buffer (1 .. Name_Len)); 116 Len := Len + Int (Name_Len); 117 Next_Literal (Lit); 118 end loop; 119 120 if Len < Int (2 ** (8 - 1)) then 121 Ityp := Standard_Integer_8; 122 elsif Len < Int (2 ** (16 - 1)) then 123 Ityp := Standard_Integer_16; 124 else 125 Ityp := Standard_Integer_32; 126 end if; 127 128 Str := End_String; 129 130 Estr := 131 Make_Defining_Identifier (Loc, 132 Chars => New_External_Name (Chars (E), 'S')); 133 134 Eind := 135 Make_Defining_Identifier (Loc, 136 Chars => New_External_Name (Chars (E), 'N')); 137 138 Set_Lit_Strings (E, Estr); 139 Set_Lit_Indexes (E, Eind); 140 141 Insert_Actions (N, 142 New_List ( 143 Make_Object_Declaration (Loc, 144 Defining_Identifier => Estr, 145 Constant_Present => True, 146 Object_Definition => 147 New_Occurrence_Of (Standard_String, Loc), 148 Expression => 149 Make_String_Literal (Loc, 150 Strval => Str)), 151 152 Make_Object_Declaration (Loc, 153 Defining_Identifier => Eind, 154 Constant_Present => True, 155 156 Object_Definition => 157 Make_Constrained_Array_Definition (Loc, 158 Discrete_Subtype_Definitions => New_List ( 159 Make_Range (Loc, 160 Low_Bound => Make_Integer_Literal (Loc, 0), 161 High_Bound => Make_Integer_Literal (Loc, Nlit))), 162 Component_Definition => 163 Make_Component_Definition (Loc, 164 Aliased_Present => False, 165 Subtype_Indication => New_Occurrence_Of (Ityp, Loc))), 166 167 Expression => 168 Make_Aggregate (Loc, 169 Expressions => Ind))), 170 Suppress => All_Checks); 171 end Build_Enumeration_Image_Tables; 172 173 ---------------------------- 174 -- Expand_Image_Attribute -- 175 ---------------------------- 176 177 -- For all cases other than user-defined enumeration types, the scheme 178 -- is as follows. First we insert the following code: 179 180 -- Snn : String (1 .. rt'Width); 181 -- Pnn : Natural; 182 -- Image_xx (tv, Snn, Pnn [,pm]); 183 -- 184 -- and then Expr is replaced by Snn (1 .. Pnn) 185 186 -- In the above expansion: 187 188 -- rt is the root type of the expression 189 -- tv is the expression with the value, usually a type conversion 190 -- pm is an extra parameter present in some cases 191 192 -- The following table shows tv, xx, and (if used) pm for the various 193 -- possible types of the argument: 194 195 -- For types whose root type is Character 196 -- xx = Character 197 -- tv = Character (Expr) 198 199 -- For types whose root type is Boolean 200 -- xx = Boolean 201 -- tv = Boolean (Expr) 202 203 -- For signed integer types with size <= Integer'Size 204 -- xx = Integer 205 -- tv = Integer (Expr) 206 207 -- For other signed integer types 208 -- xx = Long_Long_Integer 209 -- tv = Long_Long_Integer (Expr) 210 211 -- For modular types with modulus <= System.Unsigned_Types.Unsigned 212 -- xx = Unsigned 213 -- tv = System.Unsigned_Types.Unsigned (Expr) 214 215 -- For other modular integer types 216 -- xx = Long_Long_Unsigned 217 -- tv = System.Unsigned_Types.Long_Long_Unsigned (Expr) 218 219 -- For types whose root type is Wide_Character 220 -- xx = Wide_Character 221 -- tv = Wide_Character (Expr) 222 -- pm = Boolean, true if Ada 2005 mode, False otherwise 223 224 -- For types whose root type is Wide_Wide_Character 225 -- xx = Wide_Wide_Character 226 -- tv = Wide_Wide_Character (Expr) 227 228 -- For floating-point types 229 -- xx = Floating_Point 230 -- tv = Long_Long_Float (Expr) 231 -- pm = typ'Digits (typ = subtype of expression) 232 233 -- For ordinary fixed-point types 234 -- xx = Ordinary_Fixed_Point 235 -- tv = Long_Long_Float (Expr) 236 -- pm = typ'Aft (typ = subtype of expression) 237 238 -- For decimal fixed-point types with size = Integer'Size 239 -- xx = Decimal 240 -- tv = Integer (Expr) 241 -- pm = typ'Scale (typ = subtype of expression) 242 243 -- For decimal fixed-point types with size > Integer'Size 244 -- xx = Long_Long_Decimal 245 -- tv = Long_Long_Integer?(Expr) [convert with no scaling] 246 -- pm = typ'Scale (typ = subtype of expression) 247 248 -- For enumeration types other than those declared packages Standard 249 -- or System, Snn, Pnn, are expanded as above, but the call looks like: 250 251 -- Image_Enumeration_NN (rt'Pos (X), Snn, Pnn, typS, typI'Address) 252 253 -- where rt is the root type of the expression, and typS and typI are 254 -- the entities constructed as described in the spec for the procedure 255 -- Build_Enumeration_Image_Tables and NN is 32/16/8 depending on the 256 -- element type of Lit_Indexes. The rewriting of the expression to 257 -- Snn (1 .. Pnn) then occurs as in the other cases. A special case is 258 -- when pragma Discard_Names applies, in which case we replace expr by: 259 260 -- (rt'Pos (expr))'Img 261 262 -- So that the result is a space followed by the decimal value for the 263 -- position of the enumeration value in the enumeration type. 264 265 procedure Expand_Image_Attribute (N : Node_Id) is 266 Loc : constant Source_Ptr := Sloc (N); 267 Exprs : constant List_Id := Expressions (N); 268 Expr : constant Node_Id := Relocate_Node (First (Exprs)); 269 Pref : constant Node_Id := Prefix (N); 270 271 procedure Expand_User_Defined_Enumeration_Image; 272 -- Expand attribute 'Image in user-defined enumeration types, avoiding 273 -- string copy. 274 275 function Is_User_Defined_Enumeration_Type 276 (Typ : Entity_Id) return Boolean; 277 -- Return True if Typ is a user-defined enumeration type 278 279 ------------------------------------------- 280 -- Expand_User_Defined_Enumeration_Image -- 281 ------------------------------------------- 282 283 procedure Expand_User_Defined_Enumeration_Image is 284 Ins_List : constant List_Id := New_List; 285 P1_Id : constant Entity_Id := Make_Temporary (Loc, 'P'); 286 P2_Id : constant Entity_Id := Make_Temporary (Loc, 'P'); 287 P3_Id : constant Entity_Id := Make_Temporary (Loc, 'P'); 288 P4_Id : constant Entity_Id := Make_Temporary (Loc, 'P'); 289 Ptyp : constant Entity_Id := Entity (Pref); 290 Rtyp : constant Entity_Id := Root_Type (Ptyp); 291 S1_Id : constant Entity_Id := Make_Temporary (Loc, 'S'); 292 293 begin 294 -- Apply a validity check, since it is a bit drastic to get a 295 -- completely junk image value for an invalid value. 296 297 if not Expr_Known_Valid (Expr) then 298 Insert_Valid_Check (Expr); 299 end if; 300 301 -- Generate: 302 -- P1 : constant Natural := Pos; 303 304 Append_To (Ins_List, 305 Make_Object_Declaration (Loc, 306 Defining_Identifier => P1_Id, 307 Object_Definition => 308 New_Occurrence_Of (Standard_Natural, Loc), 309 Constant_Present => True, 310 Expression => 311 Convert_To (Standard_Natural, 312 Make_Attribute_Reference (Loc, 313 Attribute_Name => Name_Pos, 314 Prefix => New_Occurrence_Of (Ptyp, Loc), 315 Expressions => New_List (Expr))))); 316 317 -- Compute the index of the string start, generating: 318 -- P2 : constant Natural := call_put_enumN (P1); 319 320 Append_To (Ins_List, 321 Make_Object_Declaration (Loc, 322 Defining_Identifier => P2_Id, 323 Object_Definition => 324 New_Occurrence_Of (Standard_Natural, Loc), 325 Constant_Present => True, 326 Expression => 327 Convert_To (Standard_Natural, 328 Make_Indexed_Component (Loc, 329 Prefix => 330 New_Occurrence_Of (Lit_Indexes (Rtyp), Loc), 331 Expressions => 332 New_List (New_Occurrence_Of (P1_Id, Loc)))))); 333 334 -- Compute the index of the next value, generating: 335 -- P3 : constant Natural := call_put_enumN (P1 + 1); 336 337 declare 338 Add_Node : constant Node_Id := New_Op_Node (N_Op_Add, Loc); 339 340 begin 341 Set_Left_Opnd (Add_Node, New_Occurrence_Of (P1_Id, Loc)); 342 Set_Right_Opnd (Add_Node, Make_Integer_Literal (Loc, 1)); 343 344 Append_To (Ins_List, 345 Make_Object_Declaration (Loc, 346 Defining_Identifier => P3_Id, 347 Object_Definition => 348 New_Occurrence_Of (Standard_Natural, Loc), 349 Constant_Present => True, 350 Expression => 351 Convert_To (Standard_Natural, 352 Make_Indexed_Component (Loc, 353 Prefix => 354 New_Occurrence_Of (Lit_Indexes (Rtyp), Loc), 355 Expressions => 356 New_List (Add_Node))))); 357 end; 358 359 -- Generate: 360 -- S4 : String renames call_put_enumS (S2 .. S3 - 1); 361 362 declare 363 Sub_Node : constant Node_Id := New_Op_Node (N_Op_Subtract, Loc); 364 365 begin 366 Set_Left_Opnd (Sub_Node, New_Occurrence_Of (P3_Id, Loc)); 367 Set_Right_Opnd (Sub_Node, Make_Integer_Literal (Loc, 1)); 368 369 Append_To (Ins_List, 370 Make_Object_Renaming_Declaration (Loc, 371 Defining_Identifier => P4_Id, 372 Subtype_Mark => 373 New_Occurrence_Of (Standard_String, Loc), 374 Name => 375 Make_Slice (Loc, 376 Prefix => 377 New_Occurrence_Of (Lit_Strings (Rtyp), Loc), 378 Discrete_Range => 379 Make_Range (Loc, 380 Low_Bound => New_Occurrence_Of (P2_Id, Loc), 381 High_Bound => Sub_Node)))); 382 end; 383 384 -- Generate: 385 -- subtype S1 is string (1 .. P3 - P2); 386 387 declare 388 HB : constant Node_Id := New_Op_Node (N_Op_Subtract, Loc); 389 390 begin 391 Set_Left_Opnd (HB, New_Occurrence_Of (P3_Id, Loc)); 392 Set_Right_Opnd (HB, New_Occurrence_Of (P2_Id, Loc)); 393 394 Append_To (Ins_List, 395 Make_Subtype_Declaration (Loc, 396 Defining_Identifier => S1_Id, 397 Subtype_Indication => 398 Make_Subtype_Indication (Loc, 399 Subtype_Mark => 400 New_Occurrence_Of (Standard_String, Loc), 401 Constraint => 402 Make_Index_Or_Discriminant_Constraint (Loc, 403 Constraints => New_List ( 404 Make_Range (Loc, 405 Low_Bound => Make_Integer_Literal (Loc, 1), 406 High_Bound => HB)))))); 407 end; 408 409 -- Insert all the above declarations before N. We suppress checks 410 -- because everything is in range at this stage. 411 412 Insert_Actions (N, Ins_List, Suppress => All_Checks); 413 414 Rewrite (N, 415 Unchecked_Convert_To (S1_Id, New_Occurrence_Of (P4_Id, Loc))); 416 417 Analyze_And_Resolve (N, Standard_String); 418 end Expand_User_Defined_Enumeration_Image; 419 420 -------------------------------------- 421 -- Is_User_Defined_Enumeration_Type -- 422 -------------------------------------- 423 424 function Is_User_Defined_Enumeration_Type 425 (Typ : Entity_Id) return Boolean is 426 begin 427 return Ekind (Typ) = E_Enumeration_Type 428 and then Typ /= Standard_Boolean 429 and then Typ /= Standard_Character 430 and then Typ /= Standard_Wide_Character 431 and then Typ /= Standard_Wide_Wide_Character; 432 end Is_User_Defined_Enumeration_Type; 433 434 -- Local variables 435 436 Imid : RE_Id; 437 Ptyp : Entity_Id; 438 Rtyp : Entity_Id; 439 Tent : Entity_Id := Empty; 440 Ttyp : Entity_Id; 441 Proc_Ent : Entity_Id; 442 Enum_Case : Boolean; 443 444 Arg_List : List_Id; 445 -- List of arguments for run-time procedure call 446 447 Ins_List : List_Id; 448 -- List of actions to be inserted 449 450 Snn : constant Entity_Id := Make_Temporary (Loc, 'S'); 451 Pnn : constant Entity_Id := Make_Temporary (Loc, 'P'); 452 453 begin 454 if Is_Object_Image (Pref) then 455 Rewrite_Object_Image (N, Pref, Name_Image, Standard_String); 456 return; 457 458 -- Enable speed-optimized expansion of user-defined enumeration types 459 -- if we are compiling with optimizations enabled and enumeration type 460 -- literals are generated. Otherwise the call will be expanded into a 461 -- call to the runtime library. 462 463 elsif Optimization_Level > 0 464 and then not Global_Discard_Names 465 and then Is_User_Defined_Enumeration_Type (Root_Type (Entity (Pref))) 466 then 467 Expand_User_Defined_Enumeration_Image; 468 return; 469 end if; 470 471 Ptyp := Entity (Pref); 472 Rtyp := Root_Type (Ptyp); 473 474 -- Build declarations of Snn and Pnn to be inserted 475 476 Ins_List := New_List ( 477 478 -- Snn : String (1 .. typ'Width); 479 480 Make_Object_Declaration (Loc, 481 Defining_Identifier => Snn, 482 Object_Definition => 483 Make_Subtype_Indication (Loc, 484 Subtype_Mark => New_Occurrence_Of (Standard_String, Loc), 485 Constraint => 486 Make_Index_Or_Discriminant_Constraint (Loc, 487 Constraints => New_List ( 488 Make_Range (Loc, 489 Low_Bound => Make_Integer_Literal (Loc, 1), 490 High_Bound => 491 Make_Attribute_Reference (Loc, 492 Prefix => New_Occurrence_Of (Rtyp, Loc), 493 Attribute_Name => Name_Width)))))), 494 495 -- Pnn : Natural; 496 497 Make_Object_Declaration (Loc, 498 Defining_Identifier => Pnn, 499 Object_Definition => New_Occurrence_Of (Standard_Natural, Loc))); 500 501 -- Set Imid (RE_Id of procedure to call), and Tent, target for the 502 -- type conversion of the first argument for all possibilities. 503 504 Enum_Case := False; 505 506 if Rtyp = Standard_Boolean then 507 Imid := RE_Image_Boolean; 508 Tent := Rtyp; 509 510 -- For standard character, we have to select the version which handles 511 -- soft hyphen correctly, based on the version of Ada in use (this is 512 -- ugly, but we have no choice). 513 514 elsif Rtyp = Standard_Character then 515 if Ada_Version < Ada_2005 then 516 Imid := RE_Image_Character; 517 else 518 Imid := RE_Image_Character_05; 519 end if; 520 521 Tent := Rtyp; 522 523 elsif Rtyp = Standard_Wide_Character then 524 Imid := RE_Image_Wide_Character; 525 Tent := Rtyp; 526 527 elsif Rtyp = Standard_Wide_Wide_Character then 528 Imid := RE_Image_Wide_Wide_Character; 529 Tent := Rtyp; 530 531 elsif Is_Signed_Integer_Type (Rtyp) then 532 if Esize (Rtyp) <= Esize (Standard_Integer) then 533 Imid := RE_Image_Integer; 534 Tent := Standard_Integer; 535 else 536 Imid := RE_Image_Long_Long_Integer; 537 Tent := Standard_Long_Long_Integer; 538 end if; 539 540 elsif Is_Modular_Integer_Type (Rtyp) then 541 if Modulus (Rtyp) <= Modulus (RTE (RE_Unsigned)) then 542 Imid := RE_Image_Unsigned; 543 Tent := RTE (RE_Unsigned); 544 else 545 Imid := RE_Image_Long_Long_Unsigned; 546 Tent := RTE (RE_Long_Long_Unsigned); 547 end if; 548 549 elsif Is_Fixed_Point_Type (Rtyp) and then Has_Decimal_Small (Rtyp) then 550 if UI_To_Int (Esize (Rtyp)) <= Standard_Integer_Size then 551 Imid := RE_Image_Decimal; 552 Tent := Standard_Integer; 553 else 554 Imid := RE_Image_Long_Long_Decimal; 555 Tent := Standard_Long_Long_Integer; 556 end if; 557 558 elsif Is_Ordinary_Fixed_Point_Type (Rtyp) then 559 Imid := RE_Image_Ordinary_Fixed_Point; 560 Tent := Standard_Long_Long_Float; 561 562 elsif Is_Floating_Point_Type (Rtyp) then 563 Imid := RE_Image_Floating_Point; 564 Tent := Standard_Long_Long_Float; 565 566 -- Only other possibility is user-defined enumeration type 567 568 else 569 if Discard_Names (First_Subtype (Ptyp)) 570 or else No (Lit_Strings (Root_Type (Ptyp))) 571 then 572 -- When pragma Discard_Names applies to the first subtype, build 573 -- (Pref'Pos (Expr))'Img. 574 575 Rewrite (N, 576 Make_Attribute_Reference (Loc, 577 Prefix => 578 Make_Attribute_Reference (Loc, 579 Prefix => Pref, 580 Attribute_Name => Name_Pos, 581 Expressions => New_List (Expr)), 582 Attribute_Name => 583 Name_Img)); 584 Analyze_And_Resolve (N, Standard_String); 585 return; 586 587 else 588 -- Here for enumeration type case 589 590 Ttyp := Component_Type (Etype (Lit_Indexes (Rtyp))); 591 592 if Ttyp = Standard_Integer_8 then 593 Imid := RE_Image_Enumeration_8; 594 595 elsif Ttyp = Standard_Integer_16 then 596 Imid := RE_Image_Enumeration_16; 597 598 else 599 Imid := RE_Image_Enumeration_32; 600 end if; 601 602 -- Apply a validity check, since it is a bit drastic to get a 603 -- completely junk image value for an invalid value. 604 605 if not Expr_Known_Valid (Expr) then 606 Insert_Valid_Check (Expr); 607 end if; 608 609 Enum_Case := True; 610 end if; 611 end if; 612 613 -- Build first argument for call 614 615 if Enum_Case then 616 Arg_List := New_List ( 617 Make_Attribute_Reference (Loc, 618 Attribute_Name => Name_Pos, 619 Prefix => New_Occurrence_Of (Ptyp, Loc), 620 Expressions => New_List (Expr))); 621 622 else 623 Arg_List := New_List (Convert_To (Tent, Expr)); 624 end if; 625 626 -- Append Snn, Pnn arguments 627 628 Append_To (Arg_List, New_Occurrence_Of (Snn, Loc)); 629 Append_To (Arg_List, New_Occurrence_Of (Pnn, Loc)); 630 631 -- Get entity of procedure to call 632 633 Proc_Ent := RTE (Imid); 634 635 -- If the procedure entity is empty, that means we have a case in 636 -- no run time mode where the operation is not allowed, and an 637 -- appropriate diagnostic has already been issued. 638 639 if No (Proc_Ent) then 640 return; 641 end if; 642 643 -- Otherwise complete preparation of arguments for run-time call 644 645 -- Add extra arguments for Enumeration case 646 647 if Enum_Case then 648 Append_To (Arg_List, New_Occurrence_Of (Lit_Strings (Rtyp), Loc)); 649 Append_To (Arg_List, 650 Make_Attribute_Reference (Loc, 651 Prefix => New_Occurrence_Of (Lit_Indexes (Rtyp), Loc), 652 Attribute_Name => Name_Address)); 653 654 -- For floating-point types, append Digits argument 655 656 elsif Is_Floating_Point_Type (Rtyp) then 657 Append_To (Arg_List, 658 Make_Attribute_Reference (Loc, 659 Prefix => New_Occurrence_Of (Ptyp, Loc), 660 Attribute_Name => Name_Digits)); 661 662 -- For ordinary fixed-point types, append Aft parameter 663 664 elsif Is_Ordinary_Fixed_Point_Type (Rtyp) then 665 Append_To (Arg_List, 666 Make_Attribute_Reference (Loc, 667 Prefix => New_Occurrence_Of (Ptyp, Loc), 668 Attribute_Name => Name_Aft)); 669 670 if Has_Decimal_Small (Rtyp) then 671 Set_Conversion_OK (First (Arg_List)); 672 Set_Etype (First (Arg_List), Tent); 673 end if; 674 675 -- For decimal, append Scale and also set to do literal conversion 676 677 elsif Is_Decimal_Fixed_Point_Type (Rtyp) then 678 Append_To (Arg_List, 679 Make_Attribute_Reference (Loc, 680 Prefix => New_Occurrence_Of (Ptyp, Loc), 681 Attribute_Name => Name_Scale)); 682 683 Set_Conversion_OK (First (Arg_List)); 684 Set_Etype (First (Arg_List), Tent); 685 686 -- For Wide_Character, append Ada 2005 indication 687 688 elsif Rtyp = Standard_Wide_Character then 689 Append_To (Arg_List, 690 New_Occurrence_Of 691 (Boolean_Literals (Ada_Version >= Ada_2005), Loc)); 692 end if; 693 694 -- Now append the procedure call to the insert list 695 696 Append_To (Ins_List, 697 Make_Procedure_Call_Statement (Loc, 698 Name => New_Occurrence_Of (Proc_Ent, Loc), 699 Parameter_Associations => Arg_List)); 700 701 -- Insert declarations of Snn, Pnn, and the procedure call. We suppress 702 -- checks because we are sure that everything is in range at this stage. 703 704 Insert_Actions (N, Ins_List, Suppress => All_Checks); 705 706 -- Final step is to rewrite the expression as a slice and analyze, 707 -- again with no checks, since we are sure that everything is OK. 708 709 Rewrite (N, 710 Make_Slice (Loc, 711 Prefix => New_Occurrence_Of (Snn, Loc), 712 Discrete_Range => 713 Make_Range (Loc, 714 Low_Bound => Make_Integer_Literal (Loc, 1), 715 High_Bound => New_Occurrence_Of (Pnn, Loc)))); 716 717 Analyze_And_Resolve (N, Standard_String, Suppress => All_Checks); 718 end Expand_Image_Attribute; 719 720 ---------------------------- 721 -- Expand_Value_Attribute -- 722 ---------------------------- 723 724 -- For scalar types derived from Boolean, Character and integer types 725 -- in package Standard, typ'Value (X) expands into: 726 727 -- btyp (Value_xx (X)) 728 729 -- where btyp is he base type of the prefix 730 731 -- For types whose root type is Character 732 -- xx = Character 733 734 -- For types whose root type is Wide_Character 735 -- xx = Wide_Character 736 737 -- For types whose root type is Wide_Wide_Character 738 -- xx = Wide_Wide_Character 739 740 -- For types whose root type is Boolean 741 -- xx = Boolean 742 743 -- For signed integer types with size <= Integer'Size 744 -- xx = Integer 745 746 -- For other signed integer types 747 -- xx = Long_Long_Integer 748 749 -- For modular types with modulus <= System.Unsigned_Types.Unsigned 750 -- xx = Unsigned 751 752 -- For other modular integer types 753 -- xx = Long_Long_Unsigned 754 755 -- For floating-point types and ordinary fixed-point types 756 -- xx = Real 757 758 -- For Wide_[Wide_]Character types, typ'Value (X) expands into: 759 760 -- btyp (Value_xx (X, EM)) 761 762 -- where btyp is the base type of the prefix, and EM is the encoding method 763 764 -- For decimal types with size <= Integer'Size, typ'Value (X) 765 -- expands into 766 767 -- btyp?(Value_Decimal (X, typ'Scale)); 768 769 -- For all other decimal types, typ'Value (X) expands into 770 771 -- btyp?(Value_Long_Long_Decimal (X, typ'Scale)) 772 773 -- For enumeration types other than those derived from types Boolean, 774 -- Character, Wide_[Wide_]Character in Standard, typ'Value (X) expands to: 775 776 -- Enum'Val (Value_Enumeration_NN (typS, typI'Address, Num, X)) 777 778 -- where typS and typI and the Lit_Strings and Lit_Indexes entities 779 -- from T's root type entity, and Num is Enum'Pos (Enum'Last). The 780 -- Value_Enumeration_NN function will search the tables looking for 781 -- X and return the position number in the table if found which is 782 -- used to provide the result of 'Value (using Enum'Val). If the 783 -- value is not found Constraint_Error is raised. The suffix _NN 784 -- depends on the element type of typI. 785 786 procedure Expand_Value_Attribute (N : Node_Id) is 787 Loc : constant Source_Ptr := Sloc (N); 788 Typ : constant Entity_Id := Etype (N); 789 Btyp : constant Entity_Id := Base_Type (Typ); 790 Rtyp : constant Entity_Id := Root_Type (Typ); 791 Exprs : constant List_Id := Expressions (N); 792 Vid : RE_Id; 793 Args : List_Id; 794 Func : RE_Id; 795 Ttyp : Entity_Id; 796 797 begin 798 Args := Exprs; 799 800 if Rtyp = Standard_Character then 801 Vid := RE_Value_Character; 802 803 elsif Rtyp = Standard_Boolean then 804 Vid := RE_Value_Boolean; 805 806 elsif Rtyp = Standard_Wide_Character then 807 Vid := RE_Value_Wide_Character; 808 809 Append_To (Args, 810 Make_Integer_Literal (Loc, 811 Intval => Int (Wide_Character_Encoding_Method))); 812 813 elsif Rtyp = Standard_Wide_Wide_Character then 814 Vid := RE_Value_Wide_Wide_Character; 815 816 Append_To (Args, 817 Make_Integer_Literal (Loc, 818 Intval => Int (Wide_Character_Encoding_Method))); 819 820 elsif Rtyp = Base_Type (Standard_Short_Short_Integer) 821 or else Rtyp = Base_Type (Standard_Short_Integer) 822 or else Rtyp = Base_Type (Standard_Integer) 823 then 824 Vid := RE_Value_Integer; 825 826 elsif Is_Signed_Integer_Type (Rtyp) then 827 Vid := RE_Value_Long_Long_Integer; 828 829 elsif Is_Modular_Integer_Type (Rtyp) then 830 if Modulus (Rtyp) <= Modulus (RTE (RE_Unsigned)) then 831 Vid := RE_Value_Unsigned; 832 else 833 Vid := RE_Value_Long_Long_Unsigned; 834 end if; 835 836 elsif Is_Decimal_Fixed_Point_Type (Rtyp) then 837 if UI_To_Int (Esize (Rtyp)) <= Standard_Integer_Size then 838 Vid := RE_Value_Decimal; 839 else 840 Vid := RE_Value_Long_Long_Decimal; 841 end if; 842 843 Append_To (Args, 844 Make_Attribute_Reference (Loc, 845 Prefix => New_Occurrence_Of (Typ, Loc), 846 Attribute_Name => Name_Scale)); 847 848 Rewrite (N, 849 OK_Convert_To (Btyp, 850 Make_Function_Call (Loc, 851 Name => New_Occurrence_Of (RTE (Vid), Loc), 852 Parameter_Associations => Args))); 853 854 Set_Etype (N, Btyp); 855 Analyze_And_Resolve (N, Btyp); 856 return; 857 858 elsif Is_Real_Type (Rtyp) then 859 Vid := RE_Value_Real; 860 861 -- Only other possibility is user-defined enumeration type 862 863 else 864 pragma Assert (Is_Enumeration_Type (Rtyp)); 865 866 -- Case of pragma Discard_Names, transform the Value 867 -- attribute to Btyp'Val (Long_Long_Integer'Value (Args)) 868 869 if Discard_Names (First_Subtype (Typ)) 870 or else No (Lit_Strings (Rtyp)) 871 then 872 Rewrite (N, 873 Make_Attribute_Reference (Loc, 874 Prefix => New_Occurrence_Of (Btyp, Loc), 875 Attribute_Name => Name_Val, 876 Expressions => New_List ( 877 Make_Attribute_Reference (Loc, 878 Prefix => 879 New_Occurrence_Of (Standard_Long_Long_Integer, Loc), 880 Attribute_Name => Name_Value, 881 Expressions => Args)))); 882 883 Analyze_And_Resolve (N, Btyp); 884 885 -- Here for normal case where we have enumeration tables, this 886 -- is where we build 887 888 -- T'Val (Value_Enumeration_NN (typS, typI'Address, Num, X)) 889 890 else 891 Ttyp := Component_Type (Etype (Lit_Indexes (Rtyp))); 892 893 if Ttyp = Standard_Integer_8 then 894 Func := RE_Value_Enumeration_8; 895 elsif Ttyp = Standard_Integer_16 then 896 Func := RE_Value_Enumeration_16; 897 else 898 Func := RE_Value_Enumeration_32; 899 end if; 900 901 Prepend_To (Args, 902 Make_Attribute_Reference (Loc, 903 Prefix => New_Occurrence_Of (Rtyp, Loc), 904 Attribute_Name => Name_Pos, 905 Expressions => New_List ( 906 Make_Attribute_Reference (Loc, 907 Prefix => New_Occurrence_Of (Rtyp, Loc), 908 Attribute_Name => Name_Last)))); 909 910 Prepend_To (Args, 911 Make_Attribute_Reference (Loc, 912 Prefix => New_Occurrence_Of (Lit_Indexes (Rtyp), Loc), 913 Attribute_Name => Name_Address)); 914 915 Prepend_To (Args, 916 New_Occurrence_Of (Lit_Strings (Rtyp), Loc)); 917 918 Rewrite (N, 919 Make_Attribute_Reference (Loc, 920 Prefix => New_Occurrence_Of (Typ, Loc), 921 Attribute_Name => Name_Val, 922 Expressions => New_List ( 923 Make_Function_Call (Loc, 924 Name => 925 New_Occurrence_Of (RTE (Func), Loc), 926 Parameter_Associations => Args)))); 927 928 Analyze_And_Resolve (N, Btyp); 929 end if; 930 931 return; 932 end if; 933 934 -- Fall through for all cases except user-defined enumeration type 935 -- and decimal types, with Vid set to the Id of the entity for the 936 -- Value routine and Args set to the list of parameters for the call. 937 938 -- Compiling package Ada.Tags under No_Run_Time_Mode we disable the 939 -- expansion of the attribute into the function call statement to avoid 940 -- generating spurious errors caused by the use of Integer_Address'Value 941 -- in our implementation of Ada.Tags.Internal_Tag 942 943 -- Seems like a bit of a odd approach, there should be a better way ??? 944 945 -- There is a better way, test RTE_Available ??? 946 947 if No_Run_Time_Mode 948 and then Rtyp = RTE (RE_Integer_Address) 949 and then RTU_Loaded (Ada_Tags) 950 and then Cunit_Entity (Current_Sem_Unit) 951 = Body_Entity (RTU_Entity (Ada_Tags)) 952 then 953 Rewrite (N, 954 Unchecked_Convert_To (Rtyp, 955 Make_Integer_Literal (Loc, Uint_0))); 956 else 957 Rewrite (N, 958 Convert_To (Btyp, 959 Make_Function_Call (Loc, 960 Name => New_Occurrence_Of (RTE (Vid), Loc), 961 Parameter_Associations => Args))); 962 end if; 963 964 Analyze_And_Resolve (N, Btyp); 965 end Expand_Value_Attribute; 966 967 --------------------------------- 968 -- Expand_Wide_Image_Attribute -- 969 --------------------------------- 970 971 -- We expand typ'Wide_Image (X) as follows. First we insert this code: 972 973 -- Rnn : Wide_String (1 .. rt'Wide_Width); 974 -- Lnn : Natural; 975 -- String_To_Wide_String 976 -- (typ'Image (Expr), Rnn, Lnn, Wide_Character_Encoding_Method); 977 978 -- where rt is the root type of the prefix type 979 980 -- Now we replace the Wide_Image reference by 981 982 -- Rnn (1 .. Lnn) 983 984 -- This works in all cases because String_To_Wide_String converts any 985 -- wide character escape sequences resulting from the Image call to the 986 -- proper Wide_Character equivalent 987 988 -- not quite right for typ = Wide_Character ??? 989 990 procedure Expand_Wide_Image_Attribute (N : Node_Id) is 991 Loc : constant Source_Ptr := Sloc (N); 992 Pref : constant Entity_Id := Prefix (N); 993 Rnn : constant Entity_Id := Make_Temporary (Loc, 'S'); 994 Lnn : constant Entity_Id := Make_Temporary (Loc, 'P'); 995 Rtyp : Entity_Id; 996 997 begin 998 if Is_Object_Image (Pref) then 999 Rewrite_Object_Image (N, Pref, Name_Wide_Image, Standard_Wide_String); 1000 return; 1001 end if; 1002 1003 Rtyp := Root_Type (Entity (Pref)); 1004 1005 Insert_Actions (N, New_List ( 1006 1007 -- Rnn : Wide_String (1 .. base_typ'Width); 1008 1009 Make_Object_Declaration (Loc, 1010 Defining_Identifier => Rnn, 1011 Object_Definition => 1012 Make_Subtype_Indication (Loc, 1013 Subtype_Mark => 1014 New_Occurrence_Of (Standard_Wide_String, Loc), 1015 Constraint => 1016 Make_Index_Or_Discriminant_Constraint (Loc, 1017 Constraints => New_List ( 1018 Make_Range (Loc, 1019 Low_Bound => Make_Integer_Literal (Loc, 1), 1020 High_Bound => 1021 Make_Attribute_Reference (Loc, 1022 Prefix => New_Occurrence_Of (Rtyp, Loc), 1023 Attribute_Name => Name_Wide_Width)))))), 1024 1025 -- Lnn : Natural; 1026 1027 Make_Object_Declaration (Loc, 1028 Defining_Identifier => Lnn, 1029 Object_Definition => New_Occurrence_Of (Standard_Natural, Loc)), 1030 1031 -- String_To_Wide_String 1032 -- (typ'Image (X), Rnn, Lnn, Wide_Character_Encoding_Method); 1033 1034 Make_Procedure_Call_Statement (Loc, 1035 Name => 1036 New_Occurrence_Of (RTE (RE_String_To_Wide_String), Loc), 1037 1038 Parameter_Associations => New_List ( 1039 Make_Attribute_Reference (Loc, 1040 Prefix => Prefix (N), 1041 Attribute_Name => Name_Image, 1042 Expressions => Expressions (N)), 1043 New_Occurrence_Of (Rnn, Loc), 1044 New_Occurrence_Of (Lnn, Loc), 1045 Make_Integer_Literal (Loc, 1046 Intval => Int (Wide_Character_Encoding_Method))))), 1047 1048 -- Suppress checks because we know everything is properly in range 1049 1050 Suppress => All_Checks); 1051 1052 -- Final step is to rewrite the expression as a slice and analyze, 1053 -- again with no checks, since we are sure that everything is OK. 1054 1055 Rewrite (N, 1056 Make_Slice (Loc, 1057 Prefix => New_Occurrence_Of (Rnn, Loc), 1058 Discrete_Range => 1059 Make_Range (Loc, 1060 Low_Bound => Make_Integer_Literal (Loc, 1), 1061 High_Bound => New_Occurrence_Of (Lnn, Loc)))); 1062 1063 Analyze_And_Resolve (N, Standard_Wide_String, Suppress => All_Checks); 1064 end Expand_Wide_Image_Attribute; 1065 1066 -------------------------------------- 1067 -- Expand_Wide_Wide_Image_Attribute -- 1068 -------------------------------------- 1069 1070 -- We expand typ'Wide_Wide_Image (X) as follows. First we insert this code: 1071 1072 -- Rnn : Wide_Wide_String (1 .. rt'Wide_Wide_Width); 1073 -- Lnn : Natural; 1074 -- String_To_Wide_Wide_String 1075 -- (typ'Image (Expr), Rnn, Lnn, Wide_Character_Encoding_Method); 1076 1077 -- where rt is the root type of the prefix type 1078 1079 -- Now we replace the Wide_Wide_Image reference by 1080 1081 -- Rnn (1 .. Lnn) 1082 1083 -- This works in all cases because String_To_Wide_Wide_String converts any 1084 -- wide character escape sequences resulting from the Image call to the 1085 -- proper Wide_Wide_Character equivalent 1086 1087 -- not quite right for typ = Wide_Wide_Character ??? 1088 1089 procedure Expand_Wide_Wide_Image_Attribute (N : Node_Id) is 1090 Loc : constant Source_Ptr := Sloc (N); 1091 Pref : constant Entity_Id := Prefix (N); 1092 Rnn : constant Entity_Id := Make_Temporary (Loc, 'S'); 1093 Lnn : constant Entity_Id := Make_Temporary (Loc, 'P'); 1094 Rtyp : Entity_Id; 1095 1096 begin 1097 if Is_Object_Image (Pref) then 1098 Rewrite_Object_Image 1099 (N, Pref, Name_Wide_Wide_Image, Standard_Wide_Wide_String); 1100 return; 1101 end if; 1102 1103 Rtyp := Root_Type (Entity (Pref)); 1104 1105 Insert_Actions (N, New_List ( 1106 1107 -- Rnn : Wide_Wide_String (1 .. rt'Wide_Wide_Width); 1108 1109 Make_Object_Declaration (Loc, 1110 Defining_Identifier => Rnn, 1111 Object_Definition => 1112 Make_Subtype_Indication (Loc, 1113 Subtype_Mark => 1114 New_Occurrence_Of (Standard_Wide_Wide_String, Loc), 1115 Constraint => 1116 Make_Index_Or_Discriminant_Constraint (Loc, 1117 Constraints => New_List ( 1118 Make_Range (Loc, 1119 Low_Bound => Make_Integer_Literal (Loc, 1), 1120 High_Bound => 1121 Make_Attribute_Reference (Loc, 1122 Prefix => New_Occurrence_Of (Rtyp, Loc), 1123 Attribute_Name => Name_Wide_Wide_Width)))))), 1124 1125 -- Lnn : Natural; 1126 1127 Make_Object_Declaration (Loc, 1128 Defining_Identifier => Lnn, 1129 Object_Definition => New_Occurrence_Of (Standard_Natural, Loc)), 1130 1131 -- String_To_Wide_Wide_String 1132 -- (typ'Image (X), Rnn, Lnn, Wide_Character_Encoding_Method); 1133 1134 Make_Procedure_Call_Statement (Loc, 1135 Name => 1136 New_Occurrence_Of (RTE (RE_String_To_Wide_Wide_String), Loc), 1137 1138 Parameter_Associations => New_List ( 1139 Make_Attribute_Reference (Loc, 1140 Prefix => Prefix (N), 1141 Attribute_Name => Name_Image, 1142 Expressions => Expressions (N)), 1143 New_Occurrence_Of (Rnn, Loc), 1144 New_Occurrence_Of (Lnn, Loc), 1145 Make_Integer_Literal (Loc, 1146 Intval => Int (Wide_Character_Encoding_Method))))), 1147 1148 -- Suppress checks because we know everything is properly in range 1149 1150 Suppress => All_Checks); 1151 1152 -- Final step is to rewrite the expression as a slice and analyze, 1153 -- again with no checks, since we are sure that everything is OK. 1154 1155 Rewrite (N, 1156 Make_Slice (Loc, 1157 Prefix => New_Occurrence_Of (Rnn, Loc), 1158 Discrete_Range => 1159 Make_Range (Loc, 1160 Low_Bound => Make_Integer_Literal (Loc, 1), 1161 High_Bound => New_Occurrence_Of (Lnn, Loc)))); 1162 1163 Analyze_And_Resolve 1164 (N, Standard_Wide_Wide_String, Suppress => All_Checks); 1165 end Expand_Wide_Wide_Image_Attribute; 1166 1167 ---------------------------- 1168 -- Expand_Width_Attribute -- 1169 ---------------------------- 1170 1171 -- The processing here also handles the case of Wide_[Wide_]Width. With the 1172 -- exceptions noted, the processing is identical 1173 1174 -- For scalar types derived from Boolean, character and integer types 1175 -- in package Standard. Note that the Width attribute is computed at 1176 -- compile time for all cases except those involving non-static sub- 1177 -- types. For such subtypes, typ'[Wide_[Wide_]]Width expands into: 1178 1179 -- Result_Type (xx (yy (Ptyp'First), yy (Ptyp'Last))) 1180 1181 -- where 1182 1183 -- For types whose root type is Character 1184 -- xx = Width_Character 1185 -- yy = Character 1186 1187 -- For types whose root type is Wide_Character 1188 -- xx = Wide_Width_Character 1189 -- yy = Character 1190 1191 -- For types whose root type is Wide_Wide_Character 1192 -- xx = Wide_Wide_Width_Character 1193 -- yy = Character 1194 1195 -- For types whose root type is Boolean 1196 -- xx = Width_Boolean 1197 -- yy = Boolean 1198 1199 -- For signed integer types 1200 -- xx = Width_Long_Long_Integer 1201 -- yy = Long_Long_Integer 1202 1203 -- For modular integer types 1204 -- xx = Width_Long_Long_Unsigned 1205 -- yy = Long_Long_Unsigned 1206 1207 -- For types derived from Wide_Character, typ'Width expands into 1208 1209 -- Result_Type (Width_Wide_Character ( 1210 -- Wide_Character (typ'First), 1211 -- Wide_Character (typ'Last), 1212 1213 -- and typ'Wide_Width expands into: 1214 1215 -- Result_Type (Wide_Width_Wide_Character ( 1216 -- Wide_Character (typ'First), 1217 -- Wide_Character (typ'Last)); 1218 1219 -- and typ'Wide_Wide_Width expands into 1220 1221 -- Result_Type (Wide_Wide_Width_Wide_Character ( 1222 -- Wide_Character (typ'First), 1223 -- Wide_Character (typ'Last)); 1224 1225 -- For types derived from Wide_Wide_Character, typ'Width expands into 1226 1227 -- Result_Type (Width_Wide_Wide_Character ( 1228 -- Wide_Wide_Character (typ'First), 1229 -- Wide_Wide_Character (typ'Last), 1230 1231 -- and typ'Wide_Width expands into: 1232 1233 -- Result_Type (Wide_Width_Wide_Wide_Character ( 1234 -- Wide_Wide_Character (typ'First), 1235 -- Wide_Wide_Character (typ'Last)); 1236 1237 -- and typ'Wide_Wide_Width expands into 1238 1239 -- Result_Type (Wide_Wide_Width_Wide_Wide_Char ( 1240 -- Wide_Wide_Character (typ'First), 1241 -- Wide_Wide_Character (typ'Last)); 1242 1243 -- For real types, typ'Width and typ'Wide_[Wide_]Width expand into 1244 1245 -- if Ptyp'First > Ptyp'Last then 0 else btyp'Width end if 1246 1247 -- where btyp is the base type. This looks recursive but it isn't 1248 -- because the base type is always static, and hence the expression 1249 -- in the else is reduced to an integer literal. 1250 1251 -- For user-defined enumeration types, typ'Width expands into 1252 1253 -- Result_Type (Width_Enumeration_NN 1254 -- (typS, 1255 -- typI'Address, 1256 -- typ'Pos (typ'First), 1257 -- typ'Pos (Typ'Last))); 1258 1259 -- and typ'Wide_Width expands into: 1260 1261 -- Result_Type (Wide_Width_Enumeration_NN 1262 -- (typS, 1263 -- typI, 1264 -- typ'Pos (typ'First), 1265 -- typ'Pos (Typ'Last)) 1266 -- Wide_Character_Encoding_Method); 1267 1268 -- and typ'Wide_Wide_Width expands into: 1269 1270 -- Result_Type (Wide_Wide_Width_Enumeration_NN 1271 -- (typS, 1272 -- typI, 1273 -- typ'Pos (typ'First), 1274 -- typ'Pos (Typ'Last)) 1275 -- Wide_Character_Encoding_Method); 1276 1277 -- where typS and typI are the enumeration image strings and indexes 1278 -- table, as described in Build_Enumeration_Image_Tables. NN is 8/16/32 1279 -- for depending on the element type for typI. 1280 1281 -- Finally if Discard_Names is in effect for an enumeration type, then 1282 -- a special if expression is built that yields the space needed for the 1283 -- decimal representation of the largest pos value in the subtype. See 1284 -- code below for details. 1285 1286 procedure Expand_Width_Attribute (N : Node_Id; Attr : Atype := Normal) is 1287 Loc : constant Source_Ptr := Sloc (N); 1288 Typ : constant Entity_Id := Etype (N); 1289 Pref : constant Node_Id := Prefix (N); 1290 Ptyp : constant Entity_Id := Etype (Pref); 1291 Rtyp : constant Entity_Id := Root_Type (Ptyp); 1292 Arglist : List_Id; 1293 Ttyp : Entity_Id; 1294 XX : RE_Id; 1295 YY : Entity_Id; 1296 1297 begin 1298 -- Types derived from Standard.Boolean 1299 1300 if Rtyp = Standard_Boolean then 1301 XX := RE_Width_Boolean; 1302 YY := Rtyp; 1303 1304 -- Types derived from Standard.Character 1305 1306 elsif Rtyp = Standard_Character then 1307 case Attr is 1308 when Normal => XX := RE_Width_Character; 1309 when Wide => XX := RE_Wide_Width_Character; 1310 when Wide_Wide => XX := RE_Wide_Wide_Width_Character; 1311 end case; 1312 1313 YY := Rtyp; 1314 1315 -- Types derived from Standard.Wide_Character 1316 1317 elsif Rtyp = Standard_Wide_Character then 1318 case Attr is 1319 when Normal => XX := RE_Width_Wide_Character; 1320 when Wide => XX := RE_Wide_Width_Wide_Character; 1321 when Wide_Wide => XX := RE_Wide_Wide_Width_Wide_Character; 1322 end case; 1323 1324 YY := Rtyp; 1325 1326 -- Types derived from Standard.Wide_Wide_Character 1327 1328 elsif Rtyp = Standard_Wide_Wide_Character then 1329 case Attr is 1330 when Normal => XX := RE_Width_Wide_Wide_Character; 1331 when Wide => XX := RE_Wide_Width_Wide_Wide_Character; 1332 when Wide_Wide => XX := RE_Wide_Wide_Width_Wide_Wide_Char; 1333 end case; 1334 1335 YY := Rtyp; 1336 1337 -- Signed integer types 1338 1339 elsif Is_Signed_Integer_Type (Rtyp) then 1340 XX := RE_Width_Long_Long_Integer; 1341 YY := Standard_Long_Long_Integer; 1342 1343 -- Modular integer types 1344 1345 elsif Is_Modular_Integer_Type (Rtyp) then 1346 XX := RE_Width_Long_Long_Unsigned; 1347 YY := RTE (RE_Long_Long_Unsigned); 1348 1349 -- Real types 1350 1351 elsif Is_Real_Type (Rtyp) then 1352 Rewrite (N, 1353 Make_If_Expression (Loc, 1354 Expressions => New_List ( 1355 1356 Make_Op_Gt (Loc, 1357 Left_Opnd => 1358 Make_Attribute_Reference (Loc, 1359 Prefix => New_Occurrence_Of (Ptyp, Loc), 1360 Attribute_Name => Name_First), 1361 1362 Right_Opnd => 1363 Make_Attribute_Reference (Loc, 1364 Prefix => New_Occurrence_Of (Ptyp, Loc), 1365 Attribute_Name => Name_Last)), 1366 1367 Make_Integer_Literal (Loc, 0), 1368 1369 Make_Attribute_Reference (Loc, 1370 Prefix => New_Occurrence_Of (Base_Type (Ptyp), Loc), 1371 Attribute_Name => Name_Width)))); 1372 1373 Analyze_And_Resolve (N, Typ); 1374 return; 1375 1376 -- User-defined enumeration types 1377 1378 else 1379 pragma Assert (Is_Enumeration_Type (Rtyp)); 1380 1381 -- Whenever pragma Discard_Names is in effect, the value we need 1382 -- is the value needed to accommodate the largest integer pos value 1383 -- in the range of the subtype + 1 for the space at the start. We 1384 -- build: 1385 1386 -- Tnn : constant Integer := Rtyp'Pos (Ptyp'Last) 1387 1388 -- and replace the expression by 1389 1390 -- (if Ptyp'Range_Length = 0 then 0 1391 -- else (if Tnn < 10 then 2 1392 -- else (if Tnn < 100 then 3 1393 -- ... 1394 -- else n)))... 1395 1396 -- where n is equal to Rtyp'Pos (Ptyp'Last) + 1 1397 1398 -- Note: The above processing is in accordance with the intent of 1399 -- the RM, which is that Width should be related to the impl-defined 1400 -- behavior of Image. It is not clear what this means if Image is 1401 -- not defined (as in the configurable run-time case for GNAT) and 1402 -- gives an error at compile time. 1403 1404 -- We choose in this case to just go ahead and implement Width the 1405 -- same way, returning what Image would have returned if it has been 1406 -- available in the configurable run-time library. 1407 1408 if Discard_Names (Rtyp) then 1409 declare 1410 Tnn : constant Entity_Id := Make_Temporary (Loc, 'T'); 1411 Cexpr : Node_Id; 1412 P : Int; 1413 M : Int; 1414 K : Int; 1415 1416 begin 1417 Insert_Action (N, 1418 Make_Object_Declaration (Loc, 1419 Defining_Identifier => Tnn, 1420 Constant_Present => True, 1421 Object_Definition => 1422 New_Occurrence_Of (Standard_Integer, Loc), 1423 Expression => 1424 Make_Attribute_Reference (Loc, 1425 Prefix => New_Occurrence_Of (Rtyp, Loc), 1426 Attribute_Name => Name_Pos, 1427 Expressions => New_List ( 1428 Convert_To (Rtyp, 1429 Make_Attribute_Reference (Loc, 1430 Prefix => New_Occurrence_Of (Ptyp, Loc), 1431 Attribute_Name => Name_Last)))))); 1432 1433 -- OK, now we need to build the if expression. First get the 1434 -- value of M, the largest possible value needed. 1435 1436 P := UI_To_Int 1437 (Enumeration_Pos (Entity (Type_High_Bound (Rtyp)))); 1438 1439 K := 1; 1440 M := 1; 1441 while M < P loop 1442 M := M * 10; 1443 K := K + 1; 1444 end loop; 1445 1446 -- Build inner else 1447 1448 Cexpr := Make_Integer_Literal (Loc, K); 1449 1450 -- Wrap in inner if's until counted down to 2 1451 1452 while K > 2 loop 1453 M := M / 10; 1454 K := K - 1; 1455 1456 Cexpr := 1457 Make_If_Expression (Loc, 1458 Expressions => New_List ( 1459 Make_Op_Lt (Loc, 1460 Left_Opnd => New_Occurrence_Of (Tnn, Loc), 1461 Right_Opnd => Make_Integer_Literal (Loc, M)), 1462 Make_Integer_Literal (Loc, K), 1463 Cexpr)); 1464 end loop; 1465 1466 -- Add initial comparison for null range and we are done, so 1467 -- rewrite the attribute occurrence with this expression. 1468 1469 Rewrite (N, 1470 Convert_To (Typ, 1471 Make_If_Expression (Loc, 1472 Expressions => New_List ( 1473 Make_Op_Eq (Loc, 1474 Left_Opnd => 1475 Make_Attribute_Reference (Loc, 1476 Prefix => New_Occurrence_Of (Ptyp, Loc), 1477 Attribute_Name => Name_Range_Length), 1478 Right_Opnd => Make_Integer_Literal (Loc, 0)), 1479 Make_Integer_Literal (Loc, 0), 1480 Cexpr)))); 1481 1482 Analyze_And_Resolve (N, Typ); 1483 return; 1484 end; 1485 end if; 1486 1487 -- Normal case, not Discard_Names 1488 1489 Ttyp := Component_Type (Etype (Lit_Indexes (Rtyp))); 1490 1491 case Attr is 1492 when Normal => 1493 if Ttyp = Standard_Integer_8 then 1494 XX := RE_Width_Enumeration_8; 1495 elsif Ttyp = Standard_Integer_16 then 1496 XX := RE_Width_Enumeration_16; 1497 else 1498 XX := RE_Width_Enumeration_32; 1499 end if; 1500 1501 when Wide => 1502 if Ttyp = Standard_Integer_8 then 1503 XX := RE_Wide_Width_Enumeration_8; 1504 elsif Ttyp = Standard_Integer_16 then 1505 XX := RE_Wide_Width_Enumeration_16; 1506 else 1507 XX := RE_Wide_Width_Enumeration_32; 1508 end if; 1509 1510 when Wide_Wide => 1511 if Ttyp = Standard_Integer_8 then 1512 XX := RE_Wide_Wide_Width_Enumeration_8; 1513 elsif Ttyp = Standard_Integer_16 then 1514 XX := RE_Wide_Wide_Width_Enumeration_16; 1515 else 1516 XX := RE_Wide_Wide_Width_Enumeration_32; 1517 end if; 1518 end case; 1519 1520 Arglist := 1521 New_List ( 1522 New_Occurrence_Of (Lit_Strings (Rtyp), Loc), 1523 1524 Make_Attribute_Reference (Loc, 1525 Prefix => New_Occurrence_Of (Lit_Indexes (Rtyp), Loc), 1526 Attribute_Name => Name_Address), 1527 1528 Make_Attribute_Reference (Loc, 1529 Prefix => New_Occurrence_Of (Ptyp, Loc), 1530 Attribute_Name => Name_Pos, 1531 1532 Expressions => New_List ( 1533 Make_Attribute_Reference (Loc, 1534 Prefix => New_Occurrence_Of (Ptyp, Loc), 1535 Attribute_Name => Name_First))), 1536 1537 Make_Attribute_Reference (Loc, 1538 Prefix => New_Occurrence_Of (Ptyp, Loc), 1539 Attribute_Name => Name_Pos, 1540 1541 Expressions => New_List ( 1542 Make_Attribute_Reference (Loc, 1543 Prefix => New_Occurrence_Of (Ptyp, Loc), 1544 Attribute_Name => Name_Last)))); 1545 1546 Rewrite (N, 1547 Convert_To (Typ, 1548 Make_Function_Call (Loc, 1549 Name => New_Occurrence_Of (RTE (XX), Loc), 1550 Parameter_Associations => Arglist))); 1551 1552 Analyze_And_Resolve (N, Typ); 1553 return; 1554 end if; 1555 1556 -- If we fall through XX and YY are set 1557 1558 Arglist := New_List ( 1559 Convert_To (YY, 1560 Make_Attribute_Reference (Loc, 1561 Prefix => New_Occurrence_Of (Ptyp, Loc), 1562 Attribute_Name => Name_First)), 1563 1564 Convert_To (YY, 1565 Make_Attribute_Reference (Loc, 1566 Prefix => New_Occurrence_Of (Ptyp, Loc), 1567 Attribute_Name => Name_Last))); 1568 1569 Rewrite (N, 1570 Convert_To (Typ, 1571 Make_Function_Call (Loc, 1572 Name => New_Occurrence_Of (RTE (XX), Loc), 1573 Parameter_Associations => Arglist))); 1574 1575 Analyze_And_Resolve (N, Typ); 1576 end Expand_Width_Attribute; 1577 1578 ----------------------- 1579 -- Has_Decimal_Small -- 1580 ----------------------- 1581 1582 function Has_Decimal_Small (E : Entity_Id) return Boolean is 1583 begin 1584 return Is_Decimal_Fixed_Point_Type (E) 1585 or else 1586 (Is_Ordinary_Fixed_Point_Type (E) 1587 and then Ureal_10**Aft_Value (E) * Small_Value (E) = Ureal_1); 1588 end Has_Decimal_Small; 1589 1590 -------------------------- 1591 -- Rewrite_Object_Image -- 1592 -------------------------- 1593 1594 procedure Rewrite_Object_Image 1595 (N : Node_Id; 1596 Pref : Entity_Id; 1597 Attr_Name : Name_Id; 1598 Str_Typ : Entity_Id) 1599 is 1600 begin 1601 Rewrite (N, 1602 Make_Attribute_Reference (Sloc (N), 1603 Prefix => New_Occurrence_Of (Etype (Pref), Sloc (N)), 1604 Attribute_Name => Attr_Name, 1605 Expressions => New_List (Relocate_Node (Pref)))); 1606 1607 Analyze_And_Resolve (N, Str_Typ); 1608 end Rewrite_Object_Image; 1609end Exp_Imgv; 1610