/****************************************************************************** * Copyright (c) 2002 - 2014 IBM Corporation. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *****************************************************************************/ package com.ibm.wala.cfg.exc.intra; import java.util.HashMap; import java.util.Map.Entry; import java.util.Set; import com.ibm.wala.cfg.exc.intra.NullPointerState.State; import com.ibm.wala.classLoader.IMethod; import com.ibm.wala.fixpoint.AbstractVariable; /** * Encapsulates the state of all parameters of an invoked method * * @author markus * */ public class ParameterState extends AbstractVariable<ParameterState> { /* * Inital state is UNKNOWN. * Lattice: UNKNOWN < { NULL, NOT_NULL } < BOTH * * public enum State { UNKNOWN, BOTH, NULL, NOT_NULL }; as defined in NullPointerState * */ public static final int NO_THIS_PTR = -1; // maps the parmeter's varNum --> State private final HashMap<Integer, State> params = new HashMap<Integer, State>(); public static ParameterState createDefault(IMethod m) { ParameterState p = new ParameterState(); if (!m.isStatic()) { // set this pointer to NOT_NULL p.setState(0, State.NOT_NULL); } return p; } public ParameterState() { } /** * Constructor to make a <code>ParameteState</code> out of a regular <code>NullPointerState</code>. * * @param state The <code>NullPointerState</code> to parse. * @param parameterNumbers The numbers of parameters in <code>state</code> */ public ParameterState(NullPointerState state, int[] parameterNumbers) { //by convention the first ssa vars are the parameters for (int i=1; i < parameterNumbers.length; i++){ params.put(i, state.getState(parameterNumbers[i])); } } public void setState(int varNum, State state) { State prev = params.get(varNum); if (prev != null) { switch (prev) { case BOTH: if (state != State.BOTH) { throw new IllegalArgumentException("Try to set " + prev + " to " + state); } break; case NULL: if (!(state == State.BOTH || state == State.NULL)) { throw new IllegalArgumentException("Try to set " + prev + " to " + state); } break; case NOT_NULL: if (!(state == State.BOTH || state == State.NOT_NULL)) { throw new IllegalArgumentException("Try to set " + prev + " to " + state); } break; } } params.put(varNum, state); } public HashMap<Integer, State> getStates() { return this.params; } /** * Returns the state of an specified parameter. * * @param varNum The SSA var num of the parameter * @return the state of the parameter defined with <code>varNum</code> */ public State getState(int varNum) { State state = params.get(varNum); return (state == null ? State.UNKNOWN : state); } @Override public void copyState(ParameterState v) { throw new UnsupportedOperationException(); } /** * {@inheritDoc} */ @Override public String toString() { StringBuffer buf = new StringBuffer("<"); Set<Entry<Integer, State>> paramsSet = params.entrySet(); for (Entry<Integer, State> param : paramsSet){ switch (param.getValue()) { case BOTH: buf.append('*'); break; case NOT_NULL: buf.append('1'); break; case NULL: buf.append('0'); break; case UNKNOWN: buf.append('?'); break; default: throw new IllegalStateException(); } } buf.append('>'); return buf.toString(); } }