Address TODOs in the intrinsic module ISO_FORTRAN_ENV, and extend the
implementation of NUMERIC_STORAGE_SIZE so that the calculation of its
value is deferred until it is needed so that the effects of
-fdefault-integer-8 or -fdefault-real-8 are reflected. Emit a warning
when NUMERIC_STORAGE_SIZE is used from the module file and the default
integer and real sizes do not match.
Fixes https://github.com/llvm/llvm-project/issues/87476.
When a program attempts to use a non-object entity as the base of a
component reference or type parameter inquiry, the message is somewhat
uninformative and the position of the entity's declaration will not
reflect any updates made to the symbol during name resolution.
Includes some NFC C++17 style clean-up on some code noticed while
debugging (missing mandatory braces).
A derived type name in an IMPLICIT statement might be a host association
or it might be a forward reference to a local derived type, which may be
shadowing a host-associated name. Add a scan over the specification part
in search of derived type definitions to determine the right
interpretation.
Fixes https://github.com/llvm/llvm-project/issues/87215.
Fortran allows the INTRINSIC attribute to be specified with a distinct
attribute statement, and also as part of the attribute list of a
type-declaration-stmt. This is an odd case (especially as the declared
type is mandated to be ignored if it doesn't match the type of the
intrinsic function) that can lead to odd error messages and crashes,
since the rest of name resolution expects that intrinsics with explicit
declarations will have been declared with INTRINSIC attribute
statements. Resolve by handling an "inline" INTRINSIC attribute as a
special case while processing a type-declaration-stmt, so that
real, intrinsic :: acos, asin, atan
is processed exactly as if it had been
intrinsic acos, asin, atan; real acos, asin, atan
Fixes https://github.com/llvm/llvm-project/issues/86382.
ConvertToObjectEntity() returns true for use- and host-associated object
symbols, too. Ensure in this case that the symbol really is a
non-associated object.
Fixes https://github.com/llvm/llvm-project/issues/85776.
…d type
When the same name is used for a derived type and generic interface in a
module, and no explicit PUBLIC or PRIVATE statement appears for the name
but the derived type definition does have an explicit accessibility,
that accessibility must also apply to the generic interface.
Save both the raw procedure interface symbol as well as the result of
passing it through GetUltimate() and BypassGeneric() in symbol table
entries with ProcEntityDetails. The raw symbol of the interface needs to
be the one used for emitting procedure symbols to module files.
Fixes https://github.com/llvm/llvm-project/issues/83836.
…ines
Name resolution needs to delay its default determination of module
external procedures as subroutines until after it has skimmed the
execution parts of module procedures.
Fixes https://github.com/llvm/llvm-project/issues/83622.
It's probably a bad idea to have a Cray pointer whose type is a derived
type that is not a sequence type, but the feature is a nonstandard
extension in the first place. Downgrade the message to a warning.
Fixes https://github.com/llvm/llvm-project/issues/82210.
Use BypassGeneric() to process the name of an interface in a procedure
declaration statement, so that if it's the name of a generic with a
homonymous specific procedure, that's what defines the interface.
Fixes https://github.com/llvm/llvm-project/issues/82267.
Fortran allows a procedure declaration statement with no interface or
type, with an explicit type declaration statement elsewhere being used
to define a function's result.
Fixes https://github.com/llvm/llvm-project/issues/82006.
When DATA statement objects have derived types obtained by implicit
typing rules, their types aren't known until specification part
processing is complete. In the case of a derived type, any component
name in a designator may still be in need of name resolution. Take care
of it in the deferred check visitor that runs at the end of name
resolution in each specification and execution part.
Fixes https://github.com/llvm/llvm-project/issues/82069.
…istinguishing characteristic
We note whether a procedure's interface is explicit or implicit as an
attribute of its characteristics, so that other semantics can be checked
appropriately, but this internal attribute should not be used as a
distinguishing characteristic in itself.
Fixes https://github.com/llvm/llvm-project/issues/81876.
When statement function expressions are analyzed, ensure that the
semantics context has a valid location set, otherwise a type spec (like
"integer::") can lead to a crash.
Fixes https://github.com/llvm/llvm-project/issues/80532.
When a separate module procedure is defined with a MODULE PROCEDURE and
its corresponding interface has a binding label, the compiler was
emitting an error about mismatching binding labels because the binding
label wasn't being copied into the subprogram's definition.
The standard states that data objects involved in an asynchronous data
transfer statement gain the ASYNCHRONOUS attribute implicitly in the
surrounding subprogram or BLOCK scope. This attribute affects the checks
in call semantics, as an ASYNCHRONOUS actual object associated with an
ASYNCHRONOUS dummy argument must not require data copies in or out.
(Most compilers don't implement implied ASYNCHRONOUS attributes
correctly; XLF gets these right, and GNU is close.)
f18's module files are Fortran with a leading header comment containing
the module file format version and a hash of the following contents.
This hash is currently used only to protect module files against
corruption and truncation.
Extend the use of these hashes to catch or avoid some error cases. When
one module file depends upon another, note its hash in additional module
file header comments. This allows the compiler to detect when the module
dependency is on a module file that has been updated. Further, it allows
the compiler to find the right module file dependency when the same
module file name appears in multiple directories on the module search
path.
The order in which module files are written, when multiple modules
appear in a source file, is such that every dependency is written before
the module(s) that depend upon it, so that their hashes are known.
A warning is emitted when a module file is not the first hit on the
module file search path.
Further work is needed to add a compiler option that emits (larger)
stand-alone module files that incorporate copies of their dependencies
rather than relying on search paths. This will be desirable for
application libraries that want to ship only "top-level" module files
without needing to include their dependencies.
Another future work item would be to admit multiple modules in the same
compilation with the same name if they have distinct hashes.
The following test cases crashes. The problem is that the fix for PR
https://github.com/llvm/llvm-project/pull/80738 is not quite complete.
It should `GetUltimate()` of the `interface_` before check if it is
generic.
```
MODULE M
CONTAINS
FUNCTION Int(Arg)
INTEGER :: Int, Arg
Int = Arg
END FUNCTION
FUNCTION Int8(Arg)
INTEGER(8) :: Int8, Arg
Int8 = 8_8
END FUNCTION
END MODULE
MODULE M1
USE M
INTERFACE Int8
MODULE PROCEDURE Int
MODULE PROCEDURE Int8
END INTERFACE
END MODULE
PROGRAM PtrAssignGen
USE M
USE M1
IMPLICIT NONE
INTERFACE Int
MODULE PROCEDURE Int
MODULE PROCEDURE Int8
END INTERFACE
PROCEDURE(Int8), POINTER :: PtrInt8
PtrInt8 => Int8
IF ( PtrInt8(100_8) .NE. 8_8 ) ERROR STOP 12
END
```
Flang crashes when lowering the type of `p1` with the following code.
The problem is when it sets up the `procInterface`, it uses the generic
symbol `int`, not the specific `int`. This PR is to correct that.
```
INTERFACE Int
integer FUNCTION Int(arg)
integer :: arg
END FUNCTION
END INTERFACE
integer :: res
procedure(int), pointer :: p1
p1 => int
res = p1(4)
end
```
When there are multiple USE statement for a particular module using
renaming, it is necessary to collect a set of all of the original
renaming targets before processing any of USE statements that don't have
ONLY: clauses.
Currently, if there is a name in the module that can't be added to the
current scope -- due to a conflict with an internal or module
subprogram, or with a previously use-associated name -- the compiler
will emit a bogus error message even if that conflicting name appear on
a later USE statement of the same module as the target of a renaming.
The new regression test case added with this patch provides a motivating
example.
…edures
Fortran allows a generic interface to have the same name as a derived
type in the same scope. It also allows a generic interface to have the
same name as one of its specific procedures.
When two modules define the same name, possibly more than once each,
things get exciting. The standard is not clear, and other compilers do
variously different things. We are currently emitting some errors
prematurely for some usage in pfUnit due to how it combines two versions
of a package together via USE association.
This patch handles combinations of derived types and generic interfaces
and their specific procedures in a more principled way. Errors due to
ambiguity are deferred to actual usage of derived types and specific
procedures -- and when they're not used, the program is unambiguous and
no error issues.
When an attribute specification statement follows a declaration that
applies the SAVE attribute to a symbol, name resolution can produce a
spurious error message about redundant SAVEs.
Fixes llvm-test-suite/Fortran/gfortran/regression/proc_ptr_9.f90.
[flang] Catch more initialization errors
Diagnose some error cases related to initialization that are
slipping past semantic checking: don't allow multiple initializations
of the same symbol, and don't allow an object that was initialized
as a scalar to become an array afterward.
Fixes llvm-test-suite/Fortran/gfortran/regression/initialization_17.f90.
In
CALL FOO
PRINT *, ABS(FOO)
we currently resolve the first FOO to a global external subprogram, but
then the second FOO is treated as an implicitly typed local variable.
This happens because the name FOO is not present in the local scope.
Fix by adding FOO to the local scope using a place-holding
HostAssocDetails symbol whose existence prevents the creation of another
FOO in the local scope. The symbol stored in the parser::Name parse tree
nodes or used in typed expressions will all continue to point to the
global external subprogram.
Resolves llvm-test-suite/Fortran/gfortran/regression/pr71859.f90.
There are some very odd (even for Fortran) rules in F'2023 subclause
19.4 (paras 6 & 8) pertaining to the index variables of FORALL and DO
CONCURRENT constructs/statements, and they are not currently implemented
correctly.
Although these index variables are construct entities, they have
restrictions in the standard that would essentially allow them to also
be variables in their enclosing scopes. If their names are present in
the enclosing scope, and the construct does not have an explicit type
specification for its indices, then the names in the enclosing scope
must either be scalar variables or COMMON blocks, and their type must be
integer.
Reimplement these restrictions largely with portability warnings rather
than hard errors. Retain the semantic interpretation that the type of an
untyped index variable be taken from the type of a variable of the same
name in the enclosing scope, if it exists, although that bit of the
standard could be interpreted otherwise.
Fixes https://github.com/llvm/llvm-project/issues/76978.
The compiler requires that a Cray pointee have a SEQUENCE type, but a
recent bug report points out that a BIND(C) type should also be
accepted.
Fixes https://github.com/llvm/llvm-project/issues/76529.
Initializers in entity-decls don't need to have their expressions
analyzed immediately in name resolution unless of course they are
defining the values of named constants. By deferring the expression
analysis, the compiler can better handle references to module and
internal procedures that might appear in structure constructors; at
present, these are typically rejected as being forward references (which
they can be) to subprogram names that can't yet be checked for
compatibility with the characteristics of the corresponding procedure
component.
The compiler doesn't USE-associate names of intrinsic procedures from
modules (in the absence of ONLY:), so that the associating scope doesn't
get populated with names of intrinsics that were used only in
declarations (e.g., SELECTED_REAL_KIND). A recent bug report (below)
shows that we should modify that policy in the case of names that appear
in explicit INTRINSIC attribute statements. The behaviors of other
Fortran compilers are not consistent and the requirements of the
standard are not clear; this fix follows the precedent set by gfortran
and nvfortran.
Fixes https://github.com/llvm/llvm-project/issues/72084.
…ion result)
A function can't return a statement function, so an apparent attempt to
define a statement function with the same name as the function's result
must be a misparsed assignment statement.
Array element references are frequently parsed as function references
due to the ambiguous syntax of Fortran, and the parse tree is repaired
by semantics once the relevant symbol table entries are in hand. This
patch fixes a case in which the correction takes a path that leaves the
type of a symbol undetermined, leading to later spurious errors in
expression analysis.
Fixes https://github.com/llvm/llvm-project/issues/68652.
When a BLOCK construct is within an ASSOCIATE or related construct,
don't misinterpret an assignment to an array element of a construct
entity as being an impermissible definition of a local statement
function.
It is possible to declare the rank of an object after that object has
been used in the same specification part in a specification function
reference whose result or generic resolution may well have depended on
the object being apparently a scalar.
Catch this case, and emit a warning -- not an error, yet, due to fear of
false positives.
See the new test for examples.
Before emitting a warning message, code should check that the usage in
question should be diagnosed by calling ShouldWarn(). A fair number of
sites in the code do not, and can emit portability warnings
unconditionally, which can confuse a user that hasn't asked for them
(-pedantic) and isn't terribly concerned about portability *to* other
compilers.
Add calls to ShouldWarn() or IsEnabled() around messages that need them,
and add -pedantic to tests that now require it to test their portability
messages, and add more expected message lines to those tests when
-pedantic causes other diagnostics to fire.
Name resolution takes a quick pass over the executable part of a
(sub)program in search of symbols that appear to be called as
procedures, so that those names don't get mistakenly converted into
objects when finishing up specification part processing. This pass
doesn't currently cope with symbol shadowing by nested declarations in
executable constructs. This patch ensures that nested declarations for
symbols that could be used in contexts that might have been parsed as
function references properly shadow symbols of the same name in outer
scopes.
A recent fix (https://github.com/llvm/llvm-project/pull/66232) to
interpret a hitherto unknown name whose first appearance is as the
target of a procedure pointer initializer as an external procedure has
led to some inapproprite warning messages if the name is later defined
as an external subroutine ("X was already declared as an external").
Ensure that the EXTERNAL attribute is correctly noted as being implicit,
and that it's okay that neither the Subroutine nor Function flag has yet
been set for the implicit external.
Some compilers allow the `$acc routine(<name>)` to be placed at the
program unit level. To be compatible, this patch enables the use of acc
routine at this level. These acc routine directives must have a name.
Fortran allows forward references to type names, which can lead to
ambiguity when coupled with host association, as in:
module m
type ambiguous; integer n; end type
contains
subroutine s
type(ambiguous), pointer :: variable
type t
type(ambiguous), pointer :: component
end type
type ambiguous; real x; end type
end
end
Some other compilers resolve to a host association, some resolve to a
forward reference. This compiler will now emit an error.
Name resolution creates symbols for submodules in their parents' scopes.
This can lead to bogus errors about name clashes between submodule names
and other entities in the parents' scopes.
Create symbols for submodules but do not add them to a scope's
dictionary.
When a MODULE SUBROUTINE or MODULE FUNCTION is implemented in the same
scope as its interface and appears in a generic with the same name, the
parse::Name of the implementation was not correctly reset and remained
the SubprogramNameDetails symbol after semantics, causing a crash in
lowering that picks up the procedure symbols on the parser names.
Reset the parser::Name symbol before the new symbol is created.
1. Deal with BIND(C,NAME="")
BIND(C,NAME="") is different from BIND(C). The latter implies that there
us a binding label which is the Fortran symbol name (no Fortran mangling
must be added like underscores). The former implies there is no binding
label (the name in the object file must be the same as if it there was
no BIND(C) attribute at all).
This is correctly implemented in the front-end, but lowering mistakenly
overrode this in the code dealing with the case where BIND(C) is
inherited from a procedure interface. Handling of this last case is moved into name
resolution.
2. Deal with BIND(C) internal procedure
Also according to 18.10.2, BIND(C) does not give a p prevent name
resolution from adding a label to them, otherwise,
bindc_internal_proc.f90 was not going through semantics (bogus error
about conflicting global names). Nothing TODO in lowering other than
removing the TODO.
Example:
```
subroutine global_sub()
integer, dimension(4) :: iarr4=(/1,2,3,4/)
integer, dimension(4) :: jarr4
equivalence(iarr4,jarr4)
call sub1
print *, iarr4
contains
subroutine sub1
iarr4=jarr4((/4:1:-1/))
end subroutine sub1
end subroutine global_sub
```
`iarr4` and `jarr4` are equivalenced via a global aggregate storage,
but the references inside `sub1` are lowered differently.
`iarr4` is accessed via the global aggregate storage, while `jarr4`
is accessed via the argument tuple. This confuses the FIR alias
analysis,
that claims that a host associated entity cannot alias with a global
(if they have different source and do not have Target/Pointer
attributes deduced by the alias analysis).
I am not convinced that there is an issue in the alias analysis yet.
I think we'd better lower the accesses uniformly, i.e. if one variable
from an equivalence is lowered via the global aggregate storage, then
any other variable from this equivalence should be lowered the same way
(even if they are used via host association).
This patch makes sure that all symbols from an EQUIVALENCE get
and implicit SAVE attribute, if they do not have it already and
any symbol from the EQUIVALENCE is SAVEd (explicitly or implicitly).
This makes the further lowering consistent.
Derived-type-spec (such as `type(t)`) typically cause the instantiation
of a class which is also used to define the offsets of its data
components and the size of the class.
Fortran derived types are always "completely" defined (i.e., no
incomplete / opaque derived types exist on which we can build a pointer
to them like in C/C++) so they can have their offsets always computed.
However, we must be careful not to instantiate a derived type while it
is being defined. This can happen due to cycles introduced by forward
references, such as the one below.
```lang=fortran
type t1
type(t2), pointer :: b ! (A)
end type t1
type :: t2 ! (B)
type(t1), pointer :: a ! (C)
end type t2 ! (D)
```
At `(A)`, flang determines that this is a forward declaration so no
instantiation happens.
At `(B)`, flang determines `t2` is not a forward declaration anymore,
because we are defining it.
At `(C)`, flang chooses to instantiate `t1`. Instantiation of `t1` finds
the field `b` at `(A)`. Now `t2` is not a forward declaration anymore,
so it can be instantiated. But at this point the field `a` has not been
added to `t2`, so we compute the size of an empty class. Because this
computation is done just once, we end emitting a wrong derived type
descriptor with a `sizeinbytes` field set to 0.
Because these kind of cycles can only happen via forward referenced
derived types specifiers, the idea here is to avoid instantiating the
derived type being defined (i.e. `t2`) until `(D)`. Keeping the
attribute "is forward reference" set until `(D)` avoids that.
Fixes https://github.com/llvm/llvm-project/issues/64973
Differential Revision: https://reviews.llvm.org/D159117