Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 16 Apr 2013 15:13:55 +0200
From:      keramida@ceid.upatras.gr (Giorgos Keramidas)
To:        Bruce Evans <brde@optusnet.com.au>
Cc:        svn-src-head@FreeBSD.org, Gregory Shapiro <gshapiro@FreeBSD.org>, src-committers@FreeBSD.org, Dimitry Andric <dim@FreeBSD.org>, svn-src-all@FreeBSD.org
Subject:   Re: svn commit: r246880 - in head: lib/libsm libexec/mail.local libexec/smrsh share/mk usr.bin/vacation usr.sbin/sendmail
Message-ID:  <87zjwy62jw.fsf@saturn.laptop>
In-Reply-To: <20130416205349.W1783@besplex.bde.org> (Bruce Evans's message of "Tue, 16 Apr 2013 21:28:36 %2B1000 (EST)")
References:  <201302162017.r1GKHVdY022667@svn.freebsd.org> <87a9ozayzk.fsf@saturn.laptop> <516D13C5.70900@FreeBSD.org> <20130416205349.W1783@besplex.bde.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Tue, 16 Apr 2013 21:28:36 +1000 (EST), Bruce Evans <brde@optusnet.com.au> wrote:
>On Tue, 16 Apr 2013, Dimitry Andric wrote:
>> Have you tried the patch I posted here?
>>
>> http://lists.freebsd.org/pipermail/freebsd-current/2013-March/040634.html
>>
>> If people feel this is the right approach, I am happy to commit it.  If
>> people prefer to just shut up warnings, I am happy with that too.

Hi Dimitry,

I haven't but I will right now.  Thanks for pointing me to it :)

Also Bruce, thanks for the very detailed explanation.  I admit I was a
bit confused when a similar small test program I wrote failed to trigger
the warning in clang:

  #include <stdio.h>

  void foo(int code, const char *text);

  void
  foo(code, text)
            int code;
            const char *text;
  {
          printf("error %d: %s", code, text);
  }

  int
  main(void)
  {
          foo(0, "unknown error");
          return 0;
  }

But now -- having read all the details you wrote -- using stdbool.h and
changing the type of 'code' to bool, *does* trigger the promotion and
the warning:

  #include <stdbool.h>
  #include <stdio.h>

  void foo(bool code, const char *text);

  void
  foo(code, text)
      bool code;
      const char *text;
  {
          if (code != false)
             printf("error: %s", text);
  }

  int
  main(void)
  {
          foo(false, "unknown error");
          return 0;
  }

% cc -O2 -pipe  -std=gnu99 -Qunused-arguments -fstack-protector  -c

  proto.c
  proto.c:8:10: warning: promoted type 'int' of K&R function parameter is
  not compatible with the parameter type 'bool' declared in a previous
  prototype
        [-Wknr-promoted-parameter]
      bool code;
           ^
  proto.c:4:15: note: previous declaration is here
  void foo(bool code, const char *text);
                ^
  1 warning generated.

> stdbool is certainly incompatible with simple use of __P(()), but why does
> the error message say that the function type is 'void ()', and why doesn't
> it say that the prototype doesn't match the function?  The function is
> declared as:
>
> @ static void getsasldata __P((char *, bool, MAILER *, MCI *, ENVELOPE *));
>
> This says that the function type is the same as the parameter type.
>
> @ static void
> @ getsasldata(line, firstline, m, mci, e)
> @ 	char *line;
> @ 	bool firstline;
> @ 	MAILER *m;
> @ 	register MCI *mci;
> @ 	ENVELOPE *e;
> @ {
>
> This says that the function type is different from what the function's
> prototype is, at least if the bool is smaller than int or otherwise
> magic, which it is on at least amd64.
>
> clang prints a good error message in the following simplified example:
>
> @ #include <stdbool.h>
> @ @ void foo(bool first);
> @ @ void
> @ foo(first)
> @ 	bool first;
> @ {
> @ }
>
> @ z.c:7:7: warning: promoted type 'int' of K&R function parameter is not compatible with the parameter type 'bool' declared in a previous prototype [-Wknr-promoted-parameter]
> @         bool first;
> @              ^
> @ z.c:3:15: note: previous declaration is here
> @ void foo(bool first);
> @               ^
> @ 1 warning generated.
>
> This happens with plain cc -c.
>
> gcc of course turns the undefined behaviour from this into a portability
> problem by accepting the bad code.  It takes gcc -pedantic to get a warning.
>
> The correct prototype on amd64 is 'void foo(int first);'.  This is MD.
> Unfortunately, the correct way to declare this is unsupported AFAIK.  It
> is 'void foo(__promoteof(bool) first);'.  __P(()) is really hard to use,
> since to use it you first have to modify compilers to support
> __promoteof(), then use it on the type of all integer args whose type is
> not int or larger, or do this using MD ifdefs.
>
> Extending the example a little gives the answer to my question:
>
> @ #include <stdbool.h>
> @ @ typedef void vb(bool first);
> @ @ vb foo;
> @ void bar(vb *p);
> @ @ void
> @ foo(first)
> @ 	bool first;
> @ {
> @ 	bar(foo);
> @ }
>
> @ z.c:10:7: warning: promoted type 'int' of K&R function parameter is not compatible with the parameter type 'bool' declared in a previous prototype [-Wknr-promoted-parameter]
> @         bool first;
> @              ^
> @ z.c:5:4: note: previous declaration is here
> @ vb foo;
> @    ^
> @ z.c:12:6: warning: incompatible pointer types passing 'void ()' to parameter of type 'vb *' (aka 'void (*)(bool)') [-Wincompatible-pointer-types]
> @         bar(foo);
> @             ^~~
> @ z.c:6:14: note: passing argument to parameter 'p' here
> @ void bar(vb *p);
> @              ^
> @ 2 warnings generated.
>
> Apparently clang ignores the mismatched prototype after printing a warning
> about it, and also throws away the type info that it learns by compiling
> the K&R function, so it is left with only 'void ()' for the type.  Then
> the warnings for some reason emphasize the secondary warnings from this.
>
> The first warning should be an error.  It is only a warning for gcc -pedantic
> too.
>
> Bruce

--
Giorgos Keramidas; gkeramidas@gmail.com



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?87zjwy62jw.fsf>