diff mbox series

log: Allow LOG_DEBUG to always enable log output

Message ID 20200727022735.1435481-1-sjg@chromium.org
State Superseded
Delegated to: Tom Rini
Headers show
Series log: Allow LOG_DEBUG to always enable log output | expand

Commit Message

Simon Glass July 27, 2020, 2:27 a.m. UTC
At present if CONFIG_LOG enabled, putting LOG_DEBUG at the top of a file
(before log.h inclusion) causes _log() to be executed for every log()
call, regardless of the build- or run-time logging level.

However there is no guarantee that the log record will actually be
displayed. If the current log level is lower than LOGL_DEBUG then it will
not be.

Add a way to signal that the log record should always be displayed and
update log_passes_filters() to handle this.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 common/log.c           | 11 ++++++++---
 doc/README.log         | 10 ++++------
 include/log.h          | 16 ++++++++++++----
 test/log/syslog_test.c |  2 +-
 4 files changed, 25 insertions(+), 14 deletions(-)

Comments

Heinrich Schuchardt July 27, 2020, 6:15 a.m. UTC | #1
On 7/27/20 4:27 AM, Simon Glass wrote:
> At present if CONFIG_LOG enabled, putting LOG_DEBUG at the top of a file
> (before log.h inclusion) causes _log() to be executed for every log()
> call, regardless of the build- or run-time logging level.
>
> However there is no guarantee that the log record will actually be
> displayed. If the current log level is lower than LOGL_DEBUG then it will
> not be.
>
> Add a way to signal that the log record should always be displayed and
> update log_passes_filters() to handle this.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>

Hello Simon,

we have different debug levels:

LOGL_DEBUG
LOGL_DEBUG_CONTENT
LOGL_DEBUG_IO

If I understand you right, with your patch putting #define LOG_DEBUG at
the top of the file enables all of these. This may be more than I want.

Wouldn't it be more flexible if we could put something like:

#define LOG_DEBUG LOGL_DEBUG

at the top of the file if we want logging up to level 7 in this file.

Best regards

Heinrich

Best regards

> ---
>
>  common/log.c           | 11 ++++++++---
>  doc/README.log         | 10 ++++------
>  include/log.h          | 16 ++++++++++++----
>  test/log/syslog_test.c |  2 +-
>  4 files changed, 25 insertions(+), 14 deletions(-)
>
> diff --git a/common/log.c b/common/log.c
> index 734d26de4a..5ff8245922 100644
> --- a/common/log.c
> +++ b/common/log.c
> @@ -156,16 +156,20 @@ static bool log_has_file(const char *file_list, const char *file)
>  static bool log_passes_filters(struct log_device *ldev, struct log_rec *rec)
>  {
>  	struct log_filter *filt;
> +	int level = rec->level & LOGL_LEVEL_MASK;
> +
> +	if (rec->force_debug && level <= LOGL_DEBUG)
> +		return true;
>
>  	/* If there are no filters, filter on the default log level */
>  	if (list_empty(&ldev->filter_head)) {
> -		if (rec->level > gd->default_log_level)
> +		if (level > gd->default_log_level)
>  			return false;
>  		return true;
>  	}
>
>  	list_for_each_entry(filt, &ldev->filter_head, sibling_node) {
> -		if (rec->level > filt->max_level)
> +		if (level > filt->max_level)
>  			continue;
>  		if ((filt->flags & LOGFF_HAS_CAT) &&
>  		    !log_has_cat(filt->cat_list, rec->cat))
> @@ -208,7 +212,8 @@ int _log(enum log_category_t cat, enum log_level_t level, const char *file,
>  	va_list args;
>
>  	rec.cat = cat;
> -	rec.level = level;
> +	rec.level = level & LOGL_LEVEL_MASK;
> +	rec.force_debug = level & LOGL_FORCE_DEBUG;
>  	rec.file = file;
>  	rec.line = line;
>  	rec.func = func;
> diff --git a/doc/README.log b/doc/README.log
> index ba838824a9..554e99ca4c 100644
> --- a/doc/README.log
> +++ b/doc/README.log
> @@ -77,12 +77,10 @@ Sometimes it is useful to turn on logging just in one file. You can use this:
>
>     #define LOG_DEBUG
>
> -to enable building in of all logging statements in a single file. Put it at
> -the top of the file, before any #includes.
> -
> -To actually get U-Boot to output this you need to also set the default logging
> -level - e.g. set CONFIG_LOG_DEFAULT_LEVEL to 7 (LOGL_DEBUG) or more. Otherwise
> -debug output is suppressed and will not be generated.
> +to enable building in of all debug logging statements in a single file. Put it
> +at the top of the file, before any #includes. This overrides any log-level
> +setting in U-Boot, including CONFIG_LOG_DEFAULT_LEVEL, but just for that file.
> +All logging statements, up to and including LOGL_DEBUG, will be displayed.
>
>
>  Convenience functions
> diff --git a/include/log.h b/include/log.h
> index 2859ce1f2e..63052f74eb 100644
> --- a/include/log.h
> +++ b/include/log.h
> @@ -33,6 +33,9 @@ enum log_level_t {
>  	LOGL_COUNT,
>  	LOGL_NONE,
>
> +	LOGL_LEVEL_MASK = 0xf,	/* Mask for valid log levels */
> +	LOGL_FORCE_DEBUG = 0x10, /* Mask to force output due to LOG_DEBUG */
> +
>  	LOGL_FIRST = LOGL_EMERG,
>  	LOGL_MAX = LOGL_DEBUG_IO,
>  };
> @@ -133,7 +136,7 @@ static inline int _log_nop(enum log_category_t cat, enum log_level_t level,
>
>  #if CONFIG_IS_ENABLED(LOG)
>  #ifdef LOG_DEBUG
> -#define _LOG_DEBUG	1
> +#define _LOG_DEBUG	LOGL_FORCE_DEBUG
>  #else
>  #define _LOG_DEBUG	0
>  #endif
> @@ -141,9 +144,9 @@ static inline int _log_nop(enum log_category_t cat, enum log_level_t level,
>  /* Emit a log record if the level is less that the maximum */
>  #define log(_cat, _level, _fmt, _args...) ({ \
>  	int _l = _level; \
> -	if (CONFIG_IS_ENABLED(LOG) && (_l <= _LOG_MAX_LEVEL || _LOG_DEBUG)) \
> -		_log((enum log_category_t)(_cat), _l, __FILE__, __LINE__, \
> -		      __func__, \
> +	if (CONFIG_IS_ENABLED(LOG) && (_LOG_DEBUG || _l <= _LOG_MAX_LEVEL)) \
> +		_log((enum log_category_t)(_cat), _l | _LOG_DEBUG, __FILE__, \
> +		     __LINE__, __func__, \
>  		      pr_fmt(_fmt), ##_args); \
>  	})
>  #else
> @@ -279,8 +282,12 @@ void __assert_fail(const char *assertion, const char *file, unsigned int line,
>   * Memebers marked as 'allocated' are allocated (e.g. via strdup()) by the log
>   * system.
>   *
> + * TODO(sjg@chromium.org): Compress this struct down a bit to reduce space, e.g.
> + * a single u32 for cat, level, line and force_debug
> + *
>   * @cat: Category, representing a uclass or part of U-Boot
>   * @level: Severity level, less severe is higher
> + * @force_debug: Force output of debug
>   * @file: Name of file where the log record was generated (not allocated)
>   * @line: Line number where the log record was generated
>   * @func: Function where the log record was generated (not allocated)
> @@ -289,6 +296,7 @@ void __assert_fail(const char *assertion, const char *file, unsigned int line,
>  struct log_rec {
>  	enum log_category_t cat;
>  	enum log_level_t level;
> +	bool force_debug;
>  	const char *file;
>  	int line;
>  	const char *func;
> diff --git a/test/log/syslog_test.c b/test/log/syslog_test.c
> index 120a8b2537..df239d1e8d 100644
> --- a/test/log/syslog_test.c
> +++ b/test/log/syslog_test.c
> @@ -276,7 +276,7 @@ static int log_test_syslog_nodebug(struct unit_test_state *uts)
>  	sandbox_eth_set_tx_handler(0, sb_log_tx_handler);
>  	/* Used by ut_assert macros in the tx_handler */
>  	sandbox_eth_set_priv(0, &env);
> -	log_debug("testing %s\n", "log_debug");
> +	log_content("testing %s\n", "log_debug");
>  	sandbox_eth_set_tx_handler(0, NULL);
>  	/* Check that the callback function was not called */
>  	ut_assertnonnull(env.expected);
>
Simon Glass July 27, 2020, 11:17 p.m. UTC | #2
Hi Heinrich,

On Mon, 27 Jul 2020 at 00:15, Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
>
> On 7/27/20 4:27 AM, Simon Glass wrote:
> > At present if CONFIG_LOG enabled, putting LOG_DEBUG at the top of a file
> > (before log.h inclusion) causes _log() to be executed for every log()
> > call, regardless of the build- or run-time logging level.
> >
> > However there is no guarantee that the log record will actually be
> > displayed. If the current log level is lower than LOGL_DEBUG then it will
> > not be.
> >
> > Add a way to signal that the log record should always be displayed and
> > update log_passes_filters() to handle this.
> >
> > Signed-off-by: Simon Glass <sjg@chromium.org>
>
> Hello Simon,
>
> we have different debug levels:
>
> LOGL_DEBUG
> LOGL_DEBUG_CONTENT
> LOGL_DEBUG_IO
>
> If I understand you right, with your patch putting #define LOG_DEBUG at
> the top of the file enables all of these. This may be more than I want.
>
> Wouldn't it be more flexible if we could put something like:
>
> #define LOG_DEBUG LOGL_DEBUG
>
> at the top of the file if we want logging up to level 7 in this file.

Actually the way I implemented it, it only enables update LOGL_DEBUG.

Certainly your idea is more flexible. I wonder if we could make the
level optional, so:

#define LOG_DEBUG

means

#define LOG_DEBUG LOGL_DEBUG

Regards,
Simon
Tom Rini Aug. 5, 2020, 12:18 p.m. UTC | #3
On Sun, Jul 26, 2020 at 08:27:35PM -0600, Simon Glass wrote:

> At present if CONFIG_LOG enabled, putting LOG_DEBUG at the top of a file
> (before log.h inclusion) causes _log() to be executed for every log()
> call, regardless of the build- or run-time logging level.
> 
> However there is no guarantee that the log record will actually be
> displayed. If the current log level is lower than LOGL_DEBUG then it will
> not be.
> 
> Add a way to signal that the log record should always be displayed and
> update log_passes_filters() to handle this.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>

This exposes an underlying problem with LOG and clang I believe:
https://gitlab.denx.de/u-boot/u-boot/-/jobs/135789
Heinrich Schuchardt Aug. 5, 2020, 12:54 p.m. UTC | #4
On 05.08.20 14:18, Tom Rini wrote:
> On Sun, Jul 26, 2020 at 08:27:35PM -0600, Simon Glass wrote:
>
>> At present if CONFIG_LOG enabled, putting LOG_DEBUG at the top of a file
>> (before log.h inclusion) causes _log() to be executed for every log()
>> call, regardless of the build- or run-time logging level.
>>
>> However there is no guarantee that the log record will actually be
>> displayed. If the current log level is lower than LOGL_DEBUG then it will
>> not be.
>>
>> Add a way to signal that the log record should always be displayed and
>> update log_passes_filters() to handle this.
>>
>> Signed-off-by: Simon Glass <sjg@chromium.org>
>
> This exposes an underlying problem with LOG and clang I believe:
> https://gitlab.denx.de/u-boot/u-boot/-/jobs/135789
>

include/log.h:147:44: note: expanded from macro 'log'
        if (CONFIG_IS_ENABLED(LOG) && (_LOG_DEBUG || _l <=
_LOG_MAX_LEVEL)) \
                                                  ^
drivers/misc/p2sb_emul.c:197:10: error: converting the enum constant to
a boolean [-Werror,-Wint-in-bool-context]

This seems to be a Clang bug. _LOG_DEBUG is not an enum:

#if CONFIG_IS_ENABLED(LOG)
#ifdef LOG_DEBUG
#define _LOG_DEBUG      1
#else
#define _LOG_DEBUG      0
#endif

So there seems to be a bug in the Clang you used.

Compiling with clang on Debian Bullseye does not show the problem:

make HOSTCC=clang sandbox_defconfig
make HOSTCC=clang CC=clang -j8

clang version 9.0.1-13
LLVM version 9.0.1

Which Clang version did you use?

This is the change that added the test:
https://reviews.llvm.org/D63082

-Wint-in-bool-context seems to be new in Clang 10.

All over the U-Boot code we assume that a non-zero integer is true. Do
we really want to enable -Wint-in-bool-context?

Best regards

Heinrich
Tom Rini Aug. 5, 2020, 12:56 p.m. UTC | #5
On Wed, Aug 05, 2020 at 02:54:05PM +0200, Heinrich Schuchardt wrote:
> On 05.08.20 14:18, Tom Rini wrote:
> > On Sun, Jul 26, 2020 at 08:27:35PM -0600, Simon Glass wrote:
> >
> >> At present if CONFIG_LOG enabled, putting LOG_DEBUG at the top of a file
> >> (before log.h inclusion) causes _log() to be executed for every log()
> >> call, regardless of the build- or run-time logging level.
> >>
> >> However there is no guarantee that the log record will actually be
> >> displayed. If the current log level is lower than LOGL_DEBUG then it will
> >> not be.
> >>
> >> Add a way to signal that the log record should always be displayed and
> >> update log_passes_filters() to handle this.
> >>
> >> Signed-off-by: Simon Glass <sjg@chromium.org>
> >
> > This exposes an underlying problem with LOG and clang I believe:
> > https://gitlab.denx.de/u-boot/u-boot/-/jobs/135789
> >
> 
> include/log.h:147:44: note: expanded from macro 'log'
>         if (CONFIG_IS_ENABLED(LOG) && (_LOG_DEBUG || _l <=
> _LOG_MAX_LEVEL)) \
>                                                   ^
> drivers/misc/p2sb_emul.c:197:10: error: converting the enum constant to
> a boolean [-Werror,-Wint-in-bool-context]
> 
> This seems to be a Clang bug. _LOG_DEBUG is not an enum:
> 
> #if CONFIG_IS_ENABLED(LOG)
> #ifdef LOG_DEBUG
> #define _LOG_DEBUG      1
> #else
> #define _LOG_DEBUG      0
> #endif
> 
> So there seems to be a bug in the Clang you used.
> 
> Compiling with clang on Debian Bullseye does not show the problem:
> 
> make HOSTCC=clang sandbox_defconfig
> make HOSTCC=clang CC=clang -j8
> 
> clang version 9.0.1-13
> LLVM version 9.0.1
> 
> Which Clang version did you use?
> 
> This is the change that added the test:
> https://reviews.llvm.org/D63082
> 
> -Wint-in-bool-context seems to be new in Clang 10.
> 
> All over the U-Boot code we assume that a non-zero integer is true. Do
> we really want to enable -Wint-in-bool-context?

I'm using the official Clang 10 stable builds.
Heinrich Schuchardt Aug. 5, 2020, 6:31 p.m. UTC | #6
On 05.08.20 14:56, Tom Rini wrote:
> On Wed, Aug 05, 2020 at 02:54:05PM +0200, Heinrich Schuchardt wrote:
>> On 05.08.20 14:18, Tom Rini wrote:
>>> On Sun, Jul 26, 2020 at 08:27:35PM -0600, Simon Glass wrote:
>>>
>>>> At present if CONFIG_LOG enabled, putting LOG_DEBUG at the top of a file
>>>> (before log.h inclusion) causes _log() to be executed for every log()
>>>> call, regardless of the build- or run-time logging level.
>>>>
>>>> However there is no guarantee that the log record will actually be
>>>> displayed. If the current log level is lower than LOGL_DEBUG then it will
>>>> not be.
>>>>
>>>> Add a way to signal that the log record should always be displayed and
>>>> update log_passes_filters() to handle this.
>>>>
>>>> Signed-off-by: Simon Glass <sjg@chromium.org>
>>>
>>> This exposes an underlying problem with LOG and clang I believe:
>>> https://gitlab.denx.de/u-boot/u-boot/-/jobs/135789
>>>
>>
>> include/log.h:147:44: note: expanded from macro 'log'
>>         if (CONFIG_IS_ENABLED(LOG) && (_LOG_DEBUG || _l <=
>> _LOG_MAX_LEVEL)) \
>>                                                   ^
>> drivers/misc/p2sb_emul.c:197:10: error: converting the enum constant to
>> a boolean [-Werror,-Wint-in-bool-context]
>>
>> This seems to be a Clang bug. _LOG_DEBUG is not an enum:
>>
>> #if CONFIG_IS_ENABLED(LOG)
>> #ifdef LOG_DEBUG
>> #define _LOG_DEBUG      1
>> #else
>> #define _LOG_DEBUG      0
>> #endif
>>
>> So there seems to be a bug in the Clang you used.
>>
>> Compiling with clang on Debian Bullseye does not show the problem:
>>
>> make HOSTCC=clang sandbox_defconfig
>> make HOSTCC=clang CC=clang -j8
>>
>> clang version 9.0.1-13
>> LLVM version 9.0.1
>>
>> Which Clang version did you use?
>>
>> This is the change that added the test:
>> https://reviews.llvm.org/D63082
>>
>> -Wint-in-bool-context seems to be new in Clang 10.
>>
>> All over the U-Boot code we assume that a non-zero integer is true. Do
>> we really want to enable -Wint-in-bool-context?
>
> I'm using the official Clang 10 stable builds.
>

Do you really want to forbid using integers as booleans
(-Wint-in-bool-context)?

Best regards

Heinrich
Tom Rini Aug. 5, 2020, 6:37 p.m. UTC | #7
On Wed, Aug 05, 2020 at 08:31:55PM +0200, Heinrich Schuchardt wrote:
> On 05.08.20 14:56, Tom Rini wrote:
> > On Wed, Aug 05, 2020 at 02:54:05PM +0200, Heinrich Schuchardt wrote:
> >> On 05.08.20 14:18, Tom Rini wrote:
> >>> On Sun, Jul 26, 2020 at 08:27:35PM -0600, Simon Glass wrote:
> >>>
> >>>> At present if CONFIG_LOG enabled, putting LOG_DEBUG at the top of a file
> >>>> (before log.h inclusion) causes _log() to be executed for every log()
> >>>> call, regardless of the build- or run-time logging level.
> >>>>
> >>>> However there is no guarantee that the log record will actually be
> >>>> displayed. If the current log level is lower than LOGL_DEBUG then it will
> >>>> not be.
> >>>>
> >>>> Add a way to signal that the log record should always be displayed and
> >>>> update log_passes_filters() to handle this.
> >>>>
> >>>> Signed-off-by: Simon Glass <sjg@chromium.org>
> >>>
> >>> This exposes an underlying problem with LOG and clang I believe:
> >>> https://gitlab.denx.de/u-boot/u-boot/-/jobs/135789
> >>>
> >>
> >> include/log.h:147:44: note: expanded from macro 'log'
> >>         if (CONFIG_IS_ENABLED(LOG) && (_LOG_DEBUG || _l <=
> >> _LOG_MAX_LEVEL)) \
> >>                                                   ^
> >> drivers/misc/p2sb_emul.c:197:10: error: converting the enum constant to
> >> a boolean [-Werror,-Wint-in-bool-context]
> >>
> >> This seems to be a Clang bug. _LOG_DEBUG is not an enum:
> >>
> >> #if CONFIG_IS_ENABLED(LOG)
> >> #ifdef LOG_DEBUG
> >> #define _LOG_DEBUG      1
> >> #else
> >> #define _LOG_DEBUG      0
> >> #endif
> >>
> >> So there seems to be a bug in the Clang you used.
> >>
> >> Compiling with clang on Debian Bullseye does not show the problem:
> >>
> >> make HOSTCC=clang sandbox_defconfig
> >> make HOSTCC=clang CC=clang -j8
> >>
> >> clang version 9.0.1-13
> >> LLVM version 9.0.1
> >>
> >> Which Clang version did you use?
> >>
> >> This is the change that added the test:
> >> https://reviews.llvm.org/D63082
> >>
> >> -Wint-in-bool-context seems to be new in Clang 10.
> >>
> >> All over the U-Boot code we assume that a non-zero integer is true. Do
> >> we really want to enable -Wint-in-bool-context?
> >
> > I'm using the official Clang 10 stable builds.
> >
> 
> Do you really want to forbid using integers as booleans
> (-Wint-in-bool-context)?

So, interesting.  The Linux kernel isn't disabling this warning.  It's
mentioned in two commits, one of which is "clang found a bug here", of
which this is not the case.  The other is more like ours:
commit 968e5170939662341242812b9c82ef51cf140a33
Author: Nathan Chancellor <natechancellor@gmail.com>
Date:   Thu Sep 26 09:22:59 2019 -0700

    tracing: Fix clang -Wint-in-bool-context warnings in IF_ASSIGN macro
    
    After r372664 in clang, the IF_ASSIGN macro causes a couple hundred
    warnings along the lines of:
    
    kernel/trace/trace_output.c:1331:2: warning: converting the enum
    constant to a boolean [-Wint-in-bool-context]
    kernel/trace/trace.h:409:3: note: expanded from macro
    'trace_assign_type'
                    IF_ASSIGN(var, ent, struct ftrace_graph_ret_entry,
                    ^
    kernel/trace/trace.h:371:14: note: expanded from macro 'IF_ASSIGN'
                    WARN_ON(id && (entry)->type != id);     \
                               ^
    264 warnings generated.
    
    This warning can catch issues with constructs like:
    
        if (state == A || B)
    
    where the developer really meant:
    
        if (state == A || state == B)
    
    This is currently the only occurrence of the warning in the kernel
    tree across defconfig, allyesconfig, allmodconfig for arm32, arm64,
    and x86_64. Add the implicit '!= 0' to the WARN_ON statement to fix
    the warnings and find potential issues in the future.
    
    Link: https://github.com/llvm/llvm-project/commit/28b38c277a2941e9e891b2db30652cfd962f070b
    Link: https://github.com/ClangBuiltLinux/linux/issues/686
    Link: http://lkml.kernel.org/r/20190926162258.466321-1-natechancellor@gmail.com
    
    Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
    Signed-off-by: Nathan Chancellor <natechancellor@gmail.com>
    Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>

Which is like our case, and reworking the test to be explicit.  I lean
towards that.
Simon Glass Aug. 5, 2020, 6:56 p.m. UTC | #8
Hi Tom,

On Wed, 5 Aug 2020 at 12:37, Tom Rini <trini@konsulko.com> wrote:
>
> On Wed, Aug 05, 2020 at 08:31:55PM +0200, Heinrich Schuchardt wrote:
> > On 05.08.20 14:56, Tom Rini wrote:
> > > On Wed, Aug 05, 2020 at 02:54:05PM +0200, Heinrich Schuchardt wrote:
> > >> On 05.08.20 14:18, Tom Rini wrote:
> > >>> On Sun, Jul 26, 2020 at 08:27:35PM -0600, Simon Glass wrote:
> > >>>
> > >>>> At present if CONFIG_LOG enabled, putting LOG_DEBUG at the top of a file
> > >>>> (before log.h inclusion) causes _log() to be executed for every log()
> > >>>> call, regardless of the build- or run-time logging level.
> > >>>>
> > >>>> However there is no guarantee that the log record will actually be
> > >>>> displayed. If the current log level is lower than LOGL_DEBUG then it will
> > >>>> not be.
> > >>>>
> > >>>> Add a way to signal that the log record should always be displayed and
> > >>>> update log_passes_filters() to handle this.
> > >>>>
> > >>>> Signed-off-by: Simon Glass <sjg@chromium.org>
> > >>>
> > >>> This exposes an underlying problem with LOG and clang I believe:
> > >>> https://gitlab.denx.de/u-boot/u-boot/-/jobs/135789
> > >>>
> > >>
> > >> include/log.h:147:44: note: expanded from macro 'log'
> > >>         if (CONFIG_IS_ENABLED(LOG) && (_LOG_DEBUG || _l <=
> > >> _LOG_MAX_LEVEL)) \
> > >>                                                   ^
> > >> drivers/misc/p2sb_emul.c:197:10: error: converting the enum constant to
> > >> a boolean [-Werror,-Wint-in-bool-context]
> > >>
> > >> This seems to be a Clang bug. _LOG_DEBUG is not an enum:
> > >>
> > >> #if CONFIG_IS_ENABLED(LOG)
> > >> #ifdef LOG_DEBUG
> > >> #define _LOG_DEBUG      1
> > >> #else
> > >> #define _LOG_DEBUG      0
> > >> #endif
> > >>
> > >> So there seems to be a bug in the Clang you used.
> > >>
> > >> Compiling with clang on Debian Bullseye does not show the problem:
> > >>
> > >> make HOSTCC=clang sandbox_defconfig
> > >> make HOSTCC=clang CC=clang -j8
> > >>
> > >> clang version 9.0.1-13
> > >> LLVM version 9.0.1
> > >>
> > >> Which Clang version did you use?
> > >>
> > >> This is the change that added the test:
> > >> https://reviews.llvm.org/D63082
> > >>
> > >> -Wint-in-bool-context seems to be new in Clang 10.
> > >>
> > >> All over the U-Boot code we assume that a non-zero integer is true. Do
> > >> we really want to enable -Wint-in-bool-context?
> > >
> > > I'm using the official Clang 10 stable builds.
> > >
> >
> > Do you really want to forbid using integers as booleans
> > (-Wint-in-bool-context)?
>
> So, interesting.  The Linux kernel isn't disabling this warning.  It's
> mentioned in two commits, one of which is "clang found a bug here", of
> which this is not the case.  The other is more like ours:
> commit 968e5170939662341242812b9c82ef51cf140a33
> Author: Nathan Chancellor <natechancellor@gmail.com>
> Date:   Thu Sep 26 09:22:59 2019 -0700
>
>     tracing: Fix clang -Wint-in-bool-context warnings in IF_ASSIGN macro
>
>     After r372664 in clang, the IF_ASSIGN macro causes a couple hundred
>     warnings along the lines of:
>
>     kernel/trace/trace_output.c:1331:2: warning: converting the enum
>     constant to a boolean [-Wint-in-bool-context]
>     kernel/trace/trace.h:409:3: note: expanded from macro
>     'trace_assign_type'
>                     IF_ASSIGN(var, ent, struct ftrace_graph_ret_entry,
>                     ^
>     kernel/trace/trace.h:371:14: note: expanded from macro 'IF_ASSIGN'
>                     WARN_ON(id && (entry)->type != id);     \
>                                ^
>     264 warnings generated.
>
>     This warning can catch issues with constructs like:
>
>         if (state == A || B)
>
>     where the developer really meant:
>
>         if (state == A || state == B)
>
>     This is currently the only occurrence of the warning in the kernel
>     tree across defconfig, allyesconfig, allmodconfig for arm32, arm64,
>     and x86_64. Add the implicit '!= 0' to the WARN_ON statement to fix
>     the warnings and find potential issues in the future.
>
>     Link: https://github.com/llvm/llvm-project/commit/28b38c277a2941e9e891b2db30652cfd962f070b
>     Link: https://github.com/ClangBuiltLinux/linux/issues/686
>     Link: http://lkml.kernel.org/r/20190926162258.466321-1-natechancellor@gmail.com
>
>     Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
>     Signed-off-by: Nathan Chancellor <natechancellor@gmail.com>
>     Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
>
> Which is like our case, and reworking the test to be explicit.  I lean
> towards that.

Oh dear I really want to vote against that.

if (x)

should allow C to consider x to be a boolean. I am hitting this in
Zephyr and feels like it is undoing a long-standing C feature, with
major disruption, for no benefit I can detect.

Hopefully I am misunderstanding what -Wint-in-bool-context means, and
it just applies to enums?

Regards,
Simon
Tom Rini Aug. 5, 2020, 7:03 p.m. UTC | #9
On Wed, Aug 05, 2020 at 12:56:17PM -0600, Simon Glass wrote:
> Hi Tom,
> 
> On Wed, 5 Aug 2020 at 12:37, Tom Rini <trini@konsulko.com> wrote:
> >
> > On Wed, Aug 05, 2020 at 08:31:55PM +0200, Heinrich Schuchardt wrote:
> > > On 05.08.20 14:56, Tom Rini wrote:
> > > > On Wed, Aug 05, 2020 at 02:54:05PM +0200, Heinrich Schuchardt wrote:
> > > >> On 05.08.20 14:18, Tom Rini wrote:
> > > >>> On Sun, Jul 26, 2020 at 08:27:35PM -0600, Simon Glass wrote:
> > > >>>
> > > >>>> At present if CONFIG_LOG enabled, putting LOG_DEBUG at the top of a file
> > > >>>> (before log.h inclusion) causes _log() to be executed for every log()
> > > >>>> call, regardless of the build- or run-time logging level.
> > > >>>>
> > > >>>> However there is no guarantee that the log record will actually be
> > > >>>> displayed. If the current log level is lower than LOGL_DEBUG then it will
> > > >>>> not be.
> > > >>>>
> > > >>>> Add a way to signal that the log record should always be displayed and
> > > >>>> update log_passes_filters() to handle this.
> > > >>>>
> > > >>>> Signed-off-by: Simon Glass <sjg@chromium.org>
> > > >>>
> > > >>> This exposes an underlying problem with LOG and clang I believe:
> > > >>> https://gitlab.denx.de/u-boot/u-boot/-/jobs/135789
> > > >>>
> > > >>
> > > >> include/log.h:147:44: note: expanded from macro 'log'
> > > >>         if (CONFIG_IS_ENABLED(LOG) && (_LOG_DEBUG || _l <=
> > > >> _LOG_MAX_LEVEL)) \
> > > >>                                                   ^
> > > >> drivers/misc/p2sb_emul.c:197:10: error: converting the enum constant to
> > > >> a boolean [-Werror,-Wint-in-bool-context]
> > > >>
> > > >> This seems to be a Clang bug. _LOG_DEBUG is not an enum:
> > > >>
> > > >> #if CONFIG_IS_ENABLED(LOG)
> > > >> #ifdef LOG_DEBUG
> > > >> #define _LOG_DEBUG      1
> > > >> #else
> > > >> #define _LOG_DEBUG      0
> > > >> #endif
> > > >>
> > > >> So there seems to be a bug in the Clang you used.
> > > >>
> > > >> Compiling with clang on Debian Bullseye does not show the problem:
> > > >>
> > > >> make HOSTCC=clang sandbox_defconfig
> > > >> make HOSTCC=clang CC=clang -j8
> > > >>
> > > >> clang version 9.0.1-13
> > > >> LLVM version 9.0.1
> > > >>
> > > >> Which Clang version did you use?
> > > >>
> > > >> This is the change that added the test:
> > > >> https://reviews.llvm.org/D63082
> > > >>
> > > >> -Wint-in-bool-context seems to be new in Clang 10.
> > > >>
> > > >> All over the U-Boot code we assume that a non-zero integer is true. Do
> > > >> we really want to enable -Wint-in-bool-context?
> > > >
> > > > I'm using the official Clang 10 stable builds.
> > > >
> > >
> > > Do you really want to forbid using integers as booleans
> > > (-Wint-in-bool-context)?
> >
> > So, interesting.  The Linux kernel isn't disabling this warning.  It's
> > mentioned in two commits, one of which is "clang found a bug here", of
> > which this is not the case.  The other is more like ours:
> > commit 968e5170939662341242812b9c82ef51cf140a33
> > Author: Nathan Chancellor <natechancellor@gmail.com>
> > Date:   Thu Sep 26 09:22:59 2019 -0700
> >
> >     tracing: Fix clang -Wint-in-bool-context warnings in IF_ASSIGN macro
> >
> >     After r372664 in clang, the IF_ASSIGN macro causes a couple hundred
> >     warnings along the lines of:
> >
> >     kernel/trace/trace_output.c:1331:2: warning: converting the enum
> >     constant to a boolean [-Wint-in-bool-context]
> >     kernel/trace/trace.h:409:3: note: expanded from macro
> >     'trace_assign_type'
> >                     IF_ASSIGN(var, ent, struct ftrace_graph_ret_entry,
> >                     ^
> >     kernel/trace/trace.h:371:14: note: expanded from macro 'IF_ASSIGN'
> >                     WARN_ON(id && (entry)->type != id);     \
> >                                ^
> >     264 warnings generated.
> >
> >     This warning can catch issues with constructs like:
> >
> >         if (state == A || B)
> >
> >     where the developer really meant:
> >
> >         if (state == A || state == B)
> >
> >     This is currently the only occurrence of the warning in the kernel
> >     tree across defconfig, allyesconfig, allmodconfig for arm32, arm64,
> >     and x86_64. Add the implicit '!= 0' to the WARN_ON statement to fix
> >     the warnings and find potential issues in the future.
> >
> >     Link: https://github.com/llvm/llvm-project/commit/28b38c277a2941e9e891b2db30652cfd962f070b
> >     Link: https://github.com/ClangBuiltLinux/linux/issues/686
> >     Link: http://lkml.kernel.org/r/20190926162258.466321-1-natechancellor@gmail.com
> >
> >     Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
> >     Signed-off-by: Nathan Chancellor <natechancellor@gmail.com>
> >     Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
> >
> > Which is like our case, and reworking the test to be explicit.  I lean
> > towards that.
> 
> Oh dear I really want to vote against that.
> 
> if (x)
> 
> should allow C to consider x to be a boolean. I am hitting this in
> Zephyr and feels like it is undoing a long-standing C feature, with
> major disruption, for no benefit I can detect.
> 
> Hopefully I am misunderstanding what -Wint-in-bool-context means, and
> it just applies to enums?

Yes, it's not the simple case, it's the complex case as noted in the
kernel commit message.  Our change I believe would be:

diff --git a/include/log.h b/include/log.h
index 2859ce1f2e72..91ca2e0523f7 100644
--- a/include/log.h
+++ b/include/log.h
@@ -141,7 +141,7 @@ static inline int _log_nop(enum log_category_t cat, enum log_level_t level,
 /* Emit a log record if the level is less that the maximum */
 #define log(_cat, _level, _fmt, _args...) ({ \
 	int _l = _level; \
-	if (CONFIG_IS_ENABLED(LOG) && (_l <= _LOG_MAX_LEVEL || _LOG_DEBUG)) \
+	if (CONFIG_IS_ENABLED(LOG) && (_l <= _LOG_MAX_LEVEL || _LOG_DEBUG == 1)) \
 		_log((enum log_category_t)(_cat), _l, __FILE__, __LINE__, \
 		      __func__, \
 		      pr_fmt(_fmt), ##_args); \

It's not a new warning from clang (We've been on LLVM-10 since
February), it's only that the logging code is now being run through it
via CI.
Heinrich Schuchardt Aug. 5, 2020, 7:08 p.m. UTC | #10
Am 5. August 2020 21:03:28 MESZ schrieb Tom Rini <trini@konsulko.com>:
>On Wed, Aug 05, 2020 at 12:56:17PM -0600, Simon Glass wrote:
>> Hi Tom,
>> 
>> On Wed, 5 Aug 2020 at 12:37, Tom Rini <trini@konsulko.com> wrote:
>> >
>> > On Wed, Aug 05, 2020 at 08:31:55PM +0200, Heinrich Schuchardt
>wrote:
>> > > On 05.08.20 14:56, Tom Rini wrote:
>> > > > On Wed, Aug 05, 2020 at 02:54:05PM +0200, Heinrich Schuchardt
>wrote:
>> > > >> On 05.08.20 14:18, Tom Rini wrote:
>> > > >>> On Sun, Jul 26, 2020 at 08:27:35PM -0600, Simon Glass wrote:
>> > > >>>
>> > > >>>> At present if CONFIG_LOG enabled, putting LOG_DEBUG at the
>top of a file
>> > > >>>> (before log.h inclusion) causes _log() to be executed for
>every log()
>> > > >>>> call, regardless of the build- or run-time logging level.
>> > > >>>>
>> > > >>>> However there is no guarantee that the log record will
>actually be
>> > > >>>> displayed. If the current log level is lower than LOGL_DEBUG
>then it will
>> > > >>>> not be.
>> > > >>>>
>> > > >>>> Add a way to signal that the log record should always be
>displayed and
>> > > >>>> update log_passes_filters() to handle this.
>> > > >>>>
>> > > >>>> Signed-off-by: Simon Glass <sjg@chromium.org>
>> > > >>>
>> > > >>> This exposes an underlying problem with LOG and clang I
>believe:
>> > > >>> https://gitlab.denx.de/u-boot/u-boot/-/jobs/135789
>> > > >>>
>> > > >>
>> > > >> include/log.h:147:44: note: expanded from macro 'log'
>> > > >>         if (CONFIG_IS_ENABLED(LOG) && (_LOG_DEBUG || _l <=
>> > > >> _LOG_MAX_LEVEL)) \
>> > > >>                                                   ^
>> > > >> drivers/misc/p2sb_emul.c:197:10: error: converting the enum
>constant to
>> > > >> a boolean [-Werror,-Wint-in-bool-context]
>> > > >>
>> > > >> This seems to be a Clang bug. _LOG_DEBUG is not an enum:
>> > > >>
>> > > >> #if CONFIG_IS_ENABLED(LOG)
>> > > >> #ifdef LOG_DEBUG
>> > > >> #define _LOG_DEBUG      1
>> > > >> #else
>> > > >> #define _LOG_DEBUG      0
>> > > >> #endif
>> > > >>
>> > > >> So there seems to be a bug in the Clang you used.
>> > > >>
>> > > >> Compiling with clang on Debian Bullseye does not show the
>problem:
>> > > >>
>> > > >> make HOSTCC=clang sandbox_defconfig
>> > > >> make HOSTCC=clang CC=clang -j8
>> > > >>
>> > > >> clang version 9.0.1-13
>> > > >> LLVM version 9.0.1
>> > > >>
>> > > >> Which Clang version did you use?
>> > > >>
>> > > >> This is the change that added the test:
>> > > >> https://reviews.llvm.org/D63082
>> > > >>
>> > > >> -Wint-in-bool-context seems to be new in Clang 10.
>> > > >>
>> > > >> All over the U-Boot code we assume that a non-zero integer is
>true. Do
>> > > >> we really want to enable -Wint-in-bool-context?
>> > > >
>> > > > I'm using the official Clang 10 stable builds.
>> > > >
>> > >
>> > > Do you really want to forbid using integers as booleans
>> > > (-Wint-in-bool-context)?
>> >
>> > So, interesting.  The Linux kernel isn't disabling this warning. 
>It's
>> > mentioned in two commits, one of which is "clang found a bug here",
>of
>> > which this is not the case.  The other is more like ours:
>> > commit 968e5170939662341242812b9c82ef51cf140a33
>> > Author: Nathan Chancellor <natechancellor@gmail.com>
>> > Date:   Thu Sep 26 09:22:59 2019 -0700
>> >
>> >     tracing: Fix clang -Wint-in-bool-context warnings in IF_ASSIGN
>macro
>> >
>> >     After r372664 in clang, the IF_ASSIGN macro causes a couple
>hundred
>> >     warnings along the lines of:
>> >
>> >     kernel/trace/trace_output.c:1331:2: warning: converting the
>enum
>> >     constant to a boolean [-Wint-in-bool-context]
>> >     kernel/trace/trace.h:409:3: note: expanded from macro
>> >     'trace_assign_type'
>> >                     IF_ASSIGN(var, ent, struct
>ftrace_graph_ret_entry,
>> >                     ^
>> >     kernel/trace/trace.h:371:14: note: expanded from macro
>'IF_ASSIGN'
>> >                     WARN_ON(id && (entry)->type != id);     \
>> >                                ^
>> >     264 warnings generated.
>> >
>> >     This warning can catch issues with constructs like:
>> >
>> >         if (state == A || B)
>> >
>> >     where the developer really meant:
>> >
>> >         if (state == A || state == B)
>> >
>> >     This is currently the only occurrence of the warning in the
>kernel
>> >     tree across defconfig, allyesconfig, allmodconfig for arm32,
>arm64,
>> >     and x86_64. Add the implicit '!= 0' to the WARN_ON statement to
>fix
>> >     the warnings and find potential issues in the future.
>> >
>> >     Link:
>https://github.com/llvm/llvm-project/commit/28b38c277a2941e9e891b2db30652cfd962f070b
>> >     Link: https://github.com/ClangBuiltLinux/linux/issues/686
>> >     Link:
>http://lkml.kernel.org/r/20190926162258.466321-1-natechancellor@gmail.com
>> >
>> >     Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
>> >     Signed-off-by: Nathan Chancellor <natechancellor@gmail.com>
>> >     Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
>> >
>> > Which is like our case, and reworking the test to be explicit.  I
>lean
>> > towards that.
>> 
>> Oh dear I really want to vote against that.
>> 
>> if (x)
>> 
>> should allow C to consider x to be a boolean. I am hitting this in
>> Zephyr and feels like it is undoing a long-standing C feature, with
>> major disruption, for no benefit I can detect.
>> 
>> Hopefully I am misunderstanding what -Wint-in-bool-context means, and
>> it just applies to enums?
>
>Yes, it's not the simple case, it's the complex case as noted in the
>kernel commit message.  Our change I believe would be:
>
>diff --git a/include/log.h b/include/log.h
>index 2859ce1f2e72..91ca2e0523f7 100644
>--- a/include/log.h
>+++ b/include/log.h
>@@ -141,7 +141,7 @@ static inline int _log_nop(enum log_category_t cat,
>enum log_level_t level,
> /* Emit a log record if the level is less that the maximum */
> #define log(_cat, _level, _fmt, _args...) ({ \
> 	int _l = _level; \
>-	if (CONFIG_IS_ENABLED(LOG) && (_l <= _LOG_MAX_LEVEL || _LOG_DEBUG)) \
>+	if (CONFIG_IS_ENABLED(LOG) && (_l <= _LOG_MAX_LEVEL || _LOG_DEBUG ==
>1)) \

Why wouldn't we define _LOG_DEBUG as true or false? Shouldn't clang know that true is boolean?


> 		_log((enum log_category_t)(_cat), _l, __FILE__, __LINE__, \
> 		      __func__, \
> 		      pr_fmt(_fmt), ##_args); \
>
>It's not a new warning from clang (We've been on LLVM-10 since
>February), it's only that the logging code is now being run through it
>via CI.
Tom Rini Aug. 5, 2020, 7:32 p.m. UTC | #11
On Wed, Aug 05, 2020 at 09:08:40PM +0200, Heinrich Schuchardt wrote:
> Am 5. August 2020 21:03:28 MESZ schrieb Tom Rini <trini@konsulko.com>:
> >On Wed, Aug 05, 2020 at 12:56:17PM -0600, Simon Glass wrote:
> >> Hi Tom,
> >> 
> >> On Wed, 5 Aug 2020 at 12:37, Tom Rini <trini@konsulko.com> wrote:
> >> >
> >> > On Wed, Aug 05, 2020 at 08:31:55PM +0200, Heinrich Schuchardt
> >wrote:
> >> > > On 05.08.20 14:56, Tom Rini wrote:
> >> > > > On Wed, Aug 05, 2020 at 02:54:05PM +0200, Heinrich Schuchardt
> >wrote:
> >> > > >> On 05.08.20 14:18, Tom Rini wrote:
> >> > > >>> On Sun, Jul 26, 2020 at 08:27:35PM -0600, Simon Glass wrote:
> >> > > >>>
> >> > > >>>> At present if CONFIG_LOG enabled, putting LOG_DEBUG at the
> >top of a file
> >> > > >>>> (before log.h inclusion) causes _log() to be executed for
> >every log()
> >> > > >>>> call, regardless of the build- or run-time logging level.
> >> > > >>>>
> >> > > >>>> However there is no guarantee that the log record will
> >actually be
> >> > > >>>> displayed. If the current log level is lower than LOGL_DEBUG
> >then it will
> >> > > >>>> not be.
> >> > > >>>>
> >> > > >>>> Add a way to signal that the log record should always be
> >displayed and
> >> > > >>>> update log_passes_filters() to handle this.
> >> > > >>>>
> >> > > >>>> Signed-off-by: Simon Glass <sjg@chromium.org>
> >> > > >>>
> >> > > >>> This exposes an underlying problem with LOG and clang I
> >believe:
> >> > > >>> https://gitlab.denx.de/u-boot/u-boot/-/jobs/135789
> >> > > >>>
> >> > > >>
> >> > > >> include/log.h:147:44: note: expanded from macro 'log'
> >> > > >>         if (CONFIG_IS_ENABLED(LOG) && (_LOG_DEBUG || _l <=
> >> > > >> _LOG_MAX_LEVEL)) \
> >> > > >>                                                   ^
> >> > > >> drivers/misc/p2sb_emul.c:197:10: error: converting the enum
> >constant to
> >> > > >> a boolean [-Werror,-Wint-in-bool-context]
> >> > > >>
> >> > > >> This seems to be a Clang bug. _LOG_DEBUG is not an enum:
> >> > > >>
> >> > > >> #if CONFIG_IS_ENABLED(LOG)
> >> > > >> #ifdef LOG_DEBUG
> >> > > >> #define _LOG_DEBUG      1
> >> > > >> #else
> >> > > >> #define _LOG_DEBUG      0
> >> > > >> #endif
> >> > > >>
> >> > > >> So there seems to be a bug in the Clang you used.
> >> > > >>
> >> > > >> Compiling with clang on Debian Bullseye does not show the
> >problem:
> >> > > >>
> >> > > >> make HOSTCC=clang sandbox_defconfig
> >> > > >> make HOSTCC=clang CC=clang -j8
> >> > > >>
> >> > > >> clang version 9.0.1-13
> >> > > >> LLVM version 9.0.1
> >> > > >>
> >> > > >> Which Clang version did you use?
> >> > > >>
> >> > > >> This is the change that added the test:
> >> > > >> https://reviews.llvm.org/D63082
> >> > > >>
> >> > > >> -Wint-in-bool-context seems to be new in Clang 10.
> >> > > >>
> >> > > >> All over the U-Boot code we assume that a non-zero integer is
> >true. Do
> >> > > >> we really want to enable -Wint-in-bool-context?
> >> > > >
> >> > > > I'm using the official Clang 10 stable builds.
> >> > > >
> >> > >
> >> > > Do you really want to forbid using integers as booleans
> >> > > (-Wint-in-bool-context)?
> >> >
> >> > So, interesting.  The Linux kernel isn't disabling this warning. 
> >It's
> >> > mentioned in two commits, one of which is "clang found a bug here",
> >of
> >> > which this is not the case.  The other is more like ours:
> >> > commit 968e5170939662341242812b9c82ef51cf140a33
> >> > Author: Nathan Chancellor <natechancellor@gmail.com>
> >> > Date:   Thu Sep 26 09:22:59 2019 -0700
> >> >
> >> >     tracing: Fix clang -Wint-in-bool-context warnings in IF_ASSIGN
> >macro
> >> >
> >> >     After r372664 in clang, the IF_ASSIGN macro causes a couple
> >hundred
> >> >     warnings along the lines of:
> >> >
> >> >     kernel/trace/trace_output.c:1331:2: warning: converting the
> >enum
> >> >     constant to a boolean [-Wint-in-bool-context]
> >> >     kernel/trace/trace.h:409:3: note: expanded from macro
> >> >     'trace_assign_type'
> >> >                     IF_ASSIGN(var, ent, struct
> >ftrace_graph_ret_entry,
> >> >                     ^
> >> >     kernel/trace/trace.h:371:14: note: expanded from macro
> >'IF_ASSIGN'
> >> >                     WARN_ON(id && (entry)->type != id);     \
> >> >                                ^
> >> >     264 warnings generated.
> >> >
> >> >     This warning can catch issues with constructs like:
> >> >
> >> >         if (state == A || B)
> >> >
> >> >     where the developer really meant:
> >> >
> >> >         if (state == A || state == B)
> >> >
> >> >     This is currently the only occurrence of the warning in the
> >kernel
> >> >     tree across defconfig, allyesconfig, allmodconfig for arm32,
> >arm64,
> >> >     and x86_64. Add the implicit '!= 0' to the WARN_ON statement to
> >fix
> >> >     the warnings and find potential issues in the future.
> >> >
> >> >     Link:
> >https://github.com/llvm/llvm-project/commit/28b38c277a2941e9e891b2db30652cfd962f070b
> >> >     Link: https://github.com/ClangBuiltLinux/linux/issues/686
> >> >     Link:
> >http://lkml.kernel.org/r/20190926162258.466321-1-natechancellor@gmail.com
> >> >
> >> >     Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
> >> >     Signed-off-by: Nathan Chancellor <natechancellor@gmail.com>
> >> >     Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
> >> >
> >> > Which is like our case, and reworking the test to be explicit.  I
> >lean
> >> > towards that.
> >> 
> >> Oh dear I really want to vote against that.
> >> 
> >> if (x)
> >> 
> >> should allow C to consider x to be a boolean. I am hitting this in
> >> Zephyr and feels like it is undoing a long-standing C feature, with
> >> major disruption, for no benefit I can detect.
> >> 
> >> Hopefully I am misunderstanding what -Wint-in-bool-context means, and
> >> it just applies to enums?
> >
> >Yes, it's not the simple case, it's the complex case as noted in the
> >kernel commit message.  Our change I believe would be:
> >
> >diff --git a/include/log.h b/include/log.h
> >index 2859ce1f2e72..91ca2e0523f7 100644
> >--- a/include/log.h
> >+++ b/include/log.h
> >@@ -141,7 +141,7 @@ static inline int _log_nop(enum log_category_t cat,
> >enum log_level_t level,
> > /* Emit a log record if the level is less that the maximum */
> > #define log(_cat, _level, _fmt, _args...) ({ \
> > 	int _l = _level; \
> >-	if (CONFIG_IS_ENABLED(LOG) && (_l <= _LOG_MAX_LEVEL || _LOG_DEBUG)) \
> >+	if (CONFIG_IS_ENABLED(LOG) && (_l <= _LOG_MAX_LEVEL || _LOG_DEBUG ==
> >1)) \
> 
> Why wouldn't we define _LOG_DEBUG as true or false? Shouldn't clang know that true is boolean?

Because I didn't think of that instead, mainly.
Simon Glass Sept. 28, 2020, 4:24 a.m. UTC | #12
Hi,

On Wed, 5 Aug 2020 at 13:32, Tom Rini <trini@konsulko.com> wrote:
>
> On Wed, Aug 05, 2020 at 09:08:40PM +0200, Heinrich Schuchardt wrote:
> > Am 5. August 2020 21:03:28 MESZ schrieb Tom Rini <trini@konsulko.com>:
> > >On Wed, Aug 05, 2020 at 12:56:17PM -0600, Simon Glass wrote:
> > >> Hi Tom,
> > >>
> > >> On Wed, 5 Aug 2020 at 12:37, Tom Rini <trini@konsulko.com> wrote:
> > >> >
> > >> > On Wed, Aug 05, 2020 at 08:31:55PM +0200, Heinrich Schuchardt
> > >wrote:
> > >> > > On 05.08.20 14:56, Tom Rini wrote:
> > >> > > > On Wed, Aug 05, 2020 at 02:54:05PM +0200, Heinrich Schuchardt
> > >wrote:
> > >> > > >> On 05.08.20 14:18, Tom Rini wrote:
> > >> > > >>> On Sun, Jul 26, 2020 at 08:27:35PM -0600, Simon Glass wrote:
> > >> > > >>>
> > >> > > >>>> At present if CONFIG_LOG enabled, putting LOG_DEBUG at the
> > >top of a file
> > >> > > >>>> (before log.h inclusion) causes _log() to be executed for
> > >every log()
> > >> > > >>>> call, regardless of the build- or run-time logging level.
> > >> > > >>>>
> > >> > > >>>> However there is no guarantee that the log record will
> > >actually be
> > >> > > >>>> displayed. If the current log level is lower than LOGL_DEBUG
> > >then it will
> > >> > > >>>> not be.
> > >> > > >>>>
> > >> > > >>>> Add a way to signal that the log record should always be
> > >displayed and
> > >> > > >>>> update log_passes_filters() to handle this.
> > >> > > >>>>
> > >> > > >>>> Signed-off-by: Simon Glass <sjg@chromium.org>
> > >> > > >>>
> > >> > > >>> This exposes an underlying problem with LOG and clang I
> > >believe:
> > >> > > >>> https://gitlab.denx.de/u-boot/u-boot/-/jobs/135789
> > >> > > >>>
> > >> > > >>
> > >> > > >> include/log.h:147:44: note: expanded from macro 'log'
> > >> > > >>         if (CONFIG_IS_ENABLED(LOG) && (_LOG_DEBUG || _l <=
> > >> > > >> _LOG_MAX_LEVEL)) \
> > >> > > >>                                                   ^
> > >> > > >> drivers/misc/p2sb_emul.c:197:10: error: converting the enum
> > >constant to
> > >> > > >> a boolean [-Werror,-Wint-in-bool-context]
> > >> > > >>
> > >> > > >> This seems to be a Clang bug. _LOG_DEBUG is not an enum:
> > >> > > >>
> > >> > > >> #if CONFIG_IS_ENABLED(LOG)
> > >> > > >> #ifdef LOG_DEBUG
> > >> > > >> #define _LOG_DEBUG      1
> > >> > > >> #else
> > >> > > >> #define _LOG_DEBUG      0
> > >> > > >> #endif
> > >> > > >>
> > >> > > >> So there seems to be a bug in the Clang you used.
> > >> > > >>
> > >> > > >> Compiling with clang on Debian Bullseye does not show the
> > >problem:
> > >> > > >>
> > >> > > >> make HOSTCC=clang sandbox_defconfig
> > >> > > >> make HOSTCC=clang CC=clang -j8
> > >> > > >>
> > >> > > >> clang version 9.0.1-13
> > >> > > >> LLVM version 9.0.1
> > >> > > >>
> > >> > > >> Which Clang version did you use?
> > >> > > >>
> > >> > > >> This is the change that added the test:
> > >> > > >> https://reviews.llvm.org/D63082
> > >> > > >>
> > >> > > >> -Wint-in-bool-context seems to be new in Clang 10.
> > >> > > >>
> > >> > > >> All over the U-Boot code we assume that a non-zero integer is
> > >true. Do
> > >> > > >> we really want to enable -Wint-in-bool-context?
> > >> > > >
> > >> > > > I'm using the official Clang 10 stable builds.
> > >> > > >
> > >> > >
> > >> > > Do you really want to forbid using integers as booleans
> > >> > > (-Wint-in-bool-context)?
> > >> >
> > >> > So, interesting.  The Linux kernel isn't disabling this warning.
> > >It's
> > >> > mentioned in two commits, one of which is "clang found a bug here",
> > >of
> > >> > which this is not the case.  The other is more like ours:
> > >> > commit 968e5170939662341242812b9c82ef51cf140a33
> > >> > Author: Nathan Chancellor <natechancellor@gmail.com>
> > >> > Date:   Thu Sep 26 09:22:59 2019 -0700
> > >> >
> > >> >     tracing: Fix clang -Wint-in-bool-context warnings in IF_ASSIGN
> > >macro
> > >> >
> > >> >     After r372664 in clang, the IF_ASSIGN macro causes a couple
> > >hundred
> > >> >     warnings along the lines of:
> > >> >
> > >> >     kernel/trace/trace_output.c:1331:2: warning: converting the
> > >enum
> > >> >     constant to a boolean [-Wint-in-bool-context]
> > >> >     kernel/trace/trace.h:409:3: note: expanded from macro
> > >> >     'trace_assign_type'
> > >> >                     IF_ASSIGN(var, ent, struct
> > >ftrace_graph_ret_entry,
> > >> >                     ^
> > >> >     kernel/trace/trace.h:371:14: note: expanded from macro
> > >'IF_ASSIGN'
> > >> >                     WARN_ON(id && (entry)->type != id);     \
> > >> >                                ^
> > >> >     264 warnings generated.
> > >> >
> > >> >     This warning can catch issues with constructs like:
> > >> >
> > >> >         if (state == A || B)
> > >> >
> > >> >     where the developer really meant:
> > >> >
> > >> >         if (state == A || state == B)
> > >> >
> > >> >     This is currently the only occurrence of the warning in the
> > >kernel
> > >> >     tree across defconfig, allyesconfig, allmodconfig for arm32,
> > >arm64,
> > >> >     and x86_64. Add the implicit '!= 0' to the WARN_ON statement to
> > >fix
> > >> >     the warnings and find potential issues in the future.
> > >> >
> > >> >     Link:
> > >https://github.com/llvm/llvm-project/commit/28b38c277a2941e9e891b2db30652cfd962f070b
> > >> >     Link: https://github.com/ClangBuiltLinux/linux/issues/686
> > >> >     Link:
> > >http://lkml.kernel.org/r/20190926162258.466321-1-natechancellor@gmail.com
> > >> >
> > >> >     Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
> > >> >     Signed-off-by: Nathan Chancellor <natechancellor@gmail.com>
> > >> >     Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
> > >> >
> > >> > Which is like our case, and reworking the test to be explicit.  I
> > >lean
> > >> > towards that.
> > >>
> > >> Oh dear I really want to vote against that.
> > >>
> > >> if (x)
> > >>
> > >> should allow C to consider x to be a boolean. I am hitting this in
> > >> Zephyr and feels like it is undoing a long-standing C feature, with
> > >> major disruption, for no benefit I can detect.
> > >>
> > >> Hopefully I am misunderstanding what -Wint-in-bool-context means, and
> > >> it just applies to enums?
> > >
> > >Yes, it's not the simple case, it's the complex case as noted in the
> > >kernel commit message.  Our change I believe would be:
> > >
> > >diff --git a/include/log.h b/include/log.h
> > >index 2859ce1f2e72..91ca2e0523f7 100644
> > >--- a/include/log.h
> > >+++ b/include/log.h
> > >@@ -141,7 +141,7 @@ static inline int _log_nop(enum log_category_t cat,
> > >enum log_level_t level,
> > > /* Emit a log record if the level is less that the maximum */
> > > #define log(_cat, _level, _fmt, _args...) ({ \
> > >     int _l = _level; \
> > >-    if (CONFIG_IS_ENABLED(LOG) && (_l <= _LOG_MAX_LEVEL || _LOG_DEBUG)) \
> > >+    if (CONFIG_IS_ENABLED(LOG) && (_l <= _LOG_MAX_LEVEL || _LOG_DEBUG ==
> > >1)) \
> >
> > Why wouldn't we define _LOG_DEBUG as true or false? Shouldn't clang know that true is boolean?
>
> Because I didn't think of that instead, mainly.
>

I've resent this patch with just this change to fix clang-10.

Regards,
Simon
diff mbox series

Patch

diff --git a/common/log.c b/common/log.c
index 734d26de4a..5ff8245922 100644
--- a/common/log.c
+++ b/common/log.c
@@ -156,16 +156,20 @@  static bool log_has_file(const char *file_list, const char *file)
 static bool log_passes_filters(struct log_device *ldev, struct log_rec *rec)
 {
 	struct log_filter *filt;
+	int level = rec->level & LOGL_LEVEL_MASK;
+
+	if (rec->force_debug && level <= LOGL_DEBUG)
+		return true;
 
 	/* If there are no filters, filter on the default log level */
 	if (list_empty(&ldev->filter_head)) {
-		if (rec->level > gd->default_log_level)
+		if (level > gd->default_log_level)
 			return false;
 		return true;
 	}
 
 	list_for_each_entry(filt, &ldev->filter_head, sibling_node) {
-		if (rec->level > filt->max_level)
+		if (level > filt->max_level)
 			continue;
 		if ((filt->flags & LOGFF_HAS_CAT) &&
 		    !log_has_cat(filt->cat_list, rec->cat))
@@ -208,7 +212,8 @@  int _log(enum log_category_t cat, enum log_level_t level, const char *file,
 	va_list args;
 
 	rec.cat = cat;
-	rec.level = level;
+	rec.level = level & LOGL_LEVEL_MASK;
+	rec.force_debug = level & LOGL_FORCE_DEBUG;
 	rec.file = file;
 	rec.line = line;
 	rec.func = func;
diff --git a/doc/README.log b/doc/README.log
index ba838824a9..554e99ca4c 100644
--- a/doc/README.log
+++ b/doc/README.log
@@ -77,12 +77,10 @@  Sometimes it is useful to turn on logging just in one file. You can use this:
 
    #define LOG_DEBUG
 
-to enable building in of all logging statements in a single file. Put it at
-the top of the file, before any #includes.
-
-To actually get U-Boot to output this you need to also set the default logging
-level - e.g. set CONFIG_LOG_DEFAULT_LEVEL to 7 (LOGL_DEBUG) or more. Otherwise
-debug output is suppressed and will not be generated.
+to enable building in of all debug logging statements in a single file. Put it
+at the top of the file, before any #includes. This overrides any log-level
+setting in U-Boot, including CONFIG_LOG_DEFAULT_LEVEL, but just for that file.
+All logging statements, up to and including LOGL_DEBUG, will be displayed.
 
 
 Convenience functions
diff --git a/include/log.h b/include/log.h
index 2859ce1f2e..63052f74eb 100644
--- a/include/log.h
+++ b/include/log.h
@@ -33,6 +33,9 @@  enum log_level_t {
 	LOGL_COUNT,
 	LOGL_NONE,
 
+	LOGL_LEVEL_MASK = 0xf,	/* Mask for valid log levels */
+	LOGL_FORCE_DEBUG = 0x10, /* Mask to force output due to LOG_DEBUG */
+
 	LOGL_FIRST = LOGL_EMERG,
 	LOGL_MAX = LOGL_DEBUG_IO,
 };
@@ -133,7 +136,7 @@  static inline int _log_nop(enum log_category_t cat, enum log_level_t level,
 
 #if CONFIG_IS_ENABLED(LOG)
 #ifdef LOG_DEBUG
-#define _LOG_DEBUG	1
+#define _LOG_DEBUG	LOGL_FORCE_DEBUG
 #else
 #define _LOG_DEBUG	0
 #endif
@@ -141,9 +144,9 @@  static inline int _log_nop(enum log_category_t cat, enum log_level_t level,
 /* Emit a log record if the level is less that the maximum */
 #define log(_cat, _level, _fmt, _args...) ({ \
 	int _l = _level; \
-	if (CONFIG_IS_ENABLED(LOG) && (_l <= _LOG_MAX_LEVEL || _LOG_DEBUG)) \
-		_log((enum log_category_t)(_cat), _l, __FILE__, __LINE__, \
-		      __func__, \
+	if (CONFIG_IS_ENABLED(LOG) && (_LOG_DEBUG || _l <= _LOG_MAX_LEVEL)) \
+		_log((enum log_category_t)(_cat), _l | _LOG_DEBUG, __FILE__, \
+		     __LINE__, __func__, \
 		      pr_fmt(_fmt), ##_args); \
 	})
 #else
@@ -279,8 +282,12 @@  void __assert_fail(const char *assertion, const char *file, unsigned int line,
  * Memebers marked as 'allocated' are allocated (e.g. via strdup()) by the log
  * system.
  *
+ * TODO(sjg@chromium.org): Compress this struct down a bit to reduce space, e.g.
+ * a single u32 for cat, level, line and force_debug
+ *
  * @cat: Category, representing a uclass or part of U-Boot
  * @level: Severity level, less severe is higher
+ * @force_debug: Force output of debug
  * @file: Name of file where the log record was generated (not allocated)
  * @line: Line number where the log record was generated
  * @func: Function where the log record was generated (not allocated)
@@ -289,6 +296,7 @@  void __assert_fail(const char *assertion, const char *file, unsigned int line,
 struct log_rec {
 	enum log_category_t cat;
 	enum log_level_t level;
+	bool force_debug;
 	const char *file;
 	int line;
 	const char *func;
diff --git a/test/log/syslog_test.c b/test/log/syslog_test.c
index 120a8b2537..df239d1e8d 100644
--- a/test/log/syslog_test.c
+++ b/test/log/syslog_test.c
@@ -276,7 +276,7 @@  static int log_test_syslog_nodebug(struct unit_test_state *uts)
 	sandbox_eth_set_tx_handler(0, sb_log_tx_handler);
 	/* Used by ut_assert macros in the tx_handler */
 	sandbox_eth_set_priv(0, &env);
-	log_debug("testing %s\n", "log_debug");
+	log_content("testing %s\n", "log_debug");
 	sandbox_eth_set_tx_handler(0, NULL);
 	/* Check that the callback function was not called */
 	ut_assertnonnull(env.expected);