[flang-commits] [flang] c536367 - [flang] Avoid ICE in case of subprogram name clash with runtime namespace.
Slava Zakharin via flang-commits
flang-commits at lists.llvm.org
Mon Mar 13 10:16:41 PDT 2023
Author: Slava Zakharin
Date: 2023-03-13T10:16:33-07:00
New Revision: c5363678932a8187b06f931ea30c5d06017b1bb5
URL: https://github.com/llvm/llvm-project/commit/c5363678932a8187b06f931ea30c5d06017b1bb5
DIFF: https://github.com/llvm/llvm-project/commit/c5363678932a8187b06f931ea30c5d06017b1bb5.diff
LOG: [flang] Avoid ICE in case of subprogram name clash with runtime namespace.
This is related to llvm-project#61074.
In general, it is undefined behavior if user subprogram is declared
with a name that matches a name of function from any runtime library
that Flang is using (e.g. FortranRuntime, libm, etc.). With this change-set
we avoid ICE for invalid calls generated during math lowering by
type casing the function before the call. This happens when a user function
call is lowered before the math function call with the same name.
To detect the name clash in cases when the math function call is lowered
before the user function call we set fir.runtime attribute for the math
functions and check it when we lower the user function call.
The warnings are currently emitted only in debug compiler and
under llvm debug options. I think they should be reported
in the same way as regular Flang warnings.
Note that this change-set does not resolve issues with the conversion
passes that might introduce libm calls after the lowering.
Differential Revision: https://reviews.llvm.org/D145653
Added:
flang/test/Lower/math-name-conflict.f90
Modified:
flang/lib/Lower/ConvertCall.cpp
flang/lib/Optimizer/Builder/IntrinsicCall.cpp
flang/test/Lower/math-lowering.f90
Removed:
################################################################################
diff --git a/flang/lib/Lower/ConvertCall.cpp b/flang/lib/Lower/ConvertCall.cpp
index 6a9f3a42825c5..bf1585afe4de7 100644
--- a/flang/lib/Lower/ConvertCall.cpp
+++ b/flang/lib/Lower/ConvertCall.cpp
@@ -299,6 +299,19 @@ fir::ExtendedValue Fortran::lower::genCallOpAndResult(
funcPointer = builder.create<fir::AddrOfOp>(loc, funcOpType, symbolAttr);
else
funcSymbolAttr = symbolAttr;
+
+ // Issue a warning if the procedure name conflicts with
+ // a runtime function name a call to which has been already
+ // lowered (implying that the FuncOp has been created).
+ // The behavior is undefined in this case.
+ if (caller.getFuncOp()->hasAttrOfType<mlir::UnitAttr>(
+ fir::FIROpsDialect::getFirRuntimeAttrName()))
+ LLVM_DEBUG(mlir::emitWarning(
+ loc,
+ llvm::Twine("function name '") +
+ llvm::Twine(symbolAttr.getLeafReference()) +
+ llvm::Twine("' conflicts with a runtime function name used by "
+ "Flang - this may lead to undefined behavior")));
}
mlir::FunctionType funcType =
diff --git a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
index 75f67221deb2f..9f8b009c12e8e 100644
--- a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
+++ b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
@@ -1087,16 +1087,54 @@ static mlir::Value genLibCall(fir::FirOpBuilder &builder, mlir::Location loc,
LLVM_DEBUG(llvm::dbgs() << "Generating '" << libFuncName
<< "' call with type ";
libFuncType.dump(); llvm::dbgs() << "\n");
- mlir::func::FuncOp funcOp =
- builder.addNamedFunction(loc, libFuncName, libFuncType);
- // C-interoperability rules apply to these library functions.
- funcOp->setAttr(fir::getSymbolAttrName(),
- mlir::StringAttr::get(builder.getContext(), libFuncName));
- // TODO: ensure 'strictfp' setting on the call for "precise/strict"
- // FP mode. Set appropriate Fast-Math Flags otherwise.
- // TODO: we should also mark as many libm function as possible
- // with 'pure' attribute (of course, not in strict FP mode).
- auto libCall = builder.create<fir::CallOp>(loc, funcOp, args);
+ mlir::func::FuncOp funcOp = builder.getNamedFunction(libFuncName);
+
+ if (!funcOp) {
+ funcOp = builder.addNamedFunction(loc, libFuncName, libFuncType);
+ // C-interoperability rules apply to these library functions.
+ funcOp->setAttr(fir::getSymbolAttrName(),
+ mlir::StringAttr::get(builder.getContext(), libFuncName));
+ // Set fir.runtime attribute to distinguish the function that
+ // was just created from user functions with the same name.
+ funcOp->setAttr(fir::FIROpsDialect::getFirRuntimeAttrName(),
+ builder.getUnitAttr());
+ auto libCall = builder.create<fir::CallOp>(loc, funcOp, args);
+ // TODO: ensure 'strictfp' setting on the call for "precise/strict"
+ // FP mode. Set appropriate Fast-Math Flags otherwise.
+ // TODO: we should also mark as many libm function as possible
+ // with 'pure' attribute (of course, not in strict FP mode).
+ LLVM_DEBUG(libCall.dump(); llvm::dbgs() << "\n");
+ return libCall.getResult(0);
+ }
+
+ // The function with the same name already exists.
+ fir::CallOp libCall;
+ mlir::Type soughtFuncType = funcOp.getFunctionType();
+
+ if (soughtFuncType == libFuncType) {
+ libCall = builder.create<fir::CallOp>(loc, funcOp, args);
+ } else {
+ // A function with the same name might have been declared
+ // before (e.g. with an explicit interface and a binding label).
+ // It is in general incorrect to use the same definition for the library
+ // call, but we have no other options. Type cast the function to match
+ // the requested signature and generate an indirect call to avoid
+ // later failures caused by the signature mismatch.
+ LLVM_DEBUG(mlir::emitWarning(
+ loc, llvm::Twine("function signature mismatch for '") +
+ llvm::Twine(libFuncName) +
+ llvm::Twine("' may lead to undefined behavior.")));
+ mlir::SymbolRefAttr funcSymbolAttr = builder.getSymbolRefAttr(libFuncName);
+ mlir::Value funcPointer =
+ builder.create<fir::AddrOfOp>(loc, soughtFuncType, funcSymbolAttr);
+ funcPointer = builder.createConvert(loc, libFuncType, funcPointer);
+
+ llvm::SmallVector<mlir::Value, 3> operands{funcPointer};
+ operands.append(args.begin(), args.end());
+ libCall = builder.create<fir::CallOp>(loc, libFuncType.getResults(),
+ nullptr, operands);
+ }
+
LLVM_DEBUG(libCall.dump(); llvm::dbgs() << "\n");
return libCall.getResult(0);
}
diff --git a/flang/test/Lower/math-lowering.f90 b/flang/test/Lower/math-lowering.f90
index 857c9883c65d0..b1ee05ac85436 100644
--- a/flang/test/Lower/math-lowering.f90
+++ b/flang/test/Lower/math-lowering.f90
@@ -57,11 +57,11 @@ function test_complex8(c)
! RELAXED: {{%[A-Za-z0-9._]+}} = complex.abs {{%[A-Za-z0-9._]+}} : complex<f64>
! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @cabs({{%[A-Za-z0-9._]+}}) {{.*}}: (!fir.complex<8>) -> f64
-! PRECISE-DAG: func.func private @fabsf(f32) -> f32 attributes {fir.bindc_name = "fabsf"}
-! PRECISE-DAG: func.func private @fabs(f64) -> f64 attributes {fir.bindc_name = "fabs"}
-! PRECISE-DAG: func.func private @llvm.fabs.f128(f128) -> f128 attributes {fir.bindc_name = "llvm.fabs.f128"}
-! PRECISE-DAG: func.func private @cabsf(!fir.complex<4>) -> f32 attributes {fir.bindc_name = "cabsf"}
-! PRECISE-DAG: func.func private @cabs(!fir.complex<8>) -> f64 attributes {fir.bindc_name = "cabs"}
+! PRECISE-DAG: func.func private @fabsf(f32) -> f32 attributes {fir.bindc_name = "fabsf", fir.runtime}
+! PRECISE-DAG: func.func private @fabs(f64) -> f64 attributes {fir.bindc_name = "fabs", fir.runtime}
+! PRECISE-DAG: func.func private @llvm.fabs.f128(f128) -> f128 attributes {fir.bindc_name = "llvm.fabs.f128", fir.runtime}
+! PRECISE-DAG: func.func private @cabsf(!fir.complex<4>) -> f32 attributes {fir.bindc_name = "cabsf", fir.runtime}
+! PRECISE-DAG: func.func private @cabs(!fir.complex<8>) -> f64 attributes {fir.bindc_name = "cabs", fir.runtime}
//--- aint.f90
! RUN: bbc -emit-fir %t/aint.f90 -o - --math-runtime=fast | FileCheck --check-prefixes=ALL %t/aint.f90
@@ -101,9 +101,9 @@ function test_real10(x)
! test_real16 = aint(x)
!end function
-! ALL-DAG: func.func private @llvm.trunc.f32(f32) -> f32 attributes {fir.bindc_name = "llvm.trunc.f32"}
-! ALL-DAG: func.func private @llvm.trunc.f64(f64) -> f64 attributes {fir.bindc_name = "llvm.trunc.f64"}
-! ALL-DAG: func.func private @llvm.trunc.f80(f80) -> f80 attributes {fir.bindc_name = "llvm.trunc.f80"}
+! ALL-DAG: func.func private @llvm.trunc.f32(f32) -> f32 attributes {fir.bindc_name = "llvm.trunc.f32", fir.runtime}
+! ALL-DAG: func.func private @llvm.trunc.f64(f64) -> f64 attributes {fir.bindc_name = "llvm.trunc.f64", fir.runtime}
+! ALL-DAG: func.func private @llvm.trunc.f80(f80) -> f80 attributes {fir.bindc_name = "llvm.trunc.f80", fir.runtime}
//--- anint.f90
! RUN: bbc -emit-fir %t/anint.f90 -o - --math-runtime=fast | FileCheck --check-prefixes=ALL,FAST %t/anint.f90
@@ -149,9 +149,9 @@ function test_real10(x)
! test_real16 = anint(x)
!end function
-! PRECISE-DAG: func.func private @llvm.round.f32(f32) -> f32 attributes {fir.bindc_name = "llvm.round.f32"}
-! PRECISE-DAG: func.func private @llvm.round.f64(f64) -> f64 attributes {fir.bindc_name = "llvm.round.f64"}
-! PRECISE-DAG: func.func private @llvm.round.f80(f80) -> f80 attributes {fir.bindc_name = "llvm.round.f80"}
+! PRECISE-DAG: func.func private @llvm.round.f32(f32) -> f32 attributes {fir.bindc_name = "llvm.round.f32", fir.runtime}
+! PRECISE-DAG: func.func private @llvm.round.f64(f64) -> f64 attributes {fir.bindc_name = "llvm.round.f64", fir.runtime}
+! PRECISE-DAG: func.func private @llvm.round.f80(f80) -> f80 attributes {fir.bindc_name = "llvm.round.f80", fir.runtime}
//--- atan.f90
! RUN: bbc -emit-fir %t/atan.f90 -o - --math-runtime=fast | FileCheck --check-prefixes=ALL,FAST %t/atan.f90
@@ -181,8 +181,8 @@ function test_real8(x)
! RELAXED: {{%[A-Za-z0-9._]+}} = math.atan {{%[A-Za-z0-9._]+}} {{.*}}: f64
! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @atan({{%[A-Za-z0-9._]+}}) {{.*}}: (f64) -> f64
-! PRECISE-DAG: func.func private @atanf(f32) -> f32 attributes {fir.bindc_name = "atanf"}
-! PRECISE-DAG: func.func private @atan(f64) -> f64 attributes {fir.bindc_name = "atan"}
+! PRECISE-DAG: func.func private @atanf(f32) -> f32 attributes {fir.bindc_name = "atanf", fir.runtime}
+! PRECISE-DAG: func.func private @atan(f64) -> f64 attributes {fir.bindc_name = "atan", fir.runtime}
//--- atan2.f90
! RUN: bbc -emit-fir %t/atan2.f90 -o - --math-runtime=fast | FileCheck --check-prefixes=ALL,FAST %t/atan2.f90
@@ -212,8 +212,8 @@ function test_real8(x, y)
! RELAXED: {{%[A-Za-z0-9._]+}} = math.atan2 {{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}} {{.*}}: f64
! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @atan2({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) {{.*}}: (f64, f64) -> f64
-! PRECISE-DAG: func.func private @atan2f(f32, f32) -> f32 attributes {fir.bindc_name = "atan2f"}
-! PRECISE-DAG: func.func private @atan2(f64, f64) -> f64 attributes {fir.bindc_name = "atan2"}
+! PRECISE-DAG: func.func private @atan2f(f32, f32) -> f32 attributes {fir.bindc_name = "atan2f", fir.runtime}
+! PRECISE-DAG: func.func private @atan2(f64, f64) -> f64 attributes {fir.bindc_name = "atan2", fir.runtime}
//--- ceiling.f90
! RUN: bbc -emit-fir %t/ceiling.f90 -o - --math-runtime=fast | FileCheck --check-prefixes=ALL,FAST %t/ceiling.f90
@@ -243,8 +243,8 @@ function test_real8(x)
! RELAXED: {{%[A-Za-z0-9._]+}} = math.ceil {{%[A-Za-z0-9._]+}} {{.*}}: f64
! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @ceil({{%[A-Za-z0-9._]+}}) {{.*}}: (f64) -> f64
-! PRECISE-DAG: func.func private @ceilf(f32) -> f32 attributes {fir.bindc_name = "ceilf"}
-! PRECISE-DAG: func.func private @ceil(f64) -> f64 attributes {fir.bindc_name = "ceil"}
+! PRECISE-DAG: func.func private @ceilf(f32) -> f32 attributes {fir.bindc_name = "ceilf", fir.runtime}
+! PRECISE-DAG: func.func private @ceil(f64) -> f64 attributes {fir.bindc_name = "ceil", fir.runtime}
//--- cos.f90
! RUN: bbc -emit-fir %t/cos.f90 -o - --math-runtime=fast | FileCheck --check-prefixes=ALL,FAST %t/cos.f90
@@ -274,8 +274,8 @@ function test_real8(x)
! RELAXED: {{%[A-Za-z0-9._]+}} = math.cos {{%[A-Za-z0-9._]+}} {{.*}}: f64
! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @cos({{%[A-Za-z0-9._]+}}) {{.*}}: (f64) -> f64
-! PRECISE-DAG: func.func private @cosf(f32) -> f32 attributes {fir.bindc_name = "cosf"}
-! PRECISE-DAG: func.func private @cos(f64) -> f64 attributes {fir.bindc_name = "cos"}
+! PRECISE-DAG: func.func private @cosf(f32) -> f32 attributes {fir.bindc_name = "cosf", fir.runtime}
+! PRECISE-DAG: func.func private @cos(f64) -> f64 attributes {fir.bindc_name = "cos", fir.runtime}
//--- cosh.f90
! RUN: bbc -emit-fir %t/cosh.f90 -o - --math-runtime=fast | FileCheck --check-prefixes=ALL %t/cosh.f90
@@ -301,8 +301,8 @@ function test_real8(x)
! ALL-LABEL: @_QPtest_real8
! ALL: {{%[A-Za-z0-9._]+}} = fir.call @cosh({{%[A-Za-z0-9._]+}}) {{.*}}: (f64) -> f64
-! ALL-DAG: func.func private @coshf(f32) -> f32 attributes {fir.bindc_name = "coshf"}
-! ALL-DAG: func.func private @cosh(f64) -> f64 attributes {fir.bindc_name = "cosh"}
+! ALL-DAG: func.func private @coshf(f32) -> f32 attributes {fir.bindc_name = "coshf", fir.runtime}
+! ALL-DAG: func.func private @cosh(f64) -> f64 attributes {fir.bindc_name = "cosh", fir.runtime}
//--- erf.f90
! RUN: bbc -emit-fir %t/erf.f90 -o - --math-runtime=fast | FileCheck --check-prefixes=ALL,FAST %t/erf.f90
@@ -332,8 +332,8 @@ function test_real8(x)
! RELAXED: {{%[A-Za-z0-9._]+}} = math.erf {{%[A-Za-z0-9._]+}} {{.*}}: f64
! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @erf({{%[A-Za-z0-9._]+}}) {{.*}}: (f64) -> f64
-! PRECISE-DAG: func.func private @erff(f32) -> f32 attributes {fir.bindc_name = "erff"}
-! PRECISE-DAG: func.func private @erf(f64) -> f64 attributes {fir.bindc_name = "erf"}
+! PRECISE-DAG: func.func private @erff(f32) -> f32 attributes {fir.bindc_name = "erff", fir.runtime}
+! PRECISE-DAG: func.func private @erf(f64) -> f64 attributes {fir.bindc_name = "erf", fir.runtime}
//--- exp.f90
! RUN: bbc -emit-fir %t/exp.f90 -o - --math-runtime=fast | FileCheck --check-prefixes=ALL,FAST %t/exp.f90
@@ -363,8 +363,8 @@ function test_real8(x)
! RELAXED: {{%[A-Za-z0-9._]+}} = math.exp {{%[A-Za-z0-9._]+}} {{.*}}: f64
! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @exp({{%[A-Za-z0-9._]+}}) {{.*}}: (f64) -> f64
-! PRECISE-DAG: func.func private @expf(f32) -> f32 attributes {fir.bindc_name = "expf"}
-! PRECISE-DAG: func.func private @exp(f64) -> f64 attributes {fir.bindc_name = "exp"}
+! PRECISE-DAG: func.func private @expf(f32) -> f32 attributes {fir.bindc_name = "expf", fir.runtime}
+! PRECISE-DAG: func.func private @exp(f64) -> f64 attributes {fir.bindc_name = "exp", fir.runtime}
//--- floor.f90
! RUN: bbc -emit-fir %t/floor.f90 -o - --math-runtime=fast | FileCheck --check-prefixes=ALL,FAST %t/floor.f90
@@ -394,8 +394,8 @@ function test_real8(x)
! RELAXED: {{%[A-Za-z0-9._]+}} = math.floor {{%[A-Za-z0-9._]+}} {{.*}}: f64
! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @floor({{%[A-Za-z0-9._]+}}) {{.*}}: (f64) -> f64
-! PRECISE-DAG: func.func private @floorf(f32) -> f32 attributes {fir.bindc_name = "floorf"}
-! PRECISE-DAG: func.func private @floor(f64) -> f64 attributes {fir.bindc_name = "floor"}
+! PRECISE-DAG: func.func private @floorf(f32) -> f32 attributes {fir.bindc_name = "floorf", fir.runtime}
+! PRECISE-DAG: func.func private @floor(f64) -> f64 attributes {fir.bindc_name = "floor", fir.runtime}
//--- log.f90
! RUN: bbc -emit-fir %t/log.f90 -o - --math-runtime=fast | FileCheck --check-prefixes=ALL,FAST %t/log.f90
@@ -425,8 +425,8 @@ function test_real8(x)
! RELAXED: {{%[A-Za-z0-9._]+}} = math.log {{%[A-Za-z0-9._]+}} {{.*}}: f64
! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @log({{%[A-Za-z0-9._]+}}) {{.*}}: (f64) -> f64
-! PRECISE-DAG: func.func private @logf(f32) -> f32 attributes {fir.bindc_name = "logf"}
-! PRECISE-DAG: func.func private @log(f64) -> f64 attributes {fir.bindc_name = "log"}
+! PRECISE-DAG: func.func private @logf(f32) -> f32 attributes {fir.bindc_name = "logf", fir.runtime}
+! PRECISE-DAG: func.func private @log(f64) -> f64 attributes {fir.bindc_name = "log", fir.runtime}
//--- log10.f90
! RUN: bbc -emit-fir %t/log10.f90 -o - --math-runtime=fast | FileCheck --check-prefixes=ALL,FAST %t/log10.f90
@@ -456,8 +456,8 @@ function test_real8(x)
! RELAXED: {{%[A-Za-z0-9._]+}} = math.log10 {{%[A-Za-z0-9._]+}} {{.*}}: f64
! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @log10({{%[A-Za-z0-9._]+}}) {{.*}}: (f64) -> f64
-! PRECISE-DAG: func.func private @log10f(f32) -> f32 attributes {fir.bindc_name = "log10f"}
-! PRECISE-DAG: func.func private @log10(f64) -> f64 attributes {fir.bindc_name = "log10"}
+! PRECISE-DAG: func.func private @log10f(f32) -> f32 attributes {fir.bindc_name = "log10f", fir.runtime}
+! PRECISE-DAG: func.func private @log10(f64) -> f64 attributes {fir.bindc_name = "log10", fir.runtime}
//--- nint.f90
! RUN: bbc -emit-fir %t/nint.f90 -o - --math-runtime=fast | FileCheck --check-prefixes=ALL %t/nint.f90
@@ -485,10 +485,10 @@ function test_real8(x)
! ALL: {{%[A-Za-z0-9._]+}} = fir.call @llvm.lround.i32.f64({{%[A-Za-z0-9._]+}}) {{.*}}: (f64) -> i32
! ALL: {{%[A-Za-z0-9._]+}} = fir.call @llvm.lround.i64.f64({{%[A-Za-z0-9._]+}}) {{.*}}: (f64) -> i64
-! ALL-DAG: func.func private @llvm.lround.i32.f32(f32) -> i32 attributes {fir.bindc_name = "llvm.lround.i32.f32"}
-! ALL-DAG: func.func private @llvm.lround.i64.f32(f32) -> i64 attributes {fir.bindc_name = "llvm.lround.i64.f32"}
-! ALL-DAG: func.func private @llvm.lround.i32.f64(f64) -> i32 attributes {fir.bindc_name = "llvm.lround.i32.f64"}
-! ALL-DAG: func.func private @llvm.lround.i64.f64(f64) -> i64 attributes {fir.bindc_name = "llvm.lround.i64.f64"}
+! ALL-DAG: func.func private @llvm.lround.i32.f32(f32) -> i32 attributes {fir.bindc_name = "llvm.lround.i32.f32", fir.runtime}
+! ALL-DAG: func.func private @llvm.lround.i64.f32(f32) -> i64 attributes {fir.bindc_name = "llvm.lround.i64.f32", fir.runtime}
+! ALL-DAG: func.func private @llvm.lround.i32.f64(f64) -> i32 attributes {fir.bindc_name = "llvm.lround.i32.f64", fir.runtime}
+! ALL-DAG: func.func private @llvm.lround.i64.f64(f64) -> i64 attributes {fir.bindc_name = "llvm.lround.i64.f64", fir.runtime}
//--- exponentiation.f90
! RUN: bbc -emit-fir %t/exponentiation.f90 -o - --math-runtime=fast | FileCheck --check-prefixes=ALL,FAST %t/exponentiation.f90
@@ -544,12 +544,12 @@ function test_real8(x, y, s, i, k)
! RELAXED: {{%[A-Za-z0-9._]+}} = math.fpowi {{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}} {{.*}}: f64, i64
! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @_FortranAFPow8k({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) {{.*}}: (f64, i64) -> f64
-! PRECISE-DAG: func.func private @_FortranAFPow4i(f32, i32) -> f32 attributes {fir.bindc_name = "_FortranAFPow4i"}
-! PRECISE-DAG: func.func private @powf(f32, f32) -> f32 attributes {fir.bindc_name = "powf"}
-! PRECISE-DAG: func.func private @_FortranAFPow4k(f32, i64) -> f32 attributes {fir.bindc_name = "_FortranAFPow4k"}
-! PRECISE-DAG: func.func private @_FortranAFPow8i(f64, i32) -> f64 attributes {fir.bindc_name = "_FortranAFPow8i"}
-! PRECISE-DAG: func.func private @pow(f64, f64) -> f64 attributes {fir.bindc_name = "pow"}
-! PRECISE-DAG: func.func private @_FortranAFPow8k(f64, i64) -> f64 attributes {fir.bindc_name = "_FortranAFPow8k"}
+! PRECISE-DAG: func.func private @_FortranAFPow4i(f32, i32) -> f32 attributes {fir.bindc_name = "_FortranAFPow4i", fir.runtime}
+! PRECISE-DAG: func.func private @powf(f32, f32) -> f32 attributes {fir.bindc_name = "powf", fir.runtime}
+! PRECISE-DAG: func.func private @_FortranAFPow4k(f32, i64) -> f32 attributes {fir.bindc_name = "_FortranAFPow4k", fir.runtime}
+! PRECISE-DAG: func.func private @_FortranAFPow8i(f64, i32) -> f64 attributes {fir.bindc_name = "_FortranAFPow8i", fir.runtime}
+! PRECISE-DAG: func.func private @pow(f64, f64) -> f64 attributes {fir.bindc_name = "pow", fir.runtime}
+! PRECISE-DAG: func.func private @_FortranAFPow8k(f64, i64) -> f64 attributes {fir.bindc_name = "_FortranAFPow8k", fir.runtime}
//--- sign.f90
! RUN: bbc -emit-fir %t/sign.f90 -o - --math-runtime=fast | FileCheck --check-prefixes=ALL,FAST %t/sign.f90
@@ -599,10 +599,10 @@ function test_real16(x, y)
! RELAXED: {{%[A-Za-z0-9._]+}} = math.copysign {{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}} {{.*}}: f128
! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @llvm.copysign.f128({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) {{.*}}: (f128, f128) -> f128
-! PRECISE-DAG: func.func private @copysignf(f32, f32) -> f32 attributes {fir.bindc_name = "copysignf"}
-! PRECISE-DAG: func.func private @copysign(f64, f64) -> f64 attributes {fir.bindc_name = "copysign"}
-! PRECISE-DAG: func.func private @copysignl(f80, f80) -> f80 attributes {fir.bindc_name = "copysignl"}
-! PRECISE-DAG: func.func private @llvm.copysign.f128(f128, f128) -> f128 attributes {fir.bindc_name = "llvm.copysign.f128"}
+! PRECISE-DAG: func.func private @copysignf(f32, f32) -> f32 attributes {fir.bindc_name = "copysignf", fir.runtime}
+! PRECISE-DAG: func.func private @copysign(f64, f64) -> f64 attributes {fir.bindc_name = "copysign", fir.runtime}
+! PRECISE-DAG: func.func private @copysignl(f80, f80) -> f80 attributes {fir.bindc_name = "copysignl", fir.runtime}
+! PRECISE-DAG: func.func private @llvm.copysign.f128(f128, f128) -> f128 attributes {fir.bindc_name = "llvm.copysign.f128", fir.runtime}
//--- sin.f90
! RUN: bbc -emit-fir %t/sin.f90 -o - --math-runtime=fast | FileCheck --check-prefixes=ALL,FAST %t/sin.f90
@@ -632,8 +632,8 @@ function test_real8(x)
! RELAXED: {{%[A-Za-z0-9._]+}} = math.sin {{%[A-Za-z0-9._]+}} {{.*}}: f64
! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @sin({{%[A-Za-z0-9._]+}}) {{.*}}: (f64) -> f64
-! PRECISE-DAG: func.func private @sinf(f32) -> f32 attributes {fir.bindc_name = "sinf"}
-! PRECISE-DAG: func.func private @sin(f64) -> f64 attributes {fir.bindc_name = "sin"}
+! PRECISE-DAG: func.func private @sinf(f32) -> f32 attributes {fir.bindc_name = "sinf", fir.runtime}
+! PRECISE-DAG: func.func private @sin(f64) -> f64 attributes {fir.bindc_name = "sin", fir.runtime}
//--- sinh.f90
! RUN: bbc -emit-fir %t/sinh.f90 -o - --math-runtime=fast | FileCheck --check-prefixes=ALL %t/sinh.f90
@@ -659,8 +659,8 @@ function test_real8(x)
! ALL-LABEL: @_QPtest_real8
! ALL: {{%[A-Za-z0-9._]+}} = fir.call @sinh({{%[A-Za-z0-9._]+}}) {{.*}}: (f64) -> f64
-! ALL-DAG: func.func private @sinhf(f32) -> f32 attributes {fir.bindc_name = "sinhf"}
-! ALL-DAG: func.func private @sinh(f64) -> f64 attributes {fir.bindc_name = "sinh"}
+! ALL-DAG: func.func private @sinhf(f32) -> f32 attributes {fir.bindc_name = "sinhf", fir.runtime}
+! ALL-DAG: func.func private @sinh(f64) -> f64 attributes {fir.bindc_name = "sinh", fir.runtime}
//--- tanh.f90
! RUN: bbc -emit-fir %t/tanh.f90 -o - --math-runtime=fast | FileCheck --check-prefixes=ALL,FAST %t/tanh.f90
@@ -690,8 +690,8 @@ function test_real8(x)
! RELAXED: {{%[A-Za-z0-9._]+}} = math.tanh {{%[A-Za-z0-9._]+}} {{.*}}: f64
! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @tanh({{%[A-Za-z0-9._]+}}) {{.*}}: (f64) -> f64
-! PRECISE-DAG: func.func private @tanhf(f32) -> f32 attributes {fir.bindc_name = "tanhf"}
-! PRECISE-DAG: func.func private @tanh(f64) -> f64 attributes {fir.bindc_name = "tanh"}
+! PRECISE-DAG: func.func private @tanhf(f32) -> f32 attributes {fir.bindc_name = "tanhf", fir.runtime}
+! PRECISE-DAG: func.func private @tanh(f64) -> f64 attributes {fir.bindc_name = "tanh", fir.runtime}
//--- tan.f90
! RUN: bbc -emit-fir %t/tan.f90 -o - --math-runtime=fast | FileCheck --check-prefixes=ALL,FAST %t/tan.f90
@@ -721,5 +721,5 @@ function test_real8(x)
! RELAXED: {{%[A-Za-z0-9._]+}} = math.tan {{%[A-Za-z0-9._]+}} {{.*}}: f64
! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @tan({{%[A-Za-z0-9._]+}}) {{.*}}: (f64) -> f64
-! PRECISE-DAG: func.func private @tanf(f32) -> f32 attributes {fir.bindc_name = "tanf"}
-! PRECISE-DAG: func.func private @tan(f64) -> f64 attributes {fir.bindc_name = "tan"}
+! PRECISE-DAG: func.func private @tanf(f32) -> f32 attributes {fir.bindc_name = "tanf", fir.runtime}
+! PRECISE-DAG: func.func private @tan(f64) -> f64 attributes {fir.bindc_name = "tan", fir.runtime}
diff --git a/flang/test/Lower/math-name-conflict.f90 b/flang/test/Lower/math-name-conflict.f90
new file mode 100644
index 0000000000000..0e20f63cf132e
--- /dev/null
+++ b/flang/test/Lower/math-name-conflict.f90
@@ -0,0 +1,50 @@
+! REQUIRES: asserts
+! RUN: bbc -emit-fir %s --math-runtime=precise -o - | FileCheck -check-prefix=CHECK %s
+! RUN: bbc -emit-fir %s --math-runtime=precise -debug-only=flang-lower-intrinsic,flang-lower-expr 2>&1 | FileCheck -check-prefix=CHECK-WARN %s
+
+! CHECK-LABEL: func.func @_QPtest
+! CHECK: fir.call @atanh({{[^,]*}}){{.*}}: (i32) -> i32
+! CHECK-LABEL: func.func @_QPtest2
+! CHECK: %[[ADDR:.*]] = fir.address_of(@atanh) : (i32) -> i32
+! CHECK: %[[CAST:.*]] = fir.convert %[[ADDR]] : ((i32) -> i32) -> ((f64) -> f64)
+! CHECK: fir.call %[[CAST]]({{[^,]*}}){{.*}}: (f64) -> f64
+
+subroutine test(x)
+ interface
+ integer function atanh(x) bind(c)
+ integer,Value :: x
+ end function atanh
+ end interface
+ integer :: x
+ print *,atanh(x)
+end subroutine test
+subroutine test2(x)
+ real(8) :: x
+ print *,atanh(x)
+end subroutine test2
+
+! CHECK-LABEL: func.func @_QPtest3
+! CHECK: fir.call @asinh({{[^,]*}}){{.*}}: (f64) -> f64
+! CHECK-LABEL: func.func @_QPtest4
+! CHECK: %[[ADDR:.*]] = fir.address_of(@asinh) : (f64) -> f64
+! CHECK: %[[CAST:.*]] = fir.convert %[[ADDR]] : ((f64) -> f64) -> ((i32) -> i32)
+! CHECK: fir.call %[[CAST]]({{[^,]*}}){{.*}}: (i32) -> i32
+subroutine test3(x)
+ real(8) :: x
+ print *,asinh(x)
+end subroutine test3
+subroutine test4(x)
+ interface
+ integer function asinh(x) bind(c)
+ integer,Value :: x
+ end function asinh
+ end interface
+ integer :: x
+ print *,asinh(x)
+end subroutine test4
+
+! CHECK-WARN: warning: loc({{.*}}math-name-conflict.f90{{.*}}): function
+! CHECK-WARN-SAME: signature mismatch for 'atanh' may lead to undefined behavior.
+! CHECK-WARN: warning: loc({{.*}}math-name-conflict.f90{{.*}}): function
+! CHECK-WARN-SAME: name 'asinh' conflicts with a runtime function
+! CHECK-WARN-SAME: name used by Flang - this may lead to undefined behavior
More information about the flang-commits
mailing list