(Reference IEEE Std 1076-2008)
- Scope and visibility, 12.1 Declarative region:
With two exceptions, a declarative region is a portion of the text of the description. A single declarative region is formed by the text of each of the following:
...
i) A loop statement
...
A loop statement is a declarative region.
12.3 Visibility:
A declaration is visible only within a certain part of its scope; this part starts at the end of the declaration except in the declaration of a design unit other than a PSL verification unit, a package declaration, or a protected type declaration, in which case it starts immediately after the reserved word is occurring after the identifier of the design unit, a package declaration, or protected type declaration. This rule applies to both explicit and implicit declarations.
...
Finally, within the declarative region associated with a construct other than a record type declaration or a protected type, any declaration that occurs immediately within the region and that also occurs textually within the construct is visible by selection at the place of the suffix of an expanded name whose prefix denotes the construct. ...
...
A declaration is said to be hidden within (part of) an inner declarative region if the inner region contains a homograph of this declaration; the outer declaration is then hidden within the immediate scope of the inner homograph. Each of two declarations is said to be a homograph of the other if and only if both declarations have the same designator, 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 4.5.1).
The i
in the inner loop is a homograph of the i
in the outer loop, and the outer loops i
is not directly visible in the inner loop.
8.3 Selected names
A selected name is used to denote a named entity whose declaration appears either within the declaration of another named entity or within a design library.
...
The remaining forms of selected names are called expanded names. The prefix of an expanded name shall not be a function call.
An expanded name denotes a named entity declared immediately within a named construct if the prefix denotes a construct that is an entity declaration, an architecture body, a subprogram declaration, a subprogram body, a block statement, a process statement, a generate statement, a loop statement, or a protected type definition, and the suffix is the simple name, character literal, or operator symbol of a named entity whose declaration occurs immediately within that construct. This form of expanded name is only allowed within the construct itself, or if the prefix denotes an entity declaration and the expanded name occurs within an architecture body corresponding to the entity declaration.
So that leaves us asking how to construct an expanded name to denote a loop statement.
There's an example in 8.3 for a process statement (also shown in the LRM paragraph above):
P: process
variable DATA: INTEGER;
begin
-- Within process P, the name "P.DATA" denotes a named entity
-- declared in process P.
end process;
Statements aren't declared and don't have a name. The label serves to denote the prefix of the named entity who's simple name is the suffix.
So with a Minimal, Complete, and Verifiable example:
entity foo is
end entity;
architecture fum of foo is
signal mySignalVector: bit_vector (7 downto 0);
signal myOtherSignal: bit := '1';
begin
process
begin
L1:
for i in 0 to 9 loop
for i in 0 to 7 loop
mySignalVector(i) <= myOtherSignal;
report "outer loop i = " & integer'image(L1.i);
report "inner loop i = " & integer'image(i);
end loop;
end loop;
wait;
end process;
end architecture;
Using type bit simply to avoid a context clause, we get:
ghdl -r foo
looplabel.vhdl:14:17:@0ms:(report note): outer loop i = 0
looplabel.vhdl:15:17:@0ms:(report note): inner loop i = 0
looplabel.vhdl:14:17:@0ms:(report note): outer loop i = 0
looplabel.vhdl:15:17:@0ms:(report note): inner loop i = 1
looplabel.vhdl:14:17:@0ms:(report note): outer loop i = 0
looplabel.vhdl:15:17:@0ms:(report note): inner loop i = 2
looplabel.vhdl:14:17:@0ms:(report note): outer loop i = 0
looplabel.vhdl:15:17:@0ms:(report note): inner loop i = 3
looplabel.vhdl:14:17:@0ms:(report note): outer loop i = 0
looplabel.vhdl:15:17:@0ms:(report note): inner loop i = 4
looplabel.vhdl:14:17:@0ms:(report note): outer loop i = 0
looplabel.vhdl:15:17:@0ms:(report note): inner loop i = 5
looplabel.vhdl:14:17:@0ms:(report note): outer loop i = 0
looplabel.vhdl:15:17:@0ms:(report note): inner loop i = 6
looplabel.vhdl:14:17:@0ms:(report note): outer loop i = 0
looplabel.vhdl:15:17:@0ms:(report note): inner loop i = 7
looplabel.vhdl:14:17:@0ms:(report note): outer loop i = 1
looplabel.vhdl:15:17:@0ms:(report note): inner loop i = 0
(lines omitted for brevity)
looplabel.vhdl:14:17:@0ms:(report note): outer loop i = 9
looplabel.vhdl:15:17:@0ms:(report note): inner loop i = 0
looplabel.vhdl:14:17:@0ms:(report note): outer loop i = 9
looplabel.vhdl:15:17:@0ms:(report note): inner loop i = 1
looplabel.vhdl:14:17:@0ms:(report note): outer loop i = 9
looplabel.vhdl:15:17:@0ms:(report note): inner loop i = 2
looplabel.vhdl:14:17:@0ms:(report note): outer loop i = 9
looplabel.vhdl:15:17:@0ms:(report note): inner loop i = 3
looplabel.vhdl:14:17:@0ms:(report note): outer loop i = 9
looplabel.vhdl:15:17:@0ms:(report note): inner loop i = 4
looplabel.vhdl:14:17:@0ms:(report note): outer loop i = 9
looplabel.vhdl:15:17:@0ms:(report note): inner loop i = 5
looplabel.vhdl:14:17:@0ms:(report note): outer loop i = 9
looplabel.vhdl:15:17:@0ms:(report note): inner loop i = 6
looplabel.vhdl:14:17:@0ms:(report note): outer loop i = 9
looplabel.vhdl:15:17:@0ms:(report note): inner loop i = 7
and we find we can distinguish between the two implicitly declared i
s by using expanded names where appropriate, hardly obfuscation at all.