/******************************************************************************* * Copyright (c) 2004, 2011 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: * IBM - Initial API and implementation * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp; import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.IASTDeclaration; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration; import org.eclipse.cdt.core.dom.ast.IASTTypeId; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDefinition; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTParameterDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionScope; import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.internal.core.dom.parser.ASTQueries; import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent; /** * Represents a function declarator. */ public class CPPASTFunctionDeclarator extends CPPASTDeclarator implements ICPPASTFunctionDeclarator, IASTAmbiguityParent { private ICPPASTParameterDeclaration[] parameters = null; private IASTTypeId[] typeIds = NO_EXCEPTION_SPECIFICATION; private IASTTypeId trailingReturnType= null; private boolean varArgs; private boolean pureVirtual; private boolean isVolatile; private boolean isConst; private boolean isMutable; private ICPPFunctionScope scope = null; public CPPASTFunctionDeclarator() { } public CPPASTFunctionDeclarator(IASTName name) { super(name); } @Override public CPPASTFunctionDeclarator copy() { return copy(CopyStyle.withoutLocations); } @Override public CPPASTFunctionDeclarator copy(CopyStyle style) { CPPASTFunctionDeclarator copy = new CPPASTFunctionDeclarator(); copyBaseDeclarator(copy, style); copy.varArgs = varArgs; copy.pureVirtual = pureVirtual; copy.isVolatile = isVolatile; copy.isConst = isConst; copy.isMutable = isMutable; for (IASTParameterDeclaration param : getParameters()) copy.addParameterDeclaration(param == null ? null : param.copy(style)); for (IASTTypeId typeId : getExceptionSpecification()) copy.addExceptionSpecificationTypeId(typeId == null ? null : typeId.copy(style)); if (trailingReturnType != null) { copy.setTrailingReturnType(trailingReturnType.copy(style)); } if (style == CopyStyle.withLocations) { copy.setCopyLocation(this); } return copy; } public ICPPASTParameterDeclaration[] getParameters() { if (parameters == null) return ICPPASTParameterDeclaration.EMPTY_CPPPARAMETERDECLARATION_ARRAY; return parameters= ArrayUtil.trim(parameters); } public void addParameterDeclaration(IASTParameterDeclaration parameter) { assertNotFrozen(); if (parameter != null) { parameter.setParent(this); parameter.setPropertyInParent(FUNCTION_PARAMETER); parameters = (ICPPASTParameterDeclaration[]) ArrayUtil.append(ICPPASTParameterDeclaration.class, parameters, parameter); } } public boolean takesVarArgs() { return varArgs; } public void setVarArgs(boolean value) { assertNotFrozen(); varArgs = value; } public boolean isConst() { return isConst; } public void setConst(boolean value) { assertNotFrozen(); this.isConst = value; } public boolean isVolatile() { return isVolatile; } public void setVolatile(boolean value) { assertNotFrozen(); this.isVolatile = value; } public boolean isMutable() { return isMutable; } public void setMutable(boolean value) { assertNotFrozen(); this.isMutable = value; } public IASTTypeId[] getExceptionSpecification() { return typeIds= ArrayUtil.trim(typeIds); } public void setEmptyExceptionSpecification() { assertNotFrozen(); typeIds= IASTTypeId.EMPTY_TYPEID_ARRAY; } public void addExceptionSpecificationTypeId(IASTTypeId typeId) { assertNotFrozen(); if (typeId != null) { assert typeIds != null; typeIds = ArrayUtil.append(typeIds, typeId); typeId.setParent(this); typeId.setPropertyInParent(EXCEPTION_TYPEID); } } public IASTTypeId getTrailingReturnType() { return trailingReturnType; } public void setTrailingReturnType(IASTTypeId typeId) { assertNotFrozen(); trailingReturnType= typeId; if (typeId != null) { typeId.setParent(this); typeId.setPropertyInParent(TRAILING_RETURN_TYPE); } } public boolean isPureVirtual() { return pureVirtual; } public void setPureVirtual(boolean isPureVirtual) { assertNotFrozen(); this.pureVirtual = isPureVirtual; } @Deprecated public org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorChainInitializer[] getConstructorChain() { if (ASTQueries.findTypeRelevantDeclarator(this) == this) { IASTNode parent= getParent(); while(!(parent instanceof IASTDeclaration)) { if (parent == null) break; parent= parent.getParent(); } if (parent instanceof ICPPASTFunctionDefinition) { return ((ICPPASTFunctionDefinition) parent).getMemberInitializers(); } } return org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorChainInitializer.EMPTY_CONSTRUCTORCHAININITIALIZER_ARRAY; } @Deprecated public void addConstructorToChain(org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorChainInitializer initializer) { assertNotFrozen(); } public ICPPFunctionScope getFunctionScope() { if (scope != null) return scope; // introduce a scope for function declarations and definitions, only. IASTNode node= getParent(); while(!(node instanceof IASTDeclaration)) { if (node==null) return null; node= node.getParent(); } if (node instanceof IASTParameterDeclaration) return null; if (ASTQueries.findTypeRelevantDeclarator(this) == this) { scope = new CPPFunctionScope(this); } return scope; } @Override protected boolean postAccept(ASTVisitor action) { IASTParameterDeclaration[] params = getParameters(); for (int i = 0; i < params.length; i++) { if (!params[i].accept(action)) return false; } IASTTypeId[] ids = getExceptionSpecification(); for (int i = 0; i < ids.length; i++) { if (!ids[i].accept(action)) return false; } if (trailingReturnType != null && !trailingReturnType.accept(action)) return false; return super.postAccept(action); } public void replace(IASTNode child, IASTNode other) { if (parameters != null) { for (int i = 0; i < parameters.length; ++i) { if (child == parameters[i]) { other.setPropertyInParent(child.getPropertyInParent()); other.setParent(child.getParent()); parameters[i] = (ICPPASTParameterDeclaration) other; return; } } } assert false; } }