From commits-return-8484-archive-asf-public=cust-asf.ponee.io@groovy.apache.org Mon May 6 22:43:30 2019 Return-Path: X-Original-To: archive-asf-public@cust-asf.ponee.io Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [207.244.88.153]) by mx-eu-01.ponee.io (Postfix) with SMTP id 82D4918060F for ; Tue, 7 May 2019 00:43:30 +0200 (CEST) Received: (qmail 99782 invoked by uid 500); 6 May 2019 22:43:29 -0000 Mailing-List: contact commits-help@groovy.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@groovy.apache.org Delivered-To: mailing list commits@groovy.apache.org Received: (qmail 99773 invoked by uid 99); 6 May 2019 22:43:29 -0000 Received: from ec2-52-202-80-70.compute-1.amazonaws.com (HELO gitbox.apache.org) (52.202.80.70) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 06 May 2019 22:43:29 +0000 Received: by gitbox.apache.org (ASF Mail Server at gitbox.apache.org, from userid 33) id 92ADA87263; Mon, 6 May 2019 22:43:24 +0000 (UTC) Date: Mon, 06 May 2019 22:43:24 +0000 To: "commits@groovy.apache.org" Subject: [groovy] branch master updated: GROOVY-9063: @CompileStatic generates invalid bytecode when accessing protected instance member from 2 level of nested closures MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Message-ID: <155718260446.12164.12977955549937867391@gitbox.apache.org> From: paulk@apache.org X-Git-Host: gitbox.apache.org X-Git-Repo: groovy X-Git-Refname: refs/heads/master X-Git-Reftype: branch X-Git-Oldrev: c8e19b0a6988dbbda83e4774b9513e98ee4ed113 X-Git-Newrev: b3be233f0232f3bb6760e1f8300dd1792f15c0c9 X-Git-Rev: b3be233f0232f3bb6760e1f8300dd1792f15c0c9 X-Git-NotificationType: ref_changed_plus_diff X-Git-Multimail-Version: 1.5.dev Auto-Submitted: auto-generated This is an automated email from the ASF dual-hosted git repository. paulk pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/groovy.git The following commit(s) were added to refs/heads/master by this push: new b3be233 GROOVY-9063: @CompileStatic generates invalid bytecode when accessing protected instance member from 2 level of nested closures b3be233 is described below commit b3be233f0232f3bb6760e1f8300dd1792f15c0c9 Author: Paul King AuthorDate: Tue May 7 08:43:10 2019 +1000 GROOVY-9063: @CompileStatic generates invalid bytecode when accessing protected instance member from 2 level of nested closures --- .../transform/stc/StaticTypeCheckingVisitor.java | 40 +++++++++++++++------ src/test/groovy/bugs/Groovy9063Bug.groovy | 42 ++++++++++++++++++++++ 2 files changed, 71 insertions(+), 11 deletions(-) diff --git a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java index 8b12515..725a013 100644 --- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java +++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java @@ -531,7 +531,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport { */ private String checkOrMarkInnerPropertyOwnerAccess(Expression source, FieldNode fn, boolean lhsOfAssignment, String delegationData) { if (fn == null || fn.isStatic() || fn.isPrivate() || "delegate".equals(delegationData)) return delegationData; - if (source instanceof PropertyExpression && typeCheckingContext.getEnclosingClosure() != null) { + if (source instanceof PropertyExpression && typeCheckingContext.getEnclosingClosureStack().size() == 1) { PropertyExpression pe = (PropertyExpression) source; boolean ownerProperty = !("this".equals(pe.getPropertyAsString())); if (ownerProperty && pe.getObjectExpression() instanceof VariableExpression) { @@ -699,16 +699,23 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport { TypeCheckingContext.EnclosingClosure enclosingClosure = typeCheckingContext.getEnclosingClosure(); if (enclosingClosure != null) { - String name = vexp.getName(); - if (name.equals("owner") || name.equals("thisObject")) { - storeType(vexp, typeCheckingContext.getEnclosingClassNode()); - return; - } else if ("delegate".equals(name)) { - DelegationMetadata md = getDelegationMetadata(enclosingClosure.getClosureExpression()); - ClassNode type = typeCheckingContext.getEnclosingClassNode(); - if (md != null) type = md.getType(); - storeType(vexp, type); - return; + switch (vexp.getName()) { + case "delegate": + DelegationMetadata md = getDelegationMetadata(enclosingClosure.getClosureExpression()); + if (md != null) { + storeType(vexp, md.getType()); + return; + } + // falls through + case "owner": + if (typeCheckingContext.getEnclosingClosureStack().size() > 1) { + storeType(vexp, CLOSURE_TYPE); + return; + } + // falls through + case "thisObject": + storeType(vexp, typeCheckingContext.getEnclosingClassNode()); + return; } } @@ -3299,6 +3306,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport { if (dmd.getParent() == null) { receivers.addAll(owners); } else { + //receivers.add(new Receiver(CLOSURE_TYPE, path + "owner")); addReceivers(receivers, owners, dmd.getParent(), path + "owner."); } } @@ -3308,6 +3316,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport { if (dmd.getParent() == null) { receivers.addAll(owners); } else { + //receivers.add(new Receiver(CLOSURE_TYPE, path + "owner")); addReceivers(receivers, owners, dmd.getParent(), path + "owner."); } if (strategy == Closure.OWNER_FIRST) { @@ -3808,6 +3817,15 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport { && ((VariableExpression) objectExpression).getName().equals("it")) { owners.add(Receiver.make(typeCheckingContext.lastImplicitItType)); } + if (typeCheckingContext.delegationMetadata != null + && objectExpression instanceof VariableExpression + && ((VariableExpression) objectExpression).getName().equals("owner") + && /*isNested:*/typeCheckingContext.delegationMetadata.getParent() != null) { + owners.clear(); + List> enclosingClass = Collections.singletonList( + Receiver.make(typeCheckingContext.getEnclosingClassNode())); + addReceivers(owners, enclosingClass, typeCheckingContext.delegationMetadata.getParent(), "owner."); + } return owners; } diff --git a/src/test/groovy/bugs/Groovy9063Bug.groovy b/src/test/groovy/bugs/Groovy9063Bug.groovy new file mode 100644 index 0000000..9374e82 --- /dev/null +++ b/src/test/groovy/bugs/Groovy9063Bug.groovy @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package groovy.bugs + +class Groovy9063Bug extends GroovyTestCase { + void testProtectedFieldInClosureInEnum() { + assertScript ''' + import groovy.transform.CompileStatic + + @CompileStatic + class Groovy9063 { + protected String message = "hello" + + int nestedClosures() { + { -> + { -> + message.length() + }.call() + }.call() + } + } + + assert new Groovy9063().nestedClosures() == 5 + ''' + } +}