1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-22 14:12:10 +02:00

Bug 531098: [C++17] Add support for switch with initializer

Change-Id: I046acd311cb99215798d2cbb8d30c2ef8ff2301d
Signed-off-by: Hansruedi Patzen <hansruedi.patzen@hsr.ch>
This commit is contained in:
Hansruedi Patzen 2018-02-13 14:41:33 +01:00 committed by Nathan Ridge
parent e31e23bb4e
commit 29a51f0a61
13 changed files with 270 additions and 27 deletions

View file

@ -52,6 +52,7 @@ import org.eclipse.cdt.core.dom.ast.IASTProblem;
import org.eclipse.cdt.core.dom.ast.IASTReturnStatement; import org.eclipse.cdt.core.dom.ast.IASTReturnStatement;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTStandardFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.IASTStandardFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTSwitchStatement;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IASTTypeId; import org.eclipse.cdt.core.dom.ast.IASTTypeId;
import org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression; import org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression;
@ -703,6 +704,26 @@ public class DOMLocationTests extends AST2TestBase {
assertSoleLocation(declarator, code.indexOf(rawDeclarator), rawDeclarator.length()); assertSoleLocation(declarator, code.indexOf(rawDeclarator), rawDeclarator.length());
} }
public void testSwitchInitStatement_1() throws Exception {
String code = "void foo() { switch (int i = 1; i) {} }"; //$NON-NLS-1$
IASTTranslationUnit tu = parse(code, ParserLanguage.CPP);
ICPPASTFunctionDefinition definition = (ICPPASTFunctionDefinition) tu.getDeclarations()[0];
IASTCompoundStatement body = (IASTCompoundStatement) definition.getBody();
IASTSwitchStatement statement = (IASTSwitchStatement) body.getStatements()[0];
String rawDeclarator = "switch (int i = 1; i) {}"; //$NON-NLS-1$
assertSoleLocation(statement, code.indexOf(rawDeclarator), rawDeclarator.length());
}
public void testSwitchInitStatement_2() throws Exception {
String code = "void foo() { char c = 'a'; switch (; c) {} }"; //$NON-NLS-1$
IASTTranslationUnit tu = parse(code, ParserLanguage.CPP);
ICPPASTFunctionDefinition definition = (ICPPASTFunctionDefinition) tu.getDeclarations()[0];
IASTCompoundStatement body = (IASTCompoundStatement) definition.getBody();
IASTSwitchStatement statement = (IASTSwitchStatement) body.getStatements()[1];
String rawDeclarator = "switch (; c) {}"; //$NON-NLS-1$
assertSoleLocation(statement, code.indexOf(rawDeclarator), rawDeclarator.length());
}
public void testIfInitStatement_1() throws Exception { public void testIfInitStatement_1() throws Exception {
String code = "void foo() { if (int i = 1; i == 1) {} }"; //$NON-NLS-1$ String code = "void foo() { if (int i = 1; i == 1) {} }"; //$NON-NLS-1$
IASTTranslationUnit tu = parse(code, ParserLanguage.CPP); IASTTranslationUnit tu = parse(code, ParserLanguage.CPP);

View file

@ -244,4 +244,46 @@ public class SwitchStatementTests extends TestBase {
public void testSwitchWithNestedContinueStatement() throws Exception { public void testSwitchWithNestedContinueStatement() throws Exception {
assertEvaluationEquals(3); assertEvaluationEquals(3);
} }
// constexpr int triple(int x) {
// return x * 3;
// }
// constexpr int f(int y) {
// switch(int x = triple(y); x) {
// case 9:
// return 1;
// case 12:
// return 2;
// case 15:
// return 3;
// default:
// return 4;
// }
// }
// constexpr int x = f(5);
public void testDeclarationInSwitchInitStatement() throws Exception {
assertEvaluationEquals(3);
}
// constexpr int triple(int x) {
// return x * 3;
// }
// constexpr int f(int y) {
// switch(; int x = triple(y)) {
// case 9:
// return 1;
// case 12:
// return 2;
// case 15:
// return 3;
// default:
// return 4;
// }
// }
// constexpr int x = f(5);
public void testDeclarationInSwitchStatementControllerEmptyInit() throws Exception {
assertEvaluationEquals(3);
}
} }

View file

@ -401,3 +401,24 @@ void f()
if constexpr (;k == 42){ if constexpr (;k == 42){
} }
} }
//!Switch with emtpy init statement
//%CPP
void f()
{
constexpr int k{42};
switch (;k){
case 42:
break;
}
}
//!Switch with init statement
//%CPP
void f()
{
switch (constexpr int k{42};k){
case 42:
break;
}
}

View file

@ -12,6 +12,7 @@ package org.eclipse.cdt.core.dom.ast.cpp;
import org.eclipse.cdt.core.dom.ast.ASTNodeProperty; import org.eclipse.cdt.core.dom.ast.ASTNodeProperty;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration; import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTStatement;
import org.eclipse.cdt.core.dom.ast.IASTSwitchStatement; import org.eclipse.cdt.core.dom.ast.IASTSwitchStatement;
import org.eclipse.cdt.core.dom.ast.IScope; import org.eclipse.cdt.core.dom.ast.IScope;
@ -21,6 +22,15 @@ import org.eclipse.cdt.core.dom.ast.IScope;
*/ */
public interface ICPPASTSwitchStatement extends IASTSwitchStatement { public interface ICPPASTSwitchStatement extends IASTSwitchStatement {
/**
* {@code INIT_STATEMENT} represents the relationship between an
* {@code ICPPASTSwitchStatement} and its nested {@code IASTStatement}.
*
* @since 6.5
*/
public static final ASTNodeProperty INIT_STATEMENT = new ASTNodeProperty(
"ICPPASTSwitchStatement.INIT_STATEMENT - IASTStatement init-statement for ICPPASTSwitchStatement"); //$NON-NLS-1$
/** /**
* <code>CONTROLLER_DECLARATION</code> represents the relationship between an * <code>CONTROLLER_DECLARATION</code> represents the relationship between an
* <code>IASTSwitchStatement</code> and it's nested * <code>IASTSwitchStatement</code> and it's nested
@ -43,6 +53,26 @@ public interface ICPPASTSwitchStatement extends IASTSwitchStatement {
*/ */
public void setControllerDeclaration( IASTDeclaration d ); public void setControllerDeclaration( IASTDeclaration d );
/**
* Returns the init-statement for a switch.
*
* @return the init-statement, or <code>null</code> if the 'switch' statement doesn't
* have one.
*
* @since 6.5
*/
public IASTStatement getInitializerStatement();
/**
* Sets the optional init-statement of an switch.
*
* @param statement this statement should either be a <code>IASTSimpleDeclaration</code> or a
* <code>IASTExpressionStatement</code>.
*
* @since 6.5
*/
public void setInitializerStatement(IASTStatement statement);
/** /**
* Get the <code>IScope</code> represented by this switch. * Get the <code>IScope</code> represented by this switch.
* *

View file

@ -30,6 +30,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecSwitch;
*/ */
public class CPPASTSwitchStatement extends CPPASTAttributeOwner implements ICPPASTSwitchStatement, ICPPExecutionOwner { public class CPPASTSwitchStatement extends CPPASTAttributeOwner implements ICPPASTSwitchStatement, ICPPExecutionOwner {
private IScope scope; private IScope scope;
private IASTStatement initStatement;
private IASTExpression controllerExpression; private IASTExpression controllerExpression;
private IASTDeclaration controllerDeclaration; private IASTDeclaration controllerDeclaration;
private IASTStatement body; private IASTStatement body;
@ -55,6 +56,8 @@ public class CPPASTSwitchStatement extends CPPASTAttributeOwner implements ICPPA
@Override @Override
public CPPASTSwitchStatement copy(CopyStyle style) { public CPPASTSwitchStatement copy(CopyStyle style) {
CPPASTSwitchStatement copy = new CPPASTSwitchStatement(); CPPASTSwitchStatement copy = new CPPASTSwitchStatement();
copy.setInitializerStatement(initStatement == null ?
null : initStatement.copy(style));
copy.setControllerDeclaration(controllerDeclaration == null ? copy.setControllerDeclaration(controllerDeclaration == null ?
null : controllerDeclaration.copy(style)); null : controllerDeclaration.copy(style));
copy.setControllerExpression(controllerExpression == null ? copy.setControllerExpression(controllerExpression == null ?
@ -63,6 +66,22 @@ public class CPPASTSwitchStatement extends CPPASTAttributeOwner implements ICPPA
return copy(copy, style); return copy(copy, style);
} }
@Override
public IASTStatement getInitializerStatement() {
return initStatement;
}
@Override
public void setInitializerStatement(IASTStatement statement) {
assertNotFrozen();
this.initStatement = statement;
if (statement != null) {
statement.setParent(this);
statement.setPropertyInParent(INIT_STATEMENT);
statement = null;
}
}
@Override @Override
public IASTExpression getControllerExpression() { public IASTExpression getControllerExpression() {
return controllerExpression; return controllerExpression;
@ -105,6 +124,7 @@ public class CPPASTSwitchStatement extends CPPASTAttributeOwner implements ICPPA
} }
if (!acceptByAttributeSpecifiers(action)) return false; if (!acceptByAttributeSpecifiers(action)) return false;
if (initStatement != null && !initStatement.accept(action)) return false;
if (controllerExpression != null && !controllerExpression.accept(action)) return false; if (controllerExpression != null && !controllerExpression.accept(action)) return false;
if (controllerDeclaration != null && !controllerDeclaration.accept(action)) return false; if (controllerDeclaration != null && !controllerDeclaration.accept(action)) return false;
if (body != null && !body.accept(action)) return false; if (body != null && !body.accept(action)) return false;
@ -121,6 +141,12 @@ public class CPPASTSwitchStatement extends CPPASTAttributeOwner implements ICPPA
@Override @Override
public void replace(IASTNode child, IASTNode other) { public void replace(IASTNode child, IASTNode other) {
if (initStatement == child) {
other.setParent(child.getParent());
other.setPropertyInParent(child.getPropertyInParent());
initStatement = (IASTStatement) other;
return;
}
if (body == child) { if (body == child) {
other.setPropertyInParent(child.getPropertyInParent()); other.setPropertyInParent(child.getPropertyInParent());
other.setParent(child.getParent()); other.setParent(child.getParent());
@ -162,6 +188,7 @@ public class CPPASTSwitchStatement extends CPPASTAttributeOwner implements ICPPA
@Override @Override
public ICPPExecution getExecution() { public ICPPExecution getExecution() {
ICPPExecution initStmtExec = EvalUtil.getExecutionFromStatement(getInitializerStatement());
ICPPASTExpression controllerExpr = (ICPPASTExpression) getControllerExpression(); ICPPASTExpression controllerExpr = (ICPPASTExpression) getControllerExpression();
ICPPExecutionOwner controllerDecl = (ICPPExecutionOwner) getControllerDeclaration(); ICPPExecutionOwner controllerDecl = (ICPPExecutionOwner) getControllerDeclaration();
ICPPEvaluation controllerExprEval = controllerExpr != null ? controllerExpr.getEvaluation() : null; ICPPEvaluation controllerExprEval = controllerExpr != null ? controllerExpr.getEvaluation() : null;
@ -178,6 +205,6 @@ public class CPPASTSwitchStatement extends CPPASTAttributeOwner implements ICPPA
for (int i = 0; i < bodyStmts.length; i++) { for (int i = 0; i < bodyStmts.length; i++) {
bodyStmtExecutions[i] = EvalUtil.getExecutionFromStatement(bodyStmts[i]); bodyStmtExecutions[i] = EvalUtil.getExecutionFromStatement(bodyStmts[i]);
} }
return new ExecSwitch(controllerExprEval, controllerDeclExec, bodyStmtExecutions); return new ExecSwitch(initStmtExec, controllerExprEval, controllerDeclExec, bodyStmtExecutions);
} }
} }

View file

@ -5377,6 +5377,17 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
int startOffset; int startOffset;
startOffset = consume().getOffset(); startOffset = consume().getOffset();
consume(IToken.tLPAREN); consume(IToken.tLPAREN);
ICPPASTSwitchStatement switch_statement = getNodeFactory().newSwitchStatement();
// init-statement
IToken mark= mark();
try {
IASTStatement statement = initStatement();
switch_statement.setInitializerStatement(statement);
} catch (BacktrackException e) {
backup(mark);
}
IASTNode switch_condition = cppStyleCondition(IToken.tRPAREN); IASTNode switch_condition = cppStyleCondition(IToken.tRPAREN);
switch (LT(1)) { switch (LT(1)) {
case IToken.tRPAREN: case IToken.tRPAREN:
@ -5389,7 +5400,6 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
} }
IASTStatement switch_body = parseSwitchBody(); IASTStatement switch_body = parseSwitchBody();
ICPPASTSwitchStatement switch_statement = getNodeFactory().newSwitchStatement();
((ASTNode) switch_statement).setOffsetAndLength(startOffset, ((ASTNode) switch_statement).setOffsetAndLength(startOffset,
(switch_body != null ? calculateEndOffset(switch_body) : LA(1).getEndOffset()) - startOffset); (switch_body != null ? calculateEndOffset(switch_body) : LA(1).getEndOffset()) - startOffset);
if (switch_condition instanceof IASTExpression) { if (switch_condition instanceof IASTExpression) {

View file

@ -1622,7 +1622,14 @@ public class CPPSemantics {
nodes= new IASTNode[] {initDeclaration}; nodes= new IASTNode[] {initDeclaration};
} }
} else if (parent instanceof ICPPASTSwitchStatement) { } else if (parent instanceof ICPPASTSwitchStatement) {
nodes = new IASTNode[] { ((ICPPASTSwitchStatement) parent).getControllerDeclaration() }; ICPPASTSwitchStatement ifStatement = (ICPPASTSwitchStatement) parent;
final IASTStatement initStatement = ifStatement.getInitializerStatement();
final IASTDeclaration controllerDeclaration = ifStatement.getControllerDeclaration();
if (initStatement != null) {
nodes = new IASTNode[] {initStatement, controllerDeclaration};
} else {
nodes = new IASTNode[] {controllerDeclaration};
}
} else if (parent instanceof ICPPASTIfStatement) { } else if (parent instanceof ICPPASTIfStatement) {
ICPPASTIfStatement ifStatement = (ICPPASTIfStatement) parent; ICPPASTIfStatement ifStatement = (ICPPASTIfStatement) parent;
final IASTStatement initStatement = ifStatement.getInitializerStatement(); final IASTStatement initStatement = ifStatement.getInitializerStatement();

View file

@ -32,12 +32,6 @@ public class ExecIf implements ICPPExecution {
this.elseClauseExec = elseClauseExec; this.elseClauseExec = elseClauseExec;
} }
private void executeInitStatement(ActivationRecord record, ConstexprEvaluationContext context) {
if (initStmtExec != null) {
EvalUtil.executeStatement(initStmtExec, record, context);
}
}
private boolean conditionSatisfied(ActivationRecord record, ConstexprEvaluationContext context) { private boolean conditionSatisfied(ActivationRecord record, ConstexprEvaluationContext context) {
if (conditionExprEval != null) { if (conditionExprEval != null) {
return EvalUtil.conditionExprSatisfied(conditionExprEval, record, context); return EvalUtil.conditionExprSatisfied(conditionExprEval, record, context);
@ -49,7 +43,7 @@ public class ExecIf implements ICPPExecution {
@Override @Override
public ICPPExecution executeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context) { public ICPPExecution executeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context) {
executeInitStatement(record, context); EvalUtil.executeStatement(initStmtExec, record, context);
if (conditionSatisfied(record, context)) { if (conditionSatisfied(record, context)) {
return EvalUtil.executeStatement(thenClauseExec, record, context); return EvalUtil.executeStatement(thenClauseExec, record, context);
} else if (elseClauseExec != null) { } else if (elseClauseExec != null) {

View file

@ -17,11 +17,13 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.InstantiationContext;
import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.CoreException;
public class ExecSwitch implements ICPPExecution { public class ExecSwitch implements ICPPExecution {
private final ICPPExecution initStmtExec;
private final ICPPEvaluation controllerExprEval; private final ICPPEvaluation controllerExprEval;
private final ExecSimpleDeclaration controllerDeclExec; private final ExecSimpleDeclaration controllerDeclExec;
private final ICPPExecution[] bodyStmtExecutions; private final ICPPExecution[] bodyStmtExecutions;
public ExecSwitch(ICPPEvaluation controllerExprEval, ExecSimpleDeclaration controllerDeclExec, ICPPExecution[] bodyStmtExecutions) { public ExecSwitch(ICPPExecution initStmtExec, ICPPEvaluation controllerExprEval, ExecSimpleDeclaration controllerDeclExec, ICPPExecution[] bodyStmtExecutions) {
this.initStmtExec = initStmtExec;
this.controllerExprEval = controllerExprEval; this.controllerExprEval = controllerExprEval;
this.controllerDeclExec = controllerDeclExec; this.controllerDeclExec = controllerDeclExec;
this.bodyStmtExecutions = bodyStmtExecutions; this.bodyStmtExecutions = bodyStmtExecutions;
@ -29,6 +31,7 @@ public class ExecSwitch implements ICPPExecution {
@Override @Override
public ICPPExecution executeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context) { public ICPPExecution executeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context) {
EvalUtil.executeStatement(initStmtExec, record, context);
final int caseIndex = getMatchingCaseIndex(record, context); final int caseIndex = getMatchingCaseIndex(record, context);
for (int i = caseIndex; i < bodyStmtExecutions.length; ++i) { for (int i = caseIndex; i < bodyStmtExecutions.length; ++i) {
ICPPExecution stmtExec = bodyStmtExecutions[i]; ICPPExecution stmtExec = bodyStmtExecutions[i];
@ -72,6 +75,7 @@ public class ExecSwitch implements ICPPExecution {
@Override @Override
public ICPPExecution instantiate(InstantiationContext context, int maxDepth) { public ICPPExecution instantiate(InstantiationContext context, int maxDepth) {
ICPPExecution newInitStmtExec = initStmtExec != null ? initStmtExec.instantiate(context, maxDepth) : null;
ICPPEvaluation newControllerExprEval = controllerExprEval != null ? controllerExprEval.instantiate(context, maxDepth) : null; ICPPEvaluation newControllerExprEval = controllerExprEval != null ? controllerExprEval.instantiate(context, maxDepth) : null;
ExecSimpleDeclaration newControllerDeclExec = controllerDeclExec != null ? (ExecSimpleDeclaration) controllerDeclExec.instantiate(context, maxDepth) : null; ExecSimpleDeclaration newControllerDeclExec = controllerDeclExec != null ? (ExecSimpleDeclaration) controllerDeclExec.instantiate(context, maxDepth) : null;
ICPPExecution[] newBodyStmtExecutions = new ICPPExecution[bodyStmtExecutions.length]; ICPPExecution[] newBodyStmtExecutions = new ICPPExecution[bodyStmtExecutions.length];
@ -85,15 +89,16 @@ public class ExecSwitch implements ICPPExecution {
newBodyStmtExecutions[i] = newBodyStmtExec; newBodyStmtExecutions[i] = newBodyStmtExec;
} }
if (newControllerExprEval == controllerExprEval && newControllerDeclExec == controllerDeclExec && !executionsDidChange) { if (newInitStmtExec == initStmtExec && newControllerExprEval == controllerExprEval && newControllerDeclExec == controllerDeclExec && !executionsDidChange) {
return this; return this;
} }
return new ExecSwitch(newControllerExprEval, newControllerDeclExec, newBodyStmtExecutions); return new ExecSwitch(newInitStmtExec, newControllerExprEval, newControllerDeclExec, newBodyStmtExecutions);
} }
@Override @Override
public void marshal(ITypeMarshalBuffer buffer, boolean includeValue) throws CoreException { public void marshal(ITypeMarshalBuffer buffer, boolean includeValue) throws CoreException {
buffer.putShort(ITypeMarshalBuffer.EXEC_SWITCH); buffer.putShort(ITypeMarshalBuffer.EXEC_SWITCH);
buffer.marshalExecution(initStmtExec, includeValue);
buffer.marshalEvaluation(controllerExprEval, includeValue); buffer.marshalEvaluation(controllerExprEval, includeValue);
buffer.marshalExecution(controllerDeclExec, includeValue); buffer.marshalExecution(controllerDeclExec, includeValue);
buffer.putInt(bodyStmtExecutions.length); buffer.putInt(bodyStmtExecutions.length);
@ -103,6 +108,7 @@ public class ExecSwitch implements ICPPExecution {
} }
public static ICPPExecution unmarshal(short firstBytes, ITypeMarshalBuffer buffer) throws CoreException { public static ICPPExecution unmarshal(short firstBytes, ITypeMarshalBuffer buffer) throws CoreException {
ICPPExecution initStmtExec = buffer.unmarshalExecution();
ICPPEvaluation controllerExprEval = buffer.unmarshalEvaluation(); ICPPEvaluation controllerExprEval = buffer.unmarshalEvaluation();
ExecSimpleDeclaration controllerDeclExec = (ExecSimpleDeclaration) buffer.unmarshalExecution(); ExecSimpleDeclaration controllerDeclExec = (ExecSimpleDeclaration) buffer.unmarshalExecution();
int len = buffer.getInt(); int len = buffer.getInt();
@ -110,6 +116,6 @@ public class ExecSwitch implements ICPPExecution {
for (int i = 0; i < bodyStmtExecutions.length; i++) { for (int i = 0; i < bodyStmtExecutions.length; i++) {
bodyStmtExecutions[i] = buffer.unmarshalExecution(); bodyStmtExecutions[i] = buffer.unmarshalExecution();
} }
return new ExecSwitch(controllerExprEval, controllerDeclExec, bodyStmtExecutions); return new ExecSwitch(initStmtExec, controllerExprEval, controllerDeclExec, bodyStmtExecutions);
} }
} }

View file

@ -365,6 +365,10 @@ public class StatementWriter extends NodeWriter {
scribe.noNewLines(); scribe.noNewLines();
if (switchStatement instanceof ICPPASTSwitchStatement) { if (switchStatement instanceof ICPPASTSwitchStatement) {
ICPPASTSwitchStatement cppSwitchStatement = (ICPPASTSwitchStatement) switchStatement; ICPPASTSwitchStatement cppSwitchStatement = (ICPPASTSwitchStatement) switchStatement;
IASTStatement initStatement = cppSwitchStatement.getInitializerStatement();
if (initStatement != null) {
writeStatement(initStatement, false);
}
if (cppSwitchStatement.getControllerDeclaration() == null) { if (cppSwitchStatement.getControllerDeclaration() == null) {
cppSwitchStatement.getControllerExpression().accept(visitor); cppSwitchStatement.getControllerExpression().accept(visitor);
} else { } else {

View file

@ -292,10 +292,11 @@ public class PDOM extends PlatformObject implements IPDOM {
* *
* CDT 9.5 development (version not supported on the 9.4.x branch) * CDT 9.5 development (version not supported on the 9.4.x branch)
* 212.0 - C++ constexpr if and if init-statement evaluation * 212.0 - C++ constexpr if and if init-statement evaluation
* 213.0 - C++ switch init-statement evaluation
*/ */
private static final int MIN_SUPPORTED_VERSION= version(212, 0); private static final int MIN_SUPPORTED_VERSION= version(213, 0);
private static final int MAX_SUPPORTED_VERSION= version(212, Short.MAX_VALUE); private static final int MAX_SUPPORTED_VERSION= version(213, Short.MAX_VALUE);
private static final int DEFAULT_VERSION = version(212, 0); private static final int DEFAULT_VERSION = version(213, 0);
private static int version(int major, int minor) { private static int version(int major, int minor) {
return (major << 16) + minor; return (major << 16) + minor;

View file

@ -134,6 +134,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTRangeBasedForStatement;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTReferenceOperator; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTReferenceOperator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleTypeConstructorExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleTypeConstructorExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleTypeTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleTypeTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSwitchStatement;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateParameter;
@ -3588,24 +3589,44 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
return PROCESS_SKIP; return PROCESS_SKIP;
} }
private void beginSwitchClause() {
scribe.printNextToken(Token.tLPAREN, preferences.insert_space_before_opening_paren_in_switch);
if (preferences.insert_space_after_opening_paren_in_switch) {
scribe.space();
}
}
private int visit(IASTSwitchStatement node) { private int visit(IASTSwitchStatement node) {
final int headerIndent= scribe.numberOfIndentations; final int headerIndent= scribe.numberOfIndentations;
// 'switch' keyword // 'switch' keyword
if (!startsWithMacroExpansion(node)) { if (!startsWithMacroExpansion(node)) {
scribe.printNextToken(Token.t_switch); scribe.printNextToken(Token.t_switch);
} }
// Controller expression
IASTExpression controllerExpression = node.getControllerExpression(); IASTExpression controllerExpression = node.getControllerExpression();
if (!doNodesHaveSameOffset(node, controllerExpression)) { try {
scribe.printNextToken(Token.tLPAREN, preferences.insert_space_before_opening_paren_in_switch); // optional init-statement
if (preferences.insert_space_after_opening_paren_in_switch) { if(node instanceof ICPPASTSwitchStatement) {
IASTStatement initStatement = ((ICPPASTSwitchStatement) node).getInitializerStatement();
if (initStatement != null) {
beginSwitchClause();
fHasClauseInitStatement = true;
initStatement.accept(this);
if (preferences.insert_space_after_semicolon_in_for) {
scribe.space(); scribe.space();
} }
} }
}
// Controller expression
if (!doNodesHaveSameOffset(node, controllerExpression) && !fHasClauseInitStatement) {
beginSwitchClause();
}
controllerExpression.accept(this); controllerExpression.accept(this);
if (peekNextToken() == Token.tRPAREN) { if (peekNextToken() == Token.tRPAREN) {
scribe.printNextToken(Token.tRPAREN, preferences.insert_space_before_closing_paren_in_switch); scribe.printNextToken(Token.tRPAREN, preferences.insert_space_before_closing_paren_in_switch);
} }
} finally {
fHasClauseInitStatement = false;
}
// switch body // switch body
String brace_position = preferences.brace_position_for_switch; String brace_position = preferences.brace_position_for_switch;
int braceIndent = -1; int braceIndent = -1;

View file

@ -3312,4 +3312,63 @@ public class CodeFormatterTest extends BaseUITestCase {
public void testIfInitStatementFormat_4() throws Exception { public void testIfInitStatementFormat_4() throws Exception {
assertFormatterResult(); assertFormatterResult();
} }
//void foo() {
// switch (constexpr bool k = true; k) {
// }
//}
//void foo() {
// switch (constexpr bool k = true; k) {
// }
//}
public void testSwitchInitStatementFormat_1() throws Exception {
assertFormatterResult();
}
//void foo() {
// switch
// (constexpr bool k = true; k) {
// }
//}
//void foo() {
// switch (constexpr bool k = true; k) {
// }
//}
public void testSwitchInitStatementFormat_2() throws Exception {
assertFormatterResult();
}
//void foo() {
// switch
//
//
// (constexpr bool k = true; k) {
// }
//}
//void foo() {
// switch
//
// (constexpr bool k = true; k) {
// }
//}
public void testSwitchInitStatementFormat_3() throws Exception {
assertFormatterResult();
}
//void foo() {
// switch (constexpr bool k = true;k) {
// }
//}
//void foo() {
// switch (constexpr bool k = true; k) {
// }
//}
public void testSwitchInitStatementFormat_4() throws Exception {
assertFormatterResult();
}
} }