/******************************************************************************* * Copyright (c) 2004, 2010 IBM Corporation and others. * 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: * Andrew Niefer (IBM Corporation) - initial API and implementation * Markus Schorn (Wind River Systems) * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IProblemBinding; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.ITypedef; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer; import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding; import org.eclipse.core.runtime.Assert; /** * Specialization of a typedef in the context of a class-specialization. */ public class CPPTypedefSpecialization extends CPPSpecialization implements ITypedef, ITypeContainer { final static class RecursionResolvingBinding extends ProblemBinding { public RecursionResolvingBinding(IASTNode node, char[] arg) { super(node, IProblemBinding.SEMANTIC_RECURSION_IN_LOOKUP, arg); Assert.isTrue(CPPASTNameBase.sAllowRecursionBindings, getMessage()); } } public static final int MAX_RESOLUTION_DEPTH = 5; public static final int MAX_TYPE_NESTING = 60; private IType type; private int fResolutionDepth; public CPPTypedefSpecialization(IBinding specialized, ICPPClassType owner, ICPPTemplateParameterMap tpmap) { super(specialized, owner, tpmap); } private ITypedef getTypedef() { return (ITypedef) getSpecializedBinding(); } /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.ITypedef#getType() */ public IType getType() { return getType(MAX_TYPE_NESTING); } private IType getType(int maxDepth) { if (type == null) { try { if (++fResolutionDepth > MAX_RESOLUTION_DEPTH) { type = new RecursionResolvingBinding(getDefinition(), getNameCharArray()); } else { type= specializeType(getTypedef().getType()); // A typedef pointing to itself is a sure recipe for an infinite loop -- replace // with a problem binding. if (!verifyType(type, maxDepth)) { type = new RecursionResolvingBinding(getDefinition(), getNameCharArray()); } } } finally { --fResolutionDepth; } } return type; } private boolean verifyType(IType type, int maxTypeNesting) { for (;;) { if (--maxTypeNesting < 0) return false; if (equals(type)) return false; if (type instanceof CPPTypedefSpecialization) { type= ((CPPTypedefSpecialization) type).getType(maxTypeNesting); } else if (type instanceof ITypeContainer) { type= ((ITypeContainer) type).getType(); } else { return true; } } } public int incResolutionDepth(int increment) { fResolutionDepth += increment; return fResolutionDepth; } /* (non-Javadoc) * @see java.lang.Object#clone() */ @Override public Object clone() { IType t = null; try { t = (IType) super.clone(); } catch (CloneNotSupportedException e) { // not going to happen } return t; } /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.IType#isSameType(org.eclipse.cdt.core.dom.ast.IType) */ public boolean isSameType(IType o) { if (o == this) return true; if (o instanceof ITypedef) { IType t = getType(); if (t != null) return t.isSameType(((ITypedef) o).getType()); return false; } IType t = getType(); if (t != null) return t.isSameType(o); return false; } public void setType(IType type) { this.type = type; } }