/******************************************************************************* * Copyright (c) 2004, 2016 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) * Nathan Ridge *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp; import org.eclipse.cdt.core.dom.ILinkage; import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; import org.eclipse.cdt.core.dom.ast.IASTDeclaration; import org.eclipse.cdt.core.dom.ast.IASTDeclarator; import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; import org.eclipse.cdt.core.dom.ast.IASTInitializer; 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.IBinding; import org.eclipse.cdt.core.dom.ast.IScope; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IValue; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTParameterDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameterPackType; import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.internal.core.dom.Linkage; import org.eclipse.cdt.internal.core.dom.parser.ASTNode; import org.eclipse.cdt.internal.core.dom.parser.ASTQueries; import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil; import org.eclipse.core.runtime.PlatformObject; /** * Binding for a c++ function parameter. */ public class CPPParameter extends PlatformObject implements ICPPParameter, ICPPInternalBinding, ICPPTwoPhaseBinding { public static class CPPParameterProblem extends ProblemBinding implements ICPPParameter { public CPPParameterProblem(IASTNode node, int id, char[] arg) { super(node, id, arg); } } private IType fType; private IASTName[] fDeclarations; private int fPosition; public CPPParameter(IASTName name, int pos) { this.fDeclarations = new IASTName[] { name }; fPosition= pos; } public CPPParameter(IType type, int pos) { this.fType = type; fPosition= pos; } @Override public boolean isParameterPack() { return getType() instanceof ICPPParameterPackType; } @Override public IASTNode[] getDeclarations() { return fDeclarations; } @Override public IASTNode getDefinition() { return null; } @Override public void addDeclaration(IASTNode node) { if (!(node instanceof IASTName)) return; IASTName name = (IASTName) node; if (fDeclarations == null || fDeclarations.length == 0) { fDeclarations = new IASTName[] { name }; } else { if (isDeclaredBefore((ASTNode) node, (ASTNode) fDeclarations[0])) { fDeclarations = ArrayUtil.prepend(IASTName.class, fDeclarations, name); } else { fDeclarations = ArrayUtil.append(IASTName.class, fDeclarations, name); } } } private boolean isDeclaredBefore(ASTNode n1, ASTNode n2) { if (n1.getLength() == 0) return false; if (n2.getLength() == 0) return true; return n1.getOffset() < n2.getOffset(); } private IASTName getPrimaryDeclaration() { if (fDeclarations != null) { for (int i = 0; i < fDeclarations.length && fDeclarations[i] != null; i++) { IASTNode node = fDeclarations[i].getParent(); while (!(node instanceof IASTDeclaration)) node = node.getParent(); if (node instanceof IASTFunctionDefinition) return fDeclarations[i]; } return fDeclarations[0]; } return null; } @Override public String getName() { return new String(getNameCharArray()); } @Override public char[] getNameCharArray() { IASTName name = getPrimaryDeclaration(); if (name != null) return name.getSimpleID(); return CharArrayUtils.EMPTY; } @Override public IScope getScope() { return CPPVisitor.getContainingScope(getPrimaryDeclaration()); } public IASTNode getPhysicalNode() { if (fDeclarations != null) return fDeclarations[0]; return null; } @Override public IType getType() { if (fType == null && fDeclarations != null) { IASTNode parent= fDeclarations[0].getParent(); while (parent != null) { if (parent instanceof ICPPASTParameterDeclaration) { fType= CPPVisitor.createType((ICPPASTParameterDeclaration) parent, false); break; } parent= parent.getParent(); } } return fType; } @Override public boolean isStatic() { return false; } @Override public String[] getQualifiedName() { return new String[] { getName() }; } @Override public char[][] getQualifiedNameCharArray() { return new char[][] { getNameCharArray() }; } @Override public boolean isGloballyQualified() { return false; } @Override public void addDefinition(IASTNode node) { addDeclaration(node); } @Override public boolean isExtern() { // 7.1.1-5 extern can not be used in the declaration of a parameter return false; } @Override public boolean isMutable() { // 7.1.1-8 mutable can only apply to class members return false; } @Override public boolean isConstexpr() { return false; } @Override public boolean isAuto() { return hasStorageClass(IASTDeclSpecifier.sc_auto); } @Override public boolean isRegister() { return hasStorageClass(IASTDeclSpecifier.sc_register); } public boolean hasStorageClass(int storage) { IASTNode[] ns = getDeclarations(); if (ns == null) return false; for (int i = 0; i < ns.length && ns[i] != null; i++) { IASTNode parent = ns[i].getParent(); while (parent != null && !(parent instanceof IASTParameterDeclaration)) parent = parent.getParent(); if (parent != null) { IASTDeclSpecifier declSpec = ((IASTParameterDeclaration) parent).getDeclSpecifier(); if (declSpec.getStorageClass() == storage) return true; } } return false; } public IASTInitializer getInitializer() { if (fDeclarations == null) return null; for (int i = 0; i < fDeclarations.length && fDeclarations[i] != null; i++) { IASTNode parent = fDeclarations[i].getParent(); while (parent.getPropertyInParent() == IASTDeclarator.NESTED_DECLARATOR) parent = parent.getParent(); IASTInitializer init = ((IASTDeclarator) parent).getInitializer(); if (init != null) return init; } return null; } @Override public boolean hasDefaultValue() { return getInitializer() != null; } @Override public IValue getDefaultValue() { IASTInitializer init = getInitializer(); if (init != null) { return SemanticUtil.getValueOfInitializer(init, getType()); } return null; } @Override public ILinkage getLinkage() { return Linkage.CPP_LINKAGE; } @Override public boolean isExternC() { return false; } @Override public String toString() { String name = getName(); return name.length() != 0 ? name : "<unnamed>"; //$NON-NLS-1$ } @Override public IBinding getOwner() { IASTFunctionDeclarator decl = ASTQueries.findAncestorWithType(fDeclarations[0], IASTFunctionDeclarator.class); if (decl == null) return null; IASTName name= decl.getName(); return name != null ? name.resolveBinding() : null; } @Override public IValue getInitialValue() { return null; } @Override public IBinding resolveFinalBinding(CPPASTNameBase name) { // Check if the binding has been updated. IBinding current= name.getPreBinding(); if (current != this) return current; IASTNode node= getPrimaryDeclaration(); while (node != null && !(node instanceof IASTFunctionDeclarator)) { node= node.getParent(); } if (node instanceof IASTFunctionDeclarator) { IASTName funcName= ASTQueries.findInnermostDeclarator((IASTFunctionDeclarator) node).getName(); IBinding b= funcName.resolvePreBinding(); if (b instanceof ICPPInternalFunction) { return ((ICPPInternalFunction) b).resolveParameter(this); } } return this; } public int getParameterPosition() { return fPosition; } }