Skip to content

Commit 796d26a

Browse files
authored
[flang] Fix ISO_Fortran_binding.h to work better with C++ code (#82556)
[flang] Fix ISO_Fortran_binding.h to work better with C++ code This stems from working on LANL's "dopey" project -- https://github.com/lanl/dopey. That project contains C++ code which includes the header file "ISO_Fortran_binding.h". The dopey code wraps that include with an 'extern "C"' clause since the standard (18.5.1, paragraph 1) says that the file" shall contain C structure definitions, typedef declarations, ...". But the clang++ compiler emits error messages objecting to the fact that ISO_Fortran_binding.h contains templates. This change fixes that by preceding the problematic code in ISO_Fortran_binding.h with language linkage clauses that specify that they contain C++ code rather than C code. In the accompanying test, I needed to account for the fact that some people build the compiler by doing a `make check-flang`. In this case, the clang compiler which is required by the test will not be built. Here's an example of a C++ program that shows the problem: ``` extern "C" { #include "ISO_Fortran_binding.h" } int main() { return 0; } ```
1 parent e877245 commit 796d26a

File tree

2 files changed

+37
-4
lines changed

2 files changed

+37
-4
lines changed

flang/include/flang/ISO_Fortran_binding.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ namespace cfi_internal {
125125
// The below structure emulates a flexible array. This structure does not take
126126
// care of getting the memory storage. Note that it already contains one element
127127
// because a struct cannot be empty.
128-
template <typename T> struct FlexibleArray : T {
128+
extern "C++" template <typename T> struct FlexibleArray : T {
129129
RT_API_ATTRS T &operator[](int index) { return *(this + index); }
130130
const RT_API_ATTRS T &operator[](int index) const { return *(this + index); }
131131
RT_API_ATTRS operator T *() { return this; }
@@ -163,12 +163,12 @@ typedef struct CFI_cdesc_t {
163163
// needed, for C++'s CFI_cdesc_t's emulated flexible
164164
// dim[] array.
165165
namespace cfi_internal {
166-
template <int r> struct CdescStorage : public CFI_cdesc_t {
166+
extern "C++" template <int r> struct CdescStorage : public CFI_cdesc_t {
167167
static_assert((r > 1 && r <= CFI_MAX_RANK), "CFI_INVALID_RANK");
168168
CFI_dim_t dim[r - 1];
169169
};
170-
template <> struct CdescStorage<1> : public CFI_cdesc_t {};
171-
template <> struct CdescStorage<0> : public CFI_cdesc_t {};
170+
extern "C++" template <> struct CdescStorage<1> : public CFI_cdesc_t {};
171+
extern "C++" template <> struct CdescStorage<0> : public CFI_cdesc_t {};
172172
} // namespace cfi_internal
173173
#define CFI_CDESC_T(rank) \
174174
FORTRAN_ISO_NAMESPACE_::cfi_internal::CdescStorage<rank>
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// UNSUPPORTED: system-windows
2+
// RUN: split-file %s %t
3+
// RUN: chmod +x %t/runtest.sh
4+
// RUN: %t/runtest.sh %t %t/cppfile.cpp %flang | FileCheck %s
5+
6+
//--- cppfile.cpp
7+
extern "C" {
8+
#include "ISO_Fortran_binding.h"
9+
}
10+
#include <iostream>
11+
12+
int main() {
13+
std::cout << "PASS\n";
14+
return 0;
15+
}
16+
17+
// CHECK: PASS
18+
// clang-format off
19+
//--- runtest.sh
20+
#!/bin/bash
21+
TMPDIR=$1
22+
CPPFILE=$2
23+
FLANG=$3
24+
BINDIR=`dirname $FLANG`
25+
CPPCOMP=$BINDIR/clang++
26+
if [ -x $CPPCOMP ]
27+
then
28+
$CPPCOMP $CPPFILE -o $TMPDIR/a.out
29+
$TMPDIR/a.out # should print "PASS"
30+
else
31+
# No clang compiler, just pass by default
32+
echo "PASS"
33+
fi

0 commit comments

Comments
 (0)