Bug 95596 - string literal wrong overload resolution (char* vs std::string)
Summary: string literal wrong overload resolution (char* vs std::string)
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 10.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: rejects-valid, wrong-code
: 86498 104534 (view as bug list)
Depends on:
Blocks:
 
Reported: 2020-06-09 03:05 UTC by olli
Modified: 2022-02-14 20:11 UTC (History)
7 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2021-12-16 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description olli 2020-06-09 03:05:23 UTC
Looking at the following code gcc calls the _char*_ overload, according to the standard the string literal is of type const array of char, so the non const char pointer should not be part of the overload set.

#include <cstdio>
#include <string>
void foo(char*) { puts("char*"); }
void foo(std::string) { puts("std::string"); }
int main()
{
    foo("Hello World");
}


Compiler Explorer Link:
https://godbolt.org/z/82D4LT
Comment 1 olli 2020-06-09 07:17:03 UTC
(In reply to bzsurr from comment #0)
> Looking at the following code gcc calls the _char*_ overload, according to
> the standard the string literal is of type const array of char, so the non
> const char pointer should not be part of the overload set.
> 
> #include <cstdio>
> #include <string>
> void foo(char*) { puts("char*"); }
> void foo(std::string) { puts("std::string"); }
> int main()
> {
>     foo("Hello World");
> }
> 
> 
> Compiler Explorer Link:
> https://godbolt.org/z/82D4LT

Compiler output:
<source>: In function 'int main()':
<source>:9:9: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
    9 |     foo("Hello World");
      |         ^~~~~~~~~~~~~
Comment 2 Jonathan Wakely 2020-06-09 13:43:33 UTC
Confirmed. Even with -std=c++14 -pedantic-errors we still choose the wrong overload (and then give an error that the conversion is not allowed).

There seems to be no way to disable the conversion from string literals to char* that has been deprecated for years.
Comment 3 Jonathan Wakely 2020-06-09 13:45:14 UTC
gcc/cp/typeck.c does:

      if (cxx_dialect >= cxx11)
	pedwarn (loc, OPT_Wwrite_strings,
		 "ISO C++ forbids converting a string constant to %qT",
		 totype);
      else
	warning_at (loc, OPT_Wwrite_strings,
		    "deprecated conversion from string constant to %qT",
		    totype);

As the example above shows, allowing the conversion and then conditionally warning about it is not conforming.
Comment 4 Marek Polacek 2020-06-10 19:30:03 UTC
So this is essentially:

struct S {
  S(const char *);
};

void foo(char *) = delete;
void foo(S);

void
g ()
{
  foo ("");
}

which compiles with clang++ but not with gcc.
Comment 5 Jonathan Wakely 2020-07-22 14:05:04 UTC
Another one that G++ rejects:

  void f(char*);
  int &f(...);
  int &r = f("foo");
Comment 6 Jonathan Wakely 2020-07-22 14:06:12 UTC
*** Bug 86498 has been marked as a duplicate of this bug. ***
Comment 7 Andrew Pinski 2022-02-14 20:11:39 UTC
*** Bug 104534 has been marked as a duplicate of this bug. ***