The programming language will determine much of the information that is stored, but the target architecture will also influence what data is stored. Some assumptions about how to produce code can affect what value is stored in the table.
When one considers the range of information that can be stored about identifiers, it seems logical to classify identifiers in terms of the constructs they represent. In other words, different data will need to be stored for constants, variables, procedures, enumeration, and type definition, and so on.
Constants are identifiers that define a permanent value that can never be changed. Since programmers will wish to access these values by name, the name must be stored.
Variables are identifiers whose values may change between executions and during a single execution of a program. They represent the contents of some memory location. The symbol table needs to record both the variable name as well as its allocated storage space at runtime.
A user-defined type is a mixture of one or more current types. Types are created by name and reference a type definition structure. Each structure will record important information about itself, like its size, the names of its members, or its upper and lower bounds.
Procedures, functions, and methods are named segments of code. Naturally, the symbol table should record a procedure’s name.
The type they return (if any) should be noted. When sub-programs are accessed at runtime, it is typically by their locations in the code stream (or some handle to that location). Thus the location of the code generated for a given procedure should also be recorded.
Classes are abstract, a data type that restricts access to its members and encapsulation provides an appropriate language level polymorphism. They are a particular case of user-defined types and are structurally not different. But it may be convenient to store information about classes above and beyond that is required for other user-defined types.
There are many different ways to perform inheritance, and a symbol table record is needed to keep track of which classes are being inherited and exactly how inheritances are performed. In C++, the keywords public, private, and protected modify the visibility of inherited items and can be recorded with the inheritance information.
Arrays represent a collection of similar typed elements that may be randomly accessed by the index. For each dimension of an array, the compiler will need to know about such things as the lower boundary of the array (the lowest child index), the upper bound (the broadest child index), the index size, index type, the total size, and the type of the elements contained.
Records defines a set of possibly heterogeneous members which can be created by name. The compiler also needs to know the size of the record (how much space to allocate for all of the members).
It can store the module size, its name, parent, its members, and a timestamp. The timestamp is used to guarantee at load time that the modules have been compiled in the correct order or are all up to date.