All Downloads are FREE. Search and download functionalities are using the official Maven repository.

checker.src.org.checkerframework.checker.signedness.SignednessVisitor Maven / Gradle / Ivy

Go to download

The Checker Framework enhances Java's type system to make it more powerful and useful. This lets software developers detect and prevent errors in their Java programs. The Checker Framework includes compiler plug-ins ("checkers") that find bugs or verify their absence. It also permits you to write your own compiler plug-ins.

There is a newer version: 3.43.0
Show newest version
package org.checkerframework.checker.signedness;

import com.sun.source.tree.BinaryTree;
import com.sun.source.tree.CompoundAssignmentTree;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.Tree.Kind;
import org.checkerframework.checker.signedness.qual.Signed;
import org.checkerframework.checker.signedness.qual.Unsigned;
import org.checkerframework.common.basetype.BaseTypeChecker;
import org.checkerframework.common.basetype.BaseTypeVisitor;
import org.checkerframework.framework.source.Result;
import org.checkerframework.framework.type.AnnotatedTypeMirror;

/**
 * The SignednessVisitor enforces the Signedness Checker rules. These rules
 * are described in detail in the Checker Framework Manual.
 *
 * @checker_framework.manual #signedness-checker Signedness Checker
 */
public class SignednessVisitor extends BaseTypeVisitor {

    public SignednessVisitor(BaseTypeChecker checker) {
        super(checker);
    }

    /**
     * Enforces the following rules on binary operations involving Unsigned and
     * Signed types:
     * 
    *
  • Do not allow any Unsigned types in {@literal {/, %}} operations.
  • *
  • Do not allow signed right shift {@literal {>>}} on an Unsigned type.
  • *
  • Do not allow unsigned right shift {@literal {>>>}} on a Signed type.
  • *
  • Allow any left shift {@literal {<<}}.
  • *
  • Do not allow non-equality comparisons {@literal {<, <=, >, >=}} on Unsigned types.
  • *
  • Do not allow the mixing of Signed and Unsigned types.
  • *
*/ @Override public Void visitBinary(BinaryTree node, Void p) { ExpressionTree leftOp = node.getLeftOperand(); ExpressionTree rightOp = node.getRightOperand(); AnnotatedTypeMirror leftOpType = atypeFactory.getAnnotatedType(leftOp); AnnotatedTypeMirror rightOpType = atypeFactory.getAnnotatedType(rightOp); Kind kind = node.getKind(); switch (kind) { case DIVIDE: case REMAINDER: if (leftOpType.hasAnnotation(Unsigned.class)) { checker.report(Result.failure("operation.unsignedlhs", kind), leftOp); } else if (rightOpType.hasAnnotation(Unsigned.class)) { checker.report(Result.failure("operation.unsignedrhs", kind), rightOp); } break; case RIGHT_SHIFT: if (leftOpType.hasAnnotation(Unsigned.class)) { checker.report(Result.failure("shift.signed", kind), leftOp); } break; case UNSIGNED_RIGHT_SHIFT: if (leftOpType.hasAnnotation(Signed.class)) { checker.report(Result.failure("shift.unsigned", kind), leftOp); } break; case LEFT_SHIFT: break; case GREATER_THAN: case GREATER_THAN_EQUAL: case LESS_THAN: case LESS_THAN_EQUAL: if (leftOpType.hasAnnotation(Unsigned.class)) { checker.report(Result.failure("comparison.unsignedlhs"), leftOp); } else if (rightOpType.hasAnnotation(Unsigned.class)) { checker.report(Result.failure("comparison.unsignedrhs"), rightOp); } break; case EQUAL_TO: case NOT_EQUAL_TO: if (leftOpType.hasAnnotation(Unsigned.class) && rightOpType.hasAnnotation(Signed.class)) { checker.report(Result.failure("comparison.mixed.unsignedlhs"), node); } else if (leftOpType.hasAnnotation(Signed.class) && rightOpType.hasAnnotation(Unsigned.class)) { checker.report(Result.failure("comparison.mixed.unsignedrhs"), node); } break; default: if (leftOpType.hasAnnotation(Unsigned.class) && rightOpType.hasAnnotation(Signed.class)) { checker.report(Result.failure("operation.mixed.unsignedlhs", kind), node); } else if (leftOpType.hasAnnotation(Signed.class) && rightOpType.hasAnnotation(Unsigned.class)) { checker.report(Result.failure("operation.mixed.unsignedrhs", kind), node); } break; } return super.visitBinary(node, p); } /** * @return a string representation of kind, with trailing _ASSIGNMENT stripped off if any. */ private String kindWithOutAssignment(Kind kind) { String result = kind.toString(); if (result.endsWith("_ASSIGNMENT")) { return result.substring(0, result.length() - "_ASSIGNMENT".length()); } else { return result; } } /** * Enforces the following rules on compound assignments involving Unsigned and * Signed types: *
    *
  • Do not allow any Unsigned types in {@literal {/=, %=}} assignments.
  • *
  • Do not allow signed right shift {@literal {>>=}} to assign to an Unsigned type.
  • *
  • Do not allow unsigned right shift {@literal {>>>=}} to assign to a Signed type.
  • *
  • Allow any left shift {@literal {<<=}} assignment.
  • *
  • Do not allow mixing of Signed and Unsigned types.
  • *
*/ @Override public Void visitCompoundAssignment(CompoundAssignmentTree node, Void p) { ExpressionTree var = node.getVariable(); ExpressionTree expr = node.getExpression(); AnnotatedTypeMirror varType = atypeFactory.getAnnotatedType(var); AnnotatedTypeMirror exprType = atypeFactory.getAnnotatedType(expr); Kind kind = node.getKind(); switch (kind) { case DIVIDE_ASSIGNMENT: case REMAINDER_ASSIGNMENT: if (varType.hasAnnotation(Unsigned.class)) { checker.report( Result.failure( "compound.assignment.unsigned.variable", kindWithOutAssignment(kind)), var); } else if (exprType.hasAnnotation(Unsigned.class)) { checker.report( Result.failure( "compound.assignment.unsigned.expression", kindWithOutAssignment(kind)), expr); } break; case RIGHT_SHIFT_ASSIGNMENT: if (varType.hasAnnotation(Unsigned.class)) { checker.report( Result.failure( "compound.assignment.shift.signed", kindWithOutAssignment(kind), "unsigned"), var); } break; case UNSIGNED_RIGHT_SHIFT_ASSIGNMENT: if (varType.hasAnnotation(Signed.class)) { checker.report( Result.failure( "compound.assignment.shift.unsigned", kindWithOutAssignment(kind), "signed"), var); } break; case LEFT_SHIFT_ASSIGNMENT: break; default: if (varType.hasAnnotation(Unsigned.class) && exprType.hasAnnotation(Signed.class)) { checker.report( Result.failure( "compound.assignment.mixed.unsigned.variable", kindWithOutAssignment(kind)), expr); } else if (varType.hasAnnotation(Signed.class) && exprType.hasAnnotation(Unsigned.class)) { checker.report( Result.failure( "compound.assignment.mixed.unsigned.expression", kindWithOutAssignment(kind)), expr); } break; } return super.visitCompoundAssignment(node, p); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy