load_lib fortran.exp
 
 # Only gcc version >=11 supports assumed rank arrays.
-if { [test_compiler_info gcc*] &&
-   ![test_compiler_info {gcc-1[1-9]-*}]} {
+if { [test_compiler_info {gfortran-*} f90] &&
+     ![test_compiler_info {gfortran-1[1-9]-*} f90] } {
     untested "compiler does not support assumed rank"
     return -1
 }
        }
 
        # Currently, flang does not support rank0.
-       if {$test_count == 1 && [test_compiler_info {clang-*}]} {
+       if { $test_count == 1 && [test_compiler_info {flang-*} f90] } {
           unsupported "compiler does not support rank 0"
           continue
        }
 
 # different names, or maybe a completely different approach, for
 # representing class like structures.  The following tests are
 # cetainly going to fail.
-# Hence the test case is modified for clang.
-if {[test_compiler_info {clang-*}]} {
+# Hence the test case is modified for flang.
+if { [test_compiler_info {flang-*} f90] } {
     gdb_test "print this" " = \\( a = 0, b = \\(\\(1, 2, 3\\) \\(4, 5, 6\\)\\) \\)"
     gdb_test "print this%a" " = 0"
     gdb_test "print this%b" " = \\(\\(1, 2, 3\\) \\(4, 5, 6\\)\\)"
 
 
 # Unfortunately recent versions of GCC broke the stride information in
 # the DEBUG so tests in this file will fail.
-set gcc_with_broken_stride [test_compiler_info {gcc-[89]-*}]
+set gcc_with_broken_stride [test_compiler_info {gfortran-[89]-*} f90]
 
 if {[prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} \
         {debug f90}]} {
 
 set libfile [standard_output_file ${testfile}-lib.so]
 
 # Required for -fPIC by gdb_compile_shlib.
-if [get_compiler_info] {
+if { [get_compiler_info f90] } {
    warning "Could not get compiler info"
    return -1
 }
 
 gdb_breakpoint [gdb_get_line_number "Display namelist"]
 gdb_continue_to_breakpoint "Display namelist"
 
-if {[test_compiler_info {gcc-*}]} {
+if { [test_compiler_info {gfortran-*} f90] } {
     gdb_test "ptype nml" \
         "type = Type nml\r\n *$int :: a\r\n *$int :: b\r\n *End Type nml"
     gdb_test "print nml" \
 
     # mangling.
     proc get_linkage_name_pattern {symbol_name} {
 
-       if { [test_compiler_info icc*] || [test_compiler_info intel*]} {
+       if { [test_compiler_info {ifort-*} f90]
+            || [test_compiler_info {ifx-*} f90] } {
            return "\(?:.*_\)?${symbol_name}_?"
        } else {
            return ${symbol_name}
 
 # https://gcc.gnu.org/onlinedocs/gfortran/Argument-passing-conventions.html ).
 set stringlen ($integer8|$integer4)
 
-if {[test_compiler_info {clang-*}]} {
+if { [test_compiler_info {flang-*} f90] } {
     set some_module_class_type "Type number"
     set some_module_aux_info ", $integer8 \\(10\\)"
 } else {
     "type = void \\($integer4, $integer4, $integer4\\)"
 
 set fun_ptr_arg "$integer4"
-if {[test_compiler_info {gcc-*}]} {
+if { [test_compiler_info {gfortran-*} f90] } {
     set fun_ptr_arg "REF TO -> \\( ${fun_ptr_arg} \\)"
 }
 
     "type = void \\(character\[^,\]+, $stringlen\\)"
 
 set say_array_artificial_first_arg ""
-if {[test_compiler_info {clang-*}]} {
+if { [test_compiler_info {flang-*} f90] } {
     set say_array_artificial_first_arg "$integer8, "
 }
 
 
 # Check if not allocated VLA in type does not break
 # the debugger when accessing it.
 # break main for Flang compiler already breaks here
-if ![test_compiler_info "clang-*"] {
+if { ![test_compiler_info {flang-*} f90] } {
     gdb_breakpoint [gdb_get_line_number "before-allocated"]
     gdb_continue_to_breakpoint "before-allocated"
 }
 
--- /dev/null
+/* Copyright 2022 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+set compiler_info "unknown"
+
+#if defined (__GFORTRAN__)
+set compiler_info [join {gfortran __GNUC__ __GNUC_MINOR__ __GNUC_PATCHLEVEL__} -]
+#endif
+
+/* ARM seems to not define a patch version.  */
+#if defined (__ARM_LINUX_COMPILER__)
+set compiler_info [join {armflang __armclang_major__ __armclang_minor__ 0} -]
+#endif
+
+/* Classic flang and LLVM flang emit their respective macros differently.  */
+
+/* LLVM flang complains about non Fortran tokens so we do not use "{" here.  */
+#if defined (__flang__)
+set major __flang_major__
+set minor __flang_minor__
+set patch __flang_patchlevel__
+set compiler_info [join "flang-llvm $major $minor $patch" -]
+#endif
+
+/* Classic Flang.  */
+#if defined (__FLANG)
+set compiler_info [join {flang-classic __FLANG_MAJOR__ __FLANG_MINOR__ __FLANG_PATCHLEVEL__} -]
+#endif
+
+/* Intel LLVM emits a string like 20220100 with version 2021.2.0 and higher.  */
+#if defined (__INTEL_LLVM_COMPILER)
+set major [string range __INTEL_LLVM_COMPILER 0 3]
+set minor [string range __INTEL_LLVM_COMPILER 4 5]
+set patch [string range __INTEL_LLVM_COMPILER 6 7]
+set compiler_info [join "ifx $major $minor $patch" -]
+#elif defined (__INTEL_COMPILER)
+/* Starting with 2021 the ifort versioning scheme changed.  Before, Intel ifort
+   would define its version as e.g. 19.0.0 or rather __INTEL_COMPILER would be
+   emitted as 1900.  With 2021 the versioning became e.g. 2021.1 defined in
+   __INTEL_COMPILER.__INTEL_COMPILER_UPDATE.  No patch is emitted since the
+   change.  This compiler identification might not work with ifort versions
+   smaller than 10.  */
+#if (__INTEL_COMPILER < 2021)
+set major [string range __INTEL_COMPILER 0 1]
+set minor [string range __INTEL_COMPILER 2 2]
+#if defined (__INTEL_COMPILER_UPDATE)
+set patch __INTEL_COMPILER_UPDATE
+#else
+set patch [string range __INTEL_COMPILER 3 3]
+#endif
+#else
+set major __INTEL_COMPILER
+set minor __INTEL_COMPILER_UPDATE
+set patch 0
+#endif
+set compiler_info [join "ifort $major $minor $patch" -]
+#endif
 
 }
 
 proc fortran_int4 {} {
-    if {[test_compiler_info {gcc-4-[012]-*}]} {
+    if {[test_compiler_info {gfortran-4-[012]-*} f90]} {
        return "int4"
-    } elseif {[test_compiler_info {gcc-*}]} {
+    } elseif {[test_compiler_info {gfortran-*} f90]} {
        return "integer\\(kind=4\\)"
-    } elseif {[test_compiler_info {clang-*}]} {
+    } elseif {[test_compiler_info {flang-*} f90]} {
        return "integer"
-    } elseif {[test_compiler_info {icc-*}]} {
+    } elseif {[test_compiler_info {ifort-*} f90]} {
        return "INTEGER\\(4\\)"
-    } elseif {[test_compiler_info {intel-*}]} {
+    } elseif {[test_compiler_info {ifx-*} f90]} {
        return "INTEGER\\*4"
     } else {
        return "unknown"
 }
 
 proc fortran_int8 {} {
-    if {[test_compiler_info {gcc-4-[012]-*}]} {
+    if {[test_compiler_info {gfortran-4-[012]-*} f90]} {
        return "int8"
-    } elseif {[test_compiler_info {gcc-*}]} {
+    } elseif {[test_compiler_info {gfortran-*} f90]} {
        return "integer\\(kind=8\\)"
-    } elseif {[test_compiler_info {clang-*}]} {
+    } elseif {[test_compiler_info {flang-*} f90]} {
        return "integer\\*8"
-    } elseif {[test_compiler_info {icc-*}]} {
+    } elseif {[test_compiler_info {ifort-*} f90]} {
        return "INTEGER\\(8\\)"
-    } elseif {[test_compiler_info {intel-*}]} {
+    } elseif {[test_compiler_info {ifx-*} f90]} {
        return "INTEGER\\*8"
     } else {
        return "unknown"
 }
 
 proc fortran_real4 {} {
-    if {[test_compiler_info {gcc-4-[012]-*}]} {
+    if {[test_compiler_info {gfortran-4-[012]-*} f90]} {
        return "real4"
-    } elseif {[test_compiler_info {gcc-*}]} {
+    } elseif {[test_compiler_info {gfortran-*} f90]} {
        return "real\\(kind=4\\)"
-    } elseif {[test_compiler_info {clang-*}]} {
+    } elseif {[test_compiler_info {flang-*} f90]} {
        return "real"
-    } elseif {[test_compiler_info {icc-*}]} {
+    } elseif {[test_compiler_info {ifort-*} f90]} {
        return "REAL\\(4\\)"
-    } elseif {[test_compiler_info {intel-*}]} {
+    } elseif {[test_compiler_info {ifx-*} f90]} {
        return "REAL\\*4"
     } else {
        return "unknown"
 }
 
 proc fortran_real8 {} {
-    if {[test_compiler_info {gcc-4-[012]-*}]} {
+    if {[test_compiler_info {gfortran-4-[012]-*} f90]} {
        return "real8"
-    } elseif {[test_compiler_info {gcc-*}]} {
+    } elseif {[test_compiler_info {gfortran-*} f90]} {
        return "real\\(kind=8\\)"
-    } elseif {[test_compiler_info {clang-*}]} {
+    } elseif {[test_compiler_info {flang-*} f90]} {
        return "double precision"
-    } elseif {[test_compiler_info {icc-*}]} {
+    } elseif {[test_compiler_info {ifort-*} f90]} {
        return "REAL\\(8\\)"
-    } elseif {[test_compiler_info {intel-*}]} {
+    } elseif {[test_compiler_info {ifx-*} f90]} {
        return "REAL\\*8"
     } else {
        return "unknown"
 }
 
 proc fortran_complex4 {} {
-    if {[test_compiler_info {gcc-4-[012]-*}]} {
+    if {[test_compiler_info {gfortran-4-[012]-*} f90]} {
        return "complex4"
-    } elseif {[test_compiler_info {gcc-*}]} {
+    } elseif {[test_compiler_info {gfortran-*} f90]} {
        return "complex\\(kind=4\\)"
-    } elseif {[test_compiler_info {clang-*}]} {
+    } elseif {[test_compiler_info {flang-*} f90]} {
        return "complex"
-    } elseif {[test_compiler_info {icc-*}]} {
+    } elseif {[test_compiler_info {ifort-*} f90]} {
        return "COMPLEX\\(4\\)"
-    } elseif {[test_compiler_info {intel-*}]} {
+    } elseif {[test_compiler_info {ifx-*} f90]} {
        return "COMPLEX\\*8"
     } else {
        return "unknown"
 }
 
 proc fortran_complex8 {} {
-    if {[test_compiler_info {gcc-4-[012]-*}]} {
+    if {[test_compiler_info {gfortran-4-[012]-*} f90]} {
        return "complex8"
-    } elseif {[test_compiler_info {gcc-*}]} {
+    } elseif {[test_compiler_info {gfortran-*} f90]} {
        return "complex\\(kind=8\\)"
-    } elseif {[test_compiler_info {clang-*}]} {
+    } elseif {[test_compiler_info {flang-*} f90]} {
        return "double complex"
-    } elseif {[test_compiler_info {icc-*}]} {
+    } elseif {[test_compiler_info {ifort-*} f90]} {
        return "COMPLEX\\(8\\)"
-    } elseif {[test_compiler_info {intel-*}]} {
+    } elseif {[test_compiler_info {ifx-*} f90]} {
        return "COMPLEX\\*16"
     } else {
        return "unknown"
 }
 
 proc fortran_complex16 {} {
-    if {[test_compiler_info {gcc-4-[012]-*}]} {
+    if {[test_compiler_info {gfortran-4-[012]-*} f90]} {
        return "complex16"
-    } elseif {[test_compiler_info {gcc-*}]} {
+    } elseif {[test_compiler_info {gfortran-*} f90]} {
        return "complex\\(kind=16\\)"
-    } elseif {[test_compiler_info {clang-*}]} {
+    } elseif {[test_compiler_info {flang-*} f90]} {
        return "quad complex"
-    } elseif {[test_compiler_info {icc-*}]} {
+    } elseif {[test_compiler_info {ifort-*} f90]} {
        return "COMPLEX\\(16\\)"
-    } elseif {[test_compiler_info {intel-*}]} {
+    } elseif {[test_compiler_info {ifx-*} f90]} {
        return "COMPLEX\\*32"
     } else {
        return "unknown"
 }
 
 proc fortran_logical4 {} {
-    if {[test_compiler_info {gcc-4-[012]-*}]} {
+    if {[test_compiler_info {gfortran-4-[012]-*} f90]} {
        return "logical4"
-    } elseif {[test_compiler_info {gcc-*}]} {
+    } elseif {[test_compiler_info {gfortran-*} f90]} {
        return "logical\\(kind=4\\)"
-    } elseif {[test_compiler_info {clang-*}]} {
+    } elseif {[test_compiler_info {flang-*} f90]} {
        return "logical"
-    } elseif {[test_compiler_info {icc-*}]} {
+    } elseif {[test_compiler_info {ifort-*} f90]} {
        return "LOGICAL\\(4\\)"
-    } elseif {[test_compiler_info {intel-*}]} {
+    } elseif {[test_compiler_info {ifx-*} f90]} {
        return "LOGICAL\\*4"
     } else {
        return "unknown"
 }
 
 proc fortran_character1 {} {
-    if {[test_compiler_info {gcc-4-[012]-*}]} {
+    if {[test_compiler_info {gfortran-4-[012]-*} f90]} {
        return "character1"
-    } elseif {[test_compiler_info {gcc-*}]} {
+    } elseif {[test_compiler_info {gfortran-*} f90]} {
        return "character\\(kind=1\\)"
-    } elseif {[test_compiler_info {clang-*}]} {
+    } elseif {[test_compiler_info {flang-*} f90]} {
        return "character"
-    } elseif {[test_compiler_info {icc-*}]} {
+    } elseif {[test_compiler_info {ifort-*} f90]} {
        return "CHARACTER\\(1\\)"
-    } elseif {[test_compiler_info {intel-*}]} {
+    } elseif {[test_compiler_info {ifx-*} f90]} {
        return "CHARACTER\\*1"
     } else {
        return "unknown"
 # Return name of the main procedure based on the compiler version.
 
 proc fortran_main {} {
-    if {[test_compiler_info {gcc-4-[012]-*}]
-         || [test_compiler_info {gcc-*}]
-         || [test_compiler_info {icc-*}]
-         || [test_compiler_info {intel-*}]} {
+    if {[test_compiler_info {gfortran-*} f90]
+       || [test_compiler_info {ifort-*} f90]
+       || [test_compiler_info {ifx-*} f90]
+       || [test_compiler_info {flang-llvm-*} f90]} {
        return "MAIN__"
-    } elseif {[test_compiler_info {clang-*}]} {
+    } elseif {[test_compiler_info {flang-classic-*} f90]} {
        return "MAIN_"
     } else {
        return "unknown"
 
 # -- chastain 2004-01-06
 
 proc get_compiler_info {{arg ""}} {
-    # For compiler.c and compiler.cc
+    # For compiler.c, compiler.cc and compiler.F90.
     global srcdir
 
     # I am going to play with the log to keep noise out.
     global outdir
     global tool
 
-    # These come from compiler.c or compiler.cc
+    # These come from compiler.c, compiler.cc or compiler.F90.
     global compiler_info
 
     # Legacy global data symbols.
     set ifile "${srcdir}/lib/compiler.c"
     if { $arg == "c++" } {
        set ifile "${srcdir}/lib/compiler.cc"
+    } elseif { $arg == "f90" } {
+       set ifile "${srcdir}/lib/compiler.F90"
     }
 
     # Run $ifile through the right preprocessor.
            # eval this line
            verbose "get_compiler_info: $cppline" 2
            eval "$cppline"
+       } elseif { [ regexp "flang.*warning.*'-fdiagnostics-color=never'" "$cppline"] } {
+           # Both flang preprocessors (llvm flang and classic flang) print a
+           # warning for the unused -fdiagnostics-color=never, so we skip this
+           # output line here.
        } else {
            # unknown line
            verbose -log "get_compiler_info: $cppline"
 # Otherwise the argument is a glob-style expression to match against
 # compiler_info.
 
-proc test_compiler_info { {compiler ""} } {
+proc test_compiler_info { {compiler ""} {language ""} } {
     global compiler_info
-    get_compiler_info
+    get_compiler_info $language
 
     # If no arg, return the compiler_info string.
     if [string match "" $compiler] {
     if { !$getting_compiler_info && [lsearch -exact $options f90] != -1 } {
        # Fortran compile.
        set mod_path [standard_output_file ""]
-       if [test_compiler_info "gcc-*"] {
+       if { [test_compiler_info {gfortran-*} f90] } {
            lappend new_options "additional_flags=-J${mod_path}"
-       } elseif { [test_compiler_info {icc-*}]
-                  || [test_compiler_info {intel-*}] } {
+       } elseif { [test_compiler_info {ifort-*} f90]
+                  || [test_compiler_info {ifx-*} f90] } {
            lappend new_options "additional_flags=-module ${mod_path}"
        }
     }
     set info_options ""
     if { [lsearch -exact $options "c++"] >= 0 } {
        set info_options "c++"
+    } elseif { [lsearch -exact $options "f90"] >= 0 } {
+       set info_options "f90"
     }
     if [get_compiler_info ${info_options}] {
        return -1
     set info_options ""
     if { [lsearch -exact $options "c++"] >= 0 } {
        set info_options "c++"
+    } elseif { [lsearch -exact $options "f90"] >= 0 } {
+       set info_options "f90"
     }
     if [get_compiler_info ${info_options}] {
         return -1