ISAC: IR2099

From: Chuck Swart - MTI <cswart_at_.....>
Date: Tue Oct 09 2007 - 18:03:56 PDT
If at all possible, review this before Wednesday's meeting. Its almost 
certainly too complex to review in a few
minutes, but we need to move forward on this for VHDL-200X progress.

Chuck Swart


-- 
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.


-------------BEGINNING OF IR----------------

VHDL Issue Number:        2099

Language_Version          VHDL-2002
Classification            Language Definition Problem
Summary                   Alias declarations introduce homographs
Relevant_LRM_Sections     4.3.3.2 Nonobject aliases
                          10.3 Visibility
Related_Issues            
Key_Words_and_Phrases     nonobject aliases, homographs
Authors_Name              Peter Ashenden
Authors_Phone_Number      +61 414 709 106
Authors_Fax_Number        
Authors_Email_Address     peter@ashenden.com.au
Authors_Affiliation       Ashenden Designs
Authors_Address1          
Authors_Address2          
Authors_Address3          

Current Status:           Analyzed

Superseded By:

------------------------
Date Submitted:           14 June 2006
Date Analyzed:            26 September 2006
Author of Analysis:       Chuck Swart
Revision Number:          9
Date Last Revised:        04 September 2007

Description of Problem
----------------------

This issue was originally raised by John Ries in the Accellera VHDL-TC
review of P1076-2006/D2.11 and entered as Bugzilla bug #44. The issue
is applicable to the more recent P1076-2006/D3.0. Because it treats
issues with VHDL-2002 it has been entered as an ISAC IR.
    
On page 114 (of document P1076-2006/D2.11) in nonobject aliases it states :
    
    c) If the name denotes an enumeration type or a subtype of an
    enumeration type, then one implicit alias declaration for each of
    the literals of the base type immediately follows the alias
    declaration for the enumeration type; each such implicit
    declaration has, as its alias designator, the simple name or
    character literal of the literal and has, as its name, a name
    constructed by taking the name of the alias for the enumeration
    type or subtype and substituting the simple name or character
    literal being aliased for the simple name of the type or
    subtype. Each implicit alias has a signature that matches the
    parameter and result type profile of the literal being aliased.
    
    d) Alternatively, if the name denotes a subtype of a physical
    type, then one implicit alias declaration for each of the units of
    the base type immediately follows the alias declaration for the
    physical type; each such implicit declaration has, as its alias
    designator, the simple name of the unit and has, as its name, a
    name constructed by taking the name of the alias for the subtype
    of the physical type and substituting the simple name of the unit
    being aliased for the simple name of the subtype.
    
    e) Finally, if the name denotes a type or a subtype, then implicit
    alias declarations for each predefined operation for the
    type immediately follow the explicit alias declaration for the
    type or subtype and, if present, any implicit alias declarations
    for literals or units of the type. Each implicit alias has a
    signature that matches the parameter and result type profile of
    the implicit operation being aliased.
    
    
What happens if there is a homograph already declared or aliased?
    
For example (this is EXAMPLE 3 in the analysis section)
    
    type my_logic is ( '0', '1', 'X', 'Z');
    function "="( a, b: my_logic) return boolean;
    
    alias alt_logic is my_logic;
    -- the following alias are implicit
    
    alias '0' is '0' [ return my_logic];
    alias '1' is '1' [ return my_logic];
    alias 'X' is 'X' [ return my_logic];
    alias 'Z' is 'Z' [ return my_logic];
    alias "/=" is "/=" [ my_logic, my_logic, return boolean];
    alias "=" is "=" [ my_logic, my_logic, return boolean]; 
                                      -- note implicit "=" not explicit one.
    
    
It seems to me that all the aliases are homographs. In all cases
except the "=" these aliases denote the exact same objects so is this
an error?  In the case of "=" these are different functions: the alias
is to the predefined "=" and there is an explicit "=" already
declared.  Is this an error?  What happens if the explicit "=" is
declared after the alias?
    
This also raises the question, after I declare an alias to a type is
it legal to define an explicit version of a predefined operator on the
aliased type?
    
For example (this is EXAMPLE 4a in the analysis section)
    
    library ieee;
    package mycompare is
    
    alias std_logic is ieee.std_logic_1164.std_logic;
    
    -- there is an implicit alias
    alias "=" is ieee.std_logic_1164."="[ieee.std_logic_1164.std_ulogic,
      ieee.std_logic_1164.std_ulogic, return ieee.std_logic_1164.std_ulogic];
    
    -- Is this legal??
    function "=" ( a, b : std_logic) return boolean;
    ....
    
Does clause 10.3 statement 

    Two declarations that occur immediately within the same
    declarative region, other than the declarative region of a block
    implied by a component instantiation or the declarative region of
    a generic-mapped package or subprogram equivalent to a package
    instance or a subprogram instance, must not be homographs,
    unless exactly one of them is the implicit declaration of a
    predefined operation. In such cases, a predefined operation is
    always hidden by the other homograph.
    
apply here?
    
This needs to be resolved because the numeric_std package defines two
aliases to types. They are
    
    alias U_UNSIGNED is UNRESOLVED_UNSIGNED;
and
    alias U_SIGNED is UNRESOLVED_SIGNED;
    
Since the meaning of this is unclear, the LRM needs to either remove
the aliases from the package or define the behavior
    
Proposed Resolution
-------------------

VASG-ISAC Analysis & Rationale
------------------------------
    
It appears that the rules for nonobject aliases were written under the
assumption that the name being aliased is declared in a different
declarative region from the named entity being aliased. The example in
the LRM (see 4.5.2) illustrates that assumption, with the name BIT
being declared in STD.STANDARD. Aliasing a name declared in the same
declarative region as the aliased declaration introduces the issues
the submitter raised.
    
There are several cases for which the LRM seems overly restrictive.
Here are some examples which need to be covered (including extensions
of the submitter's examples). These examples are not necessarily
distinct, because they arise from different sources:

EXAMPLE 1a:

  package p_test is
    type my_logic is ( '0', '1', 'X', 'Z');
    alias alt_logic is my_logic;
  end package p_test;

EXAMPLE 1b: 

  package p_test is
    type my_logic is ( a, b, c, d);
    alias alt_logic is my_logic;
  end package p_test;

EXAMPLE 1b is EXAMPLE 1a with the enumeration literals changed to
avoid clouding the issue with bit and character literals. This example
implicitly declares, among other things:

  "="[my_logic, my_logic return boolean]
corresponding to the my_logic type declaration

and

  alias "=" is  "="[my_logic, my_logic return boolean]
corresponding the the alt_logic alias declaration

The issues are: Is this code legal and, if so, is an expression like 
a = b now ambiguous?

EXAMPLE 2:

  package p_test is
    alias std_logic1 is ieee.std_logic_1164.std_logic;
    alias std_logic2 is ieee.std_logic_1164.std_logic;
  end package p_test;

EXAMPLE 3:

  package p_test is
    type my_logic is ( '0', '1', 'X', 'Z');
    function "="( a, b: my_logic) return boolean;
    alias alt_logic is my_logic;
  end package p_test;

EXAMPLE 4a:

  package p_test is
    type my_logic is ( '0', '1', 'X', 'Z');
    alias alt_logic is my_logic;
    function "="( a, b: my_logic) return boolean;
  end package p_test;

EXAMPLE 4b:

  package p_test is
    type my_logic is ( '0', '1', 'X', 'Z');
    alias alt_logic is my_logic;
    function "="( a, b: alt_logic) return boolean;
  end package p_test;

EXAMPLE 5a:

  package p1 is
    function "=" (a,b: ieee.std_logic_1164.std_logic ) return boolean;
    ...
  end package p1;

  package p_test is
    use work.p1.all;
    ...
    alias std_logic is ieee.std_logic_1164.std_logic;
    -- implicit "="
    -- alias "=" is ieee.stdlogic_1164."="[ieee.stdlogic_1164.std_logic,
                                           ieee.stdlogic_1164.std_logic
                                           return boolean];
  end package p_test;

Which "=" operator, if any, is visible in package p_test?

EXAMPLE 5b:

Given the declarations from 5a, in a declarative region you have:

  use p_test.all;

Which "=" operator, if any, is visible in this declarative region?

EXAMPLE 5c:

  package p1 is
    function "=" (a,b: ieee.std_logic_1164.std_logic ) return boolean;
    ...
  end package p1;

  package p_test is
    use work.p1.all;
    ...
    alias my_std_logic is ieee.std_logic_1164.std_logic;
    -- implicit "="
    -- alias "=" is ieee.stdlogic_1164."="[ieee.stdlogic_1164.std_logic,
                                           ieee.stdlogic_1164.std_logic
                                           return boolean];
    alias "=" is work.p1."="[ieee.stdlogic_1164.std_logic,
                             ieee.stdlogic_1164.std_logic
                             return boolean];

  end package p_test;

Which "=" operator, if any, is visible in package p_test?

EXAMPLE 6:

  package p1 is
     type my_logic is ( '0', '1', 'X', 'Z');
  end package p1;

  package p2 is
  use p1.all;
     alias alt_logic is my_logic;
     function "=" ( a, b: my_logic) return boolean;
  end package p2

Under current rules the implicit alias to "=" [my_logic, my_logic,
return boolean] gives us two conflicting declarations of "=".
However, it seems that this code should be legal.

EXAMPLE 7:

  package p1 is
     type my_logic is ( '0', '1', 'X', 'Z');
  end package p1;

  package p2 is
  use p1.all;
     alias alt_logic is my_logic;
  end package p2;


  package p4 is
  use p1.all;
  use p2.all;
    constant C : alt_logic := 'X';
  end package p4;

It isn't clear whether this is legal or illegal under the VHDL-200X
interpretation which allows explicit declarations to hide implicit
declarations.

EXAMPLE 8:

  package p1 is
     type my_logic is ( '0', '1', 'X', 'Z');
  end package p1;

  package p2 is
  use p1.all;
     alias alt_logic is my_logic;
  end package p2;

  package p3 is
  use p1.all;
     alias other_logic is my_logic;
  end package p3;

  package p4 is
  use p3.all;
  use p2.all;
    constant C : alt_logic := 'X';
  end package p4;

This example appears to be illegal under current and D3.0 rules.
However, this code should probably be legal.

EXAMPLE 9a:

  package p1 is
     type T is (a,b,c); -- 1. implicit declaration "="[T,T return boolean]
     alias "=" is "=" [T,T return boolean]; -- 2. aliased "=" operator to implicit "=" from 1
     function "=" ( L,R : T) return boolean; -- 3. explicit declaration overloads "="
  end package p1;

This example is illegal under current rules because it contains two
homographs declared in the same declarative region. It's not clear
whether this should be legal under the new rules.

EXAMPLE 9b:

  package p1 is
     type T is (a,b,c); -- 1. implicit declaration "="[T,T return boolean]
     function "=" ( L,R : T) return boolean; -- 2. explicit declaration overloads "="
     alias "=" is "=" [T,T return boolean]; -- 3.  aliased "=" operator to explicit "=" from 2
  end package p1;

This example differs from 9a in that the alias refers to the
overloaded "=" operation instead of the implicitly defined "="
operation.  This example is illegal under current rules because it
contains two homographs declared in the same declarative regions. It's
not clear whether this should be legal under the new rules.

EXAMPLE 10a:

  package p1 is
      type T is (a,b,c);
  end package p1;

  package p2 is
      alias T is p1.T;
      -- alias "=" is "=" [T,T return boolean]; -- implicitly declared alias
  end package p2;

  package p3 is
      alias T is p1.T;
      -- alias "=" is "=" [T,T return boolean]; -- implicitly declared alias
  end package p2;

entity e is
  use p2.all;
  use p3.all;
  constant a1,b1: T := a;
  ... a1 = b1...
end entity e;

EXAMPLE 10b:

  package p1 is
      type T is (a,b,c);
  end package p1;

  package p2 is
      alias T is p1.T;
      function "=" (L,R:T) return boolean;
      alias "=" is "=" [T,T return boolean];
  end package p2;

  package p3 is
      alias T is p1.T;
      -- alias "=" is "=" [T,T return boolean]; -- implicitly declared alias
  end package p2;

entity e is
  use p2.all;
  use p3.all;
  constant a1,b1: T := a;
  ... a1 = b1...
end entity e;

EXAMPLE 10c:

  package p1 is
      type T is (a,b,c);
  end package p1;

  package p2 is
      alias T is p1.T;
      function "=" (L,R:T) return boolean;
      alias "=" is "=" [T,T return boolean];
  end package p2;

  package p3 is
      alias T is p1.T;
      function "=" (L,R:T) return boolean;
      alias "=" is "=" [T,T return boolean];
  end package p2;

entity e is
  use p2.all;
  use p3.all;
  constant a1,b1: T := a;
  ... a1 = b1...
end entity e;

Analysis:

Several of the examples should be legal, and implied aliases should
not introduce needless expression ambiguity.

The ISAC considered two possible approaches to resolving this issue.
The first approach is to add additional cases to Clause 10.4 to cover
various implicit/explicit combinations introduced by implicit aliases.

The second approach is to reword the LRM so that the following
principles hold:

Principle 1: An alias of a declaration is not a homograph of that
declaration and, in addition, two alias declarations with the same
designator that denote the same named entity are not homographs.  The
two declarations are viewed as if they were multiple references to the
same named entity. So nonobject aliases have more of a flavor of USE
clauses than of object declarations.

Principle 2: An implicitly declared alias of an implicitly predefined
operation is itself considered to be an implicitly predefined
operation (Implicitly declared aliases of overloaded operations don't
occur). So explicitly declared overloaded operations and explicitly
declared aliases will take precedence over implicitly declared aliases
with respect to visibility. This principle holds whether or not the
aliased name itself is explicitly declared.

Principle 3: The LRM states in clause 10.4 a) that "A potentially
visible declaration is not made directly visible if the place
considered is within the immediate scope of a homograph of the
declaration." In other words, visibility through use clauses is secondary
to visibility due to declarations. (This principle was not followed in
VHDL-200X version D3.0, but the resolution to Bugzilla Issue 131 restored
this principle in version D3.8.) Both explicit and implicit declarations
take precedence over potentially visible declarations.

The second approach appears to be the most intuitive and offers the
greatest flexibility to the language user.

This approach provides the following analysis of the various cases:

EXAMPLE 1a, by principle 1, the implicit declarations of aliases
of the enumeration values are not homographs of the original
declarations. Therefore, EXAMPLE 1a is legal and the expression a = b
is not ambiguous.

EXAMPLE 1b, the example is legal, and the expression a = b is not
ambiguous, since both "=" declarations denote the same function.

EXAMPLE 2, the implicit declarations associated with each alias are
not homographs. Therefore, example 2 is legal and the implicit operations
are visible as aliases.

EXAMPLE 3. Principle 2 implies that the explicitly declared "=" function
hides the alias of the implicit function "=" associated implicitly
with the alias alt_logic This implicit "=" function is a homograph of
the explicitly declared "=" function. EXAMPLE 3 is legal, and the
explicitly declared "=" is visible.

EXAMPLE 4a. It is legal to overload the implicitly declared "=" operation
associated with the alias alt_logic. EXAMPLE 4a is legal, and the
explicitly declared "=" is visible after its declaration.

EXAMPLE 4b. Since alt_logic is an alias for my_logic, by principle 1,
EXAMPLE 4b is the same as EXAMPLE 4a.

EXAMPLE 5a. From Principle 3, the implicit "=" operator associated
with the alias is (directly) visible and the overloaded "=" operator
from package p1 is not made directly visible.

EXAMPLE 5b. The implicit "=" operator associated with the alias is visible.

EXAMPLE 5c. This example shows how to make the overloaded "=" operator
from package p1 directly visible in package p_test.

EXAMPLE 6. by principle 3 the declared "=" operation overrides the
potentially visible one from package p1. EXAMPLE 6 is legal and the
explicitly declared "=" from package p2 is visible.

EXAMPLE 7. Each package provides a potentially visible alias of 'X',
but since both aliases refer to the same declaration, by principle 1
they are not homographs. EXAMPLE 7 is legal.

EXAMPLE 8. The implicit aliases in all packages refer to the same
declaration of 'X'. EXAMPLE 8 is legal.

EXAMPLE 9a. Two homographs are declared in the same declarative region.
Since neither is an implicit declaration or an implicit alias, this
code is illegal.

Note that an alternative solution was also examined. It was pointed
out that declarations (1) and (3) together were legal. Since both
declarations (1) and (2) refer to the same named entity, and the
situation described is legal in the absence of (2), why should the
presence of (2) make this illegal?

This solution was rejected because of the following analysis:
Declarations (3) and (1) are legal together because explicit
declarations override implicit declarations. This particular
application of the rule is necessary because the implicit operations
often do not provide the desired functionality.  However, (2) and (3)
are both explicit declarations. Note that declaration (2) accomplishes
no useful purpose. This is a very unusual situation, and could well be
a mistake on the part of the code writer. Therefore, it is reasonable
to make it illegal.

EXAMPLE 9b. The alias and the function denote the same named entity, so
by Principle 1 are not homographs, so this code is legal.

EXAMPLE 10a: The two type aliases in packages p2 and p3 are not
homographs since they denote the same named entity. Similarly, the two
implicit "=" operations are not homographs. Consequently, the "="
operation in entity e is visible and unambiguous, and the example is
legal.

EXAMPLE 10b: As in 10a, the two type aliases are not homographs since
they denote the same named entity. The two "=" aliases in package p2
and p3 are homographs, so the implicitly declared "=" alias in p3 is
overridden by the explicitly declared one in p2. The example is legal,
and the "=" operation in the entity is the overloaded one from p2.

EXAMPLE 10c: As in 10a, the two type aliases are not homographs since
they denote the same named entity. However, the "=" aliases in
packages p2 and p3 are homographs. Since neither is implicitly
declared, both are visible in entity e. Thus, the example is not
legal, since the "=" operation in entity e is ambiguous.

Note that there is a common belief that the two homographs from packages p2 and p3 are
not made directly visible. However, clause 10.4 rule b) in VHDL-2002 (and all earlier
versions) imply that both operations are directly visible. For more on this see Bugzilla #131.

With the proposed principles, all of the examples except, possibly,
EXAMPLE 5a, have reasonable interpretations. The one problematic
example is not expected to occur often in practice and EXAMPLE 5c
provides a way to get the intended effect.  The ISAC knows of no other
reasonable examples that have undesirable effects when these
principles are followed.

VASG-ISAC Recommendation for IEEE Std 1076-2002
-----------------------------------------------

The resolution of the various examples is not clear for VHDL-2002, and
may conceivably vary between implementations.

VASG-ISAC Recommendation for Future Revisions
---------------------------------------------

Make the following changes to VHDL-2002. Note that these changes also incorporate wording from
version D3.8 of VHDL-200X. These changes include:

LCS-2006-100 "Change visibility rules relating to use clauses and
explicitly declared homographs of implicit operations" (Ft-1)

Bugzilla Issue #131 "Does a potentially visible declaration hide a
label declaration?"

Bugzilla Issue #127 "Incorrect cross ref for profile in 10.3"

LCS-2006-135 "Formal generic types"

The changes relating to Bugzilla Issue #127 and LCS-2006-135 are not
related to the issues of this IR. They are included for completeness
and they are indicated with <...> in the proposed changes.

Clause 10.3 Visibility

Change:

"-- The visibility rules determine more than one possible meaning, In
such a case, the occurrence of the identifier is legal at this point
if and only if exactly one visible declaration is acceptable for the
overloading rules in the given context."

To:

"-- The visibility rules determine more than one possible meaning. In
such a case, the occurrence of the identifier is legal at this point
if and only if either exactly one visible declaration is acceptable
for the overloading rules in the given context or all visible
declarations denote the same named entity."

Change: 

Each of two declarations is said to be a homograph of the other
if both declarations have the same identifier, operator symbol, or
character literal, and if overloading is allowed for at most one of
the two. If overloading is allowed for both declarations, then each of
the two is a homograph of the other if they have the same identifier,
operator symbol, or character literal, as well as the same parameter
and result type profile ( see 3.1.1).

To:

Each of two declarations is said to be a homograph of the other if and
only if both declarations have the same identifier, operator symbol,
or character literal; and they denote different named entities; and
either overloading is allowed for at most one of the two, or
overloading is allowed for both declarations and they have the same
parameter and result type profile <(see 2.7)>.

Replace:

"Two declarations that occur immediately within the same declarative
region must not be homographs, unless exactly one of them is the
implicit declaration of a predefined operation."

with

"Two declarations that occur immediately within the same declarative
region,<, other than the declarative region of a block implied by a
component instantiation or the declarative region of a generic-mapped
package or subprogram equivalent to a package instance or a subprogram
instance,> must not be homographs, unless exactly one of them is the
implicit declaration of a predefined operation or is an implicit alias
of such an implicit declaration."

Replace:

"In such cases, a predefined operation is always hidden by the other
homograph."

With:

"In such cases, a predefined operation or alias thereof is always
hidden by the other homograph."

Clause 10.4 Use clauses

Replace

"A potentially visible declaration is actually made directly visible
except in the following two cases:

a) A potentially visible declaration is not made directly visible if
the place considered is within the immediate scope of a homograph of
the declaration.

b) Potentially visible declarations that have the same designator are
not made directly visible unless each of them is either an enumeration
literal specification or the declaration of a subprogram (either by a
subprogram declaration or by an implicit declaration)."

With

"A potentially visible declaration is actually made directly visible
except in the following three cases:

a) A potentially visible declaration is not made directly visible if
the place considered is within the immediate scope of a homograph of
the declaration.

b) If two potentially visible declarations are homographs and one is
explicitly declared and the other is implicitly declared, then the
implicit declaration is not made directly visible.

c) Potentially visible declarations that have the same designator and
that are not covered by case b) are not made directly visible unless
each of them is either an enumeration literal specification or the
declaration of a subprogram."


-------------END OF IR----------------
Received on Tue Oct 9 18:06:42 2007

This archive was generated by hypermail 2.1.8 : Tue Oct 09 2007 - 18:06:45 PDT