llvm / llvm/llvm-project

[flang] EXTERNAL/INTRINSIC + legacy initializer in type declaration silently accepted, initializer dropped

Open
#222,168 4 comments 0 reactions 1 assignee Claimed by @Adarsh-Me View on GitHub
flang:frontend
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

The legacy (extension) form of initialization in a type declaration statement is silently accepted — and the initializer silently dropped — when the name was previously declared EXTERNAL or INTRINSIC.

```fortran
program p
external foo
integer foo /1/
end program
```

```
$ flang -c ext.f90
$ echo $?
0
```

This compiles cleanly, but the initializer never reaches the emitted code. Compare with the same declaration without EXTERNAL:

```fortran
program p
integer foo /1/
end program
```

which emits the expected static-storage global:

```llvm
@_QFEfoo = internal global i32 1
```

With `external foo` present, `-S -emit-llvm` output contains no `foo` and no initializer at all — the `/1/` is dropped without any diagnostic.

The acceptance is order-dependent. Reversing the two statements produces the expected error:

```fortran
program p
integer foo /1/
external foo
end program
```

```
error: 'foo' is a data object and may not be EXTERNAL
```

The same silent acceptance happens with INTRINSIC:

```fortran
program p
intrinsic sin
integer sin /1/
end program
```

also compiles with exit status 0 and drops the initializer.

Expected behavior: an error in both orders (a procedure cannot have a DATA-style initializer), consistent with the diagnostic already produced for the reversed order.

Mechanism, as far as I can tell: in `DataChecker::Leave(const parser::EntityDecl &)` (`flang/lib/Semantics/check-data.cpp`), the initializer is accumulated for the symbol, which by then has procedure details (from EXTERNAL/INTRINSIC). `ExpressionAnalyzer::Designate` happily returns a `ProcedureDesignator` for it, no error is ever reported on the symbol, and the initialization is later discarded without a diagnostic.

Related: #220846 / #221170 fixed the crash on this same code path when the redeclaration itself errors; this case is different in that no error is reported at all, so the recently added `HasError` guard does not (and should not) fire.

Tested at current llvm-project main (also reproduces on builds predating #221170, with identical behavior).

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.