Bug 70507 - integer overflow builtins not constant expressions
Summary: integer overflow builtins not constant expressions
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 6.0
: P3 enhancement
Target Milestone: ---
Assignee: Martin Sebor
URL:
Keywords: rejects-valid
Depends on:
Blocks:
 
Reported: 2016-04-01 20:30 UTC by Martin Sebor
Modified: 2016-06-13 15:58 UTC (History)
4 users (show)

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


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Martin Sebor 2016-04-01 20:30:21 UTC
The integer overflow built-ins like __builtin_mul_overflow are not usable in constant expressions even when their arguments themselves are constants such that the computations do not overflow.  This prevents the builtins from being used by GCC itself to instrument VLAs defined in constexpr functions to detect overflow in the VLA bounds (see bug 69517 for background).

For additional problem reports caused by not treating the overflow built-ins as constant expressions see bug 68120 and bug 68971.

$ cat z.cpp && /home/msebor/build/gcc-69517/gcc/xg++ -B/home/msebor/build/gcc-69517/gcc -S -Wall -Wextra -Wpedantic -fdump-tree-optimized=/dev/stdout z.cpp
constexpr int mul (int x, int y)
{
    int z = 0;
    return __builtin_mul_overflow (x, y, &z) ? 0 : z;
}

constexpr int z1 = 1234 * 5678;        // okay
constexpr int z2 = mul (1234, 5678);   // error

z.cpp:8:24:   in constexpr expansion of ‘mul(1234, 5678)’
z.cpp:4:35: error: call to internal function
     return __builtin_mul_overflow (x, y, &z) ? 0 : z;
            ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~
Comment 1 Jakub Jelinek 2016-04-04 07:44:42 UTC
For GCC's own instrumentation you should obviously not use these builtins, but the corresponding internal functions, otherwise you take address of something that doesn't need to be addressable.

Whether we want to mark the builtins as constexpr is for us to decide,
I bet as they are storing to what the last argument points to, it could be only usable in C++14 and later constexprs, right?
Comment 2 Martin Sebor 2016-04-04 15:07:50 UTC
Thank you for the suggestion.

Storing values via pointers is not C++ 14 specific so the answer to your question is that having the builtins be treated as constexpr would be useful in both C++ 11 and C++ 14 modes.  The modified example below should help explain it:

constexpr int mul (int x, int y, int z = 0)
{
  return __builtin_mul_overflow *(x, y, &z) ? 0 : z;
}

constexpr int z = mul (1234, 5678);
Comment 3 Martin Sebor 2016-04-28 21:15:18 UTC
Testing a patch.
Comment 4 Martin Sebor 2016-05-01 16:41:06 UTC
Patch posted for review:
https://gcc.gnu.org/ml/gcc-patches/2016-05/msg00013.html
Comment 5 Jakub Jelinek 2016-06-08 19:03:49 UTC
Author: jakub
Date: Wed Jun  8 19:03:17 2016
New Revision: 237238

URL: https://gcc.gnu.org/viewcvs?rev=237238&root=gcc&view=rev
Log:
	PR c++/70507
	PR c/68120
	* builtins.def (BUILT_IN_ADD_OVERFLOW_P, BUILT_IN_SUB_OVERFLOW_P,
	BUILT_IN_MUL_OVERFLOW_P): New builtins.
	* builtins.c: Include gimple-fold.h.
	(fold_builtin_arith_overflow): Handle
	BUILT_IN_{ADD,SUB,MUL}_OVERFLOW_P.
	(fold_builtin_3): Likewise.
	* doc/extend.texi (Integer Overflow Builtins): Document
	__builtin_{add,sub,mul}_overflow_p.
gcc/c/
	* c-typeck.c (convert_arguments): Don't promote last argument
	of BUILT_IN_{ADD,SUB,MUL}_OVERFLOW_P.
gcc/cp/
	* constexpr.c: Include gimple-fold.h.
	(cxx_eval_internal_function): New function.
	(cxx_eval_call_expression): Call it.
	(potential_constant_expression_1): Handle integer arithmetic
	overflow built-ins.
	* tree.c (builtin_valid_in_constant_expr_p): Handle
	BUILT_IN_{ADD,SUB,MUL}_OVERFLOW_P.
gcc/c-family/
	* c-common.c (check_builtin_function_arguments): Handle
	BUILT_IN_{ADD,SUB,MUL}_OVERFLOW_P.
gcc/testsuite/
	* c-c++-common/builtin-arith-overflow-1.c: Add test cases.
	* c-c++-common/builtin-arith-overflow-2.c: New test.
	* g++.dg/ext/builtin-arith-overflow-1.C: New test.
	* g++.dg/cpp0x/constexpr-arith-overflow.C: New test.
	* g++.dg/cpp1y/constexpr-arith-overflow.C: New test.

Added:
    trunk/gcc/testsuite/c-c++-common/builtin-arith-overflow-2.c
    trunk/gcc/testsuite/g++.dg/cpp0x/constexpr-arith-overflow.C
    trunk/gcc/testsuite/g++.dg/cpp1y/constexpr-arith-overflow.C
    trunk/gcc/testsuite/g++.dg/ext/builtin-arith-overflow-1.C
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/builtins.c
    trunk/gcc/builtins.def
    trunk/gcc/c-family/ChangeLog
    trunk/gcc/c-family/c-common.c
    trunk/gcc/c/ChangeLog
    trunk/gcc/c/c-typeck.c
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/constexpr.c
    trunk/gcc/cp/tree.c
    trunk/gcc/doc/extend.texi
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/testsuite/c-c++-common/builtin-arith-overflow-1.c
Comment 6 Martin Sebor 2016-06-13 15:58:13 UTC
r237238 lets GCC 7 accept the integer overflow built-ins in constant expressions whenever their arguments are.