/******************************************************************************* * 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: * John Camelon (IBM) - Initial API and implementation * Markus Schorn (Wind River Systems) * Mike Kucera (IBM) * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp; import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.PRVALUE; import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.IASTArrayDeclarator; import org.eclipse.cdt.core.dom.ast.IASTArrayModifier; import org.eclipse.cdt.core.dom.ast.IASTDeclarator; import org.eclipse.cdt.core.dom.ast.IASTExpression; import org.eclipse.cdt.core.dom.ast.IASTExpressionList; import org.eclipse.cdt.core.dom.ast.IASTImplicitDestructorName; import org.eclipse.cdt.core.dom.ast.IASTImplicitName; import org.eclipse.cdt.core.dom.ast.IASTInitializer; import org.eclipse.cdt.core.dom.ast.IASTInitializerClause; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTPointerOperator; import org.eclipse.cdt.core.dom.ast.IASTTypeId; import org.eclipse.cdt.core.dom.ast.IArrayType; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorInitializer; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNewExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; 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.IASTAmbiguityParent; import org.eclipse.cdt.internal.core.dom.parser.ProblemType; import org.eclipse.cdt.internal.core.dom.parser.c.CASTExpressionList; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.DestructorCallCollector; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalTypeId; import org.eclipse.core.runtime.Assert; /** * Represents a new expression [expr.new]. */ public class CPPASTNewExpression extends ASTNode implements ICPPASTNewExpression, IASTAmbiguityParent, ICPPEvaluationOwner { private IASTInitializerClause[] fPlacement; private IASTTypeId fTypeId; private IASTInitializer fInitializer; private boolean fIsGlobal; private boolean fIsNewTypeId; private IASTExpression[] fCachedArraySizes; private ICPPEvaluation fEvaluation; private IASTImplicitName[] fImplicitNames; private IASTImplicitDestructorName[] fImplicitDestructorNames; public CPPASTNewExpression() { } public CPPASTNewExpression(IASTInitializerClause[] placement, IASTInitializer initializer, IASTTypeId typeId) { setPlacementArguments(placement); setTypeId(typeId); setInitializer(initializer); } @Override public CPPASTNewExpression copy() { return copy(CopyStyle.withoutLocations); } @Override public CPPASTNewExpression copy(CopyStyle style) { CPPASTNewExpression copy = new CPPASTNewExpression(); copy.setIsGlobal(fIsGlobal); copy.setIsNewTypeId(fIsNewTypeId); if (fPlacement != null) { IASTInitializerClause[] plcmt = new IASTInitializerClause[fPlacement.length]; for (int i = 0; i < fPlacement.length; i++) { plcmt[i] = fPlacement[i].copy(style); } copy.setPlacementArguments(plcmt); } copy.setTypeId(fTypeId == null ? null : fTypeId.copy(style)); copy.setInitializer(fInitializer == null ? null : fInitializer.copy(style)); return copy(copy, style); } @Override public boolean isGlobal() { return fIsGlobal; } @Override public void setIsGlobal(boolean value) { assertNotFrozen(); fIsGlobal = value; } @Override public IASTInitializerClause[] getPlacementArguments() { return fPlacement; } @Override public void setPlacementArguments(IASTInitializerClause[] args) { assertNotFrozen(); fPlacement = args; if (args != null) { for (IASTInitializerClause arg : args) { arg.setParent(this); arg.setPropertyInParent(NEW_PLACEMENT); } } } @Override public IASTInitializer getInitializer() { return fInitializer; } @Override public void setInitializer(IASTInitializer expression) { assertNotFrozen(); fInitializer = expression; if (expression != null) { expression.setParent(this); expression.setPropertyInParent(NEW_INITIALIZER); } } @Override public IASTTypeId getTypeId() { return fTypeId; } @Override public void setTypeId(IASTTypeId typeId) { assertNotFrozen(); fTypeId = typeId; if (typeId != null) { typeId.setParent(this); typeId.setPropertyInParent(TYPE_ID); } } @Override public boolean isNewTypeId() { return fIsNewTypeId; } @Override public void setIsNewTypeId(boolean value) { assertNotFrozen(); fIsNewTypeId = value; } /** * @see org.eclipse.cdt.core.dom.ast.IASTImplicitNameOwner#getImplicitNames() */ @Override public IASTImplicitName[] getImplicitNames() { if (fImplicitNames == null) { CPPASTImplicitName operatorName = null; ICPPFunction operatorFunction = CPPSemantics.findOverloadedOperator(this); if (operatorFunction != null && !(operatorFunction instanceof CPPImplicitFunction)) { operatorName = new CPPASTImplicitName(operatorFunction.getNameCharArray(), this); operatorName.setOperator(true); operatorName.setBinding(operatorFunction); operatorName.setOffsetAndLength(getOffset(), 3); } CPPASTImplicitName constructorName = null; IBinding constructor = CPPSemantics.findImplicitlyCalledConstructor(this); if (constructor != null) { constructorName = new CPPASTImplicitName(constructor.getNameCharArray(), this); constructorName.setBinding(constructor); constructorName.setOffsetAndLength((ASTNode) getTypeId()); } if (operatorName != null) { if (constructorName != null) { fImplicitNames = new IASTImplicitName[] { operatorName, constructorName }; } else { fImplicitNames = new IASTImplicitName[] { operatorName }; } } else { if (constructorName != null) { fImplicitNames = new IASTImplicitName[] { constructorName }; } else { fImplicitNames = IASTImplicitName.EMPTY_NAME_ARRAY; } } } return fImplicitNames; } @Override public IASTImplicitDestructorName[] getImplicitDestructorNames() { if (fImplicitDestructorNames == null) { fImplicitDestructorNames = DestructorCallCollector.getTemporariesDestructorCalls(this); } return fImplicitDestructorNames; } /** * Returns true if this expression is allocating an array. * @since 5.1 */ @Override public boolean isArrayAllocation() { IASTTypeId typeId= getTypeId(); if (typeId != null) { IASTDeclarator dtor= typeId.getAbstractDeclarator(); if (dtor != null) { dtor= ASTQueries.findTypeRelevantDeclarator(dtor); return dtor instanceof IASTArrayDeclarator; } } return false; } @Override public boolean accept(ASTVisitor action) { if (action.shouldVisitExpressions) { switch (action.visit(this)) { case ASTVisitor.PROCESS_ABORT: return false; case ASTVisitor.PROCESS_SKIP: return true; default: break; } } if (action.shouldVisitImplicitNames) { for (IASTImplicitName name : getImplicitNames()) { if (!name.accept(action)) return false; } } if (fPlacement != null) { for (IASTInitializerClause arg : fPlacement) { if (!arg.accept(action)) return false; } } if (fTypeId != null && !fTypeId.accept(action)) return false; if (fInitializer != null && !fInitializer.accept(action)) return false; if (action.shouldVisitImplicitDestructorNames && !acceptByNodes(getImplicitDestructorNames(), action)) return false; if (action.shouldVisitExpressions) { switch (action.leave(this)) { case ASTVisitor.PROCESS_ABORT: return false; case ASTVisitor.PROCESS_SKIP: return true; default: break; } } return true; } @Override public void replace(IASTNode child, IASTNode other) { if (fPlacement != null) { for (int i = 0; i < fPlacement.length; ++i) { if (child == fPlacement[i]) { other.setPropertyInParent(child.getPropertyInParent()); other.setParent(child.getParent()); fPlacement[i] = (IASTExpression) other; } } } } @Override public ICPPEvaluation getEvaluation() { if (fEvaluation == null) { IType t = fTypeId != null ? CPPVisitor.createType(fTypeId) : ProblemType.UNKNOWN_FOR_EXPRESSION; if (t instanceof IArrayType) { t = ((IArrayType) t).getType(); } ICPPEvaluation[] arguments = ICPPEvaluation.EMPTY_ARRAY; if (fInitializer instanceof ICPPASTConstructorInitializer) { IASTInitializerClause[] args = ((ICPPASTConstructorInitializer) fInitializer).getArguments(); arguments= new ICPPEvaluation[args.length]; for (int i = 0; i < arguments.length; i++) { arguments[i] = ((ICPPEvaluationOwner) args[i]).getEvaluation(); } } fEvaluation = EvalTypeId.createForNewExpression(t, this, false, arguments); } return fEvaluation; } @Override public IType getExpressionType() { return getEvaluation().getType(this); } @Override public boolean isLValue() { return false; } @Override public ValueCategory getValueCategory() { return PRVALUE; } @Override @Deprecated public IASTExpression[] getNewTypeIdArrayExpressions() { if (fCachedArraySizes == null) { if (fTypeId != null) { IASTDeclarator dtor = ASTQueries.findInnermostDeclarator(fTypeId.getAbstractDeclarator()); if (dtor instanceof IASTArrayDeclarator) { IASTArrayDeclarator ad = (IASTArrayDeclarator) dtor; IASTArrayModifier[] ams = ad.getArrayModifiers(); fCachedArraySizes = new IASTExpression[ams.length]; for (int i = 0; i < ams.length; i++) { IASTArrayModifier am = ams[i]; fCachedArraySizes[i] = am.getConstantExpression(); } return fCachedArraySizes; } } fCachedArraySizes = IASTExpression.EMPTY_EXPRESSION_ARRAY; } return fCachedArraySizes; } @Override @Deprecated public void addNewTypeIdArrayExpression(IASTExpression expression) { assertNotFrozen(); Assert.isNotNull(fTypeId); IASTDeclarator dtor= ASTQueries.findInnermostDeclarator(fTypeId.getAbstractDeclarator()); if (dtor instanceof IASTArrayDeclarator == false) { Assert.isNotNull(dtor); Assert.isTrue(dtor.getParent() == fTypeId); IASTArrayDeclarator adtor= new CPPASTArrayDeclarator(dtor.getName()); IASTPointerOperator[] ptrOps= dtor.getPointerOperators(); for (IASTPointerOperator ptr : ptrOps) { adtor.addPointerOperator(ptr); } fTypeId.setAbstractDeclarator(adtor); dtor= adtor; } IASTArrayModifier mod= new CPPASTArrayModifier(expression); ((ASTNode) mod).setOffsetAndLength((ASTNode) expression); ((IASTArrayDeclarator) dtor).addArrayModifier(mod); } @Override @Deprecated public IASTExpression getNewPlacement() { if (fPlacement == null || fPlacement.length == 0) return null; if (fPlacement.length == 1) { if (fPlacement[0] instanceof IASTExpression) return (IASTExpression) fPlacement[0]; return null; } CASTExpressionList result= new CASTExpressionList(); for (IASTInitializerClause arg : fPlacement) { if (arg instanceof IASTExpression) { result.addExpression(((IASTExpression) arg).copy()); } } result.setParent(this); result.setPropertyInParent(NEW_PLACEMENT); return result; } @Override @Deprecated public void setNewPlacement(IASTExpression expression) { assertNotFrozen(); if (expression == null) { setPlacementArguments(null); } else if (expression instanceof IASTExpressionList) { setPlacementArguments(((IASTExpressionList) expression).getExpressions()); } else { setPlacementArguments(new IASTExpression[] {expression}); } } @Override @Deprecated public IASTExpression getNewInitializer() { if (fInitializer == null || fInitializer instanceof IASTExpression) { return (IASTExpression) fInitializer; } if (fInitializer instanceof ICPPASTConstructorInitializer) { IASTExpression expr= ((ICPPASTConstructorInitializer) fInitializer).getExpression(); if (expr == null) { expr= new CPPASTExpressionList(); } else { expr= expr.copy(); } expr.setParent(this); expr.setPropertyInParent(NEW_INITIALIZER); return expr; } return null; } @Override @Deprecated public void setNewInitializer(IASTExpression expression) { assertNotFrozen(); if (expression == null) { setInitializer(null); } else if (expression instanceof IASTInitializer) { setInitializer((IASTInitializer) expression); } else { CPPASTConstructorInitializer ctorInit= new CPPASTConstructorInitializer(); ctorInit.setExpression(expression); ctorInit.setOffsetAndLength((ASTNode) expression); setInitializer(ctorInit); } } }