[
https://issues.apache.org/jira/browse/GROOVY-12553?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18134334#comment-18134334
]
ASF GitHub Bot commented on GROOVY-12553:
-----------------------------------------
jdaugherty opened a new pull request, #3082:
URL: https://github.com/apache/groovy/pull/3082
A reference to the log field added by @Log and friends was guarded only
while unbound. With the superclass read from bytecode, it was bound to
the superclass's private log field instead and the guard was dropped.
`bugs.Groovy12553` compiles the classes once together and once with one of
them compiled against the others already compiled, as an incremental build
does, and compares the class files. It fails without the fix.
- Jira: [GROOVY-12553](https://issues.apache.org/jira/browse/GROOVY-12553)
- Reproducer, with `groovyc` and a Gradle incremental build:
https://github.com/jdaugherty/groovy-log-guard-precompiled-superclass
- Backport to `GROOVY_5_1_X`:
https://github.com/jdaugherty/groovy/commit/0239ac38004340f2ee7a6537d1621c77b2f351b7,
on the branch
[`GROOVY-12553-5_1_X`](https://github.com/jdaugherty/groovy/tree/GROOVY-12553-5_1_X).
It reproduces on 4.0.33, 5.1.3 and master. Could this be backported to 5.x
once it is merged?
> @Log: a log call in a subclass is not guarded when the superclass with its
> own @Log is already compiled
> -------------------------------------------------------------------------------------------------------
>
> Key: GROOVY-12553
> URL: https://issues.apache.org/jira/browse/GROOVY-12553
> Project: Groovy
> Issue Type: Bug
> Components: AST Transforms
> Affects Versions: 4.0.33, 5.1.3
> Reporter: James Daugherty
> Priority: Major
>
> {{@Log}}, {{@Slf4j}} and the other logging annotations wrap a log call whose
> arguments are not trivial in a level check, so {{log.fine('value: ' +
> value)}} compiles as {{if (log.isLoggable(Level.FINE)) log.fine('value: ' +
> value)}}. When the class extends another class with a logging annotation, the
> guard is only added while the superclass is compiled together with it. When
> the superclass is already compiled, the call is left unguarded, so its
> arguments are evaluated whatever the level, and the same source compiles to a
> different class file depending on what else is compiled.
> {code:groovy}
> @groovy.util.logging.Log
> abstract class Base {
> void start() { log.info('starting ' + getClass().simpleName) }
> }
> @groovy.util.logging.Log
> class Sub extends Base {
> void run(Object value) {
> log.fine('value: ' + value) // not guarded when Base is already
> compiled
> }
> }
> {code}
> Reproduced with 4.0.33, 5.1.3 and master. A reproducer with a groovyc script
> and an incremental Gradle build:
> https://github.com/jdaugherty/groovy-log-guard-precompiled-superclass
> *Cause*
> {{LogASTTransformation}} adds the guard only when the {{log}} variable of the
> call is still a {{DynamicVariable}}, unbound because the log field is added
> by the transformation itself. With the superclass read from bytecode, the
> reference has already been bound to the superclass's own private {{log}}
> field, so the call is left unguarded. The transformation already accepts such
> a private field when it adds the subclass's log field.
> *Proposed fix*
> Treat a reference bound to a private field of another class the same as an
> unbound one.
> Found while making incremental builds of a Grails application produce the
> same classes as a full build; see also GROOVY-12550 and GROOVY-12544.
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)