[cfe-dev] LibC++ v3.8 - Problems with ISO C wrapper headers
Martin J. O'Riordan via cfe-dev
cfe-dev at lists.llvm.org
Sun Jan 24 07:23:51 PST 2016
It is fascinating that these words have been there since the original C++98 Standard, and we never noticed it before - a fresh pair of eyes are always good to show up unintended ambiguities.
>From the very formation of the Standards Committee in 1989, it was always our intention to preserve as much compatibility with C as possible so as to allow existing code written in C to be migrated to C++ with minimum hassle. There are unavoidable things like new keywords, and the whole notion of scope changed, but on the whole I think that the committee did a good job at achieving this goal. New keywords were always discussed at great depth, and in many cases obscure syntax that could not exist in C was used in preference to adding a new keyword.
My suspicion is that the wording in “D.5 C standard library headers [depr.c.headers]” was written without quite thinking about the consequences that some of the names in C are now overloaded in C++. Since C++ does not provide a form of using-declaration that can select discrete members from an overloaded name, it is not actually possible to achieve what was the intent of this section in the language, and why it used the “behaves as if” fuzzy wording rather than being explicit. Section “C.5 C standard library [diff.library]” (non-normative) does try to list the set of difference, but curiously does not mention that many of the functions in ‘<math.h>’ are overloaded, nor that ‘abs’ from ‘<stdlib.h>’ is overloaded in both ‘<cstdlib>’ and ‘<cmath>’.
I completed a set of changes to these headers to restore the behaviour to that which people normally expect - I don’t know of another implementation which interprets these words as literally as has been exposed here - and that interpretation in English is perfectly valid. When I ran my tests again with the modified versions, it did successfully correct the failing tests. As I indicated in the first place, these are real world programs that will build successfully and as expected on all other platforms that we have used, some are existing programs ported from other targets, so it is not a target specific issue (leaving ‘__fp16’ aside; it was just ‘__fp16’ that drew my attention to it).
I left the changes for names like ‘fpclassify’ as they are, overloaded in the global namespace because this looks like a perfectly acceptable way of manifesting a C macro implanted semantic in C++ using overloading, and I can’t think of an observable differences that a C program is likely to depend on.
At first I thought that this was just an accident due to the refactoring of ‘<cmath>’ into ‘<cmath>’ and ‘<c++/math.h>’; but it is clear from this thread that it was an intentional act based on valid reading of this statement in the Standard; though in my opinion this is a bug in the Standard and never the intent.
It has often been observed that the C++ Standard would have benefitted from the provision of a Rationale document as was provided with the C Standard, but C++ is a much larger and more complex language, and such a rationale would have taken considerable time and resources to write.
Tomorrow I will synch up to the current head revision of the v3.8 branch and compute a patch file for these changes relative to that revision. I can submit it to this list if a decision is made to accept this this change; I will have to make this change in my version either-way, as I have too many existing programs dependent on the commonly understood meaning. Also, while I am no longer an active participant on the Standard, I will draw attention of this issue to some of my colleagues who are, so that they can discuss it in the formal context of C++17.
Thanks,
MartinO
From: Hal Finkel [mailto:hfinkel at anl.gov]
Sent: 24 January 2016 00:44
To: Martin ORiordan <Martin.ORiordan at Movidius.com>
Cc: Marshall Clow <mclow.lists at gmail.com>; Richard Smith <richard at metafoo.co.uk>; Clang Dev <cfe-dev at lists.llvm.org>; Eric Fiselier <eric at efcs.ca>
Subject: Re: [cfe-dev] LibC++ v3.8 - Problems with ISO C wrapper headers
_____
From: "Martin J. O'Riordan" <martin.oriordan at movidius.com <mailto:martin.oriordan at movidius.com> >
To: "Hal Finkel" <hfinkel at anl.gov <mailto:hfinkel at anl.gov> >
Cc: "Marshall Clow" <mclow.lists at gmail.com <mailto:mclow.lists at gmail.com> >, "Richard Smith" <richard at metafoo.co.uk <mailto:richard at metafoo.co.uk> >, "Clang Dev" <cfe-dev at lists.llvm.org <mailto:cfe-dev at lists.llvm.org> >, "Eric Fiselier" <eric at efcs.ca <mailto:eric at efcs.ca> >
Sent: Saturday, January 23, 2016 4:23:21 PM
Subject: RE: [cfe-dev] LibC++ v3.8 - Problems with ISO C wrapper headers
From: Hal Finkel [mailto:hfinkel at anl.gov]
Sent: 23 January 2016 21:57
To: Martin ORiordan <Martin.ORiordan at Movidius.com <mailto:Martin.ORiordan at Movidius.com> >
Cc: Marshall Clow <mclow.lists at gmail.com <mailto:mclow.lists at gmail.com> >; Richard Smith <richard at metafoo.co.uk <mailto:richard at metafoo.co.uk> >; Clang Dev <cfe-dev at lists.llvm.org <mailto:cfe-dev at lists.llvm.org> >; Eric Fiselier <eric at efcs.ca <mailto:eric at efcs.ca> >
Subject: Re: [cfe-dev] LibC++ v3.8 - Problems with ISO C wrapper headers
The effective code subtly changes silently from:
int x = abs((int)aBar.operator double()); // choosing ‘int ::abs(int)’
to:
int x = (int)abs(aBar.operator double()); // choosing ‘double ::abs(double)’
Of all of your examples, this is the most important. The other changes result in a compilation failure, and are easy to fix. However, it is certainly my experience that, in almost all cases, the semantic change you highlight is actually a silent bug *fix*, as the author almost always intended the behavior we now have, not the behavior we provided previously. Obviously this will not be 100% true, but on balance, the change has seems positive. Either way, good compiler warnings are essential. As I recall, Clang does have a good warning for this.
-Hal
Hmm, yes and no. If they wanted different behaviour, they should have included ‘<cmath>’ and not ‘<math.h>’. It is not our place to assume to fix their possible intent. An expert C++ programmer might expect exactly the C behaviour.
I'd have a difficult time calling such an author an expert C++ programmer, as such a person would clearly understand how easy it would be for some future maintainer to break their code by a seemingly-innocuous improvement in which headers are included, or by placing the code in a different environment (e.g. by someone copying-and-pasting the code into some other file).
The very fact that they chose the C header
But it is often not the choice of the original author, at least not intentionally.
and not the C++ prescribed equivalent makes it more evident to me that this is the realm of the static analyser’s diagnostics, and not the realm of the Standard library implementation to assume it knows what they might have meant.
I think your position is completely reasonable, but there happen to be strong practical advantages to the wording as-stated that are definitely worth considering (regardless of how we got here).
-Hal
MartinO
--
Hal Finkel
Assistant Computational Scientist
Leadership Computing Facility
Argonne National Laboratory
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20160124/3b0840e1/attachment.html>
More information about the cfe-dev
mailing list