I have a file "test.cxx" with
namespace net {
extern "C" {
#include <arpa/inet.h>
}
}
int main() {
htons(1024);
}
When compiling with -O1 or more everything's fine.
When compiling with -O0:
error: ‘htons’ was not declared in this scope
suggested alternative: ‘net::htons’
Then I change htons to net::htons.
When compiling with -O0 everything's fine.
When compiling with -O1 or more:
error: expected unqualified-id before ‘(’ token
Reproduced that on gcc-4.9.2 and clang-3.7.0.
Can someone explain why does it happen?
It happens because at -O0, call is compiled to htons function and your declaration for this function is inside namespace net. In optimized version, -O2 for example, call is replaced with a macro.
You can verify this by pre-compiling your program using gcc -O0 -E v/s gcc -O2 -E
When htons is used
At -O2, htons is translated to
int main() {
(__extension__ (
{
register unsigned short int __v, __x = (unsigned short int) (1024);
if (__builtin_constant_p (__x))
__v = ((unsigned short int) ((((__x) >> 8) & 0xff) | (((__x) & 0xff) << 8)));
else
__asm__ ("rorw $8, %w0" : "=r" (__v) : "0" (__x) : "cc");
__v;
}
));
}
Making the code not throw the resolution error.
error: ‘htons’ was not declared in this scope
When net::htons is used
When you replace ntohs with net::ntohs, ntohs define is used / exposed for optimization and your pre-processed code look as:
int main() {
net::(__extension__ ({... /* removed for Brevity */ ...}));
}
And hence the error
error: expected unqualified-id before ‘(’ token
Why does it happenhtons may be implemented as a function or a macro. If it is defined as macro, htons would work fine. But if it is defined as a function net::htons would work fine.
It appears at -O1 or higher, header files expose macro versions instead of function.
Possible solutions
using namespace net; // Not recommended
#ifndef htons // Recommended
using net::htnos;
#endif
extern "C" { // Add all declarations in global space
#include <arpa/inet.h>
}
Related
I'm trying to learn new features/gimmicks of c++17, but then I got to std::byte and for some unknown reason I can't seem to be able to compile even most basic "hello world" type program with the type.
entire program:
#include <cstddef>
int main(int argc, char* argv[])
{
std::byte byte;
return 0;
}
compilation command:
g++ ./main.cpp
But the output is always:
./main.cpp: In function ‘int main(int, char**)’:
./main.cpp:4:10: error: ‘byte’ is not a member of ‘std’
std::byte byte;
I work on Ubuntu 18.04 with gcc 7.4.0. I have checked "/usr/include/c++/7.4.0/" and header file cstddef is there and byte seems to be defined.
I have also tried to use clang:
clang++ ./main.cpp
But the result was same. At this point I can only think that cstddef is corrupted/bugged. Are there any solutions to this?
As πάντα ῥεῖ pointed out in comment I was missing c++17 compile flag. Right compilation command:
g++ -std=c++17 ./main.cpp
If you use clang 5.0 (even with -std=c++17 flag) the same error occur.
In that case, to solve this you need to upgrade to clang 6.
A temporay and quick workaround is possible (but not recommanded since it plays with std namespace), it could be something like:
#if defined(__clang__) && __cplusplus >= 201703L && __clang_major__ < 6
// This is a minimal workaround for clang 5.0 with missing std::byte type
namespace std {
enum class byte : unsigned char {};
}
#endif
If I have
namespace foo {
inline int bar() {
return 1119;
}
}
__attribute__((deprecated)) inline int bar() {
return 138;
}
in header.h and
#include "header.h"
#include <iostream>
int main() {
int x = bar();
int y = foo::bar();
std::cout << x << std::endl;
std::cout << y << std::endl;
}
in source.cpp, then
g++ source.cpp -o deprecated-test
results in
source.cpp: In function ‘int main()’:
source.cpp:5:17: warning: ‘int bar()’ is deprecated [-Wdeprecated-declarations]
int x = bar();
^
In file included from source.cpp:1:
header.h:7:40: note: declared here
__attribute__((deprecated)) int bar() {
^~~
source.cpp:5:17: warning: ‘int bar()’ is deprecated [-Wdeprecated-declarations]
int x = bar();
^
In file included from source.cpp:1:
header.h:7:40: note: declared here
__attribute__((deprecated)) int bar() {
(on Ubuntu 18.10 with g++ 8.2.0).
Why does the deprecated warning print twice?
Heading off some suggestions that would be unhelpful:
[[deprecated]]:
I know with C++14 on you can use the [[deprecated]] attribute, but I need to work with C++11.
Declaration vs. definition: The docs seem to imply it should be used with function declaration rather than definition, but
I need to define the functions inline in a header rather than declare in the header and define in source files; and
Trying this approach didn't stop the warning from printing twice anyway.
As per the documentation of GCC 8.2.0:
The deprecated attribute results in a warning if the function is used anywhere
in the source file. This is useful when identifying functions that are expected
to be removed in a future version of a program. The warning also includes the
location of the declaration of the deprecated function, to enable users to easily
find further information about why the function is deprecated, or what they
should do instead. Note that the warnings only occurs for uses...
There should be only one warning and not two. So this is a bug in GCC.
There is a related bug for Type attributes (rather than Function attributes) titled: C/C++ __attribute__((deprecated)) does not appear to wrap declarations as implied from the doc.
It has been confirmed as a bug.
Consider the following (buggy) C++ code:
#include <cmath>
#include <cstdlib>
#include <iostream>
int main() {
if (abs(-0.75) != 0.75) {
std::cout << "Math is broken!\n";
return 1;
} else {
return 0;
}
}
This code is buggy because it calls abs (meaning ::abs) instead of std::abs. Depending on the implementation, ::abs might not exist, or it might be the C abs, or it might be an overload set including a version for double, like std::abs is.
With Clang on Linux, at least in my environment, it turns out to be the second option: C abs. This provokes two warnings, even without explicitly enabling any:
<source>:7:9: warning: using integer absolute value function 'abs' when argument is of floating point type [-Wabsolute-value]
if (abs(-0.75) != 0.75) {
^
<source>:7:9: note: use function 'std::abs' instead
if (abs(-0.75) != 0.75) {
^~~
std::abs
<source>:7:13: warning: implicit conversion from 'double' to 'int' changes value from -0.75 to 0 [-Wliteral-conversion]
if (abs(-0.75) != 0.75) {
~~~ ^~~~~
On GCC, I get different results in different environments and I haven’t yet figured out what details of the environment are relevant. The more common option, though, is also that it calls the C abs function. However, even with -Wall -Wextra -pedantic, it gives no warnings. I can force a warning with -Wfloat-conversion, but that gives too many false positives on the rest of my codebase (which perhaps I should fix, but that’s a different issue):
<source>: In function 'int main()':
<source>:7:18: warning: conversion to 'int' alters 'double' constant value [-Wfloat-conversion]
if (abs(-0.75) != 0.75) {
^
Is there a way to get a warning whenever I use a library function through the global namespace, when the version in namespace std is an overload?
Here's a solution. I'm not happy with it, but it might work for you:
namespace DontUseGlobalNameSpace {
// put all std functions here you want to catch
int abs(int x);
}
using namespace DontUseGlobalNameSpace;
Now, if you use abs() without qualification, you'll get a "symbol is ambiguous" error.
This is going to be difficult. The GCC <cmath> header simply includes <math.h>, #undefs its macros (just in case) and defines the C++ functions as inline functions which make some use of identifiers from <math.h>. Most of the functions in fact refer to compiler builtins: for instance, std::abs is defined using __builtin_abs and not ::abs.
Since <cmath> and your "buggy program" are all in the same translation unit, it's hard to see how the visibility could be separated: how the inline functions in <cmath> could be allowed to use <math.h> stuff, while your code wouldn't.
Well, there is the following way: <cmath> would have to be rewritten to provide its own locally scoped declarations for anything that it needs from <math.h> and not actually include that header.
What we can do instead is prepare a header file which re-declares the functions we don't want, with an __attribute__ ((deprecated)):
// put the following and lots of others like it in a header:
extern "C" int abs(int) throw () __attribute__ ((deprecated));
#include <cmath>
#include <cstdlib>
#include <iostream>
int main() {
if (abs(-0.75) != 0.75) {
std::cout << "Math is broken!\n";
return 1;
} else {
return 0;
}
}
Now:
$ g++ -Wall buggy.cc
buggy.cc: In function ‘int main()’:
buggy.cc:9:7: warning: ‘int abs(int)’ is deprecated [-Wdeprecated-declarations]
if (abs(-0.75) != 0.75) {
^~~
In file included from /usr/include/c++/6/cstdlib:75:0,
from buggy.cc:4:
/usr/include/stdlib.h:735:12: note: declared here
extern int abs (int __x) __THROW __attribute__ ((__const__)) __wur;
^~~
buggy.cc:9:16: warning: ‘int abs(int)’ is deprecated [-Wdeprecated-declarations]
if (abs(-0.75) != 0.75) {
^
In file included from /usr/include/c++/6/cstdlib:75:0,
from buggy.cc:4:
/usr/include/stdlib.h:735:12: note: declared here
extern int abs (int __x) __THROW __attribute__ ((__const__)) __wur;
^~~
A linker warning would be simpler. I tried that; the problem is that this test program doesn't actually generate an external reference to abs (even though there is an #undef abs in <cmath>). The call is being inlined, and so evades the linker warning.
Update:
Following up DanielH's comment, I have come up with a refinement of the trick which allows std::abs but blocks abs:
#include <cmath>
#include <cstdlib>
#include <iostream>
namespace proj {
// shadowing declaration
int abs(int) __attribute__ ((deprecated));
int fun() {
if (abs(-0.75) != 0.75) {
std::cout << "Math is broken!\n";
return 1;
} else {
return std::abs(-1); // must be allowed
}
}
}
int main() {
return proj::fun();
}
Simple namespaces can be used. Also, we don't need the deprecated attribute; we can just declare abs as an incompatible function, or a non-function identifier entirely:
#include <cmath>
#include <cstdlib>
#include <iostream>
namespace proj {
// shadowing declaration
class abs;
int fun() {
if (abs(-0.75) != 0.75) {
std::cout << "Math is broken!\n";
return 1;
} else {
return std::abs(-1); // must be allowed
}
}
}
int main() {
return proj::fun();
}
$ g++ -std=c++98 -Wall buggy.cc -o buggy
buggy.cc: In function ‘int proj::fun()’:
buggy.cc:10:18: error: invalid use of incomplete type ‘class proj::abs’
if (abs(-0.75) != 0.75) {
^
buggy.cc:7:9: note: forward declaration of ‘class proj::abs’
class abs;
^~~
buggy.cc:16:3: warning: control reaches end of non-void function [-Wreturn-type]
}
^
With this approach, we just need a list of names and dump them into some header that provides this:
int abs, fabs, ...; // shadow all of these as non-functions
I used -stdc++98 in the g++ command line to emphasizes that this is just old school C++ namespace semantics at work.
This code will let you detect whether the trap exists in a particular environment:
double (*)(double) = &::abs; // fails if you haven't included math.h, possibly via cmath
But it won't help you spot the places you fall into the trap.
I installed GCC 5, 6 and 7 on OSX 10.12 with Homebrew. Compiling the simple code
#include <iostream>
int main() {
uint foo = 10;
std::cout << foo << std::endl;
}
returns an error:
$ g++-7 -o uint uint.cpp
uint.cpp: In function 'int main()':
uint.cpp:5:5: error: 'uint' was not declared in this scope
uint foo = 10;
^~~~
uint.cpp:5:5: note: suggested alternative: 'int'
uint foo = 10;
^~~~
int
uint.cpp:6:18: error: 'foo' was not declared in this scope
std::cout << foo << std::endl;
^~~
uint.cpp:6:18: note: suggested alternative: 'feof'
std::cout << foo << std::endl;
^~~
feof
This error does not happen with other compilers I have access to. The code works fine with clang++ (on OSX) and with gcc4/5/6 on Linux systems.
Is there a configuration switch missing on my side? Or could this be because gcc links with libstdc++ and not with libc++ which is standard on OSX?
This is supposedly a problem with GLIBC. See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59945 and Jonathan Wakely's answer.
Glibc defines it:
#ifdef __USE_MISC
/* Old compatibility names for C types. */
typedef unsigned long int ulong;
typedef unsigned short int ushort;
typedef unsigned int uint;
#endif
__USE_MISC is defined because G++ defines _GNU_SOURCE, which is well known to cause problems, e.g. PR 11196 and PR 51749
This particular namespace pollution only occurs with C++11 because only needs to #include in C++11 mode to define std::to_string, std::stoi etc. but in general the problem affects C++98 too.
Is this gcc being overly nice and doing what the dev thinks it will do or is clang being overly fussy about something. Am I missing some subtle rule in the standard where clang is actually correct in complaining about this
Or should I use the second bit of code which is basically the how offsetof works
[adrian#localhost ~]$ g++ -Wall -pedantic -ansi a.cc
[adrian#localhost ~]$ a.out
50
[adrian#localhost ~]$ cat a.cc
#include <iostream>
struct Foo
{
char name[50];
};
int main(int argc, char *argv[])
{
std::cout << sizeof(Foo::name) << std::endl;
return 0;
}
[adrian#localhost ~]$ clang++ a.cc
a.cc:10:29: error: invalid use of non-static data member 'name'
std::cout << sizeof(Foo::name) << std::endl;
~~~~~^~~~
1 error generated.
[adrian#localhost ~]$ g++ -Wall -pedantic -ansi b.cc
[adrian#localhost ~]$ a.out
50
[adrian#localhost ~]$ cat b.cc
#include <iostream>
struct Foo
{
char name[50];
};
int main(int argc, char *argv[])
{
std::cout << sizeof(static_cast<Foo*>(0)->name) << std::endl;
return 0;
}
[adrian#localhost ~]$ clang++ b.cc
[adrian#localhost ~]$ a.out
50
I found adding -std=c++11 stops it complaining. GCC is fine
with it in either version.
Modern GCC versions allow this even in -std=c++98 mode. However, older versions, like GCC 3.3.6 of mine, do complain and refuse to compile.
So now I wonder which part of C++98 I am violating with this code.
Wikipedia explicitly states that such a feature was added in C++11, and refers to N2253, which says that the syntax was not considered invalid by the C++98 standard initially, but then intentionally clarified to disallow this (I have no idea how non-static member fields are any different from other variables with regard to their data type). Some time later they decided to make this syntax valid, but not until C++11.
The very same document mentions an ugly workaround, which can also be seen throughout the web:
sizeof(((Class*) 0)->Field)
It looks like simply using 0, NULL or nullptr may trigger compiler warnings for possible dereference of a null pointer (despite the fact that sizeof never evaluates its argument), so an arbitrary non-zero value might be used instead, although it will look like a counter-intuitive “magic constant”. Therefore, in my C++ graceful degradation layer I use:
#if __cplusplus >= 201103L
#define CXX_MODERN 2011
#else
#define CXX_LEGACY 1998
#endif
#ifdef CXX_MODERN
#define CXX_FEATURE_SIZEOF_NONSTATIC
#define CxxSizeOf(TYPE, FIELD) (sizeof TYPE::FIELD)
#else
// Use of `nullptr` may trigger warnings.
#define CxxSizeOf(TYPE, FIELD) (sizeof (reinterpret_cast<const TYPE*>(1234)->FIELD))
#endif
Usage examples:
// On block level:
class SomeHeader {
public:
uint16_t Flags;
static CxxConstExpr size_t FixedSize =
#ifdef CXX_FEATURE_SIZEOF_NONSTATIC
(sizeof Flags)
#else
sizeof(uint16_t)
#endif
;
}; // end class SomeHeader
// Inside a function:
void Foo(void) {
size_t nSize = CxxSizeOf(SomeHeader, Flags);
} // end function Foo(void)
By the way, note the syntax difference for sizeof(Type) and sizeof Expression, as they are formally not the same, even if sizeof(Expression) works — as long as sizeof (Expression) is valid. So, the most correct and portable form would be sizeof(decltype(Expression)), but unfortunately it was made available only in C++11; some compliers have provided typeof(Expression) for a long time, but this never was a standard extension.