next up previous
Next: Analyze specifiers Up: Type Analysis Previous: Constraints on operators

Associating types with identifiers

Each type is represented by a definition table key, and these keys are related to the abstract syntax tree by the Eli Typing module:

Instantiate modules[29]:

$/Type/Typing.gnrc :inst
This macro is defined in definitions 29, 49, 50, and 51.
This macro is invoked in definition 3.

This module classifies identifiers as either ``typed'' (representing entities, such as variables, that have a type property) or ``type definition'' (representing types themselves). Each occurrence of the identifier is either a ``definition'', at which the type property is set, or a ``use'' at which it is made available.

Certain constructs are also classified as ``type denotations''. These are the constructs that build new types from existing types.

Associate types with identifiers[30]:

SYMBOL Declaration          INHERITS TypedDefinition               END;
SYMBOL Declarator           INHERITS TypedDefinition               END;

SYMBOL TagDef               INHERITS TypeDefDefId, ChkTypeDefDefId END;
SYMBOL TagUse               INHERITS TypeDefUseId, ChkTypeDefUseId END;
SYMBOL ForwardDef           INHERITS TypeDefDefId, ChkTypeDefDefId END;
SYMBOL ForwardUse           INHERITS TypeDefDefId, ChkTypeDefDefId END;

SYMBOL MemberIdDef          INHERITS TypedDefId                    END;

SYMBOL enumeration_constant INHERITS TypedDefId                    END;
SYMBOL IdDef                INHERITS TypedDefId                    END;
SYMBOL IdUse                INHERITS TypedUseId,   ChkTypedUseId   END;

SYMBOL TypeIdDef            INHERITS TypeDefDefId, ChkTypeDefDefId END;
SYMBOL TypeIdUse            INHERITS TypeDefUseId, ChkTypeDefUseId END;
This macro is defined in definitions 30, 31, 32, and 33.
This macro is invoked in definition 1.

Definition table keys for derived types are created at tree nodes inheriting the TypeDenotation role of the Typing module, and passed to nodes inheriting other roles via attribute computations. Structures, unions and enumerations are specifiers; pointers, arrays, and functions are declarators.

Associate types with identifiers[31]:

ATTR IsStruct: int;

RULE: struct_or_union ::= 'struct' COMPUTE
  struct_or_union.IsStruct=1;
END;

RULE: struct_or_union ::= 'union' COMPUTE
  struct_or_union.IsStruct=0;
END;

SYMBOL struct_declaration_list INHERITS TypeDenotation, OperatorDefs COMPUTE
  SYNT.Pointer=NewType();
  SYNT.GotType=
    AddTypeToBlock(
      THIS.Pointer,
      PointerTypes,
      SingleDefTableKeyList(THIS.Type));
  SYNT.GotOper=
    ORDER(
      IF(THIS.IsStruct,
        InstClass0(TypeIs_Struct,THIS.Type),
        InstClass0(TypeIs_Union, THIS.Type)),
      InstClass1(TypeIs_Pointer,THIS.Pointer,THIS.Type));
END;

RULE: struct_or_union_specifier ::=
        struct_or_union TagDef '{' struct_declaration_list '}' COMPUTE
  struct_declaration_list.IsStruct=struct_or_union.IsStruct;
  struct_or_union_specifier.Type=struct_declaration_list.Type;
  TagDef.Type=struct_declaration_list.Type;
END;

RULE: struct_or_union_specifier ::=
        struct_or_union '{' struct_declaration_list '}' COMPUTE
  struct_declaration_list.IsStruct=struct_or_union.IsStruct;
  struct_or_union_specifier.Type=struct_declaration_list.Type;
END;

RULE: struct_or_union_specifier ::= struct_or_union ForwardUse COMPUTE
  struct_or_union_specifier.Type=ForwardUse.Type;
END;

SYMBOL enumerator_list INHERITS TypeDenotation, OperatorDefs COMPUTE
  SYNT.Pointer=NewType();
  SYNT.GotType=
    AddTypeToBlock(
      THIS.Pointer,
      PointerTypes,
      SingleDefTableKeyList(THIS.Type));
  SYNT.GotOper=
    ORDER(
      InstClass0(TypeIs_Enum,THIS.Type),
      InstClass1(TypeIs_Pointer,THIS.Pointer,THIS.Type));
END;

RULE: enum_specifier ::= 'enum' TagDef '{' enumerator_list '}' COMPUTE
  enum_specifier.Type=enumerator_list.Type;
  TagDef.Type=enumerator_list.Type;
END;

RULE: enum_specifier ::= 'enum' '{' enumerator_list '}' COMPUTE
  enum_specifier.Type=enumerator_list.Type;
END;

RULE: enum_specifier ::= 'enum' TagUse COMPUTE
  enum_specifier.Type=TagUse.Type;
END;
This macro is defined in definitions 30, 31, 32, and 33.
This macro is invoked in definition 1.

A type denoted by a specifier is independent of other types. Types denoted by declarator nodes, on the other hand, create a type by modifying another type. In each of these constructs, the original type comes from a set of specifiers. That original type is then passed through a nest of declarators, each of which creates a new type based on the type it receives.

Associate types with identifiers[32]:

CLASS SYMBOL Declaration COMPUTE
  SYNT.Type=NoKey;
END;

TREE SYMBOL declaration INHERITS Declaration END;

RULE: declaration ::= Specifiers init_declarator_list_opt ';' COMPUTE
  declaration.Type=Specifiers.Type;
END;

TREE SYMBOL struct_declaration INHERITS Declaration END;

RULE: struct_declaration ::= Specifiers struct_declarator_list ';' COMPUTE
  struct_declaration.Type=Specifiers.Type;
END;

TREE SYMBOL function_definition INHERITS Declaration END;

RULE: function_definition ::=
        Specifiers declaration_list FunctionDecl function_body COMPUTE
  function_definition.Type=Specifiers.Type;
END;

TREE SYMBOL parameter_declaration INHERITS Declaration END;

RULE: parameter_declaration ::= Specifiers COMPUTE
  parameter_declaration.Type=Specifiers.Type;
END;

RULE: parameter_declaration ::= Specifiers ParameterDecl COMPUTE
  parameter_declaration.Type=Specifiers.Type;
END;

RULE: parameter_declaration ::= Specifiers abstract_declarator COMPUTE
  parameter_declaration.Type=Specifiers.Type;
END;

TREE SYMBOL par_declaration INHERITS Declaration END;

RULE: par_declaration ::= Specifiers par_id_decls ';' COMPUTE
  par_declaration.Type=Specifiers.Type;
END;

TREE SYMBOL type_name INHERITS Declaration END;

RULE: type_name ::= Specifiers COMPUTE
  type_name.Type=Specifiers.Type;
END;

RULE: type_name ::= Specifiers abstract_declarator COMPUTE
  type_name.Type=Specifiers.Type;
END;
This macro is defined in definitions 30, 31, 32, and 33.
This macro is invoked in definition 1.

ForwardDef and TagUse require special treatment. According to Section 6.5.2.3 of the standard, each may define a new incomplete type. If the type is to be completed, a subsequent declaration can be given to specify the content. The strategy is to specify the type as the incomplete type void if and only if a type has not already been specified. When a type has already been specified, specify that type again. Since a construct in which the tag is followed by a bracketed list unconditionally set the type, that will override any type set in any other context.

Associate types with identifiers[33]:

SYMBOL ForwardType COMPUTE SYNT.Type=GetDefer(THIS.Key,TypeIs_void); END;
SYMBOL ForwardDef  INHERITS ForwardType END;
SYMBOL ForwardUse  INHERITS ForwardType END;
This macro is defined in definitions 30, 31, 32, and 33.
This macro is invoked in definition 1.



Subsections
next up previous
Next: Analyze specifiers Up: Type Analysis Previous: Constraints on operators
2008-08-30