# HG changeset patch # User jlahoda # Date 1474637732 -7200 # Node ID 61082a97bbf03180b62e05618354c2cb3681c125 # Parent 06ac98da3f8247896aa09bdfaf3b0924cc52dfd2 8047347: com.sun.source.util.Trees breaks the compiler. Summary: Clearing synthetic constructors and super constructor calls between annotation processing rounds. Reviewed-by: jjg diff -r 06ac98da3f82 -r 61082a97bbf0 langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java Thu Sep 22 18:31:35 2016 +0000 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java Fri Sep 23 15:35:32 2016 +0200 @@ -383,18 +383,16 @@ JCTree tree = (JCTree) path.getLeaf(); Symbol sym = TreeInfo.symbolFor(tree); if (sym == null) { - if (TreeInfo.isDeclaration(tree)) { - for (TreePath p = path; p != null; p = p.getParentPath()) { - JCTree t = (JCTree) p.getLeaf(); - if (t.hasTag(JCTree.Tag.CLASSDEF)) { - JCClassDecl ct = (JCClassDecl) t; - if (ct.sym != null) { - if ((ct.sym.flags_field & Flags.UNATTRIBUTED) != 0) { - attr.attribClass(ct.pos(), ct.sym); - sym = TreeInfo.symbolFor(tree); - } - break; + for (TreePath p = path; p != null; p = p.getParentPath()) { + JCTree t = (JCTree) p.getLeaf(); + if (t.hasTag(JCTree.Tag.CLASSDEF)) { + JCClassDecl ct = (JCClassDecl) t; + if (ct.sym != null) { + if ((ct.sym.flags_field & Flags.UNATTRIBUTED) != 0) { + attr.attribClass(ct.pos(), ct.sym); + sym = TreeInfo.symbolFor(tree); } + break; } } } diff -r 06ac98da3f82 -r 61082a97bbf0 langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Thu Sep 22 18:31:35 2016 +0000 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Fri Sep 23 15:35:32 2016 +0200 @@ -1503,13 +1503,35 @@ } } public void visitClassDef(JCClassDecl node) { + super.visitClassDef(node); + // remove generated constructor that may have been added during attribution: + List beforeConstructor = List.nil(); + List defs = node.defs; + while (defs.nonEmpty() && !defs.head.hasTag(Tag.METHODDEF)) { + beforeConstructor = beforeConstructor.prepend(defs.head); + defs = defs.tail; + } + if (defs.nonEmpty() && + (((JCMethodDecl) defs.head).mods.flags & Flags.GENERATEDCONSTR) != 0) { + defs = defs.tail; + while (beforeConstructor.nonEmpty()) { + defs = defs.prepend(beforeConstructor.head); + beforeConstructor = beforeConstructor.tail; + } + node.defs = defs; + } if (node.sym != null) { node.sym.completer = new ImplicitCompleter(topLevel); } node.sym = null; - super.visitClassDef(node); } public void visitMethodDef(JCMethodDecl node) { + // remove super constructor call that may have been added during attribution: + if (TreeInfo.isConstructor(node) && node.sym != null && node.sym.owner.isEnum() && + node.body.stats.nonEmpty() && TreeInfo.isSuperCall(node.body.stats.head) && + node.body.stats.head.pos == node.body.pos) { + node.body.stats = node.body.stats.tail; + } node.sym = null; super.visitMethodDef(node); } diff -r 06ac98da3f82 -r 61082a97bbf0 langtools/test/tools/javac/processing/model/trees/BrokenEnumConstructor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/processing/model/trees/BrokenEnumConstructor.java Fri Sep 23 15:35:32 2016 +0200 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8047347 + * @summary Verify that an explicit (incorrect) super constructor invocation in enums is not cleared + * by JavacProcessingEnvironment + * @library /tools/javac/lib + * @modules jdk.compiler + * @build JavacTestingAbstractProcessor OnDemandAttribution + * @compile/process/fail/ref=BrokenEnumConstructor.out -XDrawDiagnostics -processor OnDemandAttribution BrokenEnumConstructor.java + */ + +public enum BrokenEnumConstructor { + + A; + + BrokenEnumConstructor() {super(); /*illegal*/} +} diff -r 06ac98da3f82 -r 61082a97bbf0 langtools/test/tools/javac/processing/model/trees/BrokenEnumConstructor.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/processing/model/trees/BrokenEnumConstructor.out Fri Sep 23 15:35:32 2016 +0200 @@ -0,0 +1,2 @@ +BrokenEnumConstructor.java:39:30: compiler.err.call.to.super.not.allowed.in.enum.ctor: BrokenEnumConstructor +1 error diff -r 06ac98da3f82 -r 61082a97bbf0 langtools/test/tools/javac/processing/model/trees/OnDemandAttribution.java --- a/langtools/test/tools/javac/processing/model/trees/OnDemandAttribution.java Thu Sep 22 18:31:35 2016 +0000 +++ b/langtools/test/tools/javac/processing/model/trees/OnDemandAttribution.java Fri Sep 23 15:35:32 2016 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,56 +23,88 @@ /* * @test - * @bug 8038455 + * @bug 8038455 8047347 * @summary Verify that in-method ClassSymbols from one round do not affect ClassSymbols in * following rounds. * @library /tools/javac/lib * @modules jdk.compiler * @build JavacTestingAbstractProcessor OnDemandAttribution - * @compile/process -processor OnDemandAttribution OnDemandAttribution.java + * @clean Gen + * @compile/process -processor OnDemandAttribution OnDemandAttributionData.java */ +import java.io.IOException; +import java.io.Writer; import java.util.*; import javax.annotation.processing.*; import javax.lang.model.element.*; -import static javax.lang.model.util.ElementFilter.*; +import static javax.lang.model.util.ElementFilter.constructorsIn; import com.sun.source.tree.*; import com.sun.source.util.*; public class OnDemandAttribution extends JavacTestingAbstractProcessor { public OnDemandAttribution() { - class Local { } - new Object() { }; } + int round; + Set roots = new HashSet<>(); + public boolean process(Set annos,RoundEnvironment rEnv) { - TypeElement currentClass = elements.getTypeElement("OnDemandAttribution"); - ExecutableElement constr = constructorsIn(currentClass.getEnclosedElements()).get(0); - Trees trees = Trees.instance(processingEnv); - TreePath path = trees.getPath(constr); + for (Element root : rEnv.getRootElements()) { + while (root.getEnclosingElement().getKind() != ElementKind.PACKAGE) { + root = root.getEnclosingElement(); + } + roots.add(((TypeElement) root).getQualifiedName().toString()); + } + for (String root : roots) { + TypeElement currentClass = elements.getTypeElement(root); + ExecutableElement constr = constructorsIn(currentClass.getEnclosedElements()).get(0); + Trees trees = Trees.instance(processingEnv); + TreePath path = trees.getPath(constr); - new TreePathScanner() { - @Override public Void visitClass(ClassTree node, Void p) { - if (node.getSimpleName().contentEquals("Local")) { - //will also attribute the body on demand: + new TreePathScanner() { + @Override public Void visitClass(ClassTree node, Void p) { + if (node.getSimpleName().contentEquals("Local")) { + //will also attribute the body on demand: + Element el = trees.getElement(getCurrentPath()); + Name binaryName = elements.getBinaryName((TypeElement) el); + if (!binaryName.contentEquals("OnDemandAttributionData$1Local")) { + throw new IllegalStateException("Incorrect binary name=" + binaryName); + } + } + return super.visitClass(node, p); + } + @Override public Void visitNewClass(NewClassTree node, Void p) { Element el = trees.getElement(getCurrentPath()); - Name binaryName = elements.getBinaryName((TypeElement) el); - if (!binaryName.contentEquals("OnDemandAttribution$1Local")) { + Name binaryName = elements.getBinaryName((TypeElement) el.getEnclosingElement()); + if (!binaryName.contentEquals("OnDemandAttributionData$1")) { throw new IllegalStateException("Incorrect binary name=" + binaryName); } + return super.visitNewClass(node, p); } - return super.visitClass(node, p); + @Override + public Void visitMethodInvocation(MethodInvocationTree node, Void p) { + if (trees.getElement(getCurrentPath()) == null) + throw new IllegalStateException("No element for: " + node); + return super.visitMethodInvocation(node, p); + } + @Override + public Void visitIdentifier(IdentifierTree node, Void p) { + if (trees.getElement(getCurrentPath()) == null) + throw new IllegalStateException("No element for: " + node); + return super.visitIdentifier(node, p); + } + }.scan(path, null); + } + + if (round++ == 0) { + try (Writer out = filer.createSourceFile("Gen").openWriter()) { + out.write("class Gen { public static long C = 1; }"); + } catch (IOException ex) { + throw new IllegalStateException(ex); } - @Override public Void visitNewClass(NewClassTree node, Void p) { - Element el = trees.getElement(getCurrentPath()); - Name binaryName = elements.getBinaryName((TypeElement) el.getEnclosingElement()); - if (!binaryName.contentEquals("OnDemandAttribution$1")) { - throw new IllegalStateException("Incorrect binary name=" + binaryName); - } - return super.visitNewClass(node, p); - } - }.scan(path, null); + } return true; } diff -r 06ac98da3f82 -r 61082a97bbf0 langtools/test/tools/javac/processing/model/trees/OnDemandAttributionData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/processing/model/trees/OnDemandAttributionData.java Fri Sep 23 15:35:32 2016 +0200 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +public class OnDemandAttributionData { + + public OnDemandAttributionData(int i) { + class Local { } + new Aux(Gen.C) { }; + } + + class Aux { + Aux(String str) {} + Aux(int i) {} + Aux(long l) {} + } + + private void methodAttributionTest() { + System.err.println(""); + } + + enum E { + A; + + final int i; + + E() { + i = Integer.parseInt("1"); + } + + } + + enum E2 { + A; + + { + int i = Integer.parseInt("1"); + } + } +}