Over-riding an error

  • Thread starter Brian Salter-Duke
  • Start date
B

Brian Salter-Duke

I am trying to compile a large piece of Fortran code that interfaces in
a small piece of C code. For the C code compile:-

Compiling with the intel icc C compiler gives this warning:-

warning #159: declaration is incompatible with previous "shmat"
(declared at line 57 of "/usr/include/sys/shm.h")
char *shmat();
^

Compiling with gcc4 gives this error:-

error: conflicting types for 'shmat'
/usr/include/sys/shm.h:58: error: previous declaration of 'shmat'
was here

Now clearly this is a problem. shmat is declared void in shm.f. However
the icc compile actually works. I have good reasons why I do not want to
try to fix this. I would like to use gcc4 to reproduce the icc
behaviour. Is there a compiler argument that changes this problem from
an error to a warning with gcc4? I have looked long and hard, but my
lack of experience with C is telling. I came up with nothing, so I
thought I would ask those who really know C.

Brian.
 
I

Ian Collins

Brian said:
I am trying to compile a large piece of Fortran code that interfaces in
a small piece of C code. For the C code compile:-

Compiling with the intel icc C compiler gives this warning:-

warning #159: declaration is incompatible with previous "shmat"
(declared at line 57 of "/usr/include/sys/shm.h")
char *shmat();
^

Compiling with gcc4 gives this error:-

error: conflicting types for 'shmat'
/usr/include/sys/shm.h:58: error: previous declaration of 'shmat'
was here

Now clearly this is a problem. shmat is declared void in shm.f. However
the icc compile actually works. I have good reasons why I do not want to
try to fix this.

It you don't want to fix it, use a wrapper function.
 
R

Richard Tobin

Brian Salter-Duke said:
Now clearly this is a problem. shmat is declared void in shm.f. However
the icc compile actually works. I have good reasons why I do not want to
try to fix this. I would like to use gcc4 to reproduce the icc
behaviour. Is there a compiler argument that changes this problem from
an error to a warning with gcc4?

I don't think so.

I really recommend that you fix the code.

The only alternative I can think of is to create your own fake
sys/shm.h with a different declaration and use the -I flag to ensure
that gcc gets your version instead of the real one. Your version
could include the real one after #defining shmat to something else,
and then #undef it and give your own declaration.

Once again, I really recommend that you fix the code.

-- Richard
 
S

Spiros Bousbouras

I am trying to compile a large piece of Fortran code that interfaces in
a small piece of C code. For the C code compile:-

Compiling with the intel icc C compiler gives this warning:-

warning #159: declaration is incompatible with previous "shmat"
(declared at line 57 of "/usr/include/sys/shm.h")
char *shmat();
^

Compiling with gcc4 gives this error:-

error: conflicting types for 'shmat'
/usr/include/sys/shm.h:58: error: previous declaration of 'shmat'
was here

Now clearly this is a problem. shmat is declared void in shm.f.

Just to make sure you mean that there is a declaration
void shmat();
somewhere, yes ?
However the icc compile actually works.

Do you mean you have tested the code and it works correctly or
simply that the compilation finishes ?
I have good reasons why I do not want to
try to fix this. I would like to use gcc4 to reproduce the icc
behaviour.

A compiler will produce different code for a function which
doesn't return a value than for a function which returns
something, pointer-to-char on this occasion. Furthermore
different things are allowed with different declarations. For
example, with a char *shmat() declaration you are allowed to write
char *c = shmat(/*args*/) ;
but you wouldn't be allowed to write it if shmat() returned
void. So basically you are giving the compiler contradictory
information and you are hoping that somehow it will be able to
generate an executable that functions correctly. Well, you may
get what you want, if you're lucky, but frankly you don't
deserve it.
Is there a compiler argument that changes this problem from
an error to a warning with gcc4?

I don't know of one nor would I expect to find it because it
wouldn't be good for anything for the reasons I explained above.
But there is a gnu.gcc.help group so you might want to ask
there. Or ask at comp.lang.fortran in case anyone there has
encountered a problem similar to yours.
I have looked long and hard, but my
lack of experience with C is telling. I came up with nothing, so I
thought I would ask those who really know C.

C is a statically typed language. Decide whether you want a
function which returns pointer-to-char or a function which
doesn't return a value and declare it accordingly. If you need
both cases declare 2 functions and call each one based to
what is needed at that specific place in the code.
 
E

Eric Sosman

Brian said:
I am trying to compile a large piece of Fortran code that interfaces in
a small piece of C code. For the C code compile:-

Compiling with the intel icc C compiler gives this warning:-

warning #159: declaration is incompatible with previous "shmat"
(declared at line 57 of "/usr/include/sys/shm.h")
char *shmat();
^

Compiling with gcc4 gives this error:-

error: conflicting types for 'shmat'
/usr/include/sys/shm.h:58: error: previous declaration of 'shmat'
was here

Now clearly this is a problem. shmat is declared void in shm.f.

<off-topic>

If this is the POSIX shmat() function, declaring it as
returning `void' (that is, as returning no value) is wrong.

However
the icc compile actually works. I have good reasons why I do not want to
try to fix this.

We'll have to take your word for it that the reasons are
good. I have a hard time imagining a good reason, but my
imagination is something less than all-powerful.
I would like to use gcc4 to reproduce the icc
behaviour. Is there a compiler argument that changes this problem from
an error to a warning with gcc4? I have looked long and hard, but my
lack of experience with C is telling. I came up with nothing, so I
thought I would ask those who really know C.

From the C point of view, the code is wrong, R-O-N-G,
wrong, and the C answer is "Fix it."

If you're determined to leave it broken, your question
really becomes "How do I convince a particular compiler to
accept erroneous code (*and* to give it an interpretation
I'll like)?" That's a question about the particular compiler,
not a question about C, and I suggest you take it up in a
gcc forum.

What I really *want* to suggest is that you fix the broken
code, but if you're too stubborn to do so, well ...

"We're just here to glamourize you
For that endless sleep.
You might just as well look fetching
When you're six feet deep.
That's your funeral!"
-- Mr. and Mrs. Sowerberry
 
B

Brian Salter-Duke

Just to make sure you mean that there is a declaration
void shmat();
somewhere, yes ?

shmat is void in /usr/include/sys/shm.h.
Do you mean you have tested the code and it works correctly or
simply that the compilation finishes ?

It works perfectly well. Indeed thsi code is widely used and has worked
for many teats compiled with compilers other than gfortran/gcc4.
A compiler will produce different code for a function which
doesn't return a value than for a function which returns
something, pointer-to-char on this occasion. Furthermore
different things are allowed with different declarations. For
example, with a char *shmat() declaration you are allowed to write
char *c = shmat(/*args*/) ;
but you wouldn't be allowed to write it if shmat() returned
void. So basically you are giving the compiler contradictory
information and you are hoping that somehow it will be able to
generate an executable that functions correctly. Well, you may
get what you want, if you're lucky, but frankly you don't
deserve it.

I'm not actually doing anything except trying to compile well
established code with a new compiler. I am not writing this code. I
really want to understand why the icc code works. I understand what you
are saying, but then the question is "Why does icc only give a
warning?". Should it not give a very firm error? This is horendously
complex fortran code and on reflection it may well be that this
particularly code is actually never accessed. That would explain why
the icc complile gives a working executable. I plan to look at other
ways of getting around it.
I don't know of one nor would I expect to find it because it
wouldn't be good for anything for the reasons I explained above.
But there is a gnu.gcc.help group so you might want to ask
there. Or ask at comp.lang.fortran in case anyone there has
encountered a problem similar to yours.

-fpermissive is sort of what I want but that works for C++ but not C.

Thanks for all your comments.

Brian.
 
B

Brian Salter-Duke

not sure its applicable in this case, but the idea would to be to have
something like

char* my_shmat()
{
#if GCC
do something expecting a void* shmat
#else
do something else expecting a char* shmat
#endif
}

OK, I see what you mean.
Back to the question - we need more context really.

If you have the header #included, why are you redeclaring the function
at all?
Or is it actually an old style pre-ansi definition in some 3rd party
C/Fortran interface code?

As I said, I do not understand C. I am just looking at code I want to
compile. shmat is void in /usr/include/sys/shm.h and seems to be char
*shmat() in the C function I am compiling. It is certainly old code, so
it may be "old style pre-ansi definition".
By the way, the fact that its "working" doesn't mean it actually /is/
working. You should really fix the problem

I want to understand why this has worked for lots of other people for
years with compilers other than gfortran/gcc4. If I had written the
code, I'd fix it, but it is best to understand why it works in some
cases and perhaps use a work around.

Thanks for your comments.

Brian.
 
B

Ben Bacarisse

Brian Salter-Duke said:
OK, I see what you mean.


As I said, I do not understand C. I am just looking at code I want to
compile. shmat is void in /usr/include/sys/shm.h

You've said this a few times but it is so important that I want to be
sure. It is void or void *? If it really is void then your problem
is much worse than I thought and you can forget everything below.

In old code (before void came into C) char * was used the the
universal pointer type in functions like shmat. It is quite likely
that old code (like yours) declares 'char *shmat();' but on all
systems I can investigate, shmat is declared to return void * now that
this is the correct way to do such things.
and seems to be char
*shmat() in the C function I am compiling. It is certainly old code, so
it may be "old style pre-ansi definition".

It's a pre-ANSI declaration. The definition is elsewhere -- where the
shmat operation is done, usually the OS.
I want to understand why this has worked for lots of other people for
years with compilers other than gfortran/gcc4.

It was 100% correct in the "old days". After 20 years, compilers can
be forgiven for having moved on. It is a shame that the one you
obviously want to use has decided that this is a "hard" error but some
of the gcc developers were in nappies when the code was last
considered "technically correct".

In this specific case (a return type miss-match between void * and
char *) most compilers could probably let it pass (they'd generate the
same code most likely in both cases) but the error is often so serious
that gcc is quite right to make it an error in general.
If I had written the
code, I'd fix it, but it is best to understand why it works in some
cases and perhaps use a work around.

If it is simply the worry of modifying code that you don't fully
understand that is holding you back then dinnae be feart (as they say
in my home town) -- just comment out the 'char *shmat();' line -- it
is not helping at all and it is the cause of the error.

You will have to ensure that there is a valid declaration for shmat
but the best way to ensure that is to make sure that every source file
that uses shmat() includes shm.h at the start. gcc can help you
here. Comment out the line and the compile using

gcc -Wimplicit-function-declaration

Any file where gcc reports:

x.c:7: warning: implicit declaration of function ‘shmat’

needs shm.h (and sys/types.h) to be included at the top. The very
fact that you get the original error message suggests that most of the
files do this already so there won't be many (is any) to fix. If the
code is old, there will be lots of error from this warning setting but
you are interesting only in the shmat ones for the moment (you can fix
the others later if you like!).

Alternately, use the real prototype declaration of the function. By
this I mean change the 'char *shmat();' line to:

void *shmat(int shmid, const void *shmaddr, int shmflg);

This has the advantage that you don't have to check that the file
correctly includes shm.h.
 
K

Keith Thompson

Ben Bacarisse said:
If it is simply the worry of modifying code that you don't fully
understand that is holding you back then dinnae be feart (as they say
in my home town) -- just comment out the 'char *shmat();' line -- it
is not helping at all and it is the cause of the error.

You will have to ensure that there is a valid declaration for shmat
but the best way to ensure that is to make sure that every source file
that uses shmat() includes shm.h at the start. gcc can help you
here. Comment out the line and the compile using

gcc -Wimplicit-function-declaration

Any file where gcc reports:

x.c:7: warning: implicit declaration of function ¡shmat¢

needs shm.h (and sys/types.h) to be included at the top. The very
fact that you get the original error message suggests that most of the
files do this already so there won't be many (is any) to fix. If the
code is old, there will be lots of error from this warning setting but
you are interesting only in the shmat ones for the moment (you can fix
the others later if you like!).

That's what I'd recommend.
Alternately, use the real prototype declaration of the function. By
this I mean change the 'char *shmat();' line to:

void *shmat(int shmid, const void *shmaddr, int shmflg);

This has the advantage that you don't have to check that the file
correctly includes shm.h.

I definitely wouldn't recommend that. Since you need to change the
code anyway, change it to use the declaration that's already provided
in the header. Duplicating the declaration yourself is error-prone
and unnecessary.
 
E

Eric Sosman

Brian said:
[...]
Just to make sure you mean that there is a declaration
void shmat();
somewhere, yes ?

shmat is void in /usr/include/sys/shm.h.

You've written elsewhere in this thread that you "do not
understand C," so forgive me if I find your (repeated) claim
highly unlikely. Let's put it this way: Does the program
ever do anything like `x = shmat(...arguments...)' or maybe
`if (shmat(...arguments...) == NULL)' or anything else that
attempts to use a value returned by shmat()? If so, it follows
that shmat() *cannot* be declared as returning void.

Most likely explanation: Lacking an understanding of C,
you do not perceive the difference between a function returning
`void' and a function returning `void*'. Also, in
It works perfectly well. Indeed thsi code is widely used and has worked
for many teats compiled with compilers other than gfortran/gcc4.

.... the most likely explanation is that lacking an understanding
of C you do not know what you're talking about. (Especially the
part about the "multiple teats," which suggests you may have
been consorting with Eccentrica Gallumbits.)

Even from the fragmentary reports you have provided, it is
clear that there is an error in the code. The correction may
be as simple as discarding the offending redeclaration -- but
you've already said you don't want to change the code, and that
all you want to do is to get the compiler to stop complaining
about the error. And so I repeat: Your question is not about
C, but about how to make a compiler accept a non-C program, and
if you insist in your folly you should take the question to a
gcc forum.
 
B

Ben Bacarisse

Keith Thompson said:
Ben Bacarisse <[email protected]> writes:

I definitely wouldn't recommend that. Since you need to change the
code anyway, change it to use the declaration that's already provided
in the header. Duplicating the declaration yourself is error-prone
and unnecessary.

I realise I did not make the proper way to do this a strong enough
recommendation. This second suggestion is very much a kludge but I
was concerned that someone who does not know C might get intimidated
by adding headers rather than changing a declaration.

To some extent your concern about duplicating the declaration is
mitigated by the fact that we know at least one source file has both
a declaration "by hand" and an include of shm.h so any errors in the
declaration or changes to the official type will get picked up.
 
K

Keith Thompson

Eric Sosman said:
Even from the fragmentary reports you have provided, it is
clear that there is an error in the code. The correction may
be as simple as discarding the offending redeclaration -- but
you've already said you don't want to change the code, and that
all you want to do is to get the compiler to stop complaining
about the error. And so I repeat: Your question is not about
C, but about how to make a compiler accept a non-C program, and
if you insist in your folly you should take the question to a
gcc forum.

I'd like to see an explanation from the original poster of *why* he
doesn't want to (or can't) just change the code.

If changing the code, even though it's incorrect, is absolutely
forbidden, another option might be to hack the build process so that
the source code is passed through a filter that recognizes and deletes
the extraneous declaration, and the filtered code is then compiled.
It's ugly, and I'd never actually recommend it, but it *might* be the
best workaround available.

But really, fixing the code is the right solution if it's at all
possible.
 
B

Brian Salter-Duke

Brian said:
[...]
Just to make sure you mean that there is a declaration
void shmat();
somewhere, yes ?

shmat is void in /usr/include/sys/shm.h.

You've written elsewhere in this thread that you "do not
understand C," so forgive me if I find your (repeated) claim
highly unlikely. Let's put it this way: Does the program
ever do anything like `x = shmat(...arguments...)' or maybe
`if (shmat(...arguments...) == NULL)' or anything else that
attempts to use a value returned by shmat()? If so, it follows
that shmat() *cannot* be declared as returning void.

Most likely explanation: Lacking an understanding of C,
you do not perceive the difference between a function returning
`void' and a function returning `void*'. Also, in

While I do not understand a lot of C, I do understand that difference. I
was just less than totally clear above indicating that /usr/include/sys/shm.h
used the word "void" while the code I am working with uses "char". They
both have the * there
... the most likely explanation is that lacking an understanding
of C you do not know what you're talking about. (Especially the
part about the "multiple teats," which suggests you may have
been consorting with Eccentrica Gallumbits.)

My fingers hate small keyboards. I do not want to say too much about
this code that would identify it for a variety of reasons, but it has
indeed worked very well in thousands of places for very many years, but
as far as I know has never been compiled with gfortran.

The puzzle is why some compilers give no error or even a warning about
this. icc gives a warning. From what you are all saying, it should,
quite rightly, give a fatal error. It just gives a warning and the
fortran code runs fine.
Even from the fragmentary reports you have provided, it is
clear that there is an error in the code. The correction may
be as simple as discarding the offending redeclaration -- but
you've already said you don't want to change the code, and that
all you want to do is to get the compiler to stop complaining
about the error.

I am happy to make small corrections and hope to try some ideas out
further today (early morning here now), but I am conscious of the fact
that the code does work with other compilers, so I want to keep it as
close as possible to the original. Given that icc just gives a warning
and works, looking for a gcc compile parameter that did the same,
seemed a sensible starting point, but it seems there is no such
parameter.
And so I repeat: Your question is not about C, but about how to make a
compiler accept a non-C program, and if you insist in your folly you
should take the question to a gcc forum.

Could you suggest one? As far as I am concerned, a language without a
compiler is useless, so I assumed this group would also discuss C
compilers, as indeed some of you have.
 
F

Flash Gordon

Brian said:
Brian said:
[...]
Just to make sure you mean that there is a declaration
void shmat();
somewhere, yes ?
shmat is void in /usr/include/sys/shm.h.
You've written elsewhere in this thread that you "do not
understand C," so forgive me if I find your (repeated) claim
highly unlikely. Let's put it this way: Does the program
ever do anything like `x = shmat(...arguments...)' or maybe
`if (shmat(...arguments...) == NULL)' or anything else that
attempts to use a value returned by shmat()? If so, it follows
that shmat() *cannot* be declared as returning void.

Most likely explanation: Lacking an understanding of C,
you do not perceive the difference between a function returning
`void' and a function returning `void*'. Also, in

While I do not understand a lot of C, I do understand that difference. I
was just less than totally clear above indicating that /usr/include/sys/shm.h
used the word "void" while the code I am working with uses "char". They
both have the * there

It was not clear earlier, but now it is.
My fingers hate small keyboards. I do not want to say too much about
this code that would identify it for a variety of reasons, but it has
indeed worked very well in thousands of places for very many years, but

Not that surprising that it works (when you can get it to compile).
as far as I know has never been compiled with gfortran.

The puzzle is why some compilers give no error or even a warning about
this. icc gives a warning. From what you are all saying, it should,
quite rightly, give a fatal error. It just gives a warning and the
fortran code runs fine.

Either a warning or an error is acceptable as far as the standard is
concerned. It might also be that the other C compilers being used are
being given options to put them in a mode where they ignore this
problem. Or there might be conditional compilation preventing shm.h
being #included
I am happy to make small corrections and hope to try some ideas out
further today (early morning here now), but I am conscious of the fact
that the code does work with other compilers, so I want to keep it as
close as possible to the original. Given that icc just gives a warning
and works,

Which, from a standards point of view is acceptable,
looking for a gcc compile parameter that did the same,
seemed a sensible starting point, but it seems there is no such
parameter.

GNU people (rather than C people) might be able to answer that. However,
the best answer is to just comment out the erroneous declaration, then
if it is needed for some obsolete system it can simply be uncommented!
Could you suggest one? As far as I am concerned, a language without a
compiler is useless, so I assumed this group would also discuss C
compilers, as indeed some of you have.

Go to the GCC web site, http://gcc.gnu.org/ and you will find links to
their mailing lists. On those mailing lists you will find the people who
actually develop GCC, I'm not aware of anyone that knowledgeable about
gcc here (although a lot of us use it). However, they will probably tell
you to fix your code as well!
 
E

Eric Sosman

Brian said:
[...]
The puzzle is why some compilers give no error or even a warning about
this. icc gives a warning. From what you are all saying, it should,
quite rightly, give a fatal error. It just gives a warning and the
fortran code runs fine.

As far as the C language is concerned, there are only
"diagnostics." There's no distinctions between "errors" and
"warnings" and "tut-tuts" and "silent but significant pursings
of the lips as seen in BBC costume dramas."

Also, once a compiler has emitted whatever diagnostics the
situation requires (plus any others its whim may suggest), it
is free to accept the erroneous source code and translate it
into -- ah, well, there's the rub. Since the definition of the
C language only describes what correct programs will do, it does
not describe the behavior of incorrect programs. So if your
compiler accepts an erroneous source, and translates it to an
executable program, and runs that program -- well, what happens
then is beyond the power of C to prescribe. Perhaps it works as
you intended -- good luck, you're obviously right with the Gods.
Perhaps it does something you didn't want -- too bad, you have
no grounds for complaint.

Usually, people will not give up when the "it doesn't work"
state prevails, but will keep on fiddling until something good
happens. Then you're faced with the question: Is the good thing
something you can rely on, or is it just a happenstance? Here
you face a choice -- it's not one I can make on your behalf, but
I know how I myself would choose.
Even from the fragmentary reports you have provided, it is
clear that there is an error in the code. The correction may
be as simple as discarding the offending redeclaration -- but
you've already said you don't want to change the code, and that
all you want to do is to get the compiler to stop complaining
about the error.

I am happy to make small corrections [...]

From your description, it appears that the header files
declare the shmat() function. It also appears that there's a
free-hand declaration of shmat() somewhere in the code, and that
this declaration conflicts with the one provided by the headers.
The obvious course is to ditch the extraneous declaration ...

... except that it's "obvious" only in a well-behaved world,
and the world is not always well-behaved. Perhaps the code must
also work on some strange system where the relevant headers do
*not* declare shmat(), and the free-hand declaration is in fact
required. If so, you're between Scylla and Charybdis, and there
is no sure route to safety. (Wax in the ears is the traditional
remedy, but I don't see how to apply it here.)
Could you suggest [a gcc forum]?

I don't frequent them and can't vouch for their usefulness,
but gnu.gcc and gnu.gcc.help have promising-looking names.
 
S

Spiros Bousbouras

If so, you're between Scylla and Charybdis, and there
is no sure route to safety. (Wax in the ears is the traditional
remedy, but I don't see how to apply it here.)

And even if you could it is the remedy for Sirens not Scylla
and Charybdis.
 
L

lawrence.jones

Brian Salter-Duke said:
The puzzle is why some compilers give no error or even a warning about
this. icc gives a warning. From what you are all saying, it should,
quite rightly, give a fatal error. It just gives a warning and the
fortran code runs fine.

Because char * and void * are required to have the same representation
and alignment, they are, for the most part, interchangeable. Pre-ANSI C
didn't even have void * and used char * exclusively. Because of that,
many compilers don't even bother to warn about mixing them by default,
since old code might well use char * where the system headers have been
updated to use void * (which would appear to be the situation you are
in). Others choose to warn about it to encourage cleaning up the old
code. Only an overly pedantic compiler would produce an error since the
intent is perfectly clear and is all but guaranteed to work. (Note,
however, that overly pedantic compilers are very useful to ensure that
your code is as portable as possible.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top