Skip to main content
aboutsummaryrefslogblamecommitdiffstats
blob: c1af22f359ff6245a544332bc436dcef3f931b30 (plain) (tree)
1
2
3
4
5
6
7
8
9
                                                                                
                                                                


                                                                       
                                                           


                                         

                
                                                     






                                                                                 
                                                       

                                                               
                                                          




                                                        




                                                                                                          
                                                                                                                            

                                                                     
 









                                                                                                                                 
 
                 



                                            

                                            

                                                          
 
                 



                                                           

                                                     
                                                          
     
 
                 




                                                                                       
                                                                         











                                                                                                                                   
                                             
 
 




                                                                       
                                












                                                                   
                              
                                             
 








                                                                                                    
                                                                                           
 




































                                                                                                                        
 
                                                     
                                                                      
                                                                                    
                              















                                                                                                
                                                                                     






















                                                                                                            
/*******************************************************************************
 * Copyright (c) 2008, 2014 Wind River Systems, Inc. and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     Markus Schorn - Initial API and implementation
 *******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser;

import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTArraySubscriptExpression;
import org.eclipse.cdt.core.dom.ast.IASTCastExpression;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTExpressionList;
import org.eclipse.cdt.core.dom.ast.IASTFieldReference;
import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
import org.eclipse.cdt.core.dom.ast.IASTInitializerClause;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IProblemBinding;

/**
 * Handles the ambiguity between cast and function-call expressions: (type)(expr) versus (function)(expr);
 * It also handles the impact on the grouping of the sub-expressions.
 */
public abstract class ASTAmbiguousCastVsFunctionCallExpression extends ASTAmbiguousNode implements IASTAmbiguousExpression {
    private final IASTCastExpression fCastExpression;
    private final IASTFunctionCallExpression fFunctionCallExpression;

    /**
     * The operand of the cast expression must start with an expression in parenthesis (which could be read as the parameter
     * list of the function call).
     * The function-call must contain the name expression (corresponding to the type-id of the cast expression). The parameter
     * expression may be <code>null</code>, it will be computed from the cast expression.
     */
    public ASTAmbiguousCastVsFunctionCallExpression(IASTCastExpression castExpression, IASTFunctionCallExpression functionCall) {
    	fCastExpression= castExpression;
    	fFunctionCallExpression= functionCall;
    }

	@Override
	public final IASTNode[] getNodes() {
		return getExpressions();
	}

    @Override
	public final IASTExpression copy() {
		throw new UnsupportedOperationException();
	}

	@Override
	public final IASTExpression copy(CopyStyle style) {
		throw new UnsupportedOperationException();
	}

    @Override
	public void addExpression(IASTExpression e) {
		throw new UnsupportedOperationException();
    }

	@Override
	public IASTExpression[] getExpressions() {
		return new IASTExpression[] {fCastExpression, fFunctionCallExpression};
	}

	@Override
	protected final IASTNode doResolveAmbiguity(ASTVisitor visitor) {
		final IASTAmbiguityParent owner= (IASTAmbiguityParent) getParent();
		IASTNode nodeToReplace= this;

		// try cast-expression
		owner.replace(nodeToReplace, fCastExpression);
		nodeToReplace= fCastExpression;
		// resolve nested ambiguities
		fCastExpression.accept(visitor);

		// if the operand of the cast-expr is not suitable for a function call, we are done.
		final IASTUnaryExpression primaryWithParenthesis= findPrimaryExpressionInParenthesis(fCastExpression.getOperand());
		if (primaryWithParenthesis == null)
			return nodeToReplace;


		// find nested names
		final NameCollector nameCollector= new NameCollector();
		fCastExpression.getTypeId().accept(nameCollector);
		final IASTName[] names= nameCollector.getNames();

		// resolve names
		boolean hasIssue= false;
		for (IASTName name : names) {
			try {
				IBinding b = name.resolveBinding();
				if (b instanceof IProblemBinding) {
					hasIssue= true;
					break;
				}
			} catch (Exception t) {
				hasIssue= true;
				break;
			}
		}
		if (!hasIssue)
			return nodeToReplace;

		final IASTExpression operand = primaryWithParenthesis.getOperand();
		if (operand instanceof IASTExpressionList) {
			final IASTExpressionList list= (IASTExpressionList) operand;
			fFunctionCallExpression.setArguments(list.getExpressions());
		} else if (operand != null) {
			fFunctionCallExpression.setArguments(new IASTInitializerClause[] {operand});
		} else {
			fFunctionCallExpression.setArguments(IASTExpression.EMPTY_EXPRESSION_ARRAY);
		}
		setRange(fFunctionCallExpression, fCastExpression, primaryWithParenthesis);

		IASTExpression result= fFunctionCallExpression;
		IASTExpression postFix= fCastExpression.getOperand();
		if (postFix != primaryWithParenthesis) {
			result= postFix;
			while (true) {
				setStart(postFix, fFunctionCallExpression);
				if (postFix instanceof IASTArraySubscriptExpression) {
					final IASTArraySubscriptExpression ase = (IASTArraySubscriptExpression) postFix;
					postFix= ase.getArrayExpression();
					if (postFix == primaryWithParenthesis) {
						ase.setArrayExpression(fFunctionCallExpression);
						break;
					}
				} else if (postFix instanceof IASTFunctionCallExpression) {
					final IASTFunctionCallExpression fc = (IASTFunctionCallExpression) postFix;
					postFix= fc.getFunctionNameExpression();
					if (postFix == primaryWithParenthesis) {
						fc.setFunctionNameExpression(fFunctionCallExpression);
						break;
					}
				} else if (postFix instanceof IASTFieldReference) {
					final IASTFieldReference fr = (IASTFieldReference) postFix;
					postFix= fr.getFieldOwner();
					if (postFix == primaryWithParenthesis) {
						fr.setFieldOwner(fFunctionCallExpression);
						break;
					}
				} else {
					final IASTUnaryExpression ue = (IASTUnaryExpression) postFix;
					postFix= ue.getOperand();
					if (postFix == primaryWithParenthesis) {
						ue.setOperand(fFunctionCallExpression);
						break;
					}
				}
			}
		}

		owner.replace(nodeToReplace, result);
		// Resolve ambiguities in the function-call expression
		fFunctionCallExpression.getFunctionNameExpression().accept(visitor);
		return result;
	}

	private IASTUnaryExpression findPrimaryExpressionInParenthesis(IASTExpression operand) {
		while (true) {
			if (operand instanceof IASTUnaryExpression) {
				final IASTUnaryExpression unary= (IASTUnaryExpression) operand;
				switch (unary.getOperator()) {
				case IASTUnaryExpression.op_bracketedPrimary:
					return unary;
				case IASTUnaryExpression.op_postFixDecr:
				case IASTUnaryExpression.op_postFixIncr:
					operand= unary.getOperand();
					break;
				default:
					return null;
				}
			} else if (operand instanceof IASTArraySubscriptExpression) {
				operand= ((IASTArraySubscriptExpression) operand).getArrayExpression();
			} else if (operand instanceof IASTFunctionCallExpression) {
				operand= ((IASTFunctionCallExpression) operand).getFunctionNameExpression();
			} else if (operand instanceof IASTFieldReference) {
				operand= ((IASTFieldReference) operand).getFieldOwner();
			} else {
				return null;
			}
		}
	}

	private void setStart(IASTNode node, IASTNode start) {
		final ASTNode target= (ASTNode) node;
		final int offset = ((ASTNode) start).getOffset();
		target.setOffsetAndLength(offset, target.getOffset() + target.getLength() - offset);
	}

	private void setRange(IASTNode node, IASTNode from, IASTNode to) {
		final int offset = ((ASTNode) from).getOffset();
		final ASTNode t= (ASTNode) to;
		((ASTNode) node).setOffsetAndLength(offset, t.getOffset()+t.getLength()-offset);
	}
}

Back to the top