* Re: [PATCH] compiler.h: don't use temporary variable in __compiletime_assert() [not found] <1399530685-7749-1-git-send-email-johannes@sipsolutions.net> @ 2014-05-12 13:42 ` James Hogan 2014-05-12 14:38 ` Johannes Berg 2014-05-12 21:16 ` Andrew Morton 0 siblings, 2 replies; 7+ messages in thread From: James Hogan @ 2014-05-12 13:42 UTC (permalink / raw) To: Johannes Berg, Andrew Morton, linux-kernel, Peter Zijlstra, Daniel Santos Cc: Paul E. McKenney, linux-next, linux-metag Hi, On 08/05/14 07:31, Johannes Berg wrote: > From: Johannes Berg <johannes.berg@intel.com> > > Usually, BUG_ON and friends aren't even evaluated in sparse, but > recently compiletime_assert_atomic_type() was added, and that now > results in a sparse warning every time it is used. > > The reason turns out to be the temporary variable, after it sparse > no longer considers the value to be a constant, and results in a > warning and an error. The error is the more annoying part of this > as it suppresses any further warnings in the same file, hiding > other problems. > > Since this is all about compile time and the condition should be > side-effect free to start with, there's no downside (apart maybe > from a slight compilation time penalty?) to just duplicating it, > leaving sparse able to evaluate it at check time, getting rid of > the warning and error. > > Signed-off-by: Johannes Berg <johannes.berg@intel.com> > --- > include/linux/compiler.h | 5 ++--- > 1 file changed, 2 insertions(+), 3 deletions(-) > > diff --git a/include/linux/compiler.h b/include/linux/compiler.h > index 2472740d7ab2..38c0e00ddef8 100644 > --- a/include/linux/compiler.h > +++ b/include/linux/compiler.h > @@ -324,11 +324,10 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect); > > #define __compiletime_assert(condition, msg, prefix, suffix) \ > do { \ > - bool __cond = !(condition); \ > extern void prefix ## suffix(void) __compiletime_error(msg); \ > - if (__cond) \ > + if (!(condition)) \ > prefix ## suffix(); \ > - __compiletime_error_fallback(__cond); \ > + __compiletime_error_fallback(!(condition)); \ > } while (0) > > #define _compiletime_assert(condition, msg, prefix, suffix) \ > Unfortunately this breaks the build of today's linux-next for the Meta architecture (arch/metag), which happens to use a fairly old compiler (based on gcc 4.2.4) which I presume is the reason why. A bunch of compile time asserts fail, even in code which should be optimised out. E.g. here's one which I analysed: mm/gup.c: In function ‘follow_page_mask’: mm/gup.c:208: error: size of array ‘type name’ is negative Line 208 uses HPAGE_PMD_NR which expands to a HPAGE_PMD_SHIFT, which expands to a BUILD_BUG(). However that line is inside an if block conditioned on pmd_trans_huge(*pmd) which include/asm-generic/pgtable.h defines inline to return 0, so the whole block should already be being optimised out. I don't understand why your patch should break things, I suspect it's related to the sparse behaviour you're trying to work around, but can we please drop this patch until a more portable workaround can be found? I'm happy to test further patches with metag if it helps. Full "make ARCH=metag -k -s" output below. Cheers James mm/gup.c: In function ‘follow_page_mask’: mm/gup.c:208: error: size of array ‘type name’ is negative In file included from arch/metag/include/asm/fixmap.h:55, from arch/metag/mm/init.c:26: include/asm-generic/fixmap.h: In function ‘fix_to_virt’: include/asm-generic/fixmap.h:31: error: size of array ‘type name’ is negative scripts/Makefile.build:318: recipe for target 'arch/metag/mm/init.o' failed make[1]: *** [arch/metag/mm/init.o] Error 1 make[1]: Target '__build' not remade because of errors. Makefile:878: recipe for target 'arch/metag/mm' failed make: *** [arch/metag/mm] Error 2 mm/memory.c: In function ‘copy_pmd_range’: mm/memory.c:965: error: size of array ‘type name’ is negative mm/memory.c: In function ‘zap_pmd_range’: mm/memory.c:1232: error: size of array ‘type name’ is negative scripts/Makefile.build:318: recipe for target 'mm/memory.o' failed make[1]: *** [mm/memory.o] Error 1 mm/mremap.c: In function ‘move_page_tables’: mm/mremap.c:197: error: size of array ‘type name’ is negative mm/mprotect.c: In function ‘change_pmd_range’: mm/mprotect.c:164: error: size of array ‘type name’ is negative mm/mprotect.c:171: error: size of array ‘type name’ is negative mm/mprotect.c:172: error: size of array ‘type name’ is negative scripts/Makefile.build:318: recipe for target 'mm/mremap.o' failed make[1]: *** [mm/mremap.o] Error 1 scripts/Makefile.build:318: recipe for target 'mm/mprotect.o' failed make[1]: *** [mm/mprotect.o] Error 1 fs/proc/task_mmu.c: In function ‘smaps_pmd’: fs/proc/task_mmu.c:502: error: size of array ‘type name’ is negative fs/proc/task_mmu.c:504: error: size of array ‘type name’ is negative scripts/Makefile.build:318: recipe for target 'mm/gup.o' failed make[1]: *** [mm/gup.o] Error 1 scripts/Makefile.build:318: recipe for target 'fs/proc/task_mmu.o' failed make[2]: *** [fs/proc/task_mmu.o] Error 1 make[2]: Target '__build' not remade because of errors. scripts/Makefile.build:465: recipe for target 'fs/proc' failed make[1]: *** [fs/proc] Error 2 make[1]: Target '__build' not remade because of errors. Makefile:878: recipe for target 'fs' failed make: *** [fs] Error 2 mm/pgtable-generic.c: In function ‘pmdp_clear_flush_young’: mm/pgtable-generic.c:104: error: size of array ‘type name’ is negative scripts/Makefile.build:318: recipe for target 'mm/pgtable-generic.o' failed make[1]: *** [mm/pgtable-generic.o] Error 1 make[1]: Target '__build' not remade because of errors. Makefile:878: recipe for target 'mm' failed make: *** [mm] Error 2 In file included from arch/metag/include/asm/fixmap.h:55, from arch/metag/include/asm/highmem.h:7, from arch/metag/kernel/setup.c:37: include/asm-generic/fixmap.h: In function ‘fix_to_virt’: include/asm-generic/fixmap.h:31: error: size of array ‘type name’ is negative scripts/Makefile.build:318: recipe for target 'arch/metag/kernel/setup.o' failed make[1]: *** [arch/metag/kernel/setup.o] Error 1 make[1]: Target '__build' not remade because of errors. Makefile:878: recipe for target 'arch/metag/kernel' failed make: *** [arch/metag/kernel] Error 2 make: Target '_all' not remade because of errors. ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] compiler.h: don't use temporary variable in __compiletime_assert() 2014-05-12 13:42 ` [PATCH] compiler.h: don't use temporary variable in __compiletime_assert() James Hogan @ 2014-05-12 14:38 ` Johannes Berg 2014-05-12 14:56 ` James Hogan 2014-05-12 21:16 ` Andrew Morton 1 sibling, 1 reply; 7+ messages in thread From: Johannes Berg @ 2014-05-12 14:38 UTC (permalink / raw) To: James Hogan Cc: Andrew Morton, linux-kernel, Peter Zijlstra, Daniel Santos, Paul E. McKenney, linux-next, linux-metag Hi, > Unfortunately this breaks the build of today's linux-next for the Meta > architecture (arch/metag), which happens to use a fairly old compiler > (based on gcc 4.2.4) which I presume is the reason why. That's very odd. Unfortunately, I don't have most of arch/metag, it seems, where could I get it? In particular no gup.c exists for metag in Linus's current tree. > A bunch of compile time asserts fail, even in code which should be > optimised out. E.g. here's one which I analysed: > > mm/gup.c: In function ‘follow_page_mask’: > mm/gup.c:208: error: size of array ‘type name’ is negative > > Line 208 uses HPAGE_PMD_NR which expands to a HPAGE_PMD_SHIFT, which > expands to a BUILD_BUG(). However that line is inside an if block > conditioned on pmd_trans_huge(*pmd) which include/asm-generic/pgtable.h > defines inline to return 0, so the whole block should already be being > optimised out. > > I don't understand why your patch should break things, I suspect it's > related to the sparse behaviour you're trying to work around, but can we > please drop this patch until a more portable workaround can be found? > I'm happy to test further patches with metag if it helps. I don't really understand that either - if the compiler could prove that the assignment to __cond was a constant, and remember that __cond is now constant, I don't really see why it can't follow that through and consider "!(condition)" a const?? I suppose the other option for the original problem is to ignore _compiletime_assert() for sparse, like we do for BUG_ON(), but it'd probably be good to analyse more why this particular code is broken now. johannes ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] compiler.h: don't use temporary variable in __compiletime_assert() 2014-05-12 14:38 ` Johannes Berg @ 2014-05-12 14:56 ` James Hogan 0 siblings, 0 replies; 7+ messages in thread From: James Hogan @ 2014-05-12 14:56 UTC (permalink / raw) To: Johannes Berg Cc: Andrew Morton, linux-kernel, Peter Zijlstra, Daniel Santos, Paul E. McKenney, linux-next, linux-metag Hi Johannes, On 12/05/14 15:38, Johannes Berg wrote: >> Unfortunately this breaks the build of today's linux-next for the Meta >> architecture (arch/metag), which happens to use a fairly old compiler >> (based on gcc 4.2.4) which I presume is the reason why. > > That's very odd. > > Unfortunately, I don't have most of arch/metag, it seems, where could I > get it? In particular no gup.c exists for metag in Linus's current tree. Hmm, mm/gup.c appears to be a new addition in linux-next from commit 3284cee59933 (mm: move get_user_pages()-related code to separate file) so probably wasn't the best example. My build output was from commit 0bed496ac091 (compiler.h: don't use temporary variable in __compiletime_assert()) which is the first bad commit according to a bisection of linux-next/stable..linux-next/master. >> A bunch of compile time asserts fail, even in code which should be >> optimised out. E.g. here's one which I analysed: >> >> mm/gup.c: In function ‘follow_page_mask’: >> mm/gup.c:208: error: size of array ‘type name’ is negative >> >> Line 208 uses HPAGE_PMD_NR which expands to a HPAGE_PMD_SHIFT, which >> expands to a BUILD_BUG(). However that line is inside an if block >> conditioned on pmd_trans_huge(*pmd) which include/asm-generic/pgtable.h >> defines inline to return 0, so the whole block should already be being >> optimised out. >> >> I don't understand why your patch should break things, I suspect it's >> related to the sparse behaviour you're trying to work around, but can we >> please drop this patch until a more portable workaround can be found? >> I'm happy to test further patches with metag if it helps. > > I don't really understand that either - if the compiler could prove that > the assignment to __cond was a constant, and remember that __cond is now > constant, I don't really see why it can't follow that through and > consider "!(condition)" a const?? > > I suppose the other option for the original problem is to ignore > _compiletime_assert() for sparse, like we do for BUG_ON(), but it'd > probably be good to analyse more why this particular code is broken now. The first one I analysed was strange too (the fixmap.h one). It appears that this particular assert was questionable anyway for metag which is why I didn't mention it, the case above is much more clear cut. Given an unsigned int idx argument the inline function fix_to_virt basically did: BUILD_BUG_ON(idx >= __end_of_fixed_addresses) where __end_of_fixed_addresses is an enum value which is 0 when CONFIG_HIGHMEM=n. In that case it took your patch for the compiler to apparently realise that an unsigned int is always >= 0, therefore the BUILD_BUG_ON will always fire, even though nothing actually called fix_to_virt from that source file so the code wasn't being used. I briefly attempted to reproduce this issue on other arches with newer compilers without success. Cheers James ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] compiler.h: don't use temporary variable in __compiletime_assert() 2014-05-12 13:42 ` [PATCH] compiler.h: don't use temporary variable in __compiletime_assert() James Hogan 2014-05-12 14:38 ` Johannes Berg @ 2014-05-12 21:16 ` Andrew Morton 2014-05-13 7:31 ` Johannes Berg 1 sibling, 1 reply; 7+ messages in thread From: Andrew Morton @ 2014-05-12 21:16 UTC (permalink / raw) To: James Hogan Cc: Johannes Berg, linux-kernel, Peter Zijlstra, Daniel Santos, Paul E. McKenney, linux-next, linux-metag On Mon, 12 May 2014 14:42:04 +0100 James Hogan <james.hogan@imgtec.com> wrote: > > --- a/include/linux/compiler.h > > +++ b/include/linux/compiler.h > > @@ -324,11 +324,10 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect); > > > > #define __compiletime_assert(condition, msg, prefix, suffix) \ > > do { \ > > - bool __cond = !(condition); \ > > extern void prefix ## suffix(void) __compiletime_error(msg); \ > > - if (__cond) \ > > + if (!(condition)) \ > > prefix ## suffix(); \ > > - __compiletime_error_fallback(__cond); \ > > + __compiletime_error_fallback(!(condition)); \ > > } while (0) > > > > #define _compiletime_assert(condition, msg, prefix, suffix) \ > > > > Unfortunately this breaks the build of today's linux-next for the Meta > architecture (arch/metag), which happens to use a fairly old compiler > (based on gcc 4.2.4) which I presume is the reason why. > > A bunch of compile time asserts fail, even in code which should be > optimised out. E.g. here's one which I analysed: > > mm/gup.c: In function ___follow_page_mask___: > mm/gup.c:208: error: size of array ___type name___ is negative > > Line 208 uses HPAGE_PMD_NR which expands to a HPAGE_PMD_SHIFT, which > expands to a BUILD_BUG(). However that line is inside an if block > conditioned on pmd_trans_huge(*pmd) which include/asm-generic/pgtable.h > defines inline to return 0, so the whole block should already be being > optimised out. > > I don't understand why your patch should break things, I suspect it's > related to the sparse behaviour you're trying to work around, but can we > please drop this patch until a more portable workaround can be found? Older gcc's often have this problem. I suppose that build bustage is more serious than sparse false positives so yes, let's please try to find an alternative. ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] compiler.h: don't use temporary variable in __compiletime_assert() 2014-05-12 21:16 ` Andrew Morton @ 2014-05-13 7:31 ` Johannes Berg 2014-05-13 8:53 ` James Hogan 0 siblings, 1 reply; 7+ messages in thread From: Johannes Berg @ 2014-05-13 7:31 UTC (permalink / raw) To: Andrew Morton Cc: James Hogan, linux-kernel, Peter Zijlstra, Daniel Santos, Paul E. McKenney, linux-next, linux-metag On Mon, 2014-05-12 at 14:16 -0700, Andrew Morton wrote: > > I don't understand why your patch should break things, I suspect it's > > related to the sparse behaviour you're trying to work around, but can we > > please drop this patch until a more portable workaround can be found? > > Older gcc's often have this problem. > > I suppose that build bustage is more serious than sparse false > positives so yes, let's please try to find an alternative. Since most people probably don't use sparse without compiling (in fact it's pretty difficult to do so) I'll just send a patch to disable __compiletime_assert for sparse - any objections? johannes ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] compiler.h: don't use temporary variable in __compiletime_assert() 2014-05-13 7:31 ` Johannes Berg @ 2014-05-13 8:53 ` James Hogan 2014-05-13 9:26 ` Johannes Berg 0 siblings, 1 reply; 7+ messages in thread From: James Hogan @ 2014-05-13 8:53 UTC (permalink / raw) To: Johannes Berg, Andrew Morton Cc: linux-kernel, Peter Zijlstra, Daniel Santos, Paul E. McKenney, linux-next, linux-metag Hi Johannes, On 13/05/14 08:31, Johannes Berg wrote: > On Mon, 2014-05-12 at 14:16 -0700, Andrew Morton wrote: > >>> I don't understand why your patch should break things, I suspect it's >>> related to the sparse behaviour you're trying to work around, but can we >>> please drop this patch until a more portable workaround can be found? >> >> Older gcc's often have this problem. >> >> I suppose that build bustage is more serious than sparse false >> positives so yes, let's please try to find an alternative. > > Since most people probably don't use sparse without compiling (in fact > it's pretty difficult to do so) I'll just send a patch to disable > __compiletime_assert for sparse - any objections? I came up with the hack below yesterday evening. Is that the sort of thing you mean? (feel free to use this or do something else, just my 2p). Cheers James Subject: [PATCH] compiler.h: avoid sparse errors in __compiletime_error_fallback() Usually, BUG_ON and friends aren't even evaluated in sparse, but recently compiletime_assert_atomic_type() was added, and that now results in a sparse warning every time it is used. The reason turns out to be the temporary variable, after it sparse no longer considers the value to be a constant, and results in a warning and an error. The error is the more annoying part of this as it suppresses any further warnings in the same file, hiding other problems. Unfortunately the condition cannot be simply expanded out to avoid the temporary variable since it breaks compiletime_assert on old versions of GCC such as GCC 4.2.4 which the latest metag compiler is based on. Therefore #ifndef __CHECKER__ out the __compiletime_error_fallback which uses the potentially negative size array to trigger a conditional compiler error, so that sparse doesn't see it. Signed-off-by: James Hogan <james.hogan@imgtec.com> Cc: Johannes Berg <johannes.berg@intel.com> Cc: Daniel Santos <daniel.santos@pobox.com> Cc: Luciano Coelho <luciano.coelho@intel.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: Andrew Morton <akpm@linux-foundation.org> --- It's not particularly pretty, if you can think of a better solution that doesn't break old GCC I'm all ears. --- include/linux/compiler.h | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/include/linux/compiler.h b/include/linux/compiler.h index ee7239ea1583..64fdfe1cfcf0 100644 --- a/include/linux/compiler.h +++ b/include/linux/compiler.h @@ -323,9 +323,18 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect); #endif #ifndef __compiletime_error # define __compiletime_error(message) -# define __compiletime_error_fallback(condition) \ +/* + * Sparse complains of variable sized arrays due to the temporary variable in + * __compiletime_assert. Unfortunately we can't just expand it out to make + * sparse see a constant array size without breaking compiletime_assert on old + * versions of GCC (e.g. 4.2.4), so hide the array from sparse altogether. + */ +# ifndef __CHECKER__ +# define __compiletime_error_fallback(condition) \ do { ((void)sizeof(char[1 - 2 * condition])); } while (0) -#else +# endif +#endif +#ifndef __compiletime_error_fallback # define __compiletime_error_fallback(condition) do { } while (0) #endif -- 1.9.3 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH] compiler.h: don't use temporary variable in __compiletime_assert() 2014-05-13 8:53 ` James Hogan @ 2014-05-13 9:26 ` Johannes Berg 0 siblings, 0 replies; 7+ messages in thread From: Johannes Berg @ 2014-05-13 9:26 UTC (permalink / raw) To: James Hogan Cc: Andrew Morton, linux-kernel, Peter Zijlstra, Daniel Santos, Paul E. McKenney, linux-next, linux-metag Hi James, > Subject: [PATCH] compiler.h: avoid sparse errors in > __compiletime_error_fallback() > > Usually, BUG_ON and friends aren't even evaluated in sparse, but > recently compiletime_assert_atomic_type() was added, and that now > results in a sparse warning every time it is used. > > The reason turns out to be the temporary variable, after it sparse no > longer considers the value to be a constant, and results in a warning > and an error. The error is the more annoying part of this as it > suppresses any further warnings in the same file, hiding other problems. > > Unfortunately the condition cannot be simply expanded out to avoid the > temporary variable since it breaks compiletime_assert on old versions of > GCC such as GCC 4.2.4 which the latest metag compiler is based on. > > Therefore #ifndef __CHECKER__ out the __compiletime_error_fallback which > uses the potentially negative size array to trigger a conditional > compiler error, so that sparse doesn't see it. > > Signed-off-by: James Hogan <james.hogan@imgtec.com> > Cc: Johannes Berg <johannes.berg@intel.com> > Cc: Daniel Santos <daniel.santos@pobox.com> > Cc: Luciano Coelho <luciano.coelho@intel.com> > Cc: Peter Zijlstra <peterz@infradead.org> > Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com> > Cc: Andrew Morton <akpm@linux-foundation.org> Acked-by: Johannes Berg <johannes@sipsolutions.net> > It's not particularly pretty, if you can think of a better solution that > doesn't break old GCC I'm all ears. > #ifndef __compiletime_error > # define __compiletime_error(message) > -# define __compiletime_error_fallback(condition) \ > +/* > + * Sparse complains of variable sized arrays due to the temporary variable in > + * __compiletime_assert. Unfortunately we can't just expand it out to make > + * sparse see a constant array size without breaking compiletime_assert on old > + * versions of GCC (e.g. 4.2.4), so hide the array from sparse altogether. > + */ > +# ifndef __CHECKER__ > +# define __compiletime_error_fallback(condition) \ > do { ((void)sizeof(char[1 - 2 * condition])); } while (0) > -#else > +# endif > +#endif > +#ifndef __compiletime_error_fallback > # define __compiletime_error_fallback(condition) do { } while (0) > #endif That's pretty much what I had in mind, I may have expressed it a bit differently but the end result is the same. Thanks, johannes ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2014-05-13 9:26 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <1399530685-7749-1-git-send-email-johannes@sipsolutions.net>
2014-05-12 13:42 ` [PATCH] compiler.h: don't use temporary variable in __compiletime_assert() James Hogan
2014-05-12 14:38 ` Johannes Berg
2014-05-12 14:56 ` James Hogan
2014-05-12 21:16 ` Andrew Morton
2014-05-13 7:31 ` Johannes Berg
2014-05-13 8:53 ` James Hogan
2014-05-13 9:26 ` Johannes Berg
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox