/******************************************************************************* * Copyright (c) 2002 - 2006 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.analysis.typeInference; import com.ibm.wala.classLoader.IClass; import com.ibm.wala.types.TypeReference; import com.ibm.wala.util.debug.Assertions; /** * Represents a single concrete type. */ public class PointType extends TypeAbstraction { private final IClass type; /** * @throws IllegalArgumentException if type is null */ public PointType(IClass type) { if (type == null) { throw new IllegalArgumentException("type is null"); } this.type = type; assert type.getReference().isReferenceType(); } @Override public TypeAbstraction meet(TypeAbstraction rhs) { if (rhs == TOP) { return this; } else { if (rhs instanceof PointType) { PointType other = (PointType) rhs; if (type.equals(other.type)) { return this; } else if (type.isArrayClass() || other.type.isArrayClass()) { // give up on arrays. We don't care anyway. return new ConeType(type.getClassHierarchy().getRootClass()); } else { return new ConeType(type.getClassHierarchy().getLeastCommonSuperclass(this.type, other.type)); } } else if (rhs instanceof ConeType) { ConeType other = (ConeType) rhs; if (type.equals(other.getType())) { // "this" and the cone type have the same underlying type, return the cone type return other; } TypeReference T = other.getType().getReference(); if (type.isArrayClass() || T.isArrayType()) { // give up on arrays. We don't care anyway. return new ConeType(type.getClassHierarchy().getRootClass()); } IClass typeKlass = type; if (type.getClassHierarchy().isSubclassOf(typeKlass, other.getType())) { return other; } else if (other.isInterface()) { if (type.getClassHierarchy().implementsInterface(typeKlass, other.getType())) { return other; } } // if we get here, we need to do cha-based superclass and return a cone. // TODO: avoid the allocation return other.meet(new ConeType(this.getType())); } else { Assertions.UNREACHABLE("Unexpected type: " + rhs.getClass()); return null; } } } @Override public String toString() { return "point: " + type.toString(); } @Override public IClass getType() { return type; } @Override public TypeReference getTypeReference() { return type.getReference(); } @Override public boolean equals(Object obj) { if (!(obj instanceof PointType)) { return false; } PointType other = (PointType) obj; if (!type.getClassHierarchy().equals(other.type.getClassHierarchy())) { Assertions.UNREACHABLE("different chas " + this + " " + other); } return type.equals(other.type); } @Override public int hashCode() { return 37 * type.hashCode(); } public boolean isArrayType() { return getType().isArrayClass(); } public IClass getIClass() { return type; } }