doctest CHECK_TROWS_AS unused argument - c++

I'd like to doctest some conversion expression with C++ doctest.
I'm using a code similar to the following
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "doctest.h"
TEST_CASE("operator int()") {
CHECK_THROWS_AS(int(2), std::invalid_argument);
int i;
CHECK_THROWS_AS(i = int(2), std::invalid_argument);
}
However in both case I get a warning:
dd.cpp:7:7: warning: variable 'i' set but not used [-Wunused-but-set-variable]
int i;
^
dd.cpp:6:19: warning: expression result unused [-Wunused-value]
CHECK_THROWS_AS(int(2), std::invalid_argument);
^ ~
How do I silence the warning in proper C++ (not using a particular compiler feature).
By the way, in my real code, 2 is actually replaced by an object of a class whose int operator may throw.

Related

Error facing with range function in DPC++

I'm new to Sycl/DPC++ language. I wrote a sample vector addition code using Unified shared memory (USM):
#include<CL/sycl.hpp>
#include<iostream>
#include<chrono>
using namespace sycl;
int main()
{
int n=100;
int i;
queue q{ };
range<1>(n);
int *a=malloc_shared<int>(n,q);
int *b=malloc_shared<int>(n,q);
int *c=malloc_shared<int>(n,q);
for(i=0;i<n;i++)
{
a[i]=i;
b[i]=n-i;
}
q.parallel_for(n,[=](auto &i){
c[i]=a[i]+b[i];
}).wait();
for(i=0;i<n;i++){
std::cout<<c[i]<<std::endl;
}
free(a,q);
free(b,q);
free(c,q);
return 0;
}
When I compile it I get the following error:
warning: parentheses were disambiguated as redundant parentheses around declaration of variable named 'n' [-Wvexing-parse]
range<1>(n);
^~~
vec_add.cpp:11:1: note: add enclosing parentheses to perform a function-style cast
range<1>(n);
^
( )
vec_add.cpp:11:9: note: remove parentheses to silence this warning
range<1>(n);
^ ~
vec_add.cpp:11:10: error: redefinition of 'n' with a different type: 'range<1>' vs 'int'
range<1>(n);
^
vec_add.cpp:8:5: note: previous definition is here
int n=100;
^
1 warning and 1 error generated.
How to fix this error?
error: redefinition of 'n' with a different type: 'range<1>' vs 'int'
Two variables with the same name within the same scope create confusion to the compiler, so it might be the reason for the error which you are getting. You can try defining the value of n globally say for eg: #define N 100 in this case, set
range<1>(n);
to
range<1> (N);
and use that in your code.
If you want to declare the size locally then assign another variable (r) to the range as
range<1> r (n);
Now you can directly pass the 'r' variable as a parameter to the parallel_for.

Why can't I use assert with std::is_same?

Can somebody explain to me why on Earth does this code snippet refuse to work?
#include <cassert>
#include <type_traits>
using namespace std;
int main()
{
assert(is_same<int, int>::value);
}
Compilation fails because, according to the compiler:
prog.cpp:7:33: error: macro "assert" passed 2 arguments, but takes just 1
assert(is_same<int, int>::value);
^
prog.cpp: In function 'int main()':
prog.cpp:7:2: error: 'assert' was not declared in this scope
assert(is_same<int, int>::value);
^
What? is_same<int, int>::value is undoubtedly one argument. Also assert is declared at this scope, and the compiler itself confirmed it in the previous error!
http://ideone.com/LcMVkn
The macro splits your parameter(s) like this:
is_same<int , int>::value
// ^^ par1 ^^// ^^ par2 ^^
As assert() is a macro definition (with one parameter), it's handled by the C-preprocessor. The preprocessor is unaware of c++ syntax like template parameters gouped in angle brackets (<>) separated with ,. So the parameter expression is split up like shown above.
You can avoid that using extra parenthesis, so the C-preprocessor will take that parameter as a whole:
assert((is_same<int, int>::value));
// ^ ^

error: jump to label 'foo' crosses initialization of 'bar'

The following C++ example fails to compile with gcc or clang, but only generates a warning with ICC, and nothing at all with MSVC:
int main(int argc, char *argv[])
{
if (argc < 2)
goto clean_up;
#if 1 // FAIL
int i = 0;
#elif 0 // workaround - OK
{
int i = 0;
}
#else // workaround - OK
int i;
i = 0;
#endif
clean_up:
return 0;
}
g++:
init.cpp:13: error: jump to label ‘clean_up’
init.cpp:4: error: from here
init.cpp:7: error: crosses initialization of ‘int i’
clang++:
init.cpp:4:9: error: cannot jump from this goto statement to its label
goto clean_up;
^
init.cpp:7:9: note: jump bypasses variable initialization
int i = 0;
^
ICC:
init.cpp(4): warning #589: transfer of control bypasses initialization of:
variable "i" (declared at line 7)
goto clean_up;
^
I understand the cause of the error, and for a simple example such as this it is fairly easy to work around (I've included a couple of possible workarounds in the example above), but I'm working on a large cross-platform legacy code base that is peppered with error-handling macros which use a similar goto construct. Other developers working with MSVC or ICC keep introducing inline initialisations which subsequently result in errors for gcc or clang builds (and of course they just ignore the warnings they get with MSVC/ICC).
So I need to find a way to either (a) make such cases result in errors on ICC/MSVC or (b) reduce them to warnings with gcc/clang. I tried -fpermissive with gcc but that doesn't seem to help.
For extra credit I'm also curious as to the rationale behind this error for simple scalar initialisation - I can see why jumping over a constructor might be problematic, but initialising an int as in the above example doesn't seem like it could ever be an issue, and simply splitting the definition+initialisation into a definition + assignment makes the error go away?
The MSVC flag for treating a warning as en error is /we n where n is the number of the warning.
For example, /we4326 flags warning number C4326 as an error.
See https://msdn.microsoft.com/en-us/library/thxezb7y.aspx for details.

Overkilling "crosses initialization of variable" error in C++?

I noticed that g++ complain a bit too strictly about crossed initialization and I wonder why these false-positive errors could not be removed just by looking at the SSA form of the program while compiling.
Let me give a very simple example:
#include <cstdlib>
int main ()
{
goto end;
int i = 0; // unused variable declaration
end:
return EXIT_SUCCESS;
}
When compiled with g++ -Wall -Wextra -o example1 example1.cc (g++ 4.8.1), the compiler gives the following error message:
example1.cc: In function ‘int main()’:
example1.cc:10:2: error: jump to label ‘end’ [-fpermissive]
end:
^
example1.cc:6:8: error: from here [-fpermissive]
goto end;
^
example1.cc:8:7: error: crosses initialization of ‘int i’
int i = 0;
^
example1.cc:8:7: warning: unused variable ‘i’ [-Wunused-variable]
So, it will raise an error where there is actually no risk because the variable is unused (the compiler obviously has both information and cannot combine it to deduce that the error is a false-positive).
More strange, I hoped that LLVM was more efficient at analyzing a program. So, I tried clang++ (LLVM) on this simple example with clang++ -Wall -Wextra -o example1 example1.cc (clang++ 3.4). And, I got about the same error message:
example1.cc:8:7: warning: unused variable 'i' [-Wunused-variable]
int i = 0;
^
example1.cc:6:3: error: goto into protected scope
goto end;
^
example1.cc:8:7: note: jump bypasses variable initialization
int i = 0;
^
1 warning and 1 error generated.
So, I am pretty sure that I am missing something important here, a problem that make the detection of this false-positive harder than I though. But, I do not know what is it. Or maybe, the C++ specification specifically says that it must be like this.
If somebody has an idea, feel free to share !
Edit: I also compiled the exact same code in C (gcc or clang), and it went fine just with the warning about i being an unused variable. So, it reinforce the fact that this is more likely linked to the specification of C++ and not a problem detecting this issue at compile time.
There is nothing wrong with the compilers. Your code is ill-formed according to the standard.
In your particular case, the requirement of the standard may not be necessary and the jump could be allowed and the compiler could create valid code. However, this is only because the initialisation of the variable int i has no side effects.
You can make your code valid by simply enclosing the jumped section in its own scope:
#include <cstdlib>
int main ()
{
goto end;
{
int i = 0; // unused variable declaration
}
end:
// cannot use i here, as it's not defined.
return EXIT_SUCCESS;
}
This is disallowed because potentially you'd call destructors for objects that aren't properly constructed. Admittedly, int doesn't have constructor or destructor, but it's making it "fair" for all types of objects. And technically, something at label end: could be using i, and by making the rule strict, it prevents the machine having to check every single code-path (which becomes a "halting problem").

Compiler does not give error when using list initialization which will cause information loss

In c++ primer(5th), it mentioned:
When used with variables of built-in type, this form of initialization
has one
important property: The compiler will not let us list initialize variables of built-in type if the initializer might lead to the loss
of information:
longdouble ld = 3.1415926536;
int a{ld}, b = {ld}; // error: narrowing conversion required
int c(ld), d = ld; // ok: but value will be truncate
I compile the code using gcc4.8.1 , it only give a warning rather than an error.
g++ -W -Wall -Wextra -pedantic -std=c++0x -o m main.cpp
main.cpp: In function ‘int main()’:
main.cpp:64:13: warning: narrowing conversion of ‘ld’ from ‘long double’ to ‘int’ inside { } [-Wnarrowing]
int a{ld}, b= {ld};
^
main.cpp:64:22: warning: narrowing conversion of ‘ld’ from ‘long double’ to ‘int’ inside { } [-Wnarrowing]
int a{ld}, b= {ld};
Is there any flags that will turn on the feature of the important property ?
A quick search for "gcc diagnostic flag" turns up documentation resources.
Inside your program, you could do this:
#ifdef __GNUC__
# pragma GCC diagnostic error "-Wnarrowing"
#endif
There is a command-line option too: -Werror=narrowing, but since you want to alter the semantic meaning of the program itself according to GCC, putting it in the source code is probably more appropriate.
Note, when it makes a difference other than simple well-formedness, such as in overload selection, GCC does diagnose the condition correctly.
The standard never calls for errors or for warnings: the standard only requires an implementation to issue a diagnostic. Whether such a diagnostic takes the form of a compiler error, or a warning, or something entirely different from them both, is outside the scope of the standard.