blob: 2d75cdade9b5c962d67a5ed101bb95736fd65432 [file] [log] [blame]
cmake_minimum_required(VERSION 3.24.0)
include(CheckFortranCompilerFlag)
# NOTE: flang does not currently (as of 2023/03/20) support the -w flag. If
# support for the flag is added, this should be removed.
remove_definitions(-w)
# This option is added because as of 2023/03/20, several tests in this
# directory have been disabled. Some of them exercise unsupported non-standard
# extensions, others trigger a "not yet implemented" assertion while some cause
# flang to crash. This option forces all the tests to build and can be used to
# determine if any of the disabled tests can be enabled.
option(TEST_SUITE_FORTRAN_FORCE_ALL_TESTS
"Build and run all gfortran tests, including those in the 'unsupported', 'unimplemented', 'skipped', and 'failing' categories."
OFF)
# Since the FORCE_ALL_TESTS option is a bit too blunt, there are some other
# options to force building some subsets of the disabled tests.
# The 'unsupported' tests exercise non-standard extensions that are not
# currently supported. But there is a chance some may be in the future, in which
# case, it may be worthwhile seeing if any can be removed from the list and
# enabled permanently.
option(TEST_SUITE_FORTRAN_FORCE_UNSUPPORTED_TESTS
"Build and run all 'unsupported' gfortran tests. These usually test non-standard extensions."
OFF)
# The 'unimplemented' tests trigger a "not yet implemented" assertion at
# compile-time. If those features are implemented, enabling those tests may help
# in identifying those that can be removed from the list and permanently enabled
# because the root cause has been addressed.
option(TEST_SUITE_FORTRAN_FORCE_UNIMPLEMENTED_TESTS
"Build and run all 'unimplemented' gfortran tests. These are tests that fail at build-time because of unimplemented features in flang."
OFF)
# The 'skipped' tests cause flang to crash at compile-time for "non-obvious"
# reasons. They could be related to unimplemented features, or they could be
# bugs in the compiler. In any case, enabling them may help identify those tests
# that can be removed from the list and permanently enabled because the root
# cause has been addressed.
option(TEST_SUITE_FORTRAN_FORCE_SKIPPED_TESTS
"Build and run all 'skipped' gfortran tests. These are tests that cause flang to crash."
OFF)
# The 'failing' tests fail to pass either because of a bug somewhere in the
# compiler or the runtime. Enabling these tests may help identify those tests
# that can be removed from the list and permanently enabled because the root
# cause has been addressed.
option(TEST_SUITE_FORTRAN_FORCE_FAILING_TESTS
"Build and run all 'failing' tests. These tests failed at runtime, perhaps due to bugs in the code generator or bugs/unimplemented features in the runtime."
OFF)
# The ISO_Fortran_binding.h file is required to run some of the tests. This
# header is copied to ${CMAKE_INSTALL_PREFIX}/include/flang at flang install
# time which can be found automatically. If the compiler being tested here is
# not installed, that file will not be found. In that case, the path to it must
# be provided explicitly.
set(TEST_SUITE_FORTRAN_ISO_C_HEADER_DIR "" CACHE STRING
"Path to the directory containing ISO_Fortran_bindings.h header file.")
# The following cause errors if they are passed to flang via FFLAGS. This could
# be because they are currently unsupported and might eventually be supported
# or because they are GCC-specific and will never be supported.
#
# FIXME: The flags here necessarily include the value as well, not just the
# flag itself. For instance, in the list are -fcheck=all, -fcheck=bits etc. In
# principle, one only needs the -fcheck. The argument should not matter. The
# problem is that the annotation parser currently does not parse the flag into
# `flag-name` and `flag-value`. Once this is fixed, we need only have the
# flag name here.
set(FLANG_ERRORING_FFLAGS
# The "flags" that do not start with a hyphen (-) are actually arguments to
# some other flag but use the "-flag value" syntax (as opposed to the
# "-flag=value" syntax). Since we don't actually parse the command line, they
# are treated as if they were "flags" .
analyzer-max-svalue-depth=0
ggc-min-expand=0
ggc-min-heapsize=0
iv-max-considered-uses=2
large-stack-frame=4000
max-completely-peel-loop-nest-depth=1
max-completely-peeled-insns=0
max-completely-peeled-insns=200
max-cse-insns=0
max-inline-insns-auto=0
max-inline-insns-single=0
parloops-chunk-size=2
parloops-min-per-thread=5
sccvn-max-alias-queries-per-access=1
vect-epilogues-nomask=0
vect-max-peeling-for-alignment=0
# This is an argument that should go with -idirafter which is not correctly
# handled right now. Once that is fixed, this can be removed.
fdaf
"/fdaf/"
-dA
-dH
-dirafter
-dp
-faggressive-function-elimination
-fall-intrinsics
-fallow-argument-mismatch
-fallow-invalid-boz
-fautomatic
-fblas-matmul-limit=1
-fbounds-check
-fcheck-array-temporaries
-fcheck=all
-fcheck=bits
-fcheck=bounds
-fcheck=do
-fcheck=mem
-fcheck=pointer
-fcheck=recursion
-fcompare-debug
-fcoarray=lib
-fcoarray=single
-fcray-pointer
-fd-lines-as-code
-fd-lines-as-comments
-fdec
-fdec-format-defaults
-fdec-static
-fdec-structure
-fdollar-ok
-frecord-marker=4
-fbounds-check
-fcheck-bounds
-fcheck=all
-fcheck=bits
# Not sure if the -fdefault-* options will be supported. Maybe in a different
# form in which case, this will have to be modified to accommodate those.
-fdefault-real-10
-fdefault-real-16
-fdiagnostics-format=json
-fdiagnostics-show-option
-fdollar-ok
-fdump-fortran-original
-fdump-ipa-cp-details
-fdump-ipa-fnsummary-details
-fdump-ipa-inline
-fdump-ipa-inline-details
-fdump-ipa-sra-details
-fdump-rtl-combine
-fdump-rtl-expand
-fdump-tree-all
-fdump-tree-cunroll-details
-fdump-tree-cunrolli-details
-fdump-tree-dom2
-fdump-tree-dom2-details
-fdump-tree-dse-details
-fdump-tree-forwprop2
-fdump-tree-fre1
-fdump-tree-gimple
-fdump-tree-ifcvt
-fdump-tree-ldist-all
-fdump-tree-ldist-details
-fdump-tree-lim2
-fdump-tree-lim2-details
-fdump-tree-linterchange-details
-fdump-tree-lversion-details
-fdump-tree-omplower
-fdump-tree-optimized
-fdump-tree-optimized-raw
-fdump-tree-original
-fdump-tree-original-lineno
-fdump-tree-parloops2-details
-fdump-tree-pcom-details
-fdump-tree-pre
-fdump-tree-pre-details
-fdump-tree-profile_estimate
-fdump-tree-reassoc1
-fdump-tree-slp-details
-fdump-tree-slp2-details
-fdump-tree-vect-details
-fexceptions
-fexpensive-optimizations
-fexternal-blas
-ff2c
-ffixed-xmm1
-ffixed-xmm10
-ffixed-xmm11
-ffixed-xmm12
-ffixed-xmm13
-ffixed-xmm14
-ffixed-xmm15
-ffixed-xmm2
-ffixed-xmm3
-ffixed-xmm4
-ffixed-xmm5
-ffixed-xmm6
-ffixed-xmm7
-ffixed-xmm8
-ffixed-xmm9
-ffloat-store
-ffree-line-length-none
-ffrontend-optimize
-fgcse
-fgcse-after-reload
-fgnu-tm
-findirect-inlining
-finit-character=32
-finit-derived
-finit-local-zero
-finit-integer=42
-finit-integer=12345678
-finit-logical=0
-finit-logical=true
-finit-real=inf
-finline-functions
-finline-matmul-limit=0
-finline-matmul-limit=10
-finline-matmul-limit=100
-finline-matmul-limit=1000
-finline-matmul-limit=2
-finline-matmul-limit=30
-finline-small-functions
-finstrument-functions
-fipa-cp
-fipa-cp-clone
-fipa-pta
-fipa-reference
-flinker-output=nolto-rel
-floop-interchange
-fmax-array-constructor=100000
-fmax-stack-var-size=8
-fmax-stack-var-size=100
-fmodule-private
-fmodulo-sched
-fno-align-commons
-fno-asynchronous-unwind-tables
-fno-backtrace
-fno-bounds-check
-fno-check-array-temporaries
-fno-code-hoisting
-fno-dec
-fno-dse
-fno-early-inlining
-fno-f2c
-fno-frontend-loop-interchange
-fno-frontend-optimize
-fno-guess-branch-probability
-fno-init-local-zero
-fno-inline
-fno-inline-arg-packing
-fno-inline-functions-called-once
-fno-ipa-cp
-fno-ipa-icf
-fno-ipa-modref
-fno-ipa-sra
-fno-move-loop-stores
-fno-openacc
-fno-openmp
-fno-pad-source
-fno-protect-parens
-fno-range-check
-fno-realloc-lhs
-fno-schedule-insns
-fno-sign-zero
-fno-strict-aliasing
-fno-trapping-math
-fno-tree-ccp
-fno-tree-ch
-fno-tree-copy-prop
-fno-tree-dce
-fno-tree-dominator-opts
-fno-tree-forwprop
-fno-tree-fre
-fno-tree-loop-ch
-fno-tree-loop-distribute-patterns
-fno-tree-loop-im
-fno-tree-loop-ivcanon
-fno-tree-loop-optimize
-fno-tree-loop-vectorize
-fno-tree-pre
-fno-tree-scev-cprop
-fno-tree-sink
-fno-tree-slp-vectorize
-fno-tree-vectorize
-fno-tree-vrp
-fnon-call-exceptions
-fopenmp-simd
-fopt-info-vec-optimized
-fpad-source
-fpeel-loops
-fpre-include=simd-builtins-1.h
-fpre-include=simd-builtins-3.h
-fpre-include=simd-builtins-4.h
-fpre-include=simd-builtins-7.h
-fpre-include=simd-builtins-8.h
-fpreprocessed
-fpredictive-commoning
-fprefetch-loop-arrays
-fprofile-arcs
-fprofile-generate
-frecord-marker=4
-frecursive
-frepack-arrays
-frounding-math
-fsanitize=float-cast-overflow
-fsanitize=null
-fsanitize=signed-integer-overflow
-fsanitize=undefined
-fschedule-insns
-fsecond-underscore
-fsel-sched-pipelining
-fsel-sched-pipelining-outer-loops
-fselective-scheduling
-fselective-scheduling2
-fset-g77-defaults
-fshort-enums
-fstrict-aliasing
-fsplit-loops
-ftest-forall-temp
-ftest-coverage
-ftracer
-ftrapv
-ftree-loop-distribution
-ftree-loop-if-convert
-ftree-loop-vectorize
-ftree-parallelize-loops
-ftree-parallelize-loops=2
-ftree-pre
-ftree-slp-vectorize
-ftree-tail-merge
-ftree-vectorize
-ftree-vrp
-funconstrained-commons
-funroll-all-loops
-funroll-loops
-funsafe-math-optimizations
-fvect-cost-model=dynamic
-fwhole-program
-fwrapv
-gno-strict-dwarf
-idirafter
-mavx
-mavx2
-mavx512f
-mcmodel=medium
-mdalign
-mdejagnu-cpu=power4
-mdejagnu-cpu=power7
-mdejagnu-cpu=power10
-mfpmath=387
-mfpmath=sse
-mlow-precision-sqrt
-mno-avx
-mno-power8-vector
-mno-power9-vector
-mprefer-avx128
-msse
-msse2
-msse3
-msse4.1
-mtune=amdfam10
-mtune=generic
-mveclibabi=mass
-mveclibabi=svml
-mvsx
-mvzeroupper
-mzarch
-nostdinc
-nostdlib
# -Os might eventually be supported, so this might also need to be removed
# at some point
-Og
-Os
-pedantic-errors
# -pthread should be supported at some point.
-pthread
-r
# At some point, if we ever support explicit standard flags, some of these
# should be removed.
-pedantic-errors
-std=gnu
-std=legacy
-std=f95
--std=f95
-std=f2003
-std=f2008
-std=f2008ts
# At the time of writing, -W warnings are not supported. flang errors out
# saying that only -Werror is supported.
-W
-Waliasing
-Wall
-Wampersand
-Wanalyzer-too-complex
-Warray-bounds
-Warray-temporaries
-Wc-binding-type
-Wcharacter-truncation
-Wcompare-reals
-Wconversion
-Wconversion-extra
-Wdate-time
-Wdo-subscript
-Werror
-Wextra
-Wfunction-elimination
-Wimplicit-interface
-Wimplicit-procedure
-Winteger-division
-Wintrinsic-shadow
-Wintrinsics-std
-Wline-truncation
-Wmaybe-uninitialized
-Wmissing-include-dirs
-Wno-all
-Wno-analyzer-malloc-leak
-Wno-analyzer-memory-leak
-Wno-analyzer-null-dereference
-Wno-analyzer-possible-null-dereference
-Wno-analyzer-too-complex
-Wno-analyzer-use-of-uninitialized-value
-Wno-c-binding-type
-Wno-complain-wrong-lang
-Wno-cpp
-Wno-error
-Wno-error=cpp
-Wno-intrinsic-shadow
-Wno-intrinsics-std
-Wno-line-truncation
-Wno-lto-type-mismatch
-Wno-missing-include-dirs
-Wno-overwrite-recursive
-Wno-pedantic
-Wno-tabs
-Wno-underflow
-Wno-uninitialized
-Wno-unused-dummy-argument
-Wno-zerotrip
-Wopenacc-parallelism
-Wpadded
-Wrealloc-lhs
-Wrealloc-lhs-all
-Wreturn-type
-Wstringop-overflow
-Wsurprising
-Wtabs
-Wtarget-lifetime
-Wundefined-do-loop
-Wuninitialized
-Wunused
-Wunused-dummy-argument
-Wunused-function
-Wunused-label
-Wunused-parameter
-Wunused-variable
-Wzerotrip
-w
--param
)
# Determine disabled tests for this directory and return them via the OUT
# parameter.
function(gfortran_populate_disabled_tests out)
set(unsupported "")
set(unimplemented "")
set(skipped "")
set(failing "")
# This will provide the lists of unsupported, unimplemented, skipped and
# failing files.
include(${CMAKE_CURRENT_SOURCE_DIR}/DisabledFiles.cmake)
list(APPEND unsupported ${UNSUPPORTED_FILES})
list(APPEND unimplemented ${UNIMPLEMENTED_FILES})
list(APPEND skipped ${SKIPPED_FILES})
list(APPEND failing ${FAILING_FILES})
# do the same for any requested feature extentions
foreach(feature ${TEST_SUITE_FORTRAN_FEATURES})
set(UNSUPPORTED_FILES "")
set(UNIMPLEMENTED_FILES "")
set(SKIPPED_FILES "")
set(FAILING_FILES "")
include(${CMAKE_CURRENT_SOURCE_DIR}/DisabledFiles${feature}.cmake)
list(APPEND unsupported ${UNSUPPORTED_FILES})
list(APPEND unimplemented ${UNIMPLEMENTED_FILES})
list(APPEND skipped ${SKIPPED_FILES})
list(APPEND failing ${FAILING_FILES})
# enable any tests that now pass for this feature
set(SUPPORTED_FILES "")
set(IMPLEMENTED_FILES "")
set(UNSKIPPED_FILES "")
set(PASSING_FILES "")
include(${CMAKE_CURRENT_SOURCE_DIR}/EnabledFiles${feature}.cmake)
list(REMOVE_ITEM unsupported ${SUPPORTED_FILES})
list(REMOVE_ITEM unimplemented ${IMPLEMENTED_FILES})
list(REMOVE_ITEM skipped ${UNSKIPPED_FILES})
list(REMOVE_ITEM failing ${PASSING_FILES})
endforeach()
set(disabled "")
# There is still a chance that some of the unsupported tests may need to be
# enabled, for instance if the non-standard extensions that they exercise are
# supported due to user demand.
if (NOT TEST_SUITE_FORTRAN_FORCE_ALL_TESTS AND
NOT TEST_SUITE_FORTRAN_FORCE_UNSUPPORTED_TESTS)
list(APPEND disabled ${unsupported})
endif()
# For the remaining tests, there is cause to build and run the skipped, failing
# and unimplemented tests since some could be enabled once some feature is
# implemented. Eventually, all the TEST_SUITE_FORTRAN_FORCE_* options (perhaps
# with the exception of TEST_SUITE_FORTRAN_FORCE_UNSUPPORTED_TESTS) should
# become redundant and removed.
if (NOT TEST_SUITE_FORTRAN_FORCE_ALL_TESTS AND
NOT TEST_SUITE_FORTRAN_FORCE_UNIMPLEMENTED_TESTS)
list(APPEND disabled ${unimplemented})
endif()
if (NOT TEST_SUITE_FORTRAN_FORCE_ALL_TESTS AND
NOT TEST_SUITE_FORTRAN_FORCE_SKIPPED_TESTS)
list(APPEND disabled ${skipped})
endif()
if (NOT TEST_SUITE_FORTRAN_FORCE_ALL_TESTS AND
NOT TEST_SUITE_FORTRAN_FORCE_FAILING_TESTS)
list(APPEND disabled ${failing})
endif()
set(${out} ${disabled} PARENT_SCOPE)
endfunction()
# Check the test configuration to make sure that it is not out of date.
# USED_FORT is the list of Fortran files that are used in the tests. USED_OTHER
# is the list of non-Fortran files that are used. This is intended be a sanity
# check in case the test suite is updated without updating the static test
# configuration. In particular, we want to catch situations where failing to
# update the test configuration results in the new new tests being skipped
# silently.
function(gfortran_check_test_config used_fort used_other)
list(SORT used_fort)
list(REMOVE_DUPLICATES used_fort)
list(SORT used_other)
list(REMOVE_DUPLICATES used_other)
# All the Fortran files in the current directory.
file(GLOB files CONFIGURE_DEPENDS LIST_DIRECTORIES false
*.f*
*.F*
)
list(SORT files)
set(msg_unused "File not used in any test configuration")
set(msg_missing "File used in test configuration not found")
set(msg_rerun "You may need to run utils/update-test-config.py")
# Now that files and used_fort are both sorted and without any duplicates,
# they should be identical. If they are not, it suggests that some Fortran
# files have been added or removed.
foreach (f u IN ZIP_LISTS files used_fort)
if (NOT f STREQUAL u)
list(FIND used ${f} idx)
if (idx EQUAL -1)
message(FATAL_ERROR "${msg_unused}\n ${f}\n${msg_rerun}\n")
else ()
message(FATAL_ERROR "${msg_missing}\n ${u}\n${msg_rerun}\n")
endif ()
endif ()
endforeach ()
# It is highly likely that any non-Fortran files will be dependents of tests.
# They are most likely to be .c files, but we cannot guarantee that. Just
# check if the files in the test configuration exist. If any dependent files
# are added and they are missing from the test configuration, it will most
# likely result in a build-time error, so it won't pass by silently.
foreach (f ${used_other})
if (NOT EXISTS ${f})
message(FATAL_ERROR "${msg_missing}\n ${f}\n${msg_rerun}\n")
endif ()
endforeach()
endfunction()
# Generate a unique target name from the given base and prepend it with the
# given prefix.
function(gfortran_unique_target_name prefix base out)
# There are a few tests - in different directories - with duplicate filenames.
# CMake requires all target names to be unique, so we add a disambiguator. The
# disambiguator uses the path of the file relative to the top-level directory
# containing all the tests from the gfortran test suite to ensure that
# targets in different directories will have distinct names.
set(result "")
# The ${base} argument is guaranteed to be the absolute path to a source file.
string(REPLACE "${PROJECT_SOURCE_DIR}/Fortran/gfortran/" "" result "${base}")
# Replace any '/' separators with 2 underscores. Just replacing it by a single
# underscore results in conflicts. For instance, there is a conflict between
# regression/coarray_ptr_comp_2.f08 and regression/coarray/ptr_comp_2.f08
# which are unrelated tests. Other such conflicts are probably also unrelated.
string(REPLACE "/" "__" result "${result}")
# Retain the extension of the source file in the final target name because
# there are cases where two source files with the same basename but different
# extensions and they, too, represent completely different and unrelated
# tests.
string(REPLACE "." "_" result "${result}")
set(${out} "${prefix}-${result}" PARENT_SCOPE)
endfunction()
# Several tests in the suite build modules with the same name at build-time.
# Others create/write/read files with the same name at test-time. In either
# case, these are race conditions which can lead to non-deterministic failures
# at build and/or test time. To work around this, have each test run in its
# own directory.
#
# This directory is also used as module directory at build-time.
#
# It may be "cleaner" to have separate directories - one that serves as the
# module directory and the other as the working directory, but that is
# probably unnecessary.
#
# Make a working directory for the given target and return the full path of
# the resulting directory.
function(gfortran_make_working_dir tgt out)
set(working_dir "${CMAKE_CURRENT_BINARY_DIR}/${tgt}.wd")
file(MAKE_DIRECTORY ${working_dir})
set("${out}" "${working_dir}" PARENT_SCOPE)
endfunction()
# Setup a "compile" test. EXPECT_ERROR will be ON if the compile test is
# expected to fail, OFF otherwise. MAIN is the main test file. In the case of
# multi-file tests, OTHERS will be the remaining files needed by the test.
# FFLAGS are compiler flags needed by the test. LDFLAGS are linker flags needed
# by the test.
function(gfortran_add_compile_test expect_error main others fflags ldflags)
# The test-suite expects an executable to be produced at build time and for
# that executable to be run at test time. The result (in the form of the
# return code or the output written to stdout/stderr) is used to determine
# whether the test has succeeded. The "compile" tests are intended to exercise
# the behavior of the compiler itself. There isn't a clean way of having the
# compiler be executed at test time. Instead, the compiler is run at
# build time and the diagnostics/errors saved to a file as needed. This file is
# compared to a reference output at test time to determine success/failure of
# the test. A dummy executable is also built. This does nothing, but provides
# something that the test suite can "run" at test time.
# PREFIX_COMPILE will have been defined in the subdirectory from which this
# function is called.
gfortran_unique_target_name("${PREFIX_COMPILE}" "${main}" target)
gfortran_make_working_dir("${target}" working_dir)
# The output of the compilation of the test file. This may contain warnings
# and error messages. If the compilation succeeded without any warnings or
# other diagnostics, it will be empty.
set(out ${target}.out)
# Add the CMake-wide environment variable CMAKE_Fortran_FLAGS
# CMake escapes spaces. To really get a space (between arguments) use a ;
string(REPLACE " " ";" fflags "${fflags};${CMAKE_Fortran_FLAGS}")
add_custom_command(
OUTPUT ${out}
COMMAND ${CMAKE_COMMAND}
-DCMD="${CMAKE_Fortran_COMPILER_LAUNCHER};${CMAKE_Fortran_COMPILER};-c;${fflags};${ldflags};${others};${main}"
-DALWAYS_SAVE_DIAGS=OFF
-DWORKING_DIRECTORY=${working_dir}
-DOUTPUT_FILE=${out}
-P ${COMPILE_SCRIPT_BIN}
USES_TERMINAL
COMMENT "Compiling ${main}")
add_custom_target(${target}
ALL
DEPENDS ${out}
SOURCES ${main} ${others})
# The dummy and empty reference output files are in
# ${CMAKE_BINARY_DIR}/Fortran/gfortran. This function could be called from
# any of the subdirectories under ${CMAKE_BINARY_DIR}/Fortran/gfortran. The
# tests need paths relative to the directory containing the test, so calculate
# the relative path back to ${CMAKE_BINARY_DIR}/Fortran/gfortran.
file(RELATIVE_PATH relpath
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_BINARY_DIR}/Fortran/gfortran)
# The test suite expects an executable to run, so give it the dummy (see
# comments above).
llvm_test_run(EXECUTABLE %S/${relpath}/${DUMMY_EXE})
# The verification compares the saved diagnostics file against what is
# expected. For the test. The reference output may have been extracted from
# the DejaGNU annotations in the test file, or it may be an empty file if the
# compilation of the test file was expected to be successful and without any
# diagnostics.
if (expect_error)
# Since we don't check for any particular error, we expect "some" error.
# In that case, the compiler's diagnostic output will be non-empty.
llvm_test_verify(%b/not ${DIFFPROG} %S/${relpath}/${EMPTY_FILE} %S/${out})
else ()
llvm_test_verify(${DIFFPROG} %S/${relpath}/${EMPTY_FILE} %S/${out})
endif ()
llvm_add_test(${target}.test %S/${relpath}/${DUMMY_EXE})
endfunction()
# Setup an "execute" test. In the case of multi-file tests, MAIN will be the
# main file. For multi-file tests, OTHERS will be the remaining files needed by
# the test. FFLAGS are additional compiler flags needed by the test. LDFLAGS
# are the other linker flags needed by the test. If EXPECT_ERROR evaluates to
# true, the test is expected to fail.
function(gfortran_add_execute_test expect_error main others fflags ldflags)
# PREFIX_EXECUTE will have been defined in the subdirectory from which this
# function is called.
gfortran_unique_target_name("${PREFIX_EXECUTE}" "${main}" target)
gfortran_make_working_dir("${target}" working_dir)
get_filename_component(working_dir_name "${working_dir}" NAME)
llvm_test_executable_no_test(${target} ${main} ${others})
if (expect_error)
llvm_test_run(
EXECUTABLE "%b/not --crash %S/${target}"
WORKDIR "%S/${working_dir_name}")
else ()
llvm_test_run(WORKDIR "%S/${working_dir_name}")
endif ()
llvm_add_test_for_target(${target})
target_include_directories(${target}
PRIVATE ${ISO_FORTRAN_C_HEADER_DIR} ${working_dir})
target_compile_options(${target} PRIVATE "${fflags}")
target_link_options(${target} PRIVATE "${ldflags}")
set_target_properties(${target} PROPERTIES
Fortran_MODULE_DIRECTORY ${working_dir})
# This is a workaround because cmake does not currently recognize the .f03
# and .f08 extensions. A patch to fix cmake has been accepted and the fix
# should be available in CMake 3.27. It might be better to check the CMake
# version and do this conditionally.
list(APPEND sources ${main})
list(APPEND sources ${others})
foreach(source ${sources})
get_filename_component(ext ${source} LAST_EXT)
if("${ext}" STREQUAL ".f03" OR
"${ext}" STREQUAL ".F03" OR
"${ext}" STREQUAL ".f08" OR
"${ext}" STREQUAL ".F08")
set_source_files_properties(${source} PROPERTIES LANGUAGE Fortran)
endif()
endforeach()
set_target_properties(${target} PROPERTIES LINKER_LANGUAGE Fortran)
endfunction()
# The main entry point to populate the tests in the current source directory.
# This parses the static test configuration file, filters out the disabled
# tests, sets up the tests and performs some sanity checks. The keyword FFLAGS
# and LDFLAGS arguments can be used to force specific compile-time and link-time
# flags to be used when building the tests.
function(gfortran_populate_tests)
cmake_parse_arguments(GFORTRAN "" "" "FFLAGS;LDFLAGS" ${ARGN})
# These are used to collect the list of source files that are used in at
# least one test. This is used as a sanity check to ensure that all the
# source files are accounted for. This is necessary to alert the user in case
# the tests were updated by upstream gfortran but the static test
# configuration was not re-generated.
set(used_fort)
set(used_other)
string(REPLACE "${CMAKE_SOURCE_DIR}/" "" pwd "${CMAKE_CURRENT_SOURCE_DIR}")
message(STATUS "Adding directory ${pwd}")
# The target triple is roughly of the form ${arch}-${vendor}-${sys}. Cmake
# has no concept of a vendor, so we set it to "unknown". The targets
# specification in the tests generally ignores the vendor and only matches
# against either the architecture or the system, so this is ok.
string(TOLOWER "${CMAKE_SYSTEM_PROCESSOR}" arch)
string(TOLOWER "${CMAKE_SYSTEM_NAME}" sys)
set(triple "${arch}-unknown-${sys}")
set(disabled)
gfortran_populate_disabled_tests(disabled)
file(STRINGS ${CMAKE_CURRENT_SOURCE_DIR}/tests.cmake lines)
foreach (line ${lines})
# Skip comment lines where the first non-whitespace character is a #.
if (line MATCHES "^[ ]*#")
continue()
endif()
list(GET line 1 sources_t)
string(REPLACE " " ";" sources "${sources_t}")
list(TRANSFORM sources PREPEND ${CMAKE_CURRENT_SOURCE_DIR}/)
# The tests in the configuration must be added to the used list even if the
# test is disabled because the sanity check will expect that the list of
# Fortran files in the directory exactly matches the list of used Fortran
# files.
set(rest)
list(LENGTH sources nsources)
math(EXPR iend "${nsources} - 1")
foreach (i RANGE ${iend})
list(GET sources ${i} source)
if (source MATCHES "^.+[.][Ff].*$")
list(APPEND used_fort ${source})
else ()
list(APPEND used_other ${source})
endif ()
if (${i} GREATER 0)
list(APPEND rest ${source})
endif ()
endforeach()
# If the test is only allowed to run on certain targets, process those.
list(GET line 4 incl_t)
if (incl_t)
# If there are any explicit include targets, then we should assume that
# we cannot run the test on the current platform unless there is at
# least one match.
set(exclude ON)
string(REPLACE " " ";" includes ${incl_t})
foreach (incl ${includes})
string(REGEX MATCH ${incl} m ${triple})
if (m)
set(exclude OFF)
endif ()
endforeach()
# The current platform was not matched, so we should not run the test.
if (exclude)
continue()
endif ()
endif ()
# If the test is explicitly disabled on certain targets, process those.
list(GET line 5 excl_t)
if (excl_t)
# If there are any targets to explicitly exclude, then we should assume
# that we can run the test on this platform unless there is at least
# one match.
set(exclude OFF)
string(REPLACE " " ";" excludes ${excl_t})
foreach (excl ${excludes})
string(REGEX MATCH ${excl} m ${triple})
if (m)
set(exclude ON)
endif ()
endforeach ()
# The current platform was matched, so we should not run the test.
if (exclude)
continue ()
endif()
endif ()
# Only the main file will be in the list of disabled tests. If it is, move
# on to the next test in the configuration.
list(GET sources 0 main)
list(FIND disabled ${main} i)
if (NOT i EQUAL -1)
continue ()
endif()
# The test was not excluded and not disabled. Now we can process the other
# parameters and set up the test.
set(xfail OFF)
list(GET line 2 xfail_t)
if (xfail_t STREQUAL "xfail")
set(xfail ON)
endif ()
set(fflags)
list(GET line 3 options_t)
string(REPLACE " " ";" file_fflags "${options_t}")
list(REMOVE_ITEM file_fflags ${FLANG_ERRORING_FFLAGS})
list(APPEND fflags ${GFORTRAN_FFLAGS})
list(APPEND fflags ${file_fflags})
set(ldflags)
list(APPEND ldflags ${GFORTRAN_LDFLAGS})
list(GET line 0 kind)
if (kind STREQUAL "run")
gfortran_add_execute_test(${xfail} ${main} "${rest}" "${fflags}" "${ldflags}")
else()
# FIXME: For now, we treat all non-execute tests as compile tests, but we
# probably should do something more sensible for the "preprocess",
# "assemble", and "link" tests.
gfortran_add_compile_test(${xfail} ${main} "${rest}" "${fflags}" "${ldflags}")
endif()
endforeach()
# It would be nice to do the sanity check early, but that would complicate
# this code since cmake is not the nicest programming language.
gfortran_check_test_config("${used_fort}" "${used_other}")
endfunction()
set(HEADER_SEARCH_PATH "${TEST_SUITE_FORTRAN_ISO_C_HEADER_DIR}")
if (NOT HEADER_SEARCH_PATH)
get_filename_component(Fortran_BINDIR ${CMAKE_Fortran_COMPILER} DIRECTORY)
get_filename_component(Fortran_PREFIX ${Fortran_BINDIR} DIRECTORY)
set(HEADER_SEARCH_PATH "${Fortran_PREFIX}/include/flang")
endif()
find_file(ISO_FORTRAN_C_HEADER
ISO_Fortran_binding.h
PATHS ${HEADER_SEARCH_PATH}
REQUIRED)
get_filename_component(ISO_FORTRAN_C_HEADER_DIR
"${ISO_FORTRAN_C_HEADER}"
DIRECTORY)
# The program to be used to verify the results. The programs here should take
# two files as arguments, return 0 if the files are identical, non-zero
# otherwise.
set(DIFFPROG)
if (WIN32)
find_program(DIFFPROG
NAMES fc.exe
REQUIRED)
else ()
find_program(DIFFPROG
NAMES diff cmp
REQUIRED)
endif ()
# The test suite expects to be able to run something at test-time. For the
# compile tests, there is nothing to be run. While a better solution will be
# to modify the test suite to allow for cases like this, for the moment, just
# create an empty executable that will be run for each test.
set(DUMMY_SRC ${CMAKE_CURRENT_BINARY_DIR}/dummy.f90)
file(WRITE ${DUMMY_SRC} "program test\nend program test")
set(DUMMY_EXE "dummy")
add_executable(${DUMMY_EXE} ${DUMMY_SRC})
# This script compiles the files that are "compile" tests. It may save the
# diagnostics to file as needed (see the options that the script accepts). There
# should be no dependence on the source files at test-time, so copy the compile
# script over to the build directory. For the moment, nothing is compiled at
# test-time, but that might change.
set(COMPILE_SCRIPT compile-save-diags.cmake)
set(COMPILE_SCRIPT_SRC ${CMAKE_CURRENT_SOURCE_DIR}/${COMPILE_SCRIPT})
set(COMPILE_SCRIPT_BIN ${CMAKE_CURRENT_BINARY_DIR}/${COMPILE_SCRIPT})
file(COPY
${CMAKE_CURRENT_SOURCE_DIR}/${COMPILE_SCRIPT}
DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
# In some case, the "compile" tests are expected to pass. Since diagnostics are
# only saved on failure, the diagnostics file produced when compiling the test
# should be empty. An empty file can, therefore, be used as reference output.
set(EMPTY_FILE "gfortran-compile-empty.reference.out")
file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/${EMPTY_FILE})
add_subdirectory(regression)
add_subdirectory(torture)