Add a requested warning for completely unused local variables. The
implementation runs a scan over typed expressions during the existing
expression semantics pass to detect variable uses, and a routine at the
end of semantics to take a pass over the symbol tables to find unused
locals.
The new infrastructure needed to detect variable uses, and the existing
infrastructure that detects potential variable definitions, then makes
it easy to detect variables that are used without any possible
initialization or definition, so I did that too.
The warning for unused locals is off by default -- they might indicate a
misspelling (that IMPLICIT NONE would have caught), but seem otherwise
generally benign. The warning for uses of completely uninitialized and
undefined variables, however, is enabled by default, since that's likely
to indicate a program bug that should be investigated.
This patch touches a lot of files lightly. Many of these files are tests
that would have produced needless warning noise; one new test was added.
Fixes https://github.com/llvm/llvm-project/issues/173276.
Fixes#169484
The compiler crashed with an assertion failure when processing OpenMP
ATOMIC constructs containing invalid variable expressions like function
references or undeclared variables.
## Root Cause:
`CheckAtomicVariable()` assumed `GetAllDesignators()` always returns
exactly one designator, but it returns an empty vector for function
references.
## Fix:
Replaced the assertion with proper validation that emits diagnostic
errors instead of crashing.
## Testing:
Added regression test [atomic-invalid-variable.f90]
Move `GetInnermostExecPart` and `IsStrictlyStructuredBlock` from
Semantics/openmp-utils.* to Parser/openmp-utils.*. These two only depend
on the AST contents and properties.
Complex part designators do not have their own symbols. A symbol
obtained for the expression `x%re` will be the symbol for `x`, and in
this case x is allowed to be allocatable.
Fixes https://github.com/llvm/llvm-project/issues/166278.
Fixes https://github.com/llvm/llvm-project/issues/161932
Added a check for non-intrinsic types in non-pointer assignments.
Added bool checkTypeOnPointer = true to both CheckAtomicVariable and
CheckAtomicType. All atomic assignment functions now pass
!IsPointerAssignment(...) to control the check. The pointer-to-non-intrinsic
check lives in CheckAtomicType, guarded by the checkTypeOnPointer flag.
The check now applies uniformly to all atomic operations while properly
excluding pointer assignments (=>).
---------
Co-authored-by: Krish Gupta <krishgupta@Krishs-MacBook-Air.local>
This is a follow-up to PR153488 and PR155840, this time for expressions
of logical type. The handling of logical operations in Expr<T> differs
slightly from regular arithmetic operations. The difference is that the
specific operation (e.g. and, or, etc.) is not a part of the type, but
stored as a data member.
Both the matching code and the reconstruction code needed to be extended
to correctly handle the data member.
This fixes https://github.com/llvm/llvm-project/issues/144944
This is a follow-up to PR153488, this time the reassociation is enabled
for floating-point expressions, but only when associative-nath is
enabled in the language options. This can be done via -ffast-math on the
command line.
PR #153488 caused the msvc build (https://lab.llvm.org/buildbot/#/builders/166/builds/1397) to fail:
```
..\llvm-project\flang\include\flang/Evaluate/rewrite.h(78): error C2668: 'Fortran::evaluate::rewrite::Identity::operator ()': ambiguous call to overloaded function
..\llvm-project\flang\include\flang/Evaluate/rewrite.h(43): note: could be 'Fortran::evaluate::Expr<Fortran::evaluate::SomeType> Fortran::evaluate::rewrite::Identity::operator ()<Fortran::evaluate::SomeType,S>(Fortran::evaluate::Expr<Fortran::evaluate::SomeType> &&,const U &)'
with
[
S=Fortran::evaluate::value::Integer<128,true,32,unsigned int,unsigned __int64,128>,
U=Fortran::evaluate::value::Integer<128,true,32,unsigned int,unsigned __int64,128>
]
..\llvm-project\flang\lib\Semantics\check-omp-atomic.cpp(174): note: or 'Fortran::evaluate::Expr<Fortran::evaluate::SomeType> Fortran::semantics::ReassocRewriter::operator ()<Fortran::evaluate::SomeType,S,void>(Fortran::evaluate::Expr<Fortran::evaluate::SomeType> &&,const U &,Fortran::semantics::ReassocRewriter::NonIntegralTag)'
with
[
S=Fortran::evaluate::value::Integer<128,true,32,unsigned int,unsigned __int64,128>,
U=Fortran::evaluate::value::Integer<128,true,32,unsigned int,unsigned __int64,128>
]
..\llvm-project\flang\include\flang/Evaluate/rewrite.h(78): note: while trying to match the argument list '(Fortran::evaluate::Expr<Fortran::evaluate::SomeType>, const S)'
with
[
S=Fortran::evaluate::value::Integer<128,true,32,unsigned int,unsigned __int64,128>
]
..\llvm-project\flang\include\flang/Evaluate/rewrite.h(78): note: the template instantiation context (the oldest one first) is
..\llvm-project\flang\lib\Semantics\check-omp-atomic.cpp(814): note: see reference to function template instantiation 'U Fortran::evaluate::rewrite::Mutator<Fortran::semantics::ReassocRewriter>::operator ()<const Fortran::evaluate::Expr<Fortran::evaluate::SomeType>&,Fortran::evaluate::Expr<Fortran::evaluate::SomeType>>(T)' being compiled
with
[
U=Fortran::evaluate::Expr<Fortran::evaluate::SomeType>,
T=const Fortran::evaluate::Expr<Fortran::evaluate::SomeType> &
]
```
The reason is that there is an ambiguity between operator() of
ReassocRewriter itself and operator() of the base class `Identity` through
`using Id::operator();`. By the C++ specification, method declarations
in ReassocRewriter hide methods with the same signature from a using
declaration, but this does not apply to
```
evaluate::Expr<T> operator()(..., NonIntegralTag = {})
```
which has a different signature due to an additional tag parameter.
Since it has a default value, it is ambiguous with operator() without
tag parameter.
GCC and Clang both accept this, but in my understanding MSVC is correct
here.
Since the overloads of ReassocRewriter cover all cases (integral and
non-integral), removing the using declaration to avoid the ambiguity.
An atomic update expression of form
x = x + a + b
is technically illegal, since the right-hand side is parsed as (x+a)+b,
and the atomic variable x should be an argument to the top-level +. When
the type of x is integer, the result of (x+a)+b is guaranteed to be the
same as x+(a+b), so instead of reporting an error, the compiler can
treat (x+a)+b as x+(a+b).
This PR implements this kind of reassociation for integral types, and
for the two arithmetic associative/commutative operators: + and *.
Reinstate PR153098 one more time with fixes for the issues that came up:
- unused variable "lsrc",
- use of ‘outer1’ before deduction of ‘auto’.
An atomic update expression of form
x = x + a + b
is technically illegal, since the right-hand side is parsed as (x+a)+b,
and the atomic variable x should be an argument to the top-level +. When
the type of x is integer, the result of (x+a)+b is guaranteed to be the
same as x+(a+b), so instead of reporting an error, the compiler can
treat (x+a)+b as x+(a+b).
This PR implements this kind of reassociation for integral types, and
for the two arithmetic associative/commutative operators: + and *.
Reinstate PR153098 with fixes for the issues that came up:
- unused variable "lsrc",
- use of ‘outer1’ before deduction of ‘auto’.
An atomic update expression of form
x = x + a + b
is technically illegal, since the right-hand side is parsed as (x+a)+b,
and the atomic variable x should be an argument to the top-level +. When
the type of x is integer, the result of (x+a)+b is guaranteed to be the
same as x+(a+b), so instead of reporting an error, the compiler can
treat (x+a)+b as x+(a+b).
This PR implements this kind of reassociation for integral types, and
for the two arithmetic associative/commutative operators: + and *.
There semantic analysis of the ATOMIC construct will require additional
rewriting (reassociation of certain expressions for user convenience),
and that will be driven by diagnoses made in the semantic checks.
While the rewriting of min/max is not required to be done in semantic
analysis, moving it there will make all rewriting for ATOMIC construct
be located in a single location.
The structure is
- OmpBeginDirective (aka OmpDirectiveSpecification)
- Block
- optional<OmpEndDirective> (aka optional<OmpDirectiveSpecification>)
The OmpBeginDirective and OmpEndDirective are effectively different
names for OmpDirectiveSpecification. They exist to allow the semantic
analyses to distinguish between the beginning and the ending of a block
construct without maintaining additional context.
The actual changes are in the parser: parse-tree.h and openmp-parser.cpp
in particular. The rest is simply changing the way the directive/clause
information is accessed (typically for the simpler).
All standalone and block constructs now use OmpDirectiveSpecification to
store the directive/clause information.
An error report of the following code generating non-atomic code led us
to realize there are missing checks in the OpenACC atomics code. Add
some of those checks for atomic and sketch how the rest of the code
should proceed in checking the rest of the properties. The following
cases are all reported as errors.
```fortran
! Originally reported error!
!$acc atomic capture
a = b
c = b
!$acc end atomic capture
! Other ambiguous, but related errors!
!$acc atomic capture
x = i
i = x
!$acc end atomic capture
!$acc atomic capture
a = b
b = b
!$acc end atomic capture
!$acc atomic capture
a = b
a = c
!$acc end atomic capture
```
The ALLOCATORS construct is one of the few constructs that require a
special form of the associated block.
Convert the AST node to use OmpDirectiveSpecification for the directive
and the optional end directive, and to use parser::Block as the body:
the form of the block is checked in the semantic checks (with a more
meaningful message).
Create these new files in flang/lib/Semantics:
openmp-utils.cpp/.h - Common utilities
check-omp-atomic.cpp - Atomic-related checks
check-omp-loop.cpp - Loop constructs/clauses
check-omp-metadirective.cpp - Metadirective-related checks
Update lists of included headers, std in particular.
---------
Co-authored-by: Jack Styles <jack.styles@arm.com>