Can attributes be applied to constructor parameters? - c++

Clang 8.0.0 and GCC 9.1.0 seem to disagree as to whether this is valid code.
struct Foo {
Foo([[maybe_unused]] int x) {}
};
int main() {}
Clang produces no warnings (even with -Wall -Wextra -Wpedantic) but GCC produces this error:
test.cpp:2:7: error: expected unqualified-id before '[' token
2 | Foo([[maybe_unused]] int x) {}
| ^
test.cpp:2:7: error: expected ')' before '[' token
2 | Foo([[maybe_unused]] int x) {}
| ~^
| )
So which compiler has a bug?

Yes, they can be applied. The standard allows this.
10.6.6 Maybe unused attribute [dcl.attr.unused]
...
2 The attribute may be applied to the declaration of a class, a typedef-name, a variable, a non-static data member, a function, an enumeration, or an enumerator.
So Clang is correct here and this is a GCC bug.
A bug report has already been filed for this titled: maybe_unused attribute triggers syntax error when used on first argument to a constructor

Your code is valid
The [[maybe_unused]] attribute can be applied to the declaration of a struct, enum, union,
typedef, variable (including member variables), function, or enumerator. Implementations are
encouraged to not emit a diagnostic when such an entity is unused or when the entity is used despite
being marked as [[maybe_unused]].
However there is already a bug report for this in gcc maybe_unused attribute triggers syntax error when used on first argument to a constructor . gcc probably is not able to parse it correctly.

This is likely an issue in your GCC compile line.
I receive a similar error when running the following line:
gcc *.cpp -o run_me
However, no issue is given when using the following line:
gcc -std=c++17 *.cpp -o run_me -Wall -Wextra -Wpedantic
Running with standard c++11 will give the warning "use of the 'maybe_unused' attribute is a C++17 extension". Be sure to use c++17 when compiling this code.

Related

gcc 4.9.2 bug in -Wmissing-field-initializers?

I have an issue in this code - which can be copied 1:1 into a cpp file in order to test the behaving:
#include <atomic>
typedef struct
{
char sDateTime [20];
char sLogFileDirectory [300];
char sLogFileNameTemplate [300];
char sLogOutput [10][100];
std::atomic<bool> bReadyToFlush;
} LogEntries;
typedef struct
{
LogEntries leLogEntries [1] {};
} LogThreads;
Compiling with gcc 4.9.2 SLES 11 SP2 g++ -std=c++11 gcc-warning-bug.cpp -Wall -Wextra -c I receive these very strange warnings:
gcc-warning-bug.cpp:18:34: warning: missing initializer for member ‘LogEntries::sDateTime’ [-Wmissing-field-initializers]
LogEntries leLogEntries [1] {};
^
gcc-warning-bug.cpp:18:34: warning: missing initializer for member ‘LogEntries::sLogFileDirectory’ [-Wmissing-field-initializers]
gcc-warning-bug.cpp:18:34: warning: missing initializer for member ‘LogEntries::sLogFileNameTemplate’ [-Wmissing-field-initializers]
gcc-warning-bug.cpp:18:34: warning: missing initializer for member ‘LogEntries::sLogOutput’ [-Wmissing-field-initializers]
gcc-warning-bug.cpp:18:34: warning: missing initializer for member ‘LogEntries::bReadyToFlush’ [-Wmissing-field-initializers]
Adding the {} initializer in this line
std::atomic<bool> bReadyToFlush {};
even g++ is complaining in the 1st warning about LogEntries::sDateTime then the warnings are gone.
The warning is also gone when I remove the std::atomic<bool> line. The code is very simple; when you have g++ 4.9.2 check it out - it is really very strange.
EDIT: Regardless to which LogEntries struct member I add the {} initializer the warnings are gone.
How can be this behaving explained? For me it is a bug...
PS:
I consider it as a bug:
Change the array specifier in this line to 1000:
LogEntries leLogEntries [1000] {};
g++ will produce 5'000 warnings! I would suppose that it does not really make sense to repeat the warning for each array value.
UPDATE:
The 1st case is now confirmed by GNU it is a bug but already fixed in gcc 5.0
The ICE [Internal Compiler Error] is now in the bug database GNU bug database
It seems to be a bug. I was now playing a bit around and I get after a modification the compiler message gcc stopped because of an internal error.
UPDATE: As requested the code which cannot be compiled by gcc. Compiler options: g++ -std=c++11 gcc-warning-bug.cpp -Wall -Wextra -Werror -fno-strict-aliasing -fwrapv -fno-aggressive-loop-optimizations -c - some options are there because GNU requests it for a bug report.
#include <atomic>
class LogEntries
{
public:
char sDateTime [20];
std::atomic<bool> bReadyToFlush;
};
class LogThreads
{
public:
static LogEntries leLogEntries [10];
};
LogEntries LogThreads::leLogEntries [10] {};
Compiler fails with this output:
gcc-warning-bug.cpp:16:43: internal compiler error: in gimplify_init_constructor, at gimplify.c:4007
....
Please submit a full bug report,
with preprocessed source if appropriate.
Please include the complete backtrace with any bug report.
See <http://gcc.gnu.org/bugs.html> for instructions.
I will prepare the sample code and submit it to the developer team. In my project the member leLogEntries is static.
When you remove the std::atomic line then it works --> problem in the std::atomic implementation?

Can't find Xcode build setting - GCC_WARN_EFFECTIVE_CPLUSPLUS_VIOLATIONS

I'm using Xcode 6.2 to build a C++ command line application.
The Xcode Build Setting Reference states:
If you develop products using C++, you may need to customize these build settings in your targets:
GCC_WARN_EFFECTIVE_CPLUSPLUS_VIOLATIONS (Effective C++ Violation)
However this option does not appear in the build setting list for any of my targets.
Can anyone tell me where it is?
The setting in question no longer has any effect - if you place it into the pbxproj file, it appears as a user defined setting in the UI.
The setting only applies to the gnu g++ compiler, and xcode doesn't ship with that compiler any more (it ships with clang++ and a g++ wrapper that invokes clang++). a brief test of some conditions that trigger with g++ doesn't trigger with clang++ e.g.:
#include <string>
using std::string;
class foo {
string x;
int y;
void *ptr;
public:
foo() : y(1), ptr(0) {}
};
$ g++-4.9 -c -Weffc++ evil.cpp
evil.cpp:5:7: warning: 'class foo' has pointer data members [-Weffc++]
class foo {
^
evil.cpp:5:7: warning: but does not override 'foo(const foo&)' [-Weffc++]
evil.cpp:5:7: warning: or 'operator=(const foo&)' [-Weffc++]
evil.cpp: In constructor 'foo::foo()':
evil.cpp:11:5: warning: 'foo::x' should be initialized in the member initialization list [-Weffc++]
foo() : y(1), ptr(0) {}
^
$ clang++ -c -Weffc++ evil.cpp
$
There are opinions that it is too noisy to be useful - e.g. the complaint about not initializing x (a std::string) is a pointless warning in this situation, and as such is more trouble than it's worth.
You can manually add the -Weffc++ option to the compilation flags for C++ code, you can add it to the option Other C++ Flags, which is under Apple LLVM X.Y - Custom Compiler Flags (the X.Y depends on your version of XCode), but again the LLVM based compiler doesn't process that option.
It looks like the documentation is out of date for this option - I've logged a radar to have the option removed from the docs to prevent this confusion.

Excess elements in scalar initializer code compiles with gcc but not g++

Just curious why this code (that it is obviously wrong) using gcc it compiles, however the same code using the g++ it does not.
int main()
{
char *foo = {"bar", "fred", "bob"};
return 0;
}
gcc gives this warning but still compiles and generates the binary:
% gcc -o x x.c
x.c: In function ‘main’: x.c:3:5: warning: excess
elements in scalar initializer [enabled by default] x.c:3:5: warning:
(near initialization for ‘foo’) [enabled by default] x.c:3:5: warning:
excess elements in scalar initializer [enabled by default] x.c:3:5:
warning: (near initialization for ‘foo’) [enabled by default]
% ls -l x
-rwxr-xr-x 1 overdrive overdrive 6593 Jul 28 21:51 x
g++ gives this error and no any binary as an output:
% g++ -o y y.cpp
y.cpp: In function ‘int main()’:
y.cpp:3:38: error: scalar object ‘foo’ requires one element in initializer
% ls -l y
ls: cannot access y: No such file or directory
gcc and g++ version I am using is:
% g++ --version
g++ (Debian 4.7.2-5) 4.7.2
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Is there any good reason why this compiles in gcc and not in g++? or it is clearly a bug?
Yes, there is a good reason for making it a hard error in C++, even on implementations that historically accepted in C:
template <typename T, int = sizeof(T{1,2,3,4})>
void f();
template <typename T>
void f(...) { }
int main() { f<int>(); }
This is a valid C++ program. A compiler must not reject this with a complaint about an ambiguous call or a linker error complaining that the first overload is undefined: the C++ standard requires f<int>() to call the second overload, because the first overload has a substitution error.
With this in mind, implementations are faced with two options: they can either consistently reject excess initialisers, or they can carefully determine in which contexts the standard requires them to be rejected, and in which contexts the implementation can continue to allow them. The GCC and clang developers have opted to consistently reject them, which is significantly easier to implement.
C does not have any such facilities that determine expression validity at compile-time, so for C there is no way for such an extension to cause valid programs to be rejected.
According to the C 2011 Standard
The initializer for a scalar shall be a single expression, optionally
enclosed in braces
The verb shall means that the compiler shall issue a diagnostic message,:)
So it is a feature or a bug of the compiler.:)
According to the C Standard
1 A conforming implementation shall produce at least one diagnostic
message (identified in an implementation-defined manner) if a
preprocessing translation unit or translation unit contains a
violation of any syntax rule or constraint, even if the behavior is
also explicitly specified as undefined or implementation-defined

Where is definition of std::function in clang++ (3.3/Xcode)

Problem Solved => see the update at the end
I'm trying to use std::function but it looks like just include <functional> does not provide the definition. I have tried to compile following code:
#include <functional>
std::function<int(int)> f = nullptr;
with c++11 as compile option:
% clang++ -c -std=c++11 t.cc
cause:
t.cc:3:6: error: no type named 'function' in namespace 'std'
std::function<int(int)> f = nullptr;
~~~~~^
t.cc:3:14: error: expected unqualified-id
std::function<int(int)> f = nullptr;
^
2 errors generated.
what am I missing? I know C++ well but new to clang++/C++11 thus I lack of important knowledge, I guess.
I'm using clang++ on MacOS X 10.8.
Update 1
I have tried a sample at cppreference.com site but it won't compile too. Giving some option solve the problem?
Update 2
Tried above sample from cppreference.com with clang++ -c -std=c++11 -stdlib=libc++11 x.cc, and compiler still says:
x.cc:1:10: fatal error: 'functional' file not found
#include <functional>
^
1 error generated.
Where is functional? I guess I should give -stdlib=libc++11 or whatever but it does not work too:
clang: error: invalid library name in argument '-stdlib=libc++11'
How I can find list of argument for -stdlib? (note: in man page, only available options are libc++ and libstdc++ both of them don't work)
Or functional just does not work?
This is not about the definition of the function. You don't have a linker error. You have a compiler error. The problem is, presumably, that the BSD/GNU/Darwin standard library installed in the real sysroot doesn't support C++11. You have to use the one that comes with Clang by specifying the -stdlib=libc++ compiler flag.
For C++11, it's best to always invoke clang as: clang++ -std=c++11 -stdlib=libc++
I use this most of the time, so I set the environment variable $CXX to this value. That way, I'm getting the dialect and library option in both compilation and linking. -std=c++11 is insufficient, as clang will still use the (old) system gcc headers in /usr/include/c++/4.2.1.
-stdlib=libc++ will use the clang headers in /usr/lib/c++/v1 such as <functional>.
There's a similar question with an answer by Howard Hinnant, who is (IIRC) an Apple engineer.

How to compile Hinnant's short_alloc allocator

I'd like to try the new Hinnant's short_alloc allocator that, as far as I can understand, replaces the old stack_alloc allocator. However, I can't manage to compile the vector example. g++ says:
~# g++ -std=c++11 stack-allocator-test.cpp -o stack-allocator-test
In file included from stack-allocator-test.cpp:6:0:
short_alloc.h:11:13: error: ‘alignment’ is not a type
short_alloc.h:11:22: error: ISO C++ forbids declaration of ‘alignas’ with no type [-fpermissive]
short_alloc.h:11:22: error: expected ‘;’ at end of member declaration
As far as I can tell, g++ complains about line 10 and 11:
static const std::size_t alignment = 16;
alignas(alignment) char buf_[N];
It seems that the compiler doesn't like the "expression version" of alignas but it expects just the "type-id version".
I'm using g++ 4.7.2 under Ubuntu 12.10.
~# g++ --version
g++ (Ubuntu/Linaro 4.7.2-2ubuntu1) 4.7.2
Probably I'm missing something obvious, but I can't figure it out. Any help would be appreciated. (Please don't tell me I have to upgrade to a newer g++, I'm too lazy to do that :)
g++-4.7.2 doesn't support alignas. From http://gcc.gnu.org/projects/cxx0x.html:
Alignment support | N2341 | GCC 4.8
Try using g++-4.8.0 or clang; alternatively you may be able to use the __attribute__((aligned)):
__attribute__((aligned (8))) char buf_[12];
Note that __attribute__((aligned)) only accepts certain integer constant expressions (literals, template parameters); it doesn't accept static const variables.