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

wyil.check.UnsafeCheck Maven / Gradle / Ivy

// Copyright 2011 The Whiley Project Developers
//
// Licensed 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 wyil.check;

import wyil.lang.Compiler;
import wyil.lang.WyilFile;
import wyil.lang.WyilFile.Decl;
import wyil.util.AbstractVisitor;
import wyc.util.ErrorMessages;
import static wyil.lang.WyilFile.*;

import wycc.lang.Syntactic;

/**
 * Responsible for ensuring that the unsafe modifier is used
 * correctly. For example, one cannot call an unsafe method or function from
 * within an unsafe method or function. Likewise, one cannot take the address of
 * an unsafe method or function (i.e. because we currently have no way to
 * specify a modifier on a lambda type).
 *
 * @author David J. Pearce
 *
 */
public class UnsafeCheck extends AbstractVisitor implements Compiler.Check {
	/**
	 * Strict mode requires that every method which calls an unsafe method is itself
	 * unsafe.
	 */
	private boolean status = true;

	@Override
	public boolean check(WyilFile file) {
		visitModule(file);
		return status;
	}

	@Override
	public void visitInvoke(Expr.Invoke expr) {
		Decl.Link name = expr.getLink();
		Decl.Named enclosing = expr.getAncestor(Decl.Named.class);
		//
		if(isUnsafe(name.getTarget()) && !isUnsafe(enclosing)) {
			syntaxError(expr, UNSAFECALL_NOT_PERMITTED);
		}
		super.visitInvoke(expr);
	}

	@Override
	public void visitLambdaAccess(Expr.LambdaAccess expr) {
		Decl.Link name = expr.getLink();
		// At the moment there is no way to specify a modifier on a function or method
		// type. Hence, we cannot ever take the address of such an unsafe function or
		// method as, otherwise, this would provide an easy way to circumvent the
		// protection.
		if(isUnsafe(name.getTarget())) {
			syntaxError(expr, UNSAFECALL_NOT_PERMITTED);
		}
		super.visitLambdaAccess(expr);
	}

	@Override
	public void visitStaticVariableAccess(Expr.StaticVariableAccess expr) {
		Decl.Link name = expr.getLink();
		Decl.Named enclosing = expr.getAncestor(Decl.Named.class);
		//
		if(isUnsafe(name.getTarget()) && !isUnsafe(enclosing)) {
			syntaxError(expr, UNSAFECALL_NOT_PERMITTED);
		}
		super.visitStaticVariableAccess(expr);
	}

	@Override
	public void visitType(Type type) {
		// NOTE: don't traverse types as this is unnecessary. Even in a pure context,
		// seemingly impure types (e.g. references and methods) can still be used
		// safely.
	}

	public boolean isUnsafe(Decl.Named named) {
		return named.getModifiers().match(Modifier.Unsafe.class) != null;
	}

	private void syntaxError(Syntactic.Item e, int code, Syntactic.Item... context) {
		status = false;
		ErrorMessages.syntaxError(e, code, context);
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy