From 6a04c943908a9302683dd16b59fc72419ebd54b0 Mon Sep 17 00:00:00 2001 From: Ed Schonberg Date: Mon, 1 Jul 2019 13:34:30 +0000 Subject: [PATCH] [Ada] Compiler abort on use of Invalid_Value on numeric positive subtype Invalid_Value in most cases uses a predefined numeric value from a built-in table, but if the type does not include zero in its range, the literal 0 is used instead. In that case the value (produced by a call to Get_Simple_Init_Val) must be resolved for proper type information. The following must compile quietly: gnatmake -q main ---- with Problems; use Problems; with Text_IO; use Text_IO; procedure Main is begin Put_Line ("P1: " & P1'Image); Put_Line ("P2: " & P2'Image); Put_Line ("P3: " & P3'Image); Put_Line ("P4: " & P4'Image); end Main; -- package Problems is function P1 return Integer; function P2 return Long_Integer; -- Max. number of prime factors a number can have is log_2 N -- For N = 600851475143, this is ~ 40 -- type P3_Factors is array (1 .. 40) of Long_Integer; function P3 return Long_Integer; type P4_Palindrome is range 100*100 .. 999*999; function P4 return P4_Palindrome; end Problems; ---- package body Problems is function P1 return Integer is separate; function P2 return Long_Integer is separate; function P3 return Long_Integer is separate; function P4 return P4_Palindrome is separate; end Problems; ---- separate(Problems) function P1 return Integer is Sum : Integer range 0 .. 500_500 := 0; begin for I in Integer range 1 .. 1000 - 1 loop if I mod 3 = 0 or I mod 5 = 0 then Sum := Sum + I; end if; end loop; return Sum; end P1; -- separate(Problems) function P2 return Long_Integer is subtype Total is Long_Integer range 0 .. 8_000002e6 ; subtype Elem is Total range 0 .. 4e7 ; Sum : Total := 0; a, b, c : Elem; begin a := 1; b := 2; loop if b mod 2 = 0 then Sum := Sum + b; end if; c := b; b := a + b; a := c; exit when b >= 4e6; end loop; return Sum; end P2; -- with Text_IO; use Text_IO; with Ada.Numerics.Elementary_Functions; use Ada.Numerics.Elementary_Functions; separate(Problems) function P3 return Long_Integer is -- Greatest prime factor GPF : Long_Integer := 1; Dividend : Long_Integer := 600851475143; Factor : Long_Integer := 2; Quotient : Long_Integer; begin while Dividend > 1 loop Quotient := Dividend / Factor; if Dividend mod Factor = 0 then GPF := Factor; Dividend := Quotient; else if Factor >= Quotient then GPF := Dividend; exit; end if; Factor := Factor + 1; end if; end loop; return GPF; end P3; ---- with Text_IO; use Text_IO; separate(Problems) function P4 return P4_Palindrome is type TripleDigit is range 100 .. 999; a, b: TripleDigit := TripleDigit'First; c : P4_Palindrome; Max_Palindrome : P4_Palindrome := P4_Palindrome'Invalid_Value; function Is_Palindrome (X : in P4_Palindrome) return Boolean is type Int_Digit is range 0 .. 9; type Int_Digits is array (1 .. 6) of Int_Digit; type Digit_Extractor is range 0 .. P4_Palindrome'Last; Y : Digit_Extractor := Digit_Extractor (X); X_Digits : Int_Digits; begin for I in reverse X_Digits'Range loop X_Digits (I) := Int_Digit (Y mod 10); Y := Y / 10; end loop; return (X_Digits (1) = X_Digits (6) and X_Digits (2) = X_Digits (5) and X_Digits (3) = X_Digits (4)) or (X_Digits (2) = X_Digits (6) and X_Digits (3) = X_Digits (5) and X_Digits(1) = 0); end Is_Palindrome; begin for a in TripleDigit'Range loop for b in TripleDigit'Range loop c := P4_Palindrome (a * b); if Is_Palindrome (c) then if Max_Palindrome'Valid or else c > Max_Palindrome then Max_Palindrome := c; end if; end if; end loop; end loop; return Max_Palindrome; end; 2019-07-01 Ed Schonberg gcc/ada/ * exp_attr.adb (Expand_Attribute_Reference, case Invalid_Value): Resolve result of call to Get_Simple_Init_Val, which may be a conversion of a literal. From-SVN: r272855 --- gcc/ada/ChangeLog | 6 ++++++ gcc/ada/exp_attr.adb | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 5d58a2c..82e808b 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,9 @@ +2019-07-01 Ed Schonberg + + * exp_attr.adb (Expand_Attribute_Reference, case Invalid_Value): + Resolve result of call to Get_Simple_Init_Val, which may be a + conversion of a literal. + 2019-07-01 Hristian Kirtchev * freeze.adb (Freeze_Expression): Remove the horrible useless diff --git a/gcc/ada/exp_attr.adb b/gcc/ada/exp_attr.adb index 22368a1..cbf7db3 100644 --- a/gcc/ada/exp_attr.adb +++ b/gcc/ada/exp_attr.adb @@ -4242,6 +4242,11 @@ package body Exp_Attr is when Attribute_Invalid_Value => Rewrite (N, Get_Simple_Init_Val (Ptyp, N)); + -- The value produced may be a conversion of a literal, which + -- must be resolved to establish its proper type. + + Analyze_And_Resolve (N); + ---------- -- Last -- ---------- -- 2.7.4