8

I have some code that compiled fine under GCC 4.8.4. I've recently upgraded my system and now have GCC 5.2.1, and I'm getting a warning about incompatible pointer types. I've extracted the problem to a small example that reproduces the error:

typedef const double ConstSpiceDouble;
void foo(const double (*)[3]); 

int main(int argc, char **argv) {
  double a[3][3] = {{1,2,3},{1,2,3},{1,2,3}};

  foo((ConstSpiceDouble (*)[3])a);

  return 0;
}

In the real code, the typedef, the function definition, and the type cast are in a library outside of my control otherwise I would just fix the cast and the function to match. Here's the message I get from the compiler:

$ gcc -Werror -c test.c
test.c: In function ‘main’:
test.c:9:7: error: passing argument 1 of ‘foo’ from incompatible pointer type [-Werror=incompatible-pointer-types]
   foo((ConstSpiceDouble (*)[3])a);
       ^
test.c:4:6: note: expected ‘const double (*)[3]’ but argument is of type ‘const ConstSpiceDouble (*)[3] {aka const double (*)[3]}’
 void foo(const double (*)[3]);
      ^
cc1: all warnings being treated as errors

The note from gcc is especially troubling since it seems to admit that the two types are identical, yet it complains anyway.

13
  • 4
    Compiles without a hitch on GCC 5.2.0 (and Clang 3.7.0 too). I'm leaning towards a compiler bug. Commented Oct 27, 2015 at 19:10
  • That's good to know that it compiles on 5.2.0, that definitely limits the version possibilities to just 5.2.1. Commented Oct 27, 2015 at 19:44
  • What do you mean when you are saying "5.2.1"? This version is not officially released yet: svn: URL 'svn://gcc.gnu.org/svn/gcc/tags/gcc_5_2_1_release' doesn't exist Commented Oct 28, 2015 at 8:22
  • $ gcc --version gcc (Ubuntu 5.2.1-22ubuntu2) 5.2.1 20151010 Copyright (C) 2015 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. Commented Oct 28, 2015 at 13:25
  • 1
    @M.M, no question on the compiler release, and I'm more than a little annoyed that Ubuntu put a non-released GCC in their 15.10 release, but for the sake of discussion, let's assume I have remarkably little control over Ubuntu release decisions and yet still need to compile software in it. (-= I just tried the -std=c11 flag, and it had no effect. At any rate, if this is a gcc bug, it's good to find it before it gets released, and hopefully the next Ubuntu release, which will be the LTS, will have a fixed gcc. If that happens, then this temporary aggravation was worth it in the long run. Commented Nov 10, 2015 at 20:48

2 Answers 2

2

The consensus here and elsewhere seems to be that GCC is doing something unexpected with the const and the typedef. I don't know that unexpected necessarily equates to a bug, but that's for the GCC devs to determine.

I have solved my compilation problem by defining a macro for the function call that fixes the non-matching typecast that's inside the library. I generally dislike tinkering with library internals, but the macro allows me to not touch the actual library header and define it in my own code where it can be commented for the future, and test coverage of that code should be a reasonable early warning signal if the underlying library changes in such a way that the macro breaks something down the road.

This isn't so much "solved" as "worked around", but any further insight will likely have to come from the GCC devs.

Sign up to request clarification or add additional context in comments.

1 Comment

I would love to see that macro excerpt
1

If you type cast 'a' to be ConstSpiceDouble, GCC is doing something unexpected with the const and the typedef, by which eventually the type becomes 'const const double'. This you can see in the error message "const ConstSpiceDouble", which equates to 'const const double', this does not work.

Solution is to either say 'a' is const double or to say 'a' is ConstSpiceDouble before you parameter 'a' to the foo function

typedef const double ConstSpiceDouble;
void foo(const double (*)[3]); 

int main(int argc, char **argv) {

  const double a[3][3] = {{1,2,3},{1,2,3},{1,2,3}};
  // or ConstSpiceDouble a[3][3] = {{1,2,3},{1,2,3},{1,2,3}};

  foo(a);

  return 0;
}

The 'const' pre-pending seems to be a new feature in the latest versions of gcc, but of that, I am not sure :(

4 Comments

Unfortunately, in the actual code, 'a' cannot itself be const since it gets modified as the matrix is setup prior to the function call. I just pulled out the minimum amount of code that reproduced the error for clarity.
The first paragraph of this answer is wrong. There is no "automatic pre-pending" in C. The suggested alternative code compiles however it does not help because OP needs the array in main to be non-const.
have taken out the "automatic prepending" part
To be clear, "const const double" is supposed to be the same type as "const double" according to the C standard (6.7.3/5), it would be a gcc bug to treat the two differently. (But the original code doesn't actually generate "const const double" anywhere, the error message seems to indicate gcc is bumbling things even further)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.