| /******************************************************************************* |
| * Copyright (c) 2005, 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) - Initial API and implementation |
| * Bryan Wilkinson (QNX) |
| * Markus Schorn (Wind River Systems) |
| * Sergey Prigogin (Google) |
| * Nathan Ridge |
| *******************************************************************************/ |
| package org.eclipse.cdt.internal.core.dom.parser.cpp; |
| |
| import org.eclipse.cdt.core.dom.ast.ASTTypeUtil; |
| import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; |
| import org.eclipse.cdt.core.dom.ast.IASTDeclarator; |
| import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; |
| 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.IFunctionType; |
| import org.eclipse.cdt.core.dom.ast.IScope; |
| import org.eclipse.cdt.core.dom.ast.IType; |
| import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier; |
| 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.ICPPFunction; |
| import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionSpecialization; |
| import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType; |
| import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter; |
| import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; |
| import org.eclipse.cdt.core.index.IIndexBinding; |
| import org.eclipse.cdt.internal.core.dom.parser.ASTInternal; |
| import org.eclipse.cdt.internal.core.dom.parser.ASTQueries; |
| import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates; |
| import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; |
| |
| /** |
| * The specialization of a friend function in the context of a class specialization, |
| * also used as base class for function instances. |
| */ |
| public class CPPFunctionSpecialization extends CPPSpecialization implements ICPPFunctionSpecialization, |
| ICPPInternalFunction { |
| private final ICPPFunctionType fType; |
| private ICPPParameter[] fParams; |
| private final IType[] fExceptionSpecs; |
| |
| public CPPFunctionSpecialization(ICPPFunction orig, IBinding owner, ICPPTemplateParameterMap argMap, |
| ICPPFunctionType type, IType[] exceptionSpecs) { |
| super(orig, owner, argMap); |
| fType= type; |
| fExceptionSpecs= exceptionSpecs; |
| } |
| |
| private ICPPFunction getFunction() { |
| return (ICPPFunction) getSpecializedBinding(); |
| } |
| |
| public void setParameters(ICPPParameter[] params) { |
| assert fParams == null; |
| fParams = params; |
| } |
| |
| @Override |
| public ICPPParameter[] getParameters() { |
| return fParams; |
| } |
| |
| @Override |
| public int getRequiredArgumentCount() { |
| return CPPFunction.getRequiredArgumentCount(getParameters()); |
| } |
| |
| @Override |
| public boolean hasParameterPack() { |
| return CPPFunction.hasParameterPack(getParameters()); |
| } |
| |
| @Override |
| public IScope getFunctionScope() { |
| return null; |
| } |
| |
| @Override |
| public ICPPFunctionType getDeclaredType() { |
| return fType; |
| } |
| |
| @Override |
| public ICPPFunctionType getType() { |
| return fType; |
| } |
| |
| @Override |
| public boolean isMutable() { |
| return false; |
| } |
| |
| @Override |
| public boolean isInline() { |
| if (getDefinition() != null) { |
| IASTNode def = getDefinition(); |
| while (!(def instanceof IASTFunctionDefinition)) |
| def = def.getParent(); |
| return ((IASTFunctionDefinition) def).getDeclSpecifier().isInline(); |
| } |
| return getFunction().isInline(); |
| } |
| |
| @Override |
| public boolean isExternC() { |
| if (CPPVisitor.isExternC(getDefinition())) { |
| return true; |
| } |
| return getFunction().isExternC(); |
| } |
| |
| @Override |
| public boolean isStatic() { |
| return isStatic(true); |
| } |
| |
| @Override |
| public boolean isStatic(boolean resolveAll) { |
| //TODO resolveAll |
| IBinding f = getSpecializedBinding(); |
| if (f instanceof ICPPInternalFunction) |
| return ((ICPPInternalFunction) f).isStatic(resolveAll); |
| if (f instanceof IIndexBinding && f instanceof ICPPFunction) { |
| return ((ICPPFunction) f).isStatic(); |
| } |
| return CPPFunction.hasStorageClass(this, IASTDeclSpecifier.sc_static); |
| } |
| |
| @Override |
| public boolean isExtern() { |
| ICPPFunction f = (ICPPFunction) getSpecializedBinding(); |
| if (f != null) |
| return f.isExtern(); |
| return CPPFunction.hasStorageClass(this, IASTDeclSpecifier.sc_extern); |
| } |
| |
| @Override |
| public boolean isAuto() { |
| ICPPFunction f = (ICPPFunction) getSpecializedBinding(); |
| if (f != null) |
| return f.isAuto(); |
| return CPPFunction.hasStorageClass(this, IASTDeclSpecifier.sc_auto); |
| } |
| |
| @Override |
| public boolean isConstexpr() { |
| IASTNode def = getDefinition(); |
| if (def != null) { |
| ICPPASTFunctionDefinition functionDefinition = CPPFunction.getFunctionDefinition(def); |
| return ((ICPPASTDeclSpecifier) functionDefinition.getDeclSpecifier()).isConstexpr(); |
| } |
| IBinding f = getSpecializedBinding(); |
| if (f instanceof ICPPFunction) { |
| return ((ICPPFunction) f).isConstexpr(); |
| } |
| return false; |
| } |
| |
| @Override |
| public boolean isDeleted() { |
| IASTNode def = getDefinition(); |
| if (def != null) |
| return CPPFunction.isDeletedDefinition(def); |
| |
| IBinding f = getSpecializedBinding(); |
| if (f instanceof ICPPFunction) { |
| return ((ICPPFunction) f).isDeleted(); |
| } |
| return false; |
| } |
| |
| @Override |
| public boolean isRegister() { |
| ICPPFunction f = (ICPPFunction) getSpecializedBinding(); |
| if (f != null) |
| return f.isRegister(); |
| return CPPFunction.hasStorageClass(this, IASTDeclSpecifier.sc_register); |
| } |
| |
| @Override |
| public boolean takesVarArgs() { |
| ICPPFunction f = (ICPPFunction) getSpecializedBinding(); |
| if (f != null) |
| return f.takesVarArgs(); |
| |
| ICPPASTFunctionDeclarator dtor = (ICPPASTFunctionDeclarator) getDefinition(); |
| if (dtor != null) { |
| return dtor.takesVarArgs(); |
| } |
| ICPPASTFunctionDeclarator[] ds = (ICPPASTFunctionDeclarator[]) getDeclarations(); |
| if (ds != null && ds.length > 0) { |
| return ds[0].takesVarArgs(); |
| } |
| return false; |
| } |
| |
| @Override |
| public boolean isNoReturn() { |
| ICPPFunction f = (ICPPFunction) getSpecializedBinding(); |
| if (f != null) |
| return f.isNoReturn(); |
| return false; |
| } |
| |
| @Override |
| public IBinding resolveParameter(CPPParameter param) { |
| int pos= param.getParameterPosition(); |
| |
| final IASTNode[] decls= getDeclarations(); |
| int tdeclLen= decls == null ? 0 : decls.length; |
| for (int i= -1; i < tdeclLen; i++) { |
| ICPPASTFunctionDeclarator tdecl; |
| if (i == -1) { |
| tdecl= (ICPPASTFunctionDeclarator) getDefinition(); |
| if (tdecl == null) |
| continue; |
| } else if (decls != null) { |
| tdecl= (ICPPASTFunctionDeclarator) decls[i]; |
| if (tdecl == null) |
| break; |
| } else { |
| break; |
| } |
| |
| IASTParameterDeclaration[] params = tdecl.getParameters(); |
| if (pos < params.length) { |
| final IASTName oName = getParamName(params[pos]); |
| return oName.resolvePreBinding(); |
| } |
| } |
| return param; |
| } |
| |
| protected void updateFunctionParameterBindings(ICPPASTFunctionDeclarator fdtor) { |
| IASTParameterDeclaration[] updateParams = fdtor.getParameters(); |
| |
| int k= 0; |
| final IASTNode[] decls= getDeclarations(); |
| int tdeclLen= decls == null ? 0 : decls.length; |
| for (int i= -1; i < tdeclLen && k < updateParams.length; i++) { |
| ICPPASTFunctionDeclarator tdecl; |
| if (i == -1) { |
| tdecl= (ICPPASTFunctionDeclarator) getDefinition(); |
| if (tdecl == null) |
| continue; |
| } else if (decls != null) { |
| tdecl= (ICPPASTFunctionDeclarator) decls[i]; |
| if (tdecl == null) |
| break; |
| } else { |
| break; |
| } |
| |
| IASTParameterDeclaration[] params = tdecl.getParameters(); |
| int end= Math.min(params.length, updateParams.length); |
| for (; k < end; k++) { |
| final IASTName oName = getParamName(params[k]); |
| IBinding b= oName.resolvePreBinding(); |
| IASTName n = getParamName(updateParams[k]); |
| n.setBinding(b); |
| ASTInternal.addDeclaration(b, n); |
| } |
| } |
| } |
| |
| private IASTName getParamName(final IASTParameterDeclaration paramDecl) { |
| return ASTQueries.findInnermostDeclarator(paramDecl.getDeclarator()).getName(); |
| } |
| |
| private ICPPASTFunctionDeclarator extractFunctionDtor(IASTNode node) { |
| if (node instanceof IASTName) |
| node = node.getParent(); |
| if (!(node instanceof IASTDeclarator)) |
| return null; |
| node= ASTQueries.findTypeRelevantDeclarator((IASTDeclarator) node); |
| if (!(node instanceof ICPPASTFunctionDeclarator)) |
| return null; |
| |
| return (ICPPASTFunctionDeclarator) node; |
| } |
| |
| @Override |
| public void addDefinition(IASTNode node) { |
| ICPPASTFunctionDeclarator dtor = extractFunctionDtor(node); |
| if (dtor != null) { |
| updateFunctionParameterBindings(dtor); |
| super.addDefinition(dtor); |
| } |
| } |
| |
| @Override |
| public void addDeclaration(IASTNode node) { |
| ICPPASTFunctionDeclarator dtor = extractFunctionDtor(node); |
| if (dtor != null) { |
| updateFunctionParameterBindings(dtor); |
| super.addDeclaration(dtor); |
| } |
| } |
| |
| @Override |
| public String toString() { |
| StringBuilder result = new StringBuilder(); |
| result.append(getName()); |
| IFunctionType t = getType(); |
| result.append(t != null ? ASTTypeUtil.getParameterTypeString(t) : "()"); //$NON-NLS-1$ |
| ICPPTemplateParameterMap tpmap= getTemplateParameterMap(); |
| if (tpmap != null) { |
| result.append(" "); //$NON-NLS-1$ |
| result.append(tpmap.toString()); |
| } |
| return result.toString(); |
| } |
| |
| @Override |
| public IType[] getExceptionSpecification() { |
| return fExceptionSpecs; |
| } |
| |
| @Override |
| public ICPPExecution getFunctionBodyExecution() { |
| if (!isConstexpr()) { |
| return null; |
| } |
| |
| IASTNode def = getDefinition(); |
| if (def != null) { |
| return CPPFunction.computeFunctionBodyExecution(def); |
| } |
| return CPPTemplates.instantiateFunctionBody(this); |
| } |
| } |