From 37cda5b81d15240b244101cbfc5c6c38ac9b3ce1 Mon Sep 17 00:00:00 2001 From: Werner Dietl Date: Tue, 5 Apr 2022 18:31:56 -0400 Subject: [PATCH 1/6] Remove deprecated StringConcatenateAssignmentNode --- .../inference/dataflow/InferenceTransfer.java | 25 ------------------- 1 file changed, 25 deletions(-) diff --git a/src/checkers/inference/dataflow/InferenceTransfer.java b/src/checkers/inference/dataflow/InferenceTransfer.java index a13fe465..8ac9dfc1 100644 --- a/src/checkers/inference/dataflow/InferenceTransfer.java +++ b/src/checkers/inference/dataflow/InferenceTransfer.java @@ -7,7 +7,6 @@ import org.checkerframework.dataflow.cfg.node.FieldAccessNode; import org.checkerframework.dataflow.cfg.node.LocalVariableNode; import org.checkerframework.dataflow.cfg.node.Node; -import org.checkerframework.dataflow.cfg.node.StringConcatenateAssignmentNode; import org.checkerframework.dataflow.cfg.node.TernaryExpressionNode; import org.checkerframework.framework.flow.CFStore; import org.checkerframework.framework.flow.CFTransfer; @@ -176,30 +175,6 @@ public TransferResult visitAssignment(AssignmentNode assignmen } } - @Override - public TransferResult visitStringConcatenateAssignment(StringConcatenateAssignmentNode assignmentNode, TransferInput transferInput) { - // TODO: CompoundAssigment trees are not refined, see Issue 9 - CFStore store = transferInput.getRegularStore(); - - Tree targetTree = assignmentNode.getLeftOperand().getTree(); - - // Code for geting the ATM is copied from visitCompoundAssigment. - AnnotatedTypeMirror atm; - if (targetTree != null) { - // Try to use the target tree if possible. - // Getting the Type of a tree for a desugared compound assignment returns a comb variable - // which is not what we want to make a refinement variable of. - atm = typeFactory.getAnnotatedType(targetTree); - } else { - // Target trees can be null for refining library fields. - atm = typeFactory.getAnnotatedType(assignmentNode.getTree()); - } - - CFValue result = analysis.createAbstractValue(atm); - return new RegularTransferResult(finishValue(result, store), store); - - } - /** * Create a refinement variable for atm type. This inserts the refinement variable * into the store as the value for the lhs cfg node. From 8c25e92f563d695c02b00fd51e20a0a224c9a2fc Mon Sep 17 00:00:00 2001 From: Werner Dietl Date: Wed, 6 Apr 2022 16:54:49 -0400 Subject: [PATCH 2/6] Update stubparser reference --- scripts/inference-dev | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/inference-dev b/scripts/inference-dev index b5088dbc..26137636 100755 --- a/scripts/inference-dev +++ b/scripts/inference-dev @@ -34,7 +34,7 @@ libDir="$cfiDir"/lib CFBuild="${cfDir}"/dataflow/"${classes}":"${cfDir}"/javacutil/"${classes}":"${cfDir}"/framework/"${classes}":"${cfDir}"/framework/"${resources}" CFBuild="${CFBuild}":"${cfDir}"/checker/"${classes}":"${cfDir}"/checker/"${resources}":"${annoToolsDir}"/scene-lib/bin -CFDepJars="${stubparserDir}"/javaparser-core/target/stubparser-3.24.0.jar:"${afuDir}"/annotation-file-utilities-all.jar +CFDepJars="${stubparserDir}"/javaparser-core/target/stubparser-3.24.2.jar:"${afuDir}"/annotation-file-utilities-all.jar # sanity check: ensure each jar in CFDepJars actually exists in the file system # total number of jars From 8f09aead6ec7a5fc038303441a703011db364e9f Mon Sep 17 00:00:00 2001 From: Werner Dietl Date: Thu, 12 May 2022 15:30:56 -0400 Subject: [PATCH 3/6] Enable Java 17 support --- .github/workflows/main.yml | 2 +- build.gradle | 15 ++ src/checkers/inference/InferenceLauncher.java | 14 ++ src/nninf/MapGetHeuristics.java | 6 +- src/nninf/Resolver2.java | 163 ------------------ 5 files changed, 33 insertions(+), 167 deletions(-) delete mode 100644 src/nninf/Resolver2.java diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c84d4cfc..5f906d16 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -14,7 +14,7 @@ jobs: fail-fast: false matrix: group: [ cfi-tests, downstream-ontology, downstream-security-demo, downstream-universe ] - jdk: [ 8, 11 ] + jdk: [ 8, 11, 17 ] runs-on: ubuntu-latest steps: - name: Install dependencies diff --git a/build.gradle b/build.gradle index 9b7b1ad2..a24be306 100644 --- a/build.gradle +++ b/build.gradle @@ -22,6 +22,20 @@ ext { isJava8 = JavaVersion.current() == JavaVersion.VERSION_1_8 errorproneJavacVersion = '9+181-r4173-1' + + // Keep in sync with checker-framework/build.gradle. + // TODO: find a way to directly use that variable. + compilerArgsForRunningCF = [ + "--add-exports", "jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED", + "--add-exports", "jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED", + "--add-exports", "jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED", + "--add-exports", "jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED", + "--add-exports", "jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED", + "--add-exports", "jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED", + "--add-exports", "jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED", + "--add-exports", "jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED", + "--add-opens", "jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED", + ] } println '====================================' @@ -134,6 +148,7 @@ test { // Without this, the test throw "java.lang.OutOfMemoryError: Java heap space" // Corresponding pull request: https://github.com/opprop/checker-framework-inference/pull/263 forkEvery(1) + jvmArgs += compilerArgsForRunningCF } testLogging { diff --git a/src/checkers/inference/InferenceLauncher.java b/src/checkers/inference/InferenceLauncher.java index 6162bdcb..4908d34e 100644 --- a/src/checkers/inference/InferenceLauncher.java +++ b/src/checkers/inference/InferenceLauncher.java @@ -3,6 +3,7 @@ import org.checkerframework.framework.util.CheckerMain; import org.checkerframework.framework.util.ExecUtil; +import org.checkerframework.javacutil.SystemUtil; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; @@ -165,6 +166,19 @@ public void infer() { argList.add("-Xbootclasspath/p:" + bcp); } + if (SystemUtil.getJreVersion() > 8) { + // Keep in sync with build.gradle + argList.addAll(Arrays.asList("--add-exports", "jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED", + "--add-exports", "jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED", + "--add-exports", "jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED", + "--add-exports", "jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED", + "--add-exports", "jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED", + "--add-exports", "jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED", + "--add-exports", "jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED", + "--add-exports", "jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED", + "--add-opens", "jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED")); + } + argList.add("-classpath"); argList.add(getInferenceRuntimeClassPath()); diff --git a/src/nninf/MapGetHeuristics.java b/src/nninf/MapGetHeuristics.java index 80781eb4..b85a6987 100644 --- a/src/nninf/MapGetHeuristics.java +++ b/src/nninf/MapGetHeuristics.java @@ -5,6 +5,7 @@ import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType; import org.checkerframework.javacutil.AnnotationUtils; import org.checkerframework.javacutil.ElementUtils; +import org.checkerframework.javacutil.Resolver; import org.checkerframework.javacutil.TreeUtils; import java.util.List; @@ -65,7 +66,6 @@ private final ProcessingEnvironment env; private final NninfAnnotatedTypeFactory factory; private final AnnotatedTypeFactory keyForFactory; - private final Resolver2 resolver; private final ExecutableElement mapGet; @@ -75,7 +75,6 @@ public MapGetHeuristics(ProcessingEnvironment env, this.env = env; this.factory = factory; this.keyForFactory = keyForFactory; - this.resolver = new Resolver2(env); mapGet = TreeUtils.getMethod("java.util.Map", "get", 1, env); } @@ -139,7 +138,8 @@ private boolean keyForInMap(ExpressionTree key, List maps = AnnotationUtils.getElementValueArray(anno, factory.keyForValueElement, String.class); for (String map: maps) { - Element elt = resolver.findVariable(map, path); + // TODO: this whole class should be re-implemented + Element elt = null; // resolver.findVariable(map, path); if (elt != null && elt.equals(mapElement) && !isSiteRequired(TreeUtils.getReceiverTree((ExpressionTree)path.getLeaf()), elt)) { diff --git a/src/nninf/Resolver2.java b/src/nninf/Resolver2.java deleted file mode 100644 index f5a3ec5f..00000000 --- a/src/nninf/Resolver2.java +++ /dev/null @@ -1,163 +0,0 @@ -package nninf; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -import javax.annotation.processing.ProcessingEnvironment; -import javax.lang.model.element.Element; - -import org.checkerframework.javacutil.BugInCF; - -import com.sun.source.util.TreePath; -import com.sun.source.util.Trees; -import com.sun.tools.javac.api.JavacScope; -import com.sun.tools.javac.code.Kinds.Kind; -import com.sun.tools.javac.code.Kinds.KindSelector; -import com.sun.tools.javac.code.Symbol; -import com.sun.tools.javac.code.Symbol.*; -import com.sun.tools.javac.code.Type; -import com.sun.tools.javac.comp.AttrContext; -import com.sun.tools.javac.comp.Env; -import com.sun.tools.javac.comp.Resolve; -import com.sun.tools.javac.processing.JavacProcessingEnvironment; -import com.sun.tools.javac.util.Context; -import com.sun.tools.javac.util.Name; -import com.sun.tools.javac.util.Names; - -/** - * A Utility class to find symbols corresponding to string references - * - * TODO: This class is only supposed to be used temporarily until a good solution for the MapGetHeuristic is found. - */ -public class Resolver2 { - private final Resolve resolve; - private final Names names; - private final Trees trees; - - private final Method FIND_IDENT; - private final Method FIND_IDENT_IN_PACKAGE; - private final Method FIND_MEMBER_TYPE; - private final Method FIND_IDENT_IN_TYPE; - - public Resolver2(ProcessingEnvironment env) { - Context context = ((JavacProcessingEnvironment)env).getContext(); - this.resolve = Resolve.instance(context); - this.names = Names.instance(context); - this.trees = Trees.instance(env); - Method fi, fiip, fmt, fiit; - fi = fiip = fmt = fiit = null; - try { - fi = Resolve.class.getDeclaredMethod( - "findIdent", - Env.class, Name.class, KindSelector.class); - fi.setAccessible(true); - - fiip = Resolve.class.getDeclaredMethod( - "findIdentInPackage", - Env.class, TypeSymbol.class, Name.class, KindSelector.class); - fiip.setAccessible(true); - - fmt = Resolve.class.getDeclaredMethod( - "findMemberType", - Env.class, - Type.class, - Name.class, - TypeSymbol.class); - fmt.setAccessible(true); - - fiit = Resolve.class.getDeclaredMethod( - "findIdentInType", - Env.class, Type.class, Name.class, KindSelector.class); - fiit.setAccessible(true); - } catch (Exception e) { - throw new BugInCF("Compiler 'Resolve' class doesn't contain required 'findXXX' method", e); - // Need the local fi, fiip, fmt, and fiit variables to keep def assignment happy - } - this.FIND_IDENT = fi; - this.FIND_IDENT_IN_PACKAGE = fiip; - this.FIND_MEMBER_TYPE = fmt; - this.FIND_IDENT_IN_TYPE = fiit; - } - - /** - * Finds the variable referenced in the passed {@code String}. - * - * This method may only operate on variable references, e.g. local - * variables, parameters, fields. - * - * The reference string may be either an single Java identifier (e.g. "field") - * or dot-separated identifiers (e.g. "Collections.EMPTY_LIST"). - * - * The method adheres to all the rules of Java's scoping (while also - * considering the imports) for name resolution. - * - * @param reference the variable reference string - * @param path the tree path to the local scope - * @return the variable reference - */ - public Element findVariable(String reference, TreePath path) { - JavacScope scope = (JavacScope) trees.getScope(path); - Env env = scope.getEnv(); - - if (!reference.contains(".")) { - // Simple variable - return wrapInvocation( - FIND_IDENT, - env, names.fromString(reference), KindSelector.VAR); - } else { - int lastDot = reference.lastIndexOf('.'); - String expr = reference.substring(0, lastDot); - String name = reference.substring(lastDot + 1); - - Element site = findType(expr, env); - Name ident = names.fromString(name); - - return wrapInvocation( - FIND_IDENT_IN_TYPE, - env, site.asType(), ident, KindSelector.VAR); - } - - } - - private Element findType(String reference, Env env) { - if (!reference.contains(".")) { - // Simple variable - return wrapInvocation( - FIND_IDENT, - env, names.fromString(reference), KindSelector.of(KindSelector.TYP, KindSelector.PCK)); - } else { - int lastDot = reference.lastIndexOf("."); - String expr = reference.substring(0, lastDot); - String idnt = reference.substring(lastDot + 1); - - Symbol site = (Symbol)findType(expr, env); - if (site.kind == Kind.ERR) { - return site; - } - Name name = names.fromString(idnt); - if (site.kind == Kind.PCK) { - env.toplevel.packge = (PackageSymbol)site; - return wrapInvocation( - FIND_IDENT_IN_PACKAGE, - env, site, name, KindSelector.of(KindSelector.TYP, KindSelector.PCK)); - } else { - env.enclClass.sym = (ClassSymbol)site; - return wrapInvocation( - FIND_MEMBER_TYPE, - env, site.asType(), name, site); - } - } - } - - private Symbol wrapInvocation(Method method, Object... args) { - try { - return (Symbol)method.invoke(resolve, args); - } catch (IllegalAccessException e) { - throw new BugInCF("Resolver.wrapInvocation: unexpected Reflection error", e); - } catch (IllegalArgumentException e) { - throw new BugInCF("Resolver.wrapInvocation: unexpected Reflection error", e); - } catch (InvocationTargetException e) { - throw new BugInCF("Resolver.wrapInvocation: unexpected Reflection error", e); - } - } -} From adafbc049e257b0f9ab9218bc01fa3f76666b54b Mon Sep 17 00:00:00 2001 From: Alex Liu Date: Mon, 6 Jun 2022 15:06:41 -0400 Subject: [PATCH 4/6] Keep ub/lb when calling removeAnnotation (#397) --- .../inference/ExistentialVariableInserter.java | 5 +++-- src/checkers/inference/util/InferenceUtil.java | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/checkers/inference/ExistentialVariableInserter.java b/src/checkers/inference/ExistentialVariableInserter.java index c7b9b66f..0d61038a 100644 --- a/src/checkers/inference/ExistentialVariableInserter.java +++ b/src/checkers/inference/ExistentialVariableInserter.java @@ -19,6 +19,7 @@ import checkers.inference.model.ConstraintManager; import checkers.inference.model.ExistentialVariableSlot; import checkers.inference.model.Slot; +import checkers.inference.util.InferenceUtil; /** * @@ -113,7 +114,7 @@ public void insert(final Slot potentialVariable, final AnnotatedTypeMirror typeU typeUse.addAnnotation(slotManager.getAnnotation(potentialVariable)); // now remove only the primary (which has already been propagated to the bounds by fixUpBoundAnnotations) - typeUse.removeAnnotation(potentialVarAnno); + InferenceUtil.removePrimaryTypeVariableAnnotation((AnnotatedTypeVariable) typeUse, potentialVarAnno); final InsertionVisitor insertionVisitor = new InsertionVisitor(potentialVariable, potentialVarAnno, mustExist); @@ -254,7 +255,7 @@ public Void visitNull_Null(AnnotatedNullType type1, AnnotatedNullType type2, Voi @Override public Void visitTypevar_Typevar(AnnotatedTypeVariable type1, AnnotatedTypeVariable type2, Void aVoid) { if (matchesSlot(type1)) { - type1.removeAnnotation(potentialVarAnno); + InferenceUtil.removePrimaryTypeVariableAnnotation(type1, potentialVarAnno); } return super.visitTypevar_Typevar(type1, type2, aVoid); diff --git a/src/checkers/inference/util/InferenceUtil.java b/src/checkers/inference/util/InferenceUtil.java index a985ce67..cbedb516 100644 --- a/src/checkers/inference/util/InferenceUtil.java +++ b/src/checkers/inference/util/InferenceUtil.java @@ -44,6 +44,20 @@ public static Set clearAnnos(final AnnotatedTypeMirror atm) { return oldAnnos; } + /** + * TODO: This method is similar to the code in https://github.com/eisop/checker-framework + * /blob/6f12277290642f8fb89a5c614b31fe419eb0a7b1/framework/src/main/java/ + * org/checkerframework/framework/type/DefaultInferredTypesApplier.java#L134, + * it should be cleaned up when the code of this link is improved. + */ + public static void removePrimaryTypeVariableAnnotation(AnnotatedTypeVariable atv, AnnotationMirror potentialVarAnno) { + AnnotationMirror ub = atv.getUpperBound().getAnnotationInHierarchy(potentialVarAnno); + AnnotationMirror lb = atv.getLowerBound().getAnnotationInHierarchy(potentialVarAnno); + atv.removeAnnotation(potentialVarAnno); + atv.getUpperBound().addAnnotation(ub); + atv.getLowerBound().addAnnotation(lb); + } + /** * If the given condition isn't true throw an illegal argument exception with the given message */ From c3e006692a910d52c7d172c81a2c226fe6ae4e9e Mon Sep 17 00:00:00 2001 From: Alex Liu Date: Mon, 13 Jun 2022 10:53:23 -0400 Subject: [PATCH 5/6] Only set non-null bound annotations (#401) --- src/checkers/inference/util/InferenceUtil.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/checkers/inference/util/InferenceUtil.java b/src/checkers/inference/util/InferenceUtil.java index cbedb516..8d59c43e 100644 --- a/src/checkers/inference/util/InferenceUtil.java +++ b/src/checkers/inference/util/InferenceUtil.java @@ -54,8 +54,12 @@ public static void removePrimaryTypeVariableAnnotation(AnnotatedTypeVariable atv AnnotationMirror ub = atv.getUpperBound().getAnnotationInHierarchy(potentialVarAnno); AnnotationMirror lb = atv.getLowerBound().getAnnotationInHierarchy(potentialVarAnno); atv.removeAnnotation(potentialVarAnno); - atv.getUpperBound().addAnnotation(ub); - atv.getLowerBound().addAnnotation(lb); + if (ub != null) { + atv.getUpperBound().addAnnotation(ub); + } + if (lb != null) { + atv.getLowerBound().addAnnotation(lb); + } } /** From a3c710662ae9fb319834b419f7ae9bf90564e601 Mon Sep 17 00:00:00 2001 From: Werner Dietl Date: Sat, 18 Jun 2022 21:23:04 -0400 Subject: [PATCH 6/6] Suppress deprecation warning --- src/checkers/inference/InferenceAnnotatedTypeFactory.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/checkers/inference/InferenceAnnotatedTypeFactory.java b/src/checkers/inference/InferenceAnnotatedTypeFactory.java index a25df78d..293c5859 100644 --- a/src/checkers/inference/InferenceAnnotatedTypeFactory.java +++ b/src/checkers/inference/InferenceAnnotatedTypeFactory.java @@ -378,6 +378,7 @@ public ParameterizedExecutableType constructorFromUse(final NewClassTree newClas "Current path:\n" + getVisitorTreePath(); final ExecutableElement constructorElem = TreeUtils.constructor(newClassTree);; + @SuppressWarnings("deprecation") // TODO final AnnotatedTypeMirror constructorReturnType = fromNewClass(newClassTree); addComputedTypeAnnotations(newClassTree, constructorReturnType);