/******************************************************************************* * Copyright (c) 2004, 2015 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) * Sergey Prigogin (Google) * Thomas Corbat (IFS) *******************************************************************************/ 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.ICPPASTExpression; 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.ICPPASTVirtSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTVirtSpecifier.SpecifierKind; 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; /** * Represents a function declarator. */ public class CPPASTFunctionDeclarator extends CPPASTDeclarator implements ICPPASTFunctionDeclarator { private ICPPASTParameterDeclaration[] parameters; private IASTTypeId[] typeIds = NO_EXCEPTION_SPECIFICATION; private ICPPASTExpression noexceptExpression; private IASTTypeId trailingReturnType; private ICPPASTVirtSpecifier[] virtSpecifiers = NO_VIRT_SPECIFIERS; private boolean varArgs; private boolean pureVirtual; private boolean isVolatile; private boolean isConst; private boolean isMutable; private RefQualifier refQualifier; private ICPPFunctionScope scope; 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(); copy.varArgs = varArgs; copy.pureVirtual = pureVirtual; copy.isVolatile = isVolatile; copy.isConst = isConst; copy.isMutable = isMutable; copy.refQualifier = refQualifier; 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 (noexceptExpression != null) { copy.setNoexceptExpression(noexceptExpression == NOEXCEPT_DEFAULT ? noexceptExpression : (ICPPASTExpression) noexceptExpression.copy(style)); } if (trailingReturnType != null) { copy.setTrailingReturnType(trailingReturnType.copy(style)); } for (ICPPASTVirtSpecifier virtSpecifier : getVirtSpecifiers()) { copy.addVirtSpecifier(virtSpecifier.copy(style)); } return copy(copy, style); } @Override public ICPPASTParameterDeclaration[] getParameters() { if (parameters == null) return ICPPASTParameterDeclaration.EMPTY_CPPPARAMETERDECLARATION_ARRAY; return parameters= ArrayUtil.trim(parameters); } @Override public void addParameterDeclaration(IASTParameterDeclaration parameter) { assertNotFrozen(); if (parameter != null) { parameter.setParent(this); parameter.setPropertyInParent(FUNCTION_PARAMETER); parameters = ArrayUtil.append(ICPPASTParameterDeclaration.class, parameters, (ICPPASTParameterDeclaration) parameter); } } @Override public boolean takesVarArgs() { return varArgs; } @Override public void setVarArgs(boolean value) { assertNotFrozen(); varArgs = value; } @Override public boolean isConst() { return isConst; } @Override public void setConst(boolean value) { assertNotFrozen(); this.isConst = value; } @Override public boolean isVolatile() { return isVolatile; } @Override public void setVolatile(boolean value) { assertNotFrozen(); this.isVolatile = value; } @Override public boolean isMutable() { return isMutable; } @Override public void setMutable(boolean value) { assertNotFrozen(); this.isMutable = value; } @Override public IASTTypeId[] getExceptionSpecification() { return typeIds= ArrayUtil.trim(typeIds); } @Override public void setEmptyExceptionSpecification() { assertNotFrozen(); typeIds= IASTTypeId.EMPTY_TYPEID_ARRAY; } @Override public void addExceptionSpecificationTypeId(IASTTypeId typeId) { assertNotFrozen(); if (typeId != null) { assert typeIds != null; typeIds = ArrayUtil.append(typeIds, typeId); typeId.setParent(this); typeId.setPropertyInParent(EXCEPTION_TYPEID); } } @Override public ICPPASTExpression getNoexceptExpression() { return noexceptExpression; } @Override public void setNoexceptExpression(ICPPASTExpression expression) { assertNotFrozen(); noexceptExpression = expression; if (expression != null && expression != NOEXCEPT_DEFAULT) { expression.setParent(this); expression.setPropertyInParent(NOEXCEPT_EXPRESSION); } } @Override public IASTTypeId getTrailingReturnType() { return trailingReturnType; } @Override public void setTrailingReturnType(IASTTypeId typeId) { assertNotFrozen(); trailingReturnType= typeId; if (typeId != null) { typeId.setParent(this); typeId.setPropertyInParent(TRAILING_RETURN_TYPE); } } @Override public boolean isPureVirtual() { return pureVirtual; } @Override public void setPureVirtual(boolean isPureVirtual) { assertNotFrozen(); this.pureVirtual = isPureVirtual; } @Override public RefQualifier getRefQualifier() { return refQualifier; } @Override public void setRefQualifier(RefQualifier value) { assertNotFrozen(); refQualifier = value; } @Override @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; } @Override @Deprecated public void addConstructorToChain(org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorChainInitializer initializer) { assertNotFrozen(); } @Override 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 (IASTTypeId id : ids) { if (!id.accept(action)) { return false; } } if (noexceptExpression != null && noexceptExpression != NOEXCEPT_DEFAULT) { if (!noexceptExpression.accept(action)) return false; } if (trailingReturnType != null && !trailingReturnType.accept(action)) return false; ICPPASTVirtSpecifier[] virtSpecifiers = getVirtSpecifiers(); for (ICPPASTVirtSpecifier virtSpecifier : virtSpecifiers) { if (!virtSpecifier.accept(action)) { return false; } } return super.postAccept(action); } @Override 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; } } } if (child == noexceptExpression) { other.setPropertyInParent(child.getPropertyInParent()); other.setParent(child.getParent()); noexceptExpression = (ICPPASTExpression) other; return; } assert false; } @Override public boolean isOverride() { for (ICPPASTVirtSpecifier virtSpecifier : getVirtSpecifiers()) { if (virtSpecifier.getKind() == SpecifierKind.Override) { return true; } } return false; } @Override public void setOverride(boolean value) { assertNotFrozen(); // Do nothing here. Use addVirtSpecifier() instead. } @Override public boolean isFinal() { for (ICPPASTVirtSpecifier virtSpecifier : getVirtSpecifiers()) { if (virtSpecifier.getKind() == SpecifierKind.Final) { return true; } } return false; } @Override public void setFinal(boolean value) { assertNotFrozen(); // Do nothing here. Use addVirtSpecifier() instead. } @Override public ICPPASTVirtSpecifier[] getVirtSpecifiers() { return virtSpecifiers = ArrayUtil.trim(virtSpecifiers); } @Override public void addVirtSpecifier(ICPPASTVirtSpecifier virtSpecifier) { assertNotFrozen(); if (virtSpecifier != null) { assert virtSpecifiers != null; virtSpecifiers = ArrayUtil.append(virtSpecifiers, virtSpecifier); virtSpecifier.setParent(this); virtSpecifier.setPropertyInParent(EXCEPTION_TYPEID); } } }