GCC accepts this invalid code: struct a { constexpr int size() const { return 3; } }; void f(a &r) { static_assert(r.size() == 3, "error"); } The static_assert condition is non-constant because it mentions the reference 'r' whose referent is not known within that constant expression.
The invalid test case is still accepted on trunk of 6.0 and prior (interestingly, bug 60430 shows a an example of a valid program where a reference is rejected in a constexpr context). $ cat z.c && /home/msebor/build/gcc-trunk-svn/gcc/xgcc -B/home/msebor/build/gcc-trunk-svn/gcc -S -Wall -Wextra -Wpedantic -xc++ z.c && echo SUCCESS struct a { constexpr int size() const { return 3; } }; void f(a &r) { static_assert(r.size() == 3, "error"); } SUCCESS
Seems to have something to do with reference-type parameters. struct a { constexpr int size() const { return 3; } }; constexpr bool g(a&) { return true;} void f(a &r) { static_assert(r.size() == 3, "error"); // accepted static_assert(g(r), ""); // likewise a& rr = r; static_assert(g(rr), ""); // rejected static_assert(rr.size()==3, ""); // likewise }
The invalid test case is still accepted on gcc 9.0. Popped up in a SO question (https://stackoverflow.com/q/57196229/5470596).
The master branch has been updated by Jason Merrill <jason@gcc.gnu.org>: https://gcc.gnu.org/g:87fbd5347b33883006dc77e779b9edc590fcd2f0 commit r10-6417-g87fbd5347b33883006dc77e779b9edc590fcd2f0 Author: Jason Merrill <jason@redhat.com> Date: Mon Feb 3 16:03:45 2020 -0500 c++: Fix constexpr vs. reference parameter. [expr.const] specifically rules out mentioning a reference even if its address is never used, because it implies indirection that is similarly non-constant for a pointer variable. PR c++/66477 * constexpr.c (cxx_eval_constant_expression) [PARM_DECL]: Don't defer loading the value of a reference.
Fixed for GCC 10.
*** Bug 92530 has been marked as a duplicate of this bug. ***