13

I recently received a code that is accepted by clang++ but not by g++ and I would like to know which one is right.

The minimalist code reproducing the behavior is very short and talk by itself so I think an explanation would be unnecessarily complicated.

Here is a header containing an extern pointer declaration :

//(guards removed for simplicity) :
#include <type_traits>

using ptr_func = std::add_pointer<void()>::type;

extern ptr_func pointer;

And here is the source implementing the needed pointed function :

#include "function.hh"

void foo() {}

auto pointer = &foo;

The error generated by gcc is as follows :

g++ -c function.cc -std=c++14
function.cc:5:6: error: conflicting declaration ‘auto pointer’
 auto pointer = &foo;
      ^
In file included from function.cc:1:0:
function.hh:5:17: note: previous declaration as ‘void (* pointer)()’
 extern ptr_func pointer;
                 ^

Clang accepts this code without any error/warning. And replacing the pointer definition by :

decltype(foo)* pointer = &foo;

is accepted by gcc.

In my opinion, clang is right, but I am not sure so I would like to know if clang is too permissive or if gcc should accept it.

Cœur
  • 37,241
  • 25
  • 195
  • 267
Ksass'Peuk
  • 538
  • 2
  • 12
  • Which GCC version exactly? – πάντα ῥεῖ Mar 03 '15 at 15:12
  • I tested it with g++4.9.1 and g++4.9.2 – Ksass'Peuk Mar 03 '15 at 15:45
  • I've tested the code on Ideone (think it's at least using g++4.9.1) using `std::add_pointer::type;` (which looks more like a valid function pointer declaration for me). But it doesn't accept this either. Looks like `std::add_pointer` implementation for GCC doesn't work well with function pointers. – πάντα ῥεῖ Mar 03 '15 at 15:48
  • @πάνταῥεῖ `std::add_pointer::type;` would be a pointer to a pointer. The problem here is not with `add_pointer` which works correctly, but with `auto` inferred type vs. previously declared type. – interjay Mar 03 '15 at 16:02
  • 2
    Here's a simpler example that doesn't involve pointers at all: `extern int x; auto x = 1; int main() {}`. It also works on clang but not gcc. – interjay Mar 03 '15 at 16:04
  • @interjay I don't understand? Isn't `void (*)()` a function pointer signature anymore? – πάντα ῥεῖ Mar 03 '15 at 16:06
  • @πάνταῥεῖ It is, and `add_pointer` would add another pointer on top of that, so you'd get a pointer to a pointer. – interjay Mar 03 '15 at 16:07
  • @interjay THX for giving insight, I'm actually new to `std::add_pointer `. – πάντα ῥεῖ Mar 03 '15 at 16:09
  • It should be noted that msvc 2017 compiler *also* exhibits the same issue, if this is indeed a compiler bug. – greatwolf Feb 27 '17 at 05:25

1 Answers1

6

This is definitely a bug in gcc. Here's a minimal example:

int foo;
extern int* ptr;
auto ptr = &foo;

Interestingly, gcc is happy if the extern and auto declarations are reversed.

This seems to be the same as https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60352, reported last year.

The relevant clause is [basic.link]/10:

After all adjustments of types (during which typedefs (7.1.3) are replaced by their definitions), the types specified by all declarations referring to a given variable or function shall be identical, except that declarations for an array object can specify array types that differ by the presence or absence of a major array bound (8.3.4). A violation of this rule on type identity does not require a diagnostic.

ecatmur
  • 152,476
  • 27
  • 293
  • 366
  • `foo()` actually is a function in the OP's sample? Does this make a difference? – πάντα ῥεῖ Mar 03 '15 at 16:07
  • @πάνταῥεῖ I don't see why it should make any difference; `void (*)()` is a data type and to all appearances gcc is performing its type calculations correctly. – ecatmur Mar 03 '15 at 16:10
  • If this is a bug in gcc then visual c++ 2017(v19.10.24930) also has the same bug. MSVC gives `error C2373: redefinition; different type modifiers`. So you're saying out of the 3 major compiler implementations, 2 of them got this wrong and afaik this bug still persistence even in the latest versions. (testing on http://melpon.org/wandbox/) – greatwolf Feb 27 '17 at 05:22
  • @greatwolf yes, it seems that way. Note that icc agrees with clang, so it's more of a 50-50 split. – ecatmur Feb 27 '17 at 09:36
  • @LightnessRacesinOrbit this is [dcl.spec.auto]/4, no? ([dcl.spec.auto]/3 in C++11). – ecatmur Feb 27 '17 at 09:37