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

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

Related

Can attributes be applied to constructor parameters?

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.

VARIADIC MACRO compile error

I want to learn how to use macro.
I simply write a sample but failed to compile on my local g++4.9
#define P(...) printf("13", ##__VA_ARGS__)
int main() {
// your code goes here
P();
return 0;
}
I will get compile error as below
g++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
main.cpp: In function 'int main()':
main.cpp:4:42: error: expected primary-expression before ')' token
#define P(...) printf("13", ##__VA_ARGS__)
^
main.cpp:7:5: note: in expansion of macro 'P'
P();
^
But the same code can be compiled on ideone....
http://ideone.com/ucEXXz
and also by VS2015.
Is there any reasonable explanation for this?
How can I write a portable macro for all compiler....
Thanks.
In C, functions that take variable arguments require a prototype declaration, while in C++, all functions require a prototype. The declaration for printf can be found in stdio.h.
#include <stdio.h>
#define P(...) printf("13", ##__VA_ARGS__)
int main() {
P();
return 0;
}
The ##__VA_ARGS__ syntax is non-standard. It is a "swallow comma if the __VA_ARGS__ is empty" extension implemented by GCC, and seems to have been adopted by other compilers.
Regarding the behavior of -std=c++14:
The compiler can accept several base standards, such as ‘c90’ or ‘c++98’, and GNU dialects of those standards, such as ‘gnu90’ or ‘gnu++98’. When a base standard is specified, the compiler accepts all programs following that standard plus those using GNU extensions that do not contradict it. For example, -std=c90 turns off certain features of GCC that are incompatible with ISO C90, such as the asm and typeof keywords, but not other GNU extensions that do not have a meaning in ISO C90, such as omitting the middle term of a ?: expression.
GCC documentation for -std=
The ##__VA_ARGS__ extension does not conflict with the standard. What is causing it to be rejected by the coliru site is that the -pedantic flag is set.
Valid ISO C and ISO C++ programs should compile properly with or without this option (though a rare few require -ansi or a -std option specifying the required version of ISO C). However, without this option, certain GNU extensions and traditional C and C++ features are supported as well. With this option, they are rejected.
GCC documentation for -pedantic

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.

Error while using CUDA and C++11

I am using CUDA 4.1 and GCC 4.5 ... (FINALLY! CUDA supports GCC 4.5, but still waiting for GCC 4.6). Anyways, is it possible to use C++11 with the CUDA 4.1?
I tried passing:
--compiler-options "-std=c++0x"
to nvcc and it throws a bunch of errors at me:
/usr/include/c++/4.5/exception_ptr.h(100): error: copy constructor for class "std::__exception_ptr::exception_ptr" may not have a parameter of type "std::__exception_ptr::exception_ptr"
/usr/include/c++/4.5/exception_ptr.h(100): error: expected a ")"
/usr/include/c++/4.5/exception_ptr.h(110): error: expected a ")"
/usr/include/c++/4.5/exception_ptr.h(132): error: identifier "type_info" is undefined
/usr/include/c++/4.5/exception_ptr.h(101): error: identifier "__o" is undefined
/usr/include/c++/4.5/exception_ptr.h(112): error: expected a ">"
/usr/include/c++/4.5/exception_ptr.h(112): error: identifier "__o" is undefined
/usr/include/c++/4.5/nested_exception.h(62): error: expected a ";"
/usr/include/c++/4.5/nested_exception.h(64): error: expected a ";"
/usr/include/c++/4.5/nested_exception.h(77): error: member function "std::nested_exception::~nested_exception" may not be redeclared outside its class
/usr/include/c++/4.5/nested_exception.h(77): error: function "std::<error>" may not be initialized
/usr/include/c++/4.5/nested_exception.h(77): error: expected an expression
/usr/include/c++/4.5/nested_exception.h(82): error: expected a ")"
/usr/include/c++/4.5/nested_exception.h(110): error: expected a ")"
/usr/include/c++/4.5/nested_exception.h(115): error: expected a ")"
/usr/include/c++/4.5/nested_exception.h(122): error: expected a ")"
/usr/include/c++/4.5/nested_exception.h(127): error: expected a ")"
/usr/include/c++/4.5/nested_exception.h(127): error: function template "std::__throw_with_nested" has already been defined
/usr/include/c++/4.5/bits/cpp_type_traits.h(180): error: identifier "char16_t" is undefined
/usr/include/c++/4.5/bits/cpp_type_traits.h(187): error: identifier "char32_t" is undefined
/usr/include/c++/4.5/bits/cpp_type_traits.h(187): error: class "std::__is_integer<<error-type>>" has already been defined
21 errors detected in the compilation of "/tmp/tmpxft_00000ef2_00000000-4_test_cuda.cpp1.ii".
Example test.cu
#include <cuda.h>
__host__ void test() {
// nothing in method
}
Compiles fine with:
nvcc -c -o test.o test.cu
But not with C++0x
nvcc -c -o test.o test.cu --compiler-options "-std=c++0x"
No, as of this answer, nvcc does not support c++11 constructs, even if they are supported by the host compiler.
The reason it isn't as simple as passing -std=c++0x to the host compiler is that nvcc has to parse the entirety of the code in order to split it into its __host__and __device__ halves. This preprocess happens before the host compiler is presented with any code at all, so nvcc's parser needs to be able to grok c++11 for it to work.
Update on #Jared Hoberock's answer based on another message he posted on Thrust's Google Group: it seems that C++11 support has been added to CUDA 6.5 (although it is still experimental and undocumented).
Dummy example: test.cu
#include <cuda.h>
#include <iostream>
__host__ void test() {
float a = 12.;
double b = 3.;
auto c = a * b;
std::cout << c << std::endl;
}
int main()
{
test();
return 0;
}
Compilation & execution
$ nvcc -std=c++11 test.cu -o test
$ ./test
36
Without -std=c++11, I get the following (expected) error:
test.cu(7): error: explicit type is missing ("int" assumed)
Note: this example may fail to compile with GCC 5.1.
Update
CUDA 7.0 officially introduced C++11 support:
CUDA 7 adds C++11 feature support to nvcc, the CUDA C++ compiler. This means that you can use C++11 features not only in your host code compiled with nvcc, but also in device code. New C++ language features include auto, lambda functions, variadic templates, static_assert, rvalue references, range-based for loops, and more. To enable C++11 support, pass the flag --std=c++11 to nvcc (this option is not required for Microsoft Visual Studio).

clang++ C++11 invocation

Although there are some questions here concerning the C++11 support of clang, I don't seem to be able to get clang++ to eat my C++11 code.
$ clang++ --version
clang version 2.9 (tags/RELEASE_29/final)
Target: x86_64-pc-linux-gnu
Thread model: posix
According to the clang C++11 status page I should have at least partial support (e.g. right angle brackets), but it refuses all features I tested.
Is there any switch to tell clang to use C++11?
Example test:
$ clang++ -stdlib=libstdc++ cpp11.cpp
cpp11.cpp:16:33: error: a space is required between consecutive right angle brackets (use '> >')
std::vector<std::pair<int,char>> xs;
^~
> >
cpp11.cpp:18:8: error: C++ requires a type specifier for all declarations
auto y = x;
~~~~ ^
2 errors generated
ildjarn points out the correct argument, -std=c++0x or -std=c++11. The errors you're getting with that argument may be because the version of libstdc++ you're using uses some C++11, or non-standard C++, that clang 2.9 doesn't support.