How to get the C ++ compiler to emit a constexpr value (e.g. in a warning?)

(This is kind of a XY problem, but carry me.)

I get a compilation warning that the shift amount is too large. Now, to diagnose this, I would like my compiler to somehow constexpr value that is used as the sum of the shift.

The way I have done so far is to try to create an instance of a type with a numeric parameter, which, as I know, I can place out of range, and then add the constexpr value that I wanted and get an error that shows me the sum . But this is an ugly hack. Is there a way to get constexpr values ​​(hopefully not just integers) that will be thrown into the standard error stream? for example, along with some explanatory text or warning message?

I ask about GCC 6.x and later and clang 4.x and later.

+5
source share
3 answers

Well, the obvious approach is similar to what you said - make the compiler specify the value when emitting diagnostics.

 constexpr int I = 8 % 3; template<int i> class TheValueYouWantIs { static_assert(i != i); }; int main() { TheValueYouWantIs<I>(); } 

In this way:

 prog.cpp: In instantiation of 'class TheValueYouWantIs<2>': prog.cpp:8:27: required from here [...less informative stuff...] 

Warnings are obviously more dependent on the compiler, but should be easily possible. However, this will not help you with char arrays. Not a complete solution.

+1
source

GCC displays operands << when it issues an error message for overflow in constant expression. It does not display operands << when it only displays a warning message when the result is not used as a constant expression. You can use this by adding an otherwise meaningless constant.

 template <int> constexpr int f() { return 1; } template <int> constexpr int g() { return 40; } template <int I> constexpr int h() { return f<I>() << g<I>(); } int main() { h<1234>(); } 

This causes a warning without information about the problem value: warning: left shift count >= width of type [-Wshift-count-overflow] .

 template <int> constexpr int f() { return 1; } template <int> constexpr int g() { return 40; } template <int I> constexpr int h() { constexpr int i = f<I>() << g<I>(); return f<I>() << g<I>(); } int main() { h<1234>(); } 

This leads to an error with information about the problem value (along with some additional warnings): error: right operand of shift expression '(1 << 40)' is >= than the precision of the left operand .

If only the second operand is a constant expression, it is still fine, for this specific warning it is enough to turn the left operand into constant 1 .

+1
source

This is super-ugly, but it displays both the name of the expression and its meaning in a noticeable, albeit terrible, format:

 constexpr int I = 8 % 3; #define CONCATENATE( s1, s2 ) s1 ## s2 #define EXPAND_THEN_CONCATENATE( s1, s2 ) CONCATENATE( s1, s2 ) template<int i> class The_expression_named_in_the_previous_error_has_value{ static_assert(i != i, ""); }; #define ERROR_PRINT(_expr) \ EXPAND_THEN_CONCATENATE(In_the_next_error_you_will_find_the_value_of_the_expression__, _expr); \ The_expression_named_in_the_previous_error_has_value<I>(); int main() { ERROR_PRINT(I); } 

This gives (with GCC 6):

 main.cpp: In function 'int main()': main.cpp:11:25: error: 'In_the_next_error_you_will_find_the_value_of_the_expression__I' was not declared in this scope EXPAND_THEN_CONCATENATE(In_the_next_error_you_will_find_the_value_of_the_expression__, _expr); \ ^ main.cpp:3:45: note: in definition of macro 'CONCATENATE' #define CONCATENATE( s1, s2 ) s1 ## s2 ^ main.cpp:11:1: note: in expansion of macro 'EXPAND_THEN_CONCATENATE' EXPAND_THEN_CONCATENATE(In_the_next_error_you_will_find_the_value_of_the_expression__, _expr); \ ^ main.cpp:15:5: note: in expansion of macro 'ERROR_PRINT' ERROR_PRINT(I); ^ main.cpp: In instantiation of 'class The_expression_named_in_the_previous_error_has_value<2>': main.cpp:15:5: required from here main.cpp:7:61: error: static assertion failed: class The_expression_named_in_the_previous_error_has_value{ static_assert(i != i, ""); }; 

But I'm sure this can be greatly improved with some kind of constexpr-string-trickery.

0
source

Source: https://habr.com/ru/post/1274200/


All Articles