Bug 67026 - GCC incorrectly rejects well-formed constexpr function definition
Summary: GCC incorrectly rejects well-formed constexpr function definition
Status: RESOLVED DUPLICATE of bug 86678
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: unknown
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: rejects-valid
Depends on:
Blocks: constexpr
  Show dependency treegraph
 
Reported: 2015-07-27 14:24 UTC by Anders Granlund
Modified: 2023-12-30 20:46 UTC (History)
5 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail: 5.3.0, 6.0
Last reconfirmed: 2016-04-26 00:00:00


Attachments
attachment-52942-0.dat (141 bytes, message/delivery-status)
2019-09-29 04:26 UTC, postmaster
Details
attachment-52942-1.eml (1.23 KB, message/rfc822)
2019-09-29 04:26 UTC, postmaster
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Anders Granlund 2015-07-27 14:24:43 UTC
Consider the following program (proc.cc):

void g() {}
constexpr void f() { return; g(); }
int main() {}

Compile it with the following command line:

g++ prog.cc -std=c++14 -pedantic-errors

The following error message is given:

prog.cc: In function 'constexpr void f()':
prog.cc:2:31: error: call to non-constexpr function 'void g()'
 constexpr void f() { return; g(); }
                               ^
I expected to get no error message since the program is well-formed.

I have tried this with gcc HEAD 6.0.0 20150726 here:

http://melpon.org/wandbox/permlink/Hd5t7ppNQWFqioUx

For comparison clang accepts the program with no error messages.
Comment 1 Drea Pinski 2015-07-27 22:48:56 UTC
GCC does not implement the full C++14 rules for constexpr yet.  That is having a return type of void is not implemented yet.  It was invalid for C++11 to have a constexpr with void.
Comment 2 Drea Pinski 2015-07-27 22:49:57 UTC
Actually wait.  I think this is invalid and clang is incorrect in not rejecting it.  Because you have a call to a non constexpr in a constexpr function; does not matter if it is after a return or not.
Comment 3 Anders Granlund 2015-07-28 13:17:43 UTC
(In reply to Andrew Pinski from comment #2)
> Actually wait.  I think this is invalid and clang is incorrect in not
> rejecting it.  Because you have a call to a non constexpr in a constexpr
> function; does not matter if it is after a return or not.

My program is valid. Just having a call expression with a non-constexpr function inside the body of a constexpr function is not in it self a reason for the program to be ill-formed.

The c++ standard is quite permissive about what a function body of a constexpr function can contain, see [dcl.constexpr]p3 (http://eel.is/c++draft/dcl.constexpr#3).

The program would however be ill-formed with no diagnostics required, if the constexpr function could never be called without calling the non-constexpr function. For details, see [dcl.constexpr]p5 (http://eel.is/c++draft/dcl.constexpr#5).

Also the program wold be ill-formed, if the constexpr function needs to be called when evaluating an expression that needs to be a constant expression, and that call would result in a call to the non-constexpr function. For details, see [expr.const]p2 (http://eel.is/c++draft/expr.const#2) (item 2 in the list).


I choose the return type void to avoid having to return a value in f. The test case works with int as return type also.

  void g() {}
  constexpr int f() { return 0; g(); }
  int main() {}

Anyways GCC supports the return type void for constexpr functions. Also relaxed requirements on constexpr functions have been implemented since version 5 of GCC according to this:

https://gcc.gnu.org/projects/cxx1y.html
Comment 4 Markus Trippelsdorf 2015-08-29 15:54:54 UTC
Confirmed. 

Another example:

constexpr int f3() {
  return 0;
  throw;
}

Checking should stop after the return statement.
Comment 5 Martin Sebor 2016-04-27 03:21:59 UTC
All test cases still fail with the current trunk.  I've updated the Known to fail field to reflect that.

$ cat z.cpp && /home/msebor/build/gcc-trunk-git/gcc/xgcc -B/home/msebor/build/gcc-trunk-git/gcc -S -Wall -Wextra -Wpedantic z.cpp
void g () { }
constexpr int f0 () { return 0; g (); }
constexpr int f1 () { return 0; throw 0; }

z.cpp: In function ‘constexpr int f0()’:
z.cpp:2:35: error: call to non-constexpr function ‘void g()’
 constexpr int f0 () { return 0; g (); }
                                 ~~^~
z.cpp: In function ‘constexpr int f1()’:
z.cpp:3:42: error: expression ‘<throw-expression>’ is not a constant-expression
 constexpr int f1 () { return 0; throw 0; }
                                          ^
Comment 6 Ville Voutilainen 2018-11-14 09:11:17 UTC
This seems to have been fixed by the fix to 86678.

*** This bug has been marked as a duplicate of bug 86678 ***
Comment 7 Jonathan Wakely 2019-02-23 03:02:32 UTC
Author: redi
Date: Sat Feb 23 03:01:59 2019
New Revision: 269148

URL: https://gcc.gnu.org/viewcvs?rev=269148&root=gcc&view=rev
Log:
PR libstdc++/89446 fix null pointer dereference in char_traits

	PR libstdc++/89446
	* include/bits/char_traits.h (__constant_char_array): Check index is
	in range before dereferencing.
	(char_traits<char>::compare, char_traits<char>::find)
	(char_traits<char8_t>::compare, char_traits<char8_t>::find): Return
	immediately if n is zero.
	(char_traits<wchar_t>::compare, char_traits<wchar_t>::find): Likewise.
	Remove workarounds for PR 67026.
	* testsuite/21_strings/basic_string_view/operators/char/89446.cc:
	New test.
	* testsuite/21_strings/basic_string_view/operators/wchar_t/89446.cc:
	New test.

Added:
    trunk/libstdc++-v3/testsuite/21_strings/basic_string_view/operators/char/89446.cc
    trunk/libstdc++-v3/testsuite/21_strings/basic_string_view/operators/wchar_t/89446.cc
Modified:
    trunk/libstdc++-v3/ChangeLog
    trunk/libstdc++-v3/include/bits/char_traits.h
Comment 8 postmaster 2019-09-29 04:26:12 UTC Comment hidden (spam)
Comment 9 postmaster 2019-09-29 04:26:13 UTC Comment hidden (spam)