/*******************************************************************************
* Copyright (c) 2004, 2011 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)
*******************************************************************************/
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.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.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.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.core.runtime.Assert;
public class CPPASTNewExpression extends ASTNode implements ICPPASTNewExpression, IASTAmbiguityParent {
private IASTInitializerClause[] placement;
private IASTTypeId typeId;
private IASTInitializer initializer;
private IASTImplicitName[] implicitNames = null;
private boolean isGlobal;
private boolean isNewTypeId;
private IASTExpression[] cachedArraySizes;
public CPPASTNewExpression() {
}
public CPPASTNewExpression(IASTInitializerClause[] placement, IASTInitializer initializer, IASTTypeId typeId) {
setPlacementArguments(placement);
setTypeId(typeId);
setInitializer(initializer);
}
public CPPASTNewExpression copy() {
return copy(CopyStyle.withoutLocations);
}
public CPPASTNewExpression copy(CopyStyle style) {
CPPASTNewExpression copy = new CPPASTNewExpression();
copy.setIsGlobal(isGlobal);
copy.setIsNewTypeId(isNewTypeId);
if (placement != null) {
IASTInitializerClause[] plcmt = new IASTInitializerClause[placement.length];
for (int i = 0; i < placement.length; i++) {
plcmt[i] = placement[i].copy(style);
}
copy.setPlacementArguments(plcmt);
}
copy.setTypeId(typeId == null ? null : typeId.copy(style));
copy.setInitializer(initializer == null ? null : initializer.copy(style));
copy.setOffsetAndLength(this);
if (style == CopyStyle.withLocations) {
copy.setCopyLocation(this);
}
return copy;
}
public boolean isGlobal() {
return isGlobal;
}
public void setIsGlobal(boolean value) {
assertNotFrozen();
isGlobal = value;
}
public IASTInitializerClause[] getPlacementArguments() {
return placement;
}
public void setPlacementArguments(IASTInitializerClause[] args) {
assertNotFrozen();
placement = args;
if (args != null) {
for (IASTInitializerClause arg : args) {
arg.setParent(this);
arg.setPropertyInParent(NEW_PLACEMENT);
}
}
}
public IASTInitializer getInitializer() {
return initializer;
}
public void setInitializer(IASTInitializer expression) {
assertNotFrozen();
initializer = expression;
if (expression != null) {
expression.setParent(this);
expression.setPropertyInParent(NEW_INITIALIZER);
}
}
public IASTTypeId getTypeId() {
return typeId;
}
public void setTypeId(IASTTypeId typeId) {
assertNotFrozen();
this.typeId = typeId;
if (typeId != null) {
typeId.setParent(this);
typeId.setPropertyInParent(TYPE_ID);
}
}
public boolean isNewTypeId() {
return isNewTypeId;
}
public void setIsNewTypeId(boolean value) {
assertNotFrozen();
isNewTypeId = value;
}
/**
* @see org.eclipse.cdt.core.dom.ast.IASTImplicitNameOwner#getImplicitNames()
*/
public IASTImplicitName[] getImplicitNames() {
if (implicitNames == null) {
ICPPFunction operatorFunction = CPPSemantics.findOverloadedOperator(this);
if (operatorFunction == null || operatorFunction instanceof CPPImplicitFunction) {
implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY;
} else {
CPPASTImplicitName operatorName = new CPPASTImplicitName(operatorFunction.getNameCharArray(), this);
operatorName.setOperator(true);
operatorName.setBinding(operatorFunction);
operatorName.setOffsetAndLength(getOffset(), 3);
implicitNames = new IASTImplicitName[] { operatorName };
}
}
return implicitNames;
}
/**
* Returns true if this expression is allocating an array.
* @since 5.1
*/
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 (placement != null) {
for (IASTInitializerClause arg : placement) {
if (!arg.accept(action))
return false;
}
}
if (typeId != null && !typeId.accept(action))
return false;
if (initializer != null && !initializer.accept(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;
}
public void replace(IASTNode child, IASTNode other) {
if (placement != null) {
for (int i = 0; i < placement.length; ++i) {
if (child == placement[i]) {
other.setPropertyInParent(child.getPropertyInParent());
other.setParent(child.getParent());
placement[i] = (IASTExpression) other;
}
}
}
}
public IType getExpressionType() {
IType t= CPPVisitor.createType(getTypeId());
if (t instanceof IArrayType) {
t= ((IArrayType) t).getType();
}
return new CPPPointerType(t);
}
public boolean isLValue() {
return false;
}
public ValueCategory getValueCategory() {
return PRVALUE;
}
@Deprecated
public IASTExpression[] getNewTypeIdArrayExpressions() {
if (cachedArraySizes == null) {
if (typeId != null) {
IASTDeclarator dtor = ASTQueries.findInnermostDeclarator(typeId.getAbstractDeclarator());
if (dtor instanceof IASTArrayDeclarator) {
IASTArrayDeclarator ad = (IASTArrayDeclarator) dtor;
IASTArrayModifier[] ams = ad.getArrayModifiers();
cachedArraySizes = new IASTExpression[ams.length];
for (int i = 0; i < ams.length; i++) {
IASTArrayModifier am = ams[i];
cachedArraySizes[i] = am.getConstantExpression();
}
return cachedArraySizes;
}
}
cachedArraySizes = IASTExpression.EMPTY_EXPRESSION_ARRAY;
}
return cachedArraySizes;
}
@Deprecated
public void addNewTypeIdArrayExpression(IASTExpression expression) {
assertNotFrozen();
Assert.isNotNull(typeId);
IASTDeclarator dtor= ASTQueries.findInnermostDeclarator(typeId.getAbstractDeclarator());
if (dtor instanceof IASTArrayDeclarator == false) {
Assert.isNotNull(dtor);
Assert.isTrue(dtor.getParent() == typeId);
IASTArrayDeclarator adtor= new CPPASTArrayDeclarator(dtor.getName());
IASTPointerOperator[] ptrOps= dtor.getPointerOperators();
for (IASTPointerOperator ptr : ptrOps) {
adtor.addPointerOperator(ptr);
}
typeId.setAbstractDeclarator(adtor);
dtor= adtor;
}
IASTArrayModifier mod= new CPPASTArrayModifier(expression);
((ASTNode) mod).setOffsetAndLength((ASTNode)expression);
((IASTArrayDeclarator) dtor).addArrayModifier(mod);
}
@Deprecated
public IASTExpression getNewPlacement() {
if (placement == null || placement.length == 0)
return null;
if (placement.length == 1) {
if (placement[0] instanceof IASTExpression)
return (IASTExpression) placement[0];
return null;
}
CASTExpressionList result= new CASTExpressionList();
for (IASTInitializerClause arg : placement) {
if (arg instanceof IASTExpression) {
result.addExpression(((IASTExpression) arg).copy());
}
}
result.setParent(this);
result.setPropertyInParent(NEW_PLACEMENT);
return result;
}
@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});
}
}
@Deprecated
public IASTExpression getNewInitializer() {
if (initializer == null || initializer instanceof IASTExpression) {
return (IASTExpression) initializer;
}
if (initializer instanceof ICPPASTConstructorInitializer) {
IASTExpression expr= ((ICPPASTConstructorInitializer) initializer).getExpression();
if (expr == null) {
expr= new CPPASTExpressionList();
} else {
expr= expr.copy();
}
expr.setParent(this);
expr.setPropertyInParent(NEW_INITIALIZER);
return expr;
}
return null;
}
@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);
}
}
}