When writing code, for a long time I knew that && has higher precedence than ||; however, compiling it using the C++11 standard gave me a warning that I should now use parentheses when using both in a single statement.
Now I got a warning that combining >> and + also should have parentheses. Now my statements look really ugly, with 5 or more parentheses floating around them.
1) Is there a resource that says which combinations of operators now require parentheses?
2) Is there a way to silence just the operator precedence warnings, but to keep the other warnings?
Compiler gcc with flags -O2 -Wall -g
The warnings came in when I added the flag -std=c++11
Sample expression:
(((string[0] << CHAR_BIT) + string[1] << CHAR_BIT) + string[2] << CHAR_BIT) + string[3];
When does C++11 give warnings about operator precedence?
The only case when the standard requires a diagnostic message (note that the standard does not distinguish between warnings and errors that halt the compilation) is when the program violates the standard. Except when the compiler is excempt from that with wording "no diagnostic required".
All other warnings are optional for the compiler and not required by the standard.
1) Is there a resource that says which combinations of operators now require parentheses?
No, because the parentheses are not required. The warning is just a suggestion by the compiler. The program is well-formed.
The warnings came in when I added the flag -std=c++11
For what it's worth, my GCC warns regardless of the standard argument.
2) Is there a way to silence just the operator precedence warnings, but to keep the other warnings?
The warning itself tells which warning option has enabled it (here is the warning from my GCC):
warning: suggest parentheses around '+' inside '<<' [-Wparentheses]
To disable, you can use the corresponding option to disable it: -Wno-WHATEVER.
Now my statements look really ugly, with 5 or more parentheses floating around them.
I recommend instead to extract the repetitive structure, and reuse a standard algorithm:
std::accumulate(string, string + 4, 0, [](auto sum, auto value) {
return (sum << CHAR_BIT) + value;
});
Much fewer parentheses :) Note that in C++11 (prior to C++14) you can not use auto as the type of an argument of a lambda. I don't know what types you use.
See the gcc manual:
-Wparentheses
Warn if parentheses are omitted in certain contexts, such as when there is an assignment in a context where a truth value is expected,
or when operators are nested whose precedence people often get
confused about.
Also warn if a comparison like x<=y<=z appears; this is equivalent to (x<=y ? 1 : 0) <= z, which is a different interpretation from that
of ordinary mathematical notation.
Also warn for dangerous uses of the GNU extension to ?: with omitted middle operand. When the condition in the ?: operator is a
boolean expression, the omitted value is always 1. Often programmers
expect it to be a value computed inside the conditional expression
instead.
(I added the emphasis)
To turn this behavior off, specify -Wno-parentheses to gcc/g++.
Related
I have some heavily-used code that I would like GCC to optimize aggressively. But I also want to write clean, reusable code with (inlinable) functions that are called from several places. There are cases where in the inlined function, there is code that I know can be removed because the conditions can never happen.
Let's look at a concrete example:
#include <assert.h>
static inline int foo(int c)
{
if (c < 4)
return c;
else
return 4;
}
int bar(int c)
{
assert(c < 2);
return foo(c);
}
With -DNDEBUG -O3, GCC will still generate the (c < 4) comparison even though I know it is not needed, because a precondition of the bar function is that c is 0 or 1. Without -DNDEBUG, GCC does remove the comparison because it is implied by the asserts - but of course you have the overhead of the asserts then (which is a lot more).
Is there a way to convey the variable range to GCC so it can be used for optimisation?
If CLang can do better on this, I could also consider switching compilers.
You might use __builtin_unreachable (read about other builtins) in a test to tell the compiler, e.g.,
if (x<2 || x>100)
__builtin_unreachable();
// Here the compiler knows that x is between 3 and 99 inclusive
In your case, add this at the start of your bar (probably wrapped in some nice looking macro):
if (c >= 2)
__builtin_unreachable();
If you optimize strongly (e.g., -O2 at least), the compiler knows that x is between 3 and 99 (and recent versions of GCC contain code to do such analysis—at least processing simple constant interval constraints like above—and take advantage of them in later optimization passes).
However, I am not so sure that you should use that! (at least don't use it often and wrap that in some assert-like macro), because it might not worth the trouble, and because the compiler is in practice only able to handle and propagate simple constraints (whose details are compiler version specific).
As far as I know, both recent Clang and GCC accepts that builtin.
Also look into __builtin_trap (which also emits runtime code).
I accidentally typed the following code but my code successfully built and even ran properly.
std::string myString = "This is my string ";
std::shared_ptr<std::string> s = std::make_shared<std::string>(myString);
p->pushString(s);”accidental typo”;
It just showed a warning Expression result unused.
Why it is not a compiler or run time error?
I am using Xcode editor
Thanks
Why it is not a compiler [...] error?
Because it does not violate any rule of the C++ standard. If a program conforms to the standard then the compiler should allow its compilation. However, it was friendly enough to warn you that the expression is useless.
or run time error?
The expression doesn't result in any executed code, so it would be quite surprising if it resulted in a run time error.
You know that you can have arbitrary expressions as statements? That's how simple functions calls works, or assignments. In fact the statement
p->pushString(s);
is actually such an expression-statement. The p->pushString(s) part is an expression, it's the context (with the terminating semi-colon) that turns it into a statement.
That also means you can do something like
5;
Or in your case
"some string here";
Those are valid statements. They do however produce a result, which is (legally) discarded or ignored, but might cause the compiler to emit a warning about the ignored result.
It's really no different than e.g.
some_function_which_returns_a_result(); // Result ignored
In 2013 there was a question on converting a big working code from double to quadruple precision: "Converting a working code from double-precision to quadruple-precision: How to read quadruple-precision numbers in FORTRAN from an input file", and the consensus was to declare variables using an adjustable parameter "WP" that specifies the "working precision", instead of having a separate version of the program with variables declared using D+01, and another version using Q+01. This way we can easily switch back and forth by defining WP=real128 or WP=real64 at the top, and the rest doesn't need to change.
But how do we do this?
I tried the suggestion in the answer to that question, by making a simple code TEST.F90:
PROGRAM TEST
use ISO_FORTRAN_ENV
WP= real128
IMPLICIT NONE
real (WP) :: X
X= 5.4857990945E-4_WP
END PROGRAM TEST
compiled with:
~/gcc-4.6/bin/gfortran -o tst.x TEST.F90
But it gives:
IMPLICIT NONE
1
Error: Unexpected IMPLICIT NONE statement at (1)
QLEVEL16.F90:5.12:
real (WP) :: MEL
1
Error: Parameter 'wp' at (1) has not been declared or is a variable, which does not reduce to a constant expression
QLEVEL16.F90:6.29:
MEL= 5.4857990945E-4_WP
1
Error: Missing kind-parameter at (1)
The kind specifier must be an integer parameter - and you do not declare it appropriately. Furthermore, implicit none must go before any declaration.
Here is a working version addressing both issues:
PROGRAM TEST
use ISO_FORTRAN_ENV
IMPLICIT NONE
integer, parameter :: WP= real128
real (WP) :: X
X= 5.4857990945E-4_WP
END PROGRAM TEST
Actually many code using this WP approach. Many with select_*_kind intrinsic function. But I think there is a 'easier' way. It's to use default precision without specifying any kind keyword andusing compiler's flag to choose what the default precision is.
Pro is this method is easier if you don't need a precise control of precision on each variable. Con is that will heavily depend on compiler flags, which varies for each compiler or even might not available.
For gfortran, there is more flags -freal4-real8 or -freal4-real16 to promote each explicitly specified lower precision variable to higher precision.
The following program compiles without errors or warning with gcc 4.8.1,
-Wall -std=c++11:
template<unsigned N>
struct A{};
int main(){
A<1-2> a;
(void)a;
return 0;
}
clang 3.3 with the same options gives this error:
error: non-type template argument evaluates to -1, which cannot be narrowed to type 'unsigned int' [-Wc++11-narrowing]
As per this question, it looks
like gcc's present policy just to give warnings for narrowing conversions where
the Standard indicates errors, and where clang gives the indicated errors.
But in this case gcc does not even give a warning.
None of the examples of narrowing conversion errors that are given by the
Standard at § 8.5.4/7 (reproduced in that question)
covers the case of a narrowing conversion of a non-type template argument,
but at § 14.3.2/5 the Standard says:
For a non-type template-parameter of integral or enumeration type, conversions permitted in a con-
verted constant expression (5.19) are applied.
And § 5.19/3 says:
A converted constant expression of type T is a literal constant expression, implicitly converted to type T,
where the implicit conversion (if any) is permitted in a literal constant expression and the implicit conversion
sequence contains only user-defined conversions, lvalue-to-rvalue conversions (4.1), integral promotions (4.5),
and integral conversions (4.7) other than narrowing conversions (8.5.4)
(my emphasis).
This seems to me to mean that even by its own yardstick gcc is at fault in not at all diagnosing a
narrowing conversion in this case. Do I read this right? Is there a
Standard-based counter-argument?
I am asking the question with more feeling that mere curiosity. In a
recursive TMP setting, clang's error diagnostic in this case will pinpoint a
bug in which an unsigned non-type template argument falls
through 0, whereas all you get from gcc is "maximum template instantiation depth exceeded".
GCC is not so pedantic like Clang, however, it can still detect those kind of errors:
gcc -Wsign-conversion 1.cpp
1.cpp: In function 'int main()':
1.cpp:5:10: warning: negative integer implicitly converted to unsigned type [-Wsign-conversion]
A<1-2> a;
^
-Wall does not actually turn on all possible checks.
Read this page for more examples: http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
I'm using gcc.EXE (GCC) 4.8.0 20130203 (experimental)
When learning to code, I was taught the following style when checking the value of a variable:
int x;
Object *object;
...
if(x == 7) { ... }
if(object == NULL) { ... }
However, now that I am in the field, I have encountered more than one co-worker who swears by the approach of switching the lhs and rhs in the if statements:
if(7 == x) { ... }
if(NULL == object) { ... }
The reasoning being that if you accidentally type = instead of ==, then the code will fail at compile. Being unaccustomed to this style, reading 7 == x is difficult for me, slowing my comprehension of their code.
It seems if I adopt this style, I will likely someday in the future save myself from debugging an x = 7 bug, but in the mean time, every time somebody reads my code I may be wasting their time because I fear the syntax is unorthodox.
Is the 7 == x style generally accepted and readable in the industry, or is this just a personal preference of my coworkers?
The reasoning being that if you accidentally type = instead of ==, then the code will fail at compile.
True. On the other hand, I believe modern C and C++ compilers (I'm assuming you're using one of those languages? You haven't said) will warn you if you do this.
Have you tried it with the compiler you're using? If it doesn't do it by default, look to see if there are flags you can use to provoke it - ideally to make it an error rather than just a warning.
For example, using the Microsoft C compiler, I get:
cl /Wall Test.c
test.c(3) : warning C4706: assignment within conditional expression
That's pretty clear, IMO. (The default warning settings don't spot it, admittedly.)
Being unaccustomed to this style, reading 7 == x is difficult for me, slowing my comprehension of their code.
Indeed. Your approach is the more natural style, and should (IMO) be used unless you're really dealing with a compiler which doesn't spot this as a potential problem (and you have no alternative to using that compiler).
EDIT: Note that this isn't a problem in all languages - not even all C-like languages.
For example, although both Java and C# have a similar if construct, the condition expression in both needs to be implicitly convertible to a Boolean value. While the assignment part would compile, the type of the expression in your first example would be int, which isn't implicitly convertible to the relevant Boolean type in either language, leading to a compile-time error. The rare situation where you'd still have a problem would be:
if (foo == true)
which, if typo'd to:
if (foo = true)
would compile and do the wrong thing. The MS C# compiler even warns you about that, although it's generally better to just use
if (foo)
or
if (!foo)
where possible. That just leaves things like:
if (x == MethodReturningBool())
vs
if (MethodReturningBool() == x)
which is still pretty rare, and there's still a warning for it in the MS C# compiler (and probably in some Java compilers).