Bug 49748 - char * const * cannot be assigned to char const * const *
Summary: char * const * cannot be assigned to char const * const *
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: 4.4.3
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-07-14 16:09 UTC by Alain Knaff
Modified: 2015-02-26 18:22 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments
Test program for const warning bug (531 bytes, text/x-csrc)
2011-07-14 17:38 UTC, Alain Knaff
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Alain Knaff 2011-07-14 16:09:08 UTC
Trying to assign a pointer value A with type "char * const *" into a variable B declared as "char const * const * " triggers a warning, although the const-yness of the type is _increased_ not decreased.

Such a thing may be needed when trying to call a function that displays a list of strings:

void displayList(char const * const * list)
{
   /* display list */
}

The char const * declaration is needed if somewhere in the program, this function is called with an array of static strings:

   char const  *list1[] = { "hello", "world", NULL };
   displayList(list1);


However, if elsewhere in the program, we want to call the function with a list of _dynamically_ allocated strings, we get a "initialization from incompatible pointer type" warning:
   char **list2;
   for(i=0; i< N; i++)
      list2[i] = strdup( some expression );

   ...
   displayList(list2);
  
   for(i=0; i<N; i++)
      free(list2[i]);

Because of the free(), we cannot declare list2[] as char const ** , but then this restriction on _adding_ the const qualifier during assignment or parameter passing is causing trouble.


There is a very similar case, where such a restriction on adding a const qualifier makes sense:

  assiging  char **  to  char const **

(i.e. the case where in the target, only the string _contents_ are const, but not the string pointers themselves).

In this case, the assignment warning would be appropriate, in order to prevent the following:

char *launderConst(char const *in)
{
    char * source[1];
    char const ** target = source;

    target[0] = in;
    return source[0];
}


However if the target list itself is const (rather than just its string contents), we would never be able to do this:
    char const *const* target = source;
    target[0] = in;

So why the warning about the first line, if the second one is forbidden anyways (assigning a value to a const)?


Or is there another way of declaring the displayList() function without triggering a warning in any of both use-cases?
Comment 1 Jonathan Wakely 2011-07-14 16:44:08 UTC
the bug reporting guidelines clearly ask for a complete and self-contained test case, not several snippets of code which don't form a complete program
http://gcc.gnu.org/bugs/

the warning is correct, see http://c-faq.com/ansi/constmismatch.html
Comment 2 Alain Knaff 2011-07-14 17:38:59 UTC
Created attachment 24756 [details]
Test program for const warning bug

> the warning is correct, see http://c-faq.com/ansi/constmismatch.html

Thanks for this link. This does indeed confirm what I said, in much less words than I needed. Moreover, it points out that the issue doesn't exist in C++.

However, it doesn't explain why the issue still present in C.

Any insights into this question?

If this is just to keep some paper-pushers happy, maybe we could keep the current behavior as the default, but have a -W flag to make gcc mimic g++'s behavior?
Comment 3 Tim Ruehsen 2012-02-23 14:12:00 UTC
Just to clarify it and to add a complete program.

#### x.c ####
void f(const char *const *args) {}

int main(int argc, char **argv) {
        f(argv);
        return 0;
}
####

Compiling with g++ (4.6.2) will do without warning.
Compiling with gcc (4.6.2) gives:

x.c: In function 'main':
x.c:4:2: warning: passing argument 1 of 'f' from incompatible pointer type [enabled by default]
x.c:1:6: note: expected 'const char * const*' but argument is of type 'char **'


This is somewhat annoying when trying to harden older C sources with -Wwrite-strings.
One has to insert (very) many casts to avoid the above warning.
This is much work that could be avoided by an apropriate -W option.
Comment 4 Marek Polacek 2015-02-26 18:22:20 UTC
(In reply to Tim Ruehsen from comment #3)
> This is much work that could be avoided by an apropriate -W option.

GCC 5 has now the -Wincompatible-pointer-types option that can be used to quiet the warning.