--- /dev/null
+# OpenMP Semantic Analysis
+
+## F18 for OpenMP
+
+1. Define and document the parse tree representation for
+ * Directives (listed below)
+ * Clauses (listed below)
+ * Documentation
+1. All the directives and clauses need source provenance for messages
+1. Define and document how an OpenMP directive in the parse tree
+will be represented as the parent of the statement(s)
+to which the directive applies.
+The parser itself will not be able to construct this representation;
+there will be subsequent passes that do so
+just like for example _do-stmt_ and _do-construct_.
+1. Define and document the symbol table extensions
+1. Define and document the module file extensions
+
+
+### Directives
+
+OpenMP divides directives into three categories as follows.
+The directives that are in the same categories share some characteristics.
+
+
+
+#### Declarative directives
+
+An OpenMP directive that may only be placed in a declarative context.
+A declarative directive results in one or more declarations only;
+it is not associated with the immediate execution of any user code.
+
+List of existing ones:
+* declare simd
+* declare target
+* threadprivate
+* declare reduction
+
+There is a parser node for each of these directives and
+the parser node saves information associated with the directive,
+for example,
+the name of the procedure-name in the `declare simd` directive.
+
+Each parse tree node keeps source provenance,
+one for the directive name itself and
+one for the entire directive starting from the directive name.
+
+A top-level class, `OpenMPDeclarativeConstruct`,
+holds all four of the node types as discriminated unions
+along with the source provenance for the entire directive
+starting from `!$OMP`.
+
+In the `parser-tree.h`,
+`OpenMPDeclarativeConstruct` is part
+of the `SpecificationConstruct` and `SpecificationPart`
+in F18 because
+a declarative directive can only be placed in the specification part
+of a Fortran program.
+
+All the `_Names` or `_Designators` associated
+with the declarative directive will be resolved in later phases.
+
+#### Executable directives
+
+An OpenMP directive that is **not** declarative.
+That is, it may only be placed in an executable context.
+It contains stand-alone directives and constructs
+that are associated with code blocks.
+The stand-alone directive is described in the next section.
+
+The constructs associated with code blocks listed below
+share a similar structure:
+_Begin Directive_, _Clause List_, _Code Block_, _End Directive_.
+The _End Directive_ is optional for constructs
+like Loop-associated constructs.
+
+* Block-associated constructs (`OpenMPBlockConstruct`)
+* Loop-associated constructs (`OpenMPLoopConstruct`)
+* Atomic construct (`OpenMPAtomicConstruct`)
+* Sections Construct (`OpenMPSectionsConstruct`,
+ contains Sections/Parallel Sections constructs)
+* Critical Construct (`OpenMPCriticalConstruct`)
+
+A top-level class, `OpenMPConstruct`,
+includes stand-alone directive and constructs
+listed above as discriminated unions.
+
+In the `parse-tree.h`, `OpenMPConstruct` is an element
+of the `ExecutableConstruct`.
+
+All the `_Names` or `_Designators` associated
+with the executable directive will be resolved in Semantic Analysis.
+
+When the backtracking parser can not identify the associated code blocks,
+the parse tree will be rewritten later in the Semantics Analysis.
+
+#### Stand-alone Directives
+
+An OpenMP executable directive that has no associated user code
+except for that which appears in clauses in the directive.
+
+List of existing ones:
+* taskyield
+* barrier
+* taskwait
+* target enter data
+* target exit data
+* target update
+* ordered
+* flush
+* cancel
+* cancellation point
+
+A higher-level class is created for each categorys
+which contains directives listed above that share a similar structure:
+* OpenMPSimpleStandaloneConstruct
+(taskyield, barrier, taskwait,
+target enter/exit data, target update, ordered)
+* OpenMPFlushConstruct
+* OpenMPCancelConstruct
+* OpenMPCancellationPointConstruct
+
+A top-level class, `OpenMPStandaloneConstruct`,
+holds all four of the node types as discriminated unions
+along with the source provenance for the entire directive.
+Also, each parser node for the stand-alone directive saves
+the source provenance for the directive name itself.
+
+### Clauses
+
+Each clause represented as a distinct class in `parse-tree.h`.
+A top-level class, `OmpClause`, includes all the clauses as discriminated unions. The parser node for `OmpClause` saves the source provenance for the entire clause.
+
+All the `_Names` or `_Designators` associated
+with the clauses will be resolved in Semantic Analysis.
+
+Note that the backtracking parser will not validate
+that the list of clauses associated
+with a directive is valid other than to make sure they are well-formed.
+In particular,
+the parser does not check that
+the association between directive and clauses is correct
+nor check that the values in the directives or clauses are correct.
+These checks are deferred to later phases of semantics to simplify the parser.
+
+## Symbol Table Extensions for OpenMP
+
+Name resolution can be impacted by the OpenMP code.
+In addition to the regular steps to do the name resolution,
+new scopes and symbols may need to be created
+when encountering certain OpenMP constructs.
+This section describes the extensions
+for OpenMP during Symbol Table construction.
+
+OpenMP uses the fork-join model of parallel execution and
+all OpenMP threads have access to
+a _shared_ memory place to store and retrieve variables
+but each thread can also have access to
+its _threadprivate_ memory that must not be accessed by other threads.
+
+For the directives and clauses that can control the data environments,
+compiler needs to determine two kinds of _access_
+to variables used in the directive’s associated structured block:
+**shared** and **private**.
+Each variable referenced in the structured block
+has an original variable immediately outside of the OpenMP constructs. Reference to a shared variable in the structured block
+becomes a reference to the original variable.
+However, each private variable referenced in the structured block,
+a new version of the original variable (of the same type and size)
+will be created in the threadprivate memory.
+
+There are exceptions that directives/clauses
+need to create a new `Symbol` without creating a new `Scope`,
+but in general,
+when encountering each of the data environment controlling directives
+(discussed in the following sections),
+a new `Scope` will be created.
+For each private variable referenced in the structured block,
+a new `Symbol` is created out of the original variable
+and the new `Symbol` is associated
+with original variable’s `Symbol` via `HostAssocDetails`.
+A new set of OpenMP specific flags are added
+into `Flag` class in `symbol.h` to indicate the types of
+associations,
+data-sharing attributes,
+and data-mapping attributes
+in the OpenMP data environments.
+
+### New Symbol without new Scope
+
+OpenMP directives that require new `Symbol` to be created
+but not new `Scope` are listed in the following table
+in terms of the Symbol Table extensions for OpenMP:
+
+<table>
+ <tr>
+ <td rowspan="2" colspan="2" >Directives/Clauses
+ </td>
+ <td rowspan="2" >Create New
+<p>
+Symbol
+<p>
+w/
+ </td>
+ <td colspan="2" >Add Flag
+ </td>
+ </tr>
+ <tr>
+ <td>on Symbol of
+ </td>
+ <td>Flag
+ </td>
+ </tr>
+ <tr>
+ <td rowspan="4" >Declarative Directives
+ </td>
+ <td>declare simd [(proc-name)]
+ </td>
+ <td>-
+ </td>
+ <td>The name of the enclosing function, subroutine, or interface body to which it applies, or proc-name
+ </td>
+ <td>OmpDeclareSimd
+ </td>
+ </tr>
+ <tr>
+ <td>declare target
+ </td>
+ <td>-
+ </td>
+ <td>The name of the enclosing function, subroutine, or interface body to which it applies
+ </td>
+ <td>OmpDeclareTarget
+ </td>
+ </tr>
+ <tr>
+ <td>threadprivate(list)
+ </td>
+ <td>-
+ </td>
+ <td>named variables and named common blocks
+ </td>
+ <td>OmpThreadPrivate
+ </td>
+ </tr>
+ <tr>
+ <td>declare reduction
+ </td>
+ <td>*
+ </td>
+ <td>reduction-identifier
+ </td>
+ <td>OmpDeclareReduction
+ </td>
+ </tr>
+ <tr>
+ <td>Stand-alone directives
+ </td>
+ <td>flush
+ </td>
+ <td>-
+ </td>
+ <td>variable, array section or common block name
+ </td>
+ <td>OmpFlushed
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2" >critical [(name)]
+ </td>
+ <td>-
+ </td>
+ <td>name (user-defined identifier)
+ </td>
+ <td>OmpCriticalLock
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2" >if ([ directive-name-modifier :] scalar-logical-expr)
+ </td>
+ <td>-
+ </td>
+ <td>directive-name-modifier
+ </td>
+ <td>OmpIfSpecified
+ </td>
+ </tr>
+</table>
+
+
+ - No Action
+
+ * Discussed in “Module File Extensions for OpenMP” section
+
+
+### New Symbol with new Scope
+
+For the following OpenMP regions:
+
+* `target` regions
+* `teams` regions
+* `parallel` regions
+* `simd` regions
+* task generating regions (created by `task` or `taskloop` constructs)
+* worksharing regions
+(created by `do`, `sections`, `single`, or `workshare` constructs)
+
+A new `Scope` will be created
+when encountering the above OpenMP constructs
+to ensure the correct data environment during the Code Generation.
+To determine whether a variable referenced in these regions
+needs the creation of a new `Symbol`,
+all the data-sharing attribute rules
+described in OpenMP Spec [2.15.1] apply during the Name Resolution.
+The available data-sharing attributes are:
+**_shared_**,
+**_private_**,
+**_linear_**,
+**_firstprivate_**,
+and **_lastprivate_**.
+The attribute is represented as `Flag` in the `Symbol` object.
+
+More details are listed in the following table:
+
+<table>
+ <tr>
+ <td rowspan="2" >Attribute
+ </td>
+ <td rowspan="2" >Create New Symbol
+ </td>
+ <td colspan="2" >Add Flag
+ </td>
+ </tr>
+ <tr>
+ <td>on Symbol of
+ </td>
+ <td>Flag
+ </td>
+ </tr>
+ <tr>
+ <td>shared
+ </td>
+ <td>No
+ </td>
+ <td>Original variable
+ </td>
+ <td>OmpShared
+ </td>
+ </tr>
+ <tr>
+ <td>private
+ </td>
+ <td>Yes
+ </td>
+ <td>New Symbol
+ </td>
+ <td>OmpPrivate
+ </td>
+ </tr>
+ <tr>
+ <td>linear
+ </td>
+ <td>Yes
+ </td>
+ <td>New Symbol
+ </td>
+ <td>OmpLinear
+ </td>
+ </tr>
+ <tr>
+ <td>firstprivate
+ </td>
+ <td>Yes
+ </td>
+ <td>New Symbol
+ </td>
+ <td>OmpFirstPrivate
+ </td>
+ </tr>
+ <tr>
+ <td>lastprivate
+ </td>
+ <td>Yes
+ </td>
+ <td>New Symbol
+ </td>
+ <td>OmpLastPrivate
+ </td>
+ </tr>
+</table>
+
+To determine the right data-sharing attribute,
+OpenMP defines that the data-sharing attributes
+of variables that are referenced in a construct can be
+_predetermined_, _explicitly determined_, or _implicitly determined_.
+
+#### Predetermined data-sharing attributes
+
+* Assumed-size arrays are **shared**
+* The loop iteration variable(s)
+in the associated _do-loop(s)_ of a
+_do_,
+_parallel do_,
+_taskloop_,
+or _distributeconstruct_
+is (are) **private**
+* A loop iteration variable
+for a sequential loop in a _parallel_ or task generating construct
+is **private** in the innermost such construct that encloses the loop
+* Implied-do indices and _forall_ indices are **private**
+* The loop iteration variable in the associated _do-loop_
+of a _simd_ construct with just one associated _do-_taskloop_
+is **linear** with a linear-step
+that is the increment of the associated _do-loop_
+* The loop iteration variables in the associated _do-loop(s)_ of a _simd_
+construct with multiple associated _do-loop(s)_ are **lastprivate**
+
+#### Explicitly determined data-sharing attributes
+
+Variables with _explicitly determined_ data-sharing attributes are:
+
+* Variables are referenced in a given construct
+* Variables are listed in a data-sharing attribute clause on the construct.
+
+The data-sharing attribute clauses are:
+* _default_ clause
+(discussed in “Implicitly determined data-sharing attributes”)
+* _shared_ clause
+* _private_ clause
+* _linear_ clause
+* _firstprivate_ clause
+* _lastprivate_ clause
+* _reduction_ clause
+(new `Symbol` created with the flag `OmpReduction` set)
+
+Note that variables with _predetermined_ data-sharing attributes
+may not be listed (with exceptions) in data-sharing attribute clauses.
+
+#### Implicitly determined data-sharing attributes
+
+Variables with implicitly determined data-sharing attributes are:
+
+* Variables are referenced in a given construct
+* Variables do not have _predetermined_ data-sharing attributes
+* Variables are not listed in a data-sharing attribute clause
+on the construct.
+
+Rules for variables with _implicitly determined_ data-sharing attributes:
+
+* In a _parallel_ construct, if no _default_ clause is present,
+these variables are **shared**
+* In a task generating construct,
+if no _default_ clause is present,
+a variable for which the data-sharing attribute
+is not determined by the rules above
+and that in the enclosing context is determined
+to be shared by all implicit tasks
+bound to the current team is **shared**
+* In a _target_ construct,
+variables that are not mapped after applying data-mapping attribute rules
+(discussed later) are **firstprivate**
+* In an orphaned task generating construct,
+if no _default_ clause is present, dummy arguments are **firstprivate**
+* In a task generating construct, if no _default_ clause is present,
+a variable for which the data-sharing attribute is not determined
+by the rules above is **firstprivate**
+* For constructs other than task generating constructs or _target_constructs,
+if no _default_ clause is present,
+these variables reference the variables with the same names
+that exist in the enclosing context
+* In a _parallel_, _teams_, or task generating construct,
+the data-sharing attributes of these variables are determined
+by the _default_clause, if present:
+ * _default(shared)_
+ clause causes all variables referenced in the construct
+ that have _implicitly determined_ data-sharing attributes
+ to be **shared**
+ * _default(private)_
+ clause causes all variables referenced in the construct
+ that have _implicitly determined_ data-sharing attributes
+ to be **private**
+ * _default(firstprivate)_
+ clause causes all variables referenced in the construct
+ that have _implicitly determined_ data-sharing attributes
+ to be **firstprivate**
+ * _default(none)_
+ clause requires that each variable
+ that is referenced in the construct,
+ and that does not have a _predetermined_ data-sharing attribute,
+ must have its data-sharing attribute _explicitly determined_
+ by being listed in a data-sharing attribute clause
+
+
+### Data-mapping Attribute
+
+When encountering the _target data_ and _target_ directives,
+the data-mapping attributes of any variable referenced in a target region
+will be determined and represented as `Flag` in the `Symbol` object
+of the variable.
+No `Symbol` or `Scope` will be created.
+
+The basic steps to determine the data-mapping attribute are:
+
+1. If _map_ clause is present,
+the data-mapping attribute is determined by the _map-type_
+on the clause and its corresponding `Flag` are listed below:
+
+<table>
+ <tr>
+ <td>
+data-mapping attribute
+ </td>
+ <td>Flag
+ </td>
+ </tr>
+ <tr>
+ <td>to
+ </td>
+ <td>OmpMapTo
+ </td>
+ </tr>
+ <tr>
+ <td>from
+ </td>
+ <td>OmpMapFrom
+ </td>
+ </tr>
+ <tr>
+ <td>tofrom \
+(default if map-type is not present)
+ </td>
+ <td>OmpMapTo & OmpMapFrom
+ </td>
+ </tr>
+ <tr>
+ <td>alloc
+ </td>
+ <td>OmpMapAlloc
+ </td>
+ </tr>
+ <tr>
+ <td>release
+ </td>
+ <td>OmpMapRelease
+ </td>
+ </tr>
+ <tr>
+ <td>delete
+ </td>
+ <td>OmpMapDelete
+ </td>
+ </tr>
+</table>
+
+2. Otherwise, the following data-mapping rules apply
+for variables referenced in a _target_ construct
+that are _not_ declared in the construct and
+do not appear in data-sharing attribute or map clauses:
+ * If a variable appears in a _to _or _link _clause on a _declare target _directive then it is treated as if it had appeared in a _map _clause with a _map-type_ of **tofrom**
+3. Otherwise, the following implicit data-mapping attribute rules apply:
+ * If a _defaultmap(tofrom:scalar)_ clause is _not_ present
+ then a scalar variable is not mapped,
+ but instead has an implicit data-sharing attribute of **firstprivate**
+ * If a _defaultmap(tofrom:scalar)_ clause is present
+ then a scalar variable is treated as if it had appeared
+ in a map clause with a map-type of **tofrom**
+ * If a variable is not a scalar
+ then it is treated as if it had appeared in a map clause
+ with a _map-type_ of **tofrom**
+
+After the completion of the Name Resolution phase, all the data-sharing or data-mapping attributes marked for the `Symbols` may be used later in the Semantics Analysis and in the Code Generation.
+
+## Module File Extensions for OpenMP
+
+After the successful compilation of modules and submodules that may contain the following Declarative Directives, the entire directive starts from `!$OMP` needs to be written out into `.mod` files in their corresponding Specification Part:
+
+* _declare simd_ or _declare target_
+
+ In the “New Symbol without new Scope” section,
+ we described that when encountering these two declarative directives,
+ new `Flag` will be applied to the Symbol of the name of
+ the enclosing function, subroutine, or interface body to
+ which it applies, or proc-name.
+ This `Flag` should be part of the API information
+ for the given subroutine or function
+
+* _declare reduction_
+
+ The _reduction-identifier_ in this directive
+ can be use-associated or host-associated.
+ However, it will not act like other Symbols
+ because user may have a reduction name
+ that is the same as a Fortran entity name in the same scope.
+ Therefore a specific data structure needs to be created
+ to save the _reduction-identifier_ information
+ in the Scope and this directive needs to be written into `.mod` files
+
+## Phases of OpenMP Analysis
+
+1. Create the parse tree for OpenMP
+ 1. Add types for directives and clauses.
+ 1. Add type(s) that will be used for directives
+ 2. Add type(s) that will be used for clauses
+ 3. Add other types, e.g. wrappers or other containers
+ 4. Use std::variant to encapsulate meaningful types
+ 2. Implemented in the parser for OpenMP (openmp-grammar.h)
+2. Create canonical nesting
+ 1. Restructure parse tree to reflect the association
+ of directives and stmts
+ 1. Associate `OpenMPLoopConstruct`
+ with `DoConstruct` and `OpenMPEndLoopDirective`
+ 1. Investigate, and perhaps reuse,
+ the algorithm used to restructure do-loops
+ 2. Add a pass near the code that restructures do-loops;
+ but do not extend the code that handles do-loop for OpenMP;
+ keep this code separate.
+ 3. Report errors that prevent restructuring
+ (e.g. loop directive not followed by loop)
+ We should abort in case of errors
+ because there is no point to perform further checks
+ if it is not a legal OpenMP construct
+ 4. N.B. Consider moving this code and the do-loops code to the parser namespace.
+3. Validate the structured-block
+ 1. Structured-block is a block of executable statements
+ 1. Single entry and single exit
+ 1. Access to the structured block must not be the result of a branch
+ 1. The point of exit cannot be a branch out of the structured block
+4. Check that directive and clause combinations are legal
+ 1. Begin and End directive should match
+ 1. Simply check that the clauses are allowed by the directives
+ 1. Write as a separate pass for simplicity and correctness of the parse tree
+5. Write parse tree tests
+ 1. At this point, the parse tree should be perfectly formed
+ 1. Write tests that check for correct form and provenance information
+ 1. Write tests for errors that can occur during the restructuring
+6. Scope, symbol tables, and name resolution
+ 1. Update the existing code to handle names and scopes introduced by OpenMP
+ 1. Write tests to make sure names are properly implemented
+7. Check semantics that is specific to each directive
+ 1. Validate the directive and its clauses
+ 1. Some clause checks require the result of name resolution,
+ i.e. “A list item may appear in a _linear_ or _firstprivate_ clause
+ but not both.”
+ 1. TBD:
+ Validate the nested statement for legality in the scope of the directive
+ 1. Check the nesting of regions [OpenMP 4.5 spec 2.17]
+8. Module file utilities
+ 1. Write necessary OpenMP declarative directives to `.mod` files
+ 2. Update the existing code
+ to read available OpenMP directives from the `.mod` files