From owner-svn-src-head@freebsd.org Tue Aug 4 11:03:53 2015 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 24CE69B26F2; Tue, 4 Aug 2015 11:03:53 +0000 (UTC) (envelope-from brde@optusnet.com.au) Received: from mail109.syd.optusnet.com.au (mail109.syd.optusnet.com.au [211.29.132.80]) by mx1.freebsd.org (Postfix) with ESMTP id D335010A1; Tue, 4 Aug 2015 11:03:52 +0000 (UTC) (envelope-from brde@optusnet.com.au) Received: from c211-30-166-197.carlnfd1.nsw.optusnet.com.au (c211-30-166-197.carlnfd1.nsw.optusnet.com.au [211.30.166.197]) by mail109.syd.optusnet.com.au (Postfix) with ESMTPS id 44F59D62AB5; Tue, 4 Aug 2015 21:03:48 +1000 (AEST) Date: Tue, 4 Aug 2015 21:03:47 +1000 (EST) From: Bruce Evans X-X-Sender: bde@besplex.bde.org To: Ed Schouten cc: Edward Tomasz Napierala , src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: Re: svn commit: r286281 - head/sys/kern In-Reply-To: Message-ID: <20150804200922.S2008@besplex.bde.org> References: <201508040851.t748pv15099722@repo.freebsd.org> MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII; format=flowed X-Optus-CM-Score: 0 X-Optus-CM-Analysis: v=2.1 cv=ItbjC+Lg c=1 sm=1 tr=0 a=KA6XNC2GZCFrdESI5ZmdjQ==:117 a=PO7r1zJSAAAA:8 a=JzwRw_2MAAAA:8 a=kj9zAlcOel0A:10 a=6I5d2MoRAAAA:8 a=WvSndk5DmgNJwsFNOsgA:9 a=CjuIK1q_8ugA:10 X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 04 Aug 2015 11:03:53 -0000 On Tue, 4 Aug 2015, Ed Schouten wrote: > 2015-08-04 10:51 GMT+02:00 Edward Tomasz Napierala : >> Mark vgonel() as static. It was already declared static earlier; >> no idea why compilers don't warn about this. > > That's because according to the standard, those keywords are meant to pile up: > > static void foo(void); > _Noreturn void foo(void); > void foo(void) { > ... > } > > is the same as: > > static _Noreturn void foo(void) { > ... > } This is a bug in the standard. You can build up enormously complicated declarations, with the full declaration not visible in any one of the parts. E.g.: int foo(); int foo(int (*foo1())); int foo(int (*foo1(int (*foo2())))); int foo(int (*foo1(int (*foo2(int (*foo3)()))))); /* ... */ Every declaration in this sequence completes the type a little more, but the type is never complete. To obfuscate this further, remove the function parameter names, or use different ones in each prototype. To complicate this further, there are many possibilities. E.g., make foo() have several function args and (partially) complete each of these independently. Or use attributes to give even more independence in the steps. I don't know of any useful use for this except to complete function definitions in K&R or bad code. The code might have "int foo();" in it and you want to add a complete prototype without changing the original declaration. The complete prototypes should be declared in one step to avoid further obfuscations. Compilers have very bad support for warning about this. -Wredundant-decls is broken in gcc from when it was born up to at least gcc-4.2.1. The above declarations are non-redundant non-redeclarations, but gcc warns that they are redundant redaclaration. -Wredundant-decls is even more broken in clang. It doesn't warn even if all of the above declarations are repeated so that every declaration in the second copy is redundant. "Building up" doesn't work for all parts of declarations. In particular, the rules for linkage and storage class are confusing without building up, and building up doesn't work for them. Consider: static int foo; int foo; vs int foo; static int foo; According to TenDRA C90, the former is valid, but according to gcc and clang it is invalid. The latter is invalid according to all 3 compilers, so building up by adding the static is always invalid. I only trust TenDRA here. The former is a valid obfuscation (the opposite of building up) for all 3 compilers if foo is replaced by foo(). Now change 'int foo;' to 'extern int foo;' in the former. Then all 3 compilers accept it. extern is generally more confusing than static, especially in combination with inline. For static inline, the most common obfuscation is like this one for vgonel. You declare the function as inline in its prototype but not in its function body. This makes it inline if it is static in both. With static in neither and extern in either, both or neither, the behaviour is even more confusing. Bruce