Bug 51785 - gets not anymore declared
Summary: gets not anymore declared
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: libstdc++ (show other bugs)
Version: 4.6.2
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-01-07 15:31 UTC by Ulrich Drepper
Modified: 2021-07-18 18:40 UTC (History)
7 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2012-01-11 00:00:00


Attachments
gets conditionally declared/used (1.18 KB, patch)
2012-03-01 00:21 UTC, Benjamin Kosnik
Details | Diff
gets conditionally declared/used v2 (1.53 KB, patch)
2012-03-02 06:30 UTC, Benjamin Kosnik
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Ulrich Drepper 2012-01-07 15:31:15 UTC
glibc 2.15 and later don't declare gets anymore for ISO C11 mode and if _GNU_SOURCE is defined.  This causes problems with the cstdio header which unconditionally uses

using ::gets;


Something has to be done about this.  If you want glibc to define a macro to signal that gets is not declared let me know.  Otherwise recognize __USE_GNU.

The problem still applies to the trunk.
Comment 1 Marc Glisse 2012-01-07 19:05:28 UTC
I thought this was fixed in glibc:
http://sourceware.org/bugzilla/show_bug.cgi?id=13566
?
Comment 2 Tom de Vries 2012-01-10 22:24:10 UTC
(In reply to comment #1)
> I thought this was fixed in glibc:
> http://sourceware.org/bugzilla/show_bug.cgi?id=13566
> ?

AFAIU GLIBC BZ #13528 was fixed, but there is a new checkin from Ulrich which  breaks libstdc++ build in a similar way:
...
$ git show c3a87236702cb73be1dada3438bbd3c3934e83f8
commit c3a87236702cb73be1dada3438bbd3c3934e83f8
Author: Ulrich Drepper <drepper@gmail.com>
Date:   Sat Jan 7 10:41:00 2012 -0500

    Do not declare gets in _GNU_SOURCE mode at all

diff --git a/ChangeLog b/ChangeLog
index 8f9558c..f089e19 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,7 @@
 2012-01-07  Ulrich Drepper  <drepper@gmail.com>
 
+       * libio/stdio.h: Do not declare gets at all for _GNU_SOURCE.
+
        * elf/tst-unique3.cc: Add explicit declaration of gets.
        * elf/tst-unique3lib.cc: Likewise.
        * elf/tst-unique3lib2.cc: Likewise.
diff --git a/libio/stdio.h b/libio/stdio.h
index d9cb573..28c98e9 100644
--- a/libio/stdio.h
+++ b/libio/stdio.h
@@ -629,7 +629,7 @@ extern char *fgets (char *__restrict __s, int __n, FILE *__restrict __stream)
      __wur;
 
 #if !defined __USE_ISOC11 \
-    || (defined __cplusplus && __cplusplus <= 201103L)
+    || (defined __cplusplus && __cplusplus <= 201103L && !defined __USE_GNU)
 /* Get a newline-terminated string from stdin, removing the newline.
    DO NOT USE THIS FUNCTION!!  There is no limit on how much it will read.
...
Comment 3 Tom de Vries 2012-01-11 13:00:37 UTC
This attempt at 'a glibc version check and defining the std::gets prototype in libstdc++' (PR 51773 comment 11) unbreaks the libstdc++ build:
...
Index: libstdc++-v3/include/c_std/cstdio
===================================================================
--- libstdc++-v3/include/c_std/cstdio (revision 183073)
+++ libstdc++-v3/include/c_std/cstdio (working copy)
@@ -88,6 +88,12 @@
 #undef vprintf
 #undef vsprintf
 
+#if __GLIBC_PREREQ (2,15)
+extern "C" {
+  extern char *gets (char *__s) __attribute__((deprecated));
+}
+#endif
+
 namespace std
 {
   using ::FILE;
Index: libstdc++-v3/include/c_global/cstdio
===================================================================
--- libstdc++-v3/include/c_global/cstdio (revision 183073)
+++ libstdc++-v3/include/c_global/cstdio (working copy)
@@ -89,6 +89,12 @@
 #undef vprintf
 #undef vsprintf
 
+#if __GLIBC_PREREQ (2,15)
+extern "C" {
+  extern char *gets (char *__s) __attribute__((deprecated));
+}
+#endif
+
 namespace std
 {
   using ::FILE;
...
Comment 4 Jonathan Wakely 2012-01-11 13:25:08 UTC
Thanks - I can't test this myself as I don't have the latest glibc sources but will confirm it and change component to libstdc++

Ulrich, G++ unconditionally defines _GNU_SOURCE so __USE_GNU will always be defined when <cstdio> includes <stdio.h>, so there's no point checking for it.

I think Tom's fix is along the right lines, but we probably want to check for the gets() declaration using autoconf and define a _GLIBCXX macro rather than having __GLIBC_PREREQ in the headers, then do:

#ifdef _GLIBCXX_NEED_GETS_DECL
extern "C" {
  extern char *gets (char *__s) __attribute__((deprecated));
}
#endif

At some point we might need to handle the case where the underlying platform doesn't provide gets() at all (e.g. if libstdc++ is used on a platform which only supports C11) but that's not the case for GNU libc and we can worry about that if/when it happens.
Comment 5 Marc Glisse 2012-01-11 13:49:54 UTC
If we are just going to declare gets when glibc doesn't, the easiest solution is a fixinclude that reverts Ulrich's latest glibc commit. Somehow that doesn't feel right...
Comment 6 Jakub Jelinek 2012-02-05 20:34:05 UTC
Yeah, IMHO the removal of gets (== ::gets) for _GNU_SOURCE is very much intentional.  C++ probably only talks about std::gets, doesn't it?
So IMHO then should libstdc++ just for glibc versions that don't provide gets prototype with _GNU_SOURCE defined instead add
namespace std
{
  char *gets (char *) __asm ("gets");
};
Comment 7 Jonathan Wakely 2012-02-05 21:00:36 UTC
(In reply to comment #6)
> Yeah, IMHO the removal of gets (== ::gets) for _GNU_SOURCE is very much
> intentional.  C++ probably only talks about std::gets, doesn't it?

No, std::gets must be declared by <cstdio> and ::gets must be declared by <stdio.h>
Comment 8 Jonathan Wakely 2012-02-05 21:26:26 UTC
Though personally I'm not concerned if libstdc++ doesn't define gets(), noone should be using it, I am concerned that libstdc++ fails to build because of the using decl.
Comment 9 Ramana Radhakrishnan 2012-02-28 14:41:56 UTC
I ran into this failure today when upgrading my copy of (e)glibc in my cross-environment. What's the best way of progressing this further ? 

Doesn't this mean that trunk is broken for building with anything later than glibc-2.15 ? 

Ramana
Comment 10 jsm-csl@polyomino.org.uk 2012-02-28 15:23:38 UTC
If the libstdc++ people are going to do something for 4.7, it really needs 
to be done very soon.

Let's assume glibc should at least get a further change for the sake of 
older GCC versions - changing !defined __USE_GNU to (!defined __USE_GNU || 
(defined __GNUC__ && !__GNUC_PREREQ (4, 7))).  But if this isn't fixed for 
4.7, that conditional in stdio.h would need to use __GNUC_PREREQ (4, 8) 
instead.
Comment 11 Paolo Carlini 2012-02-28 15:35:59 UTC
If the release managers agree, I would be in favor of a quick fix per Comment 3, with a huge comment in the code explaining the issue. But I can't test it right now.
Comment 12 Marc Glisse 2012-02-28 15:47:04 UTC
(In reply to comment #10)
> If the libstdc++ people are going to do something for 4.7, it really needs 
> to be done very soon.

The question is: what do the glibc people want? By removing the gets prototype, they are explicitly going against the C++ standard. Seems to me that libstdc++ should respect that choice (add a test in configure to see if gets is provided, and protect "using ::gets;" with #ifdef) and not provide gets. The alternative is to disagree with the glibc developers and fixinclude stdio.h.
Comment 13 Jakub Jelinek 2012-02-28 15:49:26 UTC
I'm ok with #c3 patch + comment if it works, using special configure macro instead of __GLIBC_PREREQ is IMHO undesirable, because then if you build gcc against glibc 2.14 and afterwards upgrade glibc to 2.15, it will suddenly break.
Comment 14 Ramana Radhakrishnan 2012-02-28 16:09:52 UTC
I can confirm that a build for arm-linux-gnueabi completes and do some cross-testing on qemu if that's deemed to be enough.

Any other ideas for testing. 

Ramana

Here's a suggestion for the comments in this patch. 

diff --git a/libstdc++-v3/include/c_global/cstdio b/libstdc++-v3/include/c_global/cstdio
index 049704d..76755ac 100644
--- a/libstdc++-v3/include/c_global/cstdio
+++ b/libstdc++-v3/include/c_global/cstdio
@@ -89,6 +89,17 @@
 #undef vprintf
 #undef vsprintf
 
+/* glibc 2.15 and later do not declare gets anymore for 
+   ISO C11 mode and if __GNU_SOURCE is defined. See 
+   http://gcc.gnu.org/PR51785 for more on this topic. If
+   this is being changed an equivalent change has to be made
+   in include/c_std/c_stdio.  */
+#if __GLIBC_PREREQ (2,15)
+extern "C" {
+  extern char *gets (char *__s) __attribute__((deprecated));
+}
+#endif
+
 namespace std
 {
   using ::FILE;
diff --git a/libstdc++-v3/include/c_std/cstdio b/libstdc++-v3/include/c_std/cstdio
index 510f599..29142bb 100644
--- a/libstdc++-v3/include/c_std/cstdio
+++ b/libstdc++-v3/include/c_std/cstdio
@@ -88,6 +88,17 @@
 #undef vprintf
 #undef vsprintf
 
+/* glibc 2.15 and later do not declare gets anymore for
+   ISO C11 mode and if __GNU_SOURCE is defined. See 
+   http://gcc.gnu.org/PR51785 for more on this topic. If
+   this hunk below is being changed please also investigate
+   the change for include/c_global/cstdio.  */
+#if __GLIBC_PREREQ (2,15)
+extern "C" {
+  extern char *gets (char *__s) __attribute__((deprecated));
+}
+#endif
+
 namespace std
 {
   using ::FILE;
Comment 15 Jakub Jelinek 2012-02-28 16:18:30 UTC
Ideally, when using
#define _GNU_SOURCE
#include <stdio.h>

in a C++ program ::gets wouldn't be available (the _GNU_SOURCE requests GNU namespace rather than standard C++ one), but when using
#include <list>
#include <stdio.h>
it would provide it (with deprecated attribute), because then the user didn't request _GNU_SOURCE.  But for that we'd need some new macro to request additional prototype for STL needs.
Comment 16 Paolo Carlini 2012-02-28 16:42:55 UTC
I suppose that post 4.7.0 we have to revisit this issue anyway, because C++11 definitely wants to declare std::gets, irrespective of C11. I'm wondering if it would be possible to just take this into account in <stdio.h>, I seem to remember that the glibc headers in a few places already use __cplusplus, right? We also have the __CORRECT_ISO_CPP_STRING_H_PROTO story as an example of interaction between glibc and C++.

That said, for 4.7.0, I think that in any case we want: 1- To fully run the testsuite on a GNU/Linux system using glibc2.15; 2- Convince ourselves that whatever we do in the C++ library is not going to interact badly with further tweaks at the glibc level..
Comment 17 jsm-csl@polyomino.org.uk 2012-02-28 17:05:50 UTC
2.15 has the gets prototype.  It's 2.16 where it has been removed (but the 
version in the headers only changes from 2.15 to 2.16 when the final 2.16 
release is made so you can't distinguish 2.15 from 2.16 development 
versions simply by examining preprocessor macros).
Comment 18 Paolo Carlini 2012-02-28 18:25:54 UTC
Ah, thanks Joseph. Thus, to repeat, anything we do in terms of macros has to be for *2.16* and later.
Comment 19 Benjamin Kosnik 2012-03-01 00:21:11 UTC
Created attachment 26794 [details]
gets conditionally declared/used


Here's a way to deal with gets that is pretty simple. If it's around at configure time, it's used. If not, it's dropped from <cstdio>. This uses the same configure bits and approach used for math.

This should prevent any compile error at bootstrap time. That seems sufficient for gcc-4.7 release. RMs?

Note, I'm on f17 and I'm not running into this during make/check of trunk gcc. 
If somebody can give me self-contained sources that fail on f17 it would be appreciated.

Please don't put in GLIBC macros to cstdio. Boo.

Instead, if you need to layer on a glibc part to this, you should start with this patch, and then conditionally define/undefine _GLIBCXX_HAVE_GETS in 

libstdc++-v3/config/os/gnu-linux/os_defines.h

based on the glibc prerequisites and version checks.

-benjamin
Comment 20 Jakub Jelinek 2012-03-01 13:30:26 UTC
f17 doesn't include glibc 2.16, just patched glibc 2.15, which doesn't have these header changes yet.
The thing I don't like on the last patch is that it hardcodes configure time tests, so when glibc is upgraded say from 2.15 to 2.16, but gcc isn't upgraded, suddenly anything that includes <cstdio> fails to compile.
So I'd prefer something like #c14 patch instead, perhaps testing a macro that is
depending on __GLIBC_PREREQ defined in linux os-defines.h.

Can you please resolve this either way till tomorrow noon UTC (4.7 branching/4.7.0-rc1)?
Thanks.
Comment 21 Richard Biener 2012-03-01 13:44:39 UTC
Wouldn't an unconditional

#if _GNU_SOURCE
  extern char *gets (char *__s);
  using ::gets;
#endif

work as well?

alternatively the FE could provide a language extension that would allow

  __using_if_available ::gets;

;)

Anyway, we don't need to rush anything for 4.7.0, fixing this for 4.7.1
and in a correct way is enough IMHO.
Comment 22 Jonathan Wakely 2012-03-01 13:50:57 UTC
(In reply to comment #21)
> Wouldn't an unconditional
> 
> #if _GNU_SOURCE
>   extern char *gets (char *__s);
>   using ::gets;
> #endif
> 
> work as well?

extern "C" or extern "C++" ?

What if someone defines _GNU_SOURCE on a non-glibc platform (maybe defined unconditionally in a makefile, expecting it to do nothing) but it causes gets() to be declared with a different language linkage to the one in the system's stdio.h?
Comment 23 Benjamin Kosnik 2012-03-02 06:30:29 UTC
Created attachment 26807 [details]
gets conditionally declared/used  v2


As per Jakub's comments. Since time is an issue I'm going to check this in after regression tests complete.
Comment 24 Benjamin Kosnik 2012-03-02 07:14:02 UTC
Author: bkoz
Date: Fri Mar  2 07:13:55 2012
New Revision: 184774

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=184774
Log:
2012-03-01  Benjamin Kosnik  <bkoz@redhat.com>
            Ramana Radhakrishnan <ramana@gcc.gnu.org>

	PR libstdc++/51785
	* acinclude.m4 (GLIBCXX_CHECK_STDIO_PROTO): New.
	* configure.ac: Call it.
	* configure: Regenerate.
	* config.h.in: Same.
	* config/os/gnu-linux/os_defines.h: Conditionally undefine
	_GLIBCXX_HAVE_GETS.
	* include/c_global/cstdio: Conditionally declare deprecated gets.
	* include/c_std/cstdio: Same.

Modified:
    trunk/libstdc++-v3/ChangeLog
    trunk/libstdc++-v3/acinclude.m4
    trunk/libstdc++-v3/config.h.in
    trunk/libstdc++-v3/config/os/gnu-linux/os_defines.h
    trunk/libstdc++-v3/configure
    trunk/libstdc++-v3/configure.ac
    trunk/libstdc++-v3/include/c_global/cstdio
    trunk/libstdc++-v3/include/c_std/cstdio
Comment 25 Jakub Jelinek 2012-03-02 07:29:29 UTC
extern "C" extern

(twice) - too many externs?
Comment 26 Joseph S. Myers 2012-03-09 22:13:49 UTC
The __USE_GNU conditional has now been removed from glibc after further discussion on libc-alpha, so the libstdc++ changes can be reverted (probably after 4.7.0).
Comment 27 Paolo Carlini 2012-03-09 23:48:17 UTC
Thanks a lot Joseph, a very good solution.
Comment 28 andyg1001 2016-12-06 13:31:24 UTC
Erm, am I the first to notice that this "solution" is broken?

The os_defines.h include that undefines _GLIBCXX_HAVE_GETS is included before _GLIBCXX_HAVE_GETS is (re)defined inside c++config.h.

Therefore, _GLIBCXX_HAVE_GETS is still defined when we get to <cstdio>.

Seems still to be broken even in trunk.
Comment 29 Jonathan Wakely 2017-01-18 17:34:23 UTC
(In reply to andyg1001 from comment #28)
> Erm, am I the first to notice that this "solution" is broken?

No, see https://gcc.gnu.org/ml/libstdc++/2016-09/msg00228.html

> The os_defines.h include that undefines _GLIBCXX_HAVE_GETS is included
> before _GLIBCXX_HAVE_GETS is (re)defined inside c++config.h.
> 
> Therefore, _GLIBCXX_HAVE_GETS is still defined when we get to <cstdio>.
>
> Seems still to be broken even in trunk.

PR 77795 improved things. What's still broken? We need a testcase showing the problem.
Comment 30 Jonathan Wakely 2018-09-26 21:06:06 UTC
Is there anything still broken in supported releases? (i.e. gcc-6 or later)
Comment 31 Andrew Pinski 2021-07-18 18:40:07 UTC
I don't think there is any thing more to fix here.  gets works correctly as far as I Know.