mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-23 14:42:11 +02:00
Bug 522216, 527427: [C++17] Support for constexpr if and init-statements
Change-Id: Ia8195c66334edb107848901619e85fbfb5c78b18 Signed-off-by: Hansruedi Patzen <hansruedi.patzen@hsr.ch>
This commit is contained in:
parent
cb5c699871
commit
a51f7c0659
17 changed files with 688 additions and 63 deletions
|
@ -10651,4 +10651,148 @@ public class AST2TemplateTests extends AST2CPPTestBase {
|
|||
public void testLongDependentFunctionCallChain_530692() throws Exception {
|
||||
parseAndCheckBindings();
|
||||
}
|
||||
|
||||
// // A metafunction that loops infinitely on odd inputs.
|
||||
// template <int N>
|
||||
// struct meta {
|
||||
// static constexpr int value = 1 + meta<N - 2>::value;
|
||||
// };
|
||||
// template <>
|
||||
// struct meta<0> {
|
||||
// static constexpr int value = 0;
|
||||
// };
|
||||
//
|
||||
// // A constexpr function that calls 'meta' on an odd input
|
||||
// // but only in the uninstantiated branch of a constexpr if.
|
||||
// template <int N>
|
||||
// constexpr int foo() {
|
||||
// if constexpr (N % 2 != 0) {
|
||||
// return meta<N - 1>::value;
|
||||
// } else {
|
||||
// return meta<N>::value;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // Call the function
|
||||
// constexpr int waldo = foo<7>();
|
||||
public void testConditionalInstantiationOfConstexprIfTrueBranch_527427() throws Exception {
|
||||
BindingAssertionHelper helper = getAssertionHelper();
|
||||
helper.assertVariableValue("waldo", 3);
|
||||
}
|
||||
|
||||
// // A metafunction that loops infinitely on odd inputs.
|
||||
// template <int N>
|
||||
// struct meta {
|
||||
// static constexpr int value = 1 + meta<N - 2>::value;
|
||||
// };
|
||||
// template <>
|
||||
// struct meta<0> {
|
||||
// static constexpr int value = 0;
|
||||
// };
|
||||
//
|
||||
// // A constexpr function that calls 'meta' on an odd input
|
||||
// // but only in the uninstantiated branch of a constexpr if.
|
||||
// template <int N>
|
||||
// constexpr int foo() {
|
||||
// if constexpr (N % 2 == 0) {
|
||||
// return meta<N>::value;
|
||||
// } else {
|
||||
// return meta<N - 1>::value;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // Call the function
|
||||
// constexpr int waldo = foo<7>();
|
||||
public void testConditionalInstantiationOfConstexprIfFalseBranch_527427() throws Exception {
|
||||
BindingAssertionHelper helper = getAssertionHelper();
|
||||
helper.assertVariableValue("waldo", 3);
|
||||
}
|
||||
|
||||
// template <int N>
|
||||
// constexpr int fib() {
|
||||
// if constexpr (N == 0) {
|
||||
// return 0;
|
||||
// } else if constexpr (N == 1) {
|
||||
// return 1;
|
||||
// } else {
|
||||
// return fib<N - 1>() + fib<N - 2>();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // Call the function
|
||||
// constexpr int waldo = fib<7>();
|
||||
public void testConstexprFibonacciConstexprIf_527427() throws Exception {
|
||||
BindingAssertionHelper helper = getAssertionHelper();
|
||||
helper.assertVariableValue("waldo", 13);
|
||||
}
|
||||
|
||||
// constexpr int g(int x) {
|
||||
// return x * 2;
|
||||
// }
|
||||
//
|
||||
// template <int N>
|
||||
// constexpr int foo() {
|
||||
// if constexpr (constexpr auto x = g(N)) {
|
||||
// return 14 / x;
|
||||
// } else {
|
||||
// return 0;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // Call the function
|
||||
// constexpr int waldo = foo<2>();
|
||||
public void testConstexprIfDeclarationTrueBranch_527427() throws Exception {
|
||||
BindingAssertionHelper helper = getAssertionHelper();
|
||||
helper.assertVariableValue("waldo", 3);
|
||||
}
|
||||
|
||||
// constexpr int g(int x) {
|
||||
// return x * 2;
|
||||
// }
|
||||
//
|
||||
// template <int N>
|
||||
// constexpr int foo() {
|
||||
// if constexpr (constexpr auto x = g(N)) {
|
||||
// return 14 / x;
|
||||
// } else {
|
||||
// return 42;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // Call the function
|
||||
// constexpr int waldo = foo<0>();
|
||||
public void testConstexprIfDeclarationFalseBranch_527427() throws Exception {
|
||||
BindingAssertionHelper helper = getAssertionHelper();
|
||||
helper.assertVariableValue("waldo", 42);
|
||||
}
|
||||
|
||||
// constexpr auto foo() {
|
||||
// if constexpr (false) {
|
||||
// return "Error";
|
||||
// } else {
|
||||
// return 42;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // Call the function
|
||||
// constexpr auto waldo = foo();
|
||||
public void testReturnAutoConstexprIfDeclarationFalseBranchValueExpression_527427() throws Exception {
|
||||
BindingAssertionHelper helper = getAssertionHelper();
|
||||
helper.assertVariableValue("waldo", 42);
|
||||
}
|
||||
|
||||
// constexpr auto foo() {
|
||||
// if constexpr (true) {
|
||||
// return 42;
|
||||
// } else {
|
||||
// return "Error";
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // Call the function
|
||||
// constexpr auto waldo = foo();
|
||||
public void testReturnAutoConstexprIfDeclarationTrueBranchValueExpression_527427() throws Exception {
|
||||
BindingAssertionHelper helper = getAssertionHelper();
|
||||
helper.assertVariableValue("waldo", 42);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -703,6 +703,56 @@ public class DOMLocationTests extends AST2TestBase {
|
|||
assertSoleLocation(declarator, code.indexOf(rawDeclarator), rawDeclarator.length());
|
||||
}
|
||||
|
||||
public void testIfInitStatement_1() throws Exception {
|
||||
String code = "void foo() { if (int i = 1; i == 1) {} }"; //$NON-NLS-1$
|
||||
IASTTranslationUnit tu = parse(code, ParserLanguage.CPP);
|
||||
ICPPASTFunctionDefinition definition = (ICPPASTFunctionDefinition) tu.getDeclarations()[0];
|
||||
IASTCompoundStatement body = (IASTCompoundStatement) definition.getBody();
|
||||
IASTIfStatement statement = (IASTIfStatement) body.getStatements()[0];
|
||||
String rawDeclarator = "if (int i = 1; i == 1) {}"; //$NON-NLS-1$
|
||||
assertSoleLocation(statement, code.indexOf(rawDeclarator), rawDeclarator.length());
|
||||
}
|
||||
|
||||
public void testIfInitStatement_2() throws Exception {
|
||||
String code = "void foo() { if (; bool b = true) {} }"; //$NON-NLS-1$
|
||||
IASTTranslationUnit tu = parse(code, ParserLanguage.CPP);
|
||||
ICPPASTFunctionDefinition definition = (ICPPASTFunctionDefinition) tu.getDeclarations()[0];
|
||||
IASTCompoundStatement body = (IASTCompoundStatement) definition.getBody();
|
||||
IASTIfStatement statement = (IASTIfStatement) body.getStatements()[0];
|
||||
String rawDeclarator = "if (; bool b = true) {}"; //$NON-NLS-1$
|
||||
assertSoleLocation(statement, code.indexOf(rawDeclarator), rawDeclarator.length());
|
||||
}
|
||||
|
||||
public void testConstexprIf_1() throws Exception {
|
||||
String code = "void foo() { if constexpr (true) {} }"; //$NON-NLS-1$
|
||||
IASTTranslationUnit tu = parse(code, ParserLanguage.CPP);
|
||||
ICPPASTFunctionDefinition definition = (ICPPASTFunctionDefinition) tu.getDeclarations()[0];
|
||||
IASTCompoundStatement body = (IASTCompoundStatement) definition.getBody();
|
||||
IASTIfStatement statement = (IASTIfStatement) body.getStatements()[0];
|
||||
String rawDeclarator = "if constexpr (true) {}"; //$NON-NLS-1$
|
||||
assertSoleLocation(statement, code.indexOf(rawDeclarator), rawDeclarator.length());
|
||||
}
|
||||
|
||||
public void testConstexprIf_2() throws Exception {
|
||||
String code = "void foo() { if constexpr (constexpr int i = 1; i == 1) {} }"; //$NON-NLS-1$
|
||||
IASTTranslationUnit tu = parse(code, ParserLanguage.CPP);
|
||||
ICPPASTFunctionDefinition definition = (ICPPASTFunctionDefinition) tu.getDeclarations()[0];
|
||||
IASTCompoundStatement body = (IASTCompoundStatement) definition.getBody();
|
||||
IASTIfStatement statement = (IASTIfStatement) body.getStatements()[0];
|
||||
String rawDeclarator = "if constexpr (constexpr int i = 1; i == 1) {}"; //$NON-NLS-1$
|
||||
assertSoleLocation(statement, code.indexOf(rawDeclarator), rawDeclarator.length());
|
||||
}
|
||||
|
||||
public void testConstexprIf_3() throws Exception {
|
||||
String code = "void foo() { if constexpr (; constexpr bool b = true) {} }"; //$NON-NLS-1$
|
||||
IASTTranslationUnit tu = parse(code, ParserLanguage.CPP);
|
||||
ICPPASTFunctionDefinition definition = (ICPPASTFunctionDefinition) tu.getDeclarations()[0];
|
||||
IASTCompoundStatement body = (IASTCompoundStatement) definition.getBody();
|
||||
IASTIfStatement statement = (IASTIfStatement) body.getStatements()[0];
|
||||
String rawDeclarator = "if constexpr (; constexpr bool b = true) {}"; //$NON-NLS-1$
|
||||
assertSoleLocation(statement, code.indexOf(rawDeclarator), rawDeclarator.length());
|
||||
}
|
||||
|
||||
// int main(void){
|
||||
// #define one 1
|
||||
// int integer = one;
|
||||
|
|
|
@ -194,4 +194,69 @@ public class IfStatementTests extends TestBase {
|
|||
public void testDeclarationInIfStatementCondition3() throws Exception {
|
||||
assertEvaluationEquals(7);
|
||||
}
|
||||
|
||||
// constexpr int g(int x) {
|
||||
// return x * 2;
|
||||
// }
|
||||
// constexpr int f(int y) {
|
||||
// if(int x = g(y); x == 2) {
|
||||
// return 14 / x;
|
||||
// } else {
|
||||
// return 0;
|
||||
// }
|
||||
// }
|
||||
|
||||
// constexpr int x = f(1);
|
||||
public void testInitStatementInIfStatementCondition1() throws Exception {
|
||||
assertEvaluationEquals(7);
|
||||
}
|
||||
|
||||
// constexpr int g(int x) {
|
||||
// return x * 2;
|
||||
// }
|
||||
// constexpr int f(int y) {
|
||||
// if(int x = g(y); x != 2) {
|
||||
// return 14 / x;
|
||||
// } else {
|
||||
// return 0;
|
||||
// }
|
||||
// }
|
||||
|
||||
// constexpr int x = f(1);
|
||||
public void testInitStatementInIfStatementCondition2() throws Exception {
|
||||
assertEvaluationEquals(0);
|
||||
}
|
||||
|
||||
// constexpr int g(int x) {
|
||||
// return x * 2;
|
||||
// }
|
||||
// constexpr int f() {
|
||||
// if constexpr (constexpr int x = g(1); x != 2) {
|
||||
// return 14 / x;
|
||||
// } else {
|
||||
// return 0;
|
||||
// }
|
||||
// }
|
||||
|
||||
// constexpr int x = f();
|
||||
public void testInitStatementInIfStatementCondition3() throws Exception {
|
||||
assertEvaluationEquals(0);
|
||||
}
|
||||
|
||||
// constexpr int g(int x) {
|
||||
// return x * 2;
|
||||
// }
|
||||
// constexpr int f(int y) {
|
||||
// int x = g(y);
|
||||
// if(; x == 2) {
|
||||
// return 14 / x;
|
||||
// } else {
|
||||
// return 0;
|
||||
// }
|
||||
// }
|
||||
|
||||
// constexpr int x = f(1);
|
||||
public void testEmptyInitStatementInIfStatementCondition1() throws Exception {
|
||||
assertEvaluationEquals(7);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -146,7 +146,7 @@ int f()
|
|||
}
|
||||
|
||||
|
||||
//!IfStatementTest
|
||||
//!BasicNoBraceIfStatementTest
|
||||
//%CPP
|
||||
int g()
|
||||
{
|
||||
|
@ -210,7 +210,7 @@ int foo()
|
|||
}
|
||||
|
||||
|
||||
//!SwitchStatementTest
|
||||
//!CSwitchStatementTest
|
||||
//%C
|
||||
void foo()
|
||||
{
|
||||
|
@ -240,7 +240,7 @@ int foo(int a)
|
|||
}
|
||||
|
||||
|
||||
//!GNUSwitchStatementTest
|
||||
//!GNUCSwitchStatementTest
|
||||
//%C
|
||||
int foo(int a)
|
||||
{
|
||||
|
@ -323,8 +323,81 @@ int foo()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
//!ArrayDeclarationStatementTest
|
||||
//%CPP
|
||||
string* newElements = new string[m_capacity];
|
||||
|
||||
//!Basic Constexpr If
|
||||
//%CPP
|
||||
void f()
|
||||
{
|
||||
constexpr bool b{false};
|
||||
if constexpr (b){
|
||||
}
|
||||
}
|
||||
|
||||
//!Constexpr If with init-statement
|
||||
//%CPP
|
||||
void f()
|
||||
{
|
||||
if constexpr (constexpr bool b{false};b){
|
||||
}
|
||||
}
|
||||
|
||||
//!Constexpr If with init-statement and declaration
|
||||
//%CPP
|
||||
void f()
|
||||
{
|
||||
if constexpr (constexpr bool b{false};int k = 42){
|
||||
}
|
||||
}
|
||||
|
||||
//!If with init-statement
|
||||
//%CPP
|
||||
void f()
|
||||
{
|
||||
if (bool b{false};b == true){
|
||||
}
|
||||
}
|
||||
|
||||
//!If with init-statement and declaration
|
||||
//%CPP
|
||||
void f()
|
||||
{
|
||||
if (bool b{false};int k = 42){
|
||||
}
|
||||
}
|
||||
|
||||
//!If with constexpr init-statement and declaration
|
||||
//%CPP
|
||||
void f()
|
||||
{
|
||||
if (constexpr bool b{false};int k = 42){
|
||||
}
|
||||
}
|
||||
|
||||
//!If with empty init-statement and declaration
|
||||
//%CPP
|
||||
void f()
|
||||
{
|
||||
if (;int k = 42){
|
||||
}
|
||||
}
|
||||
|
||||
//!If with empty init-statement and expression
|
||||
//%CPP
|
||||
void f()
|
||||
{
|
||||
int k{42};
|
||||
if (;k == 42){
|
||||
}
|
||||
}
|
||||
|
||||
//!Constexpr If with empty init-statement and expression
|
||||
//%CPP
|
||||
void f()
|
||||
{
|
||||
constexpr int k{42};
|
||||
if constexpr (;k == 42){
|
||||
}
|
||||
}
|
|
@ -10,8 +10,10 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.core.dom.ast.cpp;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.ASTNodeProperty;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTIfStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IScope;
|
||||
|
||||
/**
|
||||
|
@ -21,6 +23,15 @@ import org.eclipse.cdt.core.dom.ast.IScope;
|
|||
* @noimplement This interface is not intended to be implemented by clients.
|
||||
*/
|
||||
public interface ICPPASTIfStatement extends IASTIfStatement {
|
||||
/**
|
||||
* {@code INIT_STATEMENT} represents the relationship between an
|
||||
* {@code ICPPASTIfStatement} and its nested {@code IASTStatement}.
|
||||
*
|
||||
* @since 6.5
|
||||
*/
|
||||
public static final ASTNodeProperty INIT_STATEMENT = new ASTNodeProperty(
|
||||
"ICPPASTIfStatement.INIT_STATEMENT - IASTStatement init-statement for ICPPASTIfStatement"); //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Returns the condition declaration. The condition declaration and the condition expression are
|
||||
* mutually exclusive.
|
||||
|
@ -34,7 +45,43 @@ public interface ICPPASTIfStatement extends IASTIfStatement {
|
|||
* Sets the condition declaration.
|
||||
*/
|
||||
public void setConditionDeclaration(IASTDeclaration d);
|
||||
|
||||
/**
|
||||
* Sets the isConstxpr member variable.
|
||||
*
|
||||
* @since 6.5
|
||||
*/
|
||||
public void setIsConstexpr(boolean isConstexpr);
|
||||
|
||||
/**
|
||||
* Checks whether this if statement is a constexpr if statement.
|
||||
*
|
||||
* @return true iff this if statement is a constexpr if.
|
||||
*
|
||||
* @since 6.5
|
||||
*/
|
||||
public boolean isConstexpr();
|
||||
|
||||
/**
|
||||
* Returns the init-statement for an if.
|
||||
*
|
||||
* @return the init-statement, or <code>null</code> if the 'if' statement doesn't
|
||||
* have one.
|
||||
*
|
||||
* @since 6.5
|
||||
*/
|
||||
public IASTStatement getInitializerStatement();
|
||||
|
||||
/**
|
||||
* Sets the optional init-statement of an if.
|
||||
*
|
||||
* @param statement this statement should either be a <code>IASTSimpleDeclaration</code> or a
|
||||
* <code>IASTExpressionStatement</code>.
|
||||
*
|
||||
* @since 6.5
|
||||
*/
|
||||
public void setInitializerStatement(IASTStatement statement);
|
||||
|
||||
/**
|
||||
* Returns the implicit <code>IScope</code> represented by this if statement
|
||||
*
|
||||
|
|
|
@ -2379,13 +2379,13 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
protected abstract IASTAmbiguousExpression createAmbiguousBinaryVsCastExpression(IASTBinaryExpression binary, IASTCastExpression castExpr);
|
||||
protected abstract IASTAmbiguousExpression createAmbiguousCastVsFunctionCallExpression(IASTCastExpression castExpr, IASTFunctionCallExpression funcCall);
|
||||
|
||||
protected IASTStatement forInitStatement() throws BacktrackException, EndOfFileException {
|
||||
protected IASTStatement initStatement() throws BacktrackException, EndOfFileException {
|
||||
if (LT(1) == IToken.tSEMI)
|
||||
return parseNullStatement();
|
||||
try {
|
||||
return parseDeclarationOrExpressionStatement();
|
||||
} catch (BacktrackException e) {
|
||||
// Missing semicolon within for loop does not make a complete for-statement
|
||||
// A init statement always terminates with a semicolon
|
||||
IASTNode before = e.getNodeBeforeProblem();
|
||||
if (before != null) {
|
||||
e.initialize(e.getProblem());
|
||||
|
|
|
@ -2144,7 +2144,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
int startOffset;
|
||||
startOffset = consume().getOffset();
|
||||
consume(IToken.tLPAREN);
|
||||
IASTStatement init = forInitStatement();
|
||||
IASTStatement init = initStatement();
|
||||
IASTExpression for_condition = null;
|
||||
switch (LT(1)) {
|
||||
case IToken.tSEMI:
|
||||
|
|
|
@ -29,6 +29,8 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecSimpleDeclarat
|
|||
* If statement in C++
|
||||
*/
|
||||
public class CPPASTIfStatement extends CPPASTAttributeOwner implements ICPPASTIfStatement, ICPPExecutionOwner {
|
||||
private boolean isConstexpr;
|
||||
private IASTStatement initStatement;
|
||||
private IASTExpression condition;
|
||||
private IASTStatement thenClause;
|
||||
private IASTStatement elseClause;
|
||||
|
@ -44,7 +46,7 @@ public class CPPASTIfStatement extends CPPASTAttributeOwner implements ICPPASTIf
|
|||
setElseClause(elseClause);
|
||||
}
|
||||
|
||||
public CPPASTIfStatement(IASTExpression condition, IASTStatement thenClause, IASTStatement elseClause) {
|
||||
public CPPASTIfStatement(IASTExpression condition, IASTStatement thenClause, IASTStatement elseClause) {
|
||||
setConditionExpression(condition);
|
||||
setThenClause(thenClause);
|
||||
setElseClause(elseClause);
|
||||
|
@ -58,6 +60,8 @@ public class CPPASTIfStatement extends CPPASTAttributeOwner implements ICPPASTIf
|
|||
@Override
|
||||
public CPPASTIfStatement copy(CopyStyle style) {
|
||||
CPPASTIfStatement copy = new CPPASTIfStatement();
|
||||
copy.setIsConstexpr(isConstexpr);
|
||||
copy.setInitializerStatement(initStatement == null ? null : initStatement.copy(style));
|
||||
copy.setConditionDeclaration(condDecl == null ? null : condDecl.copy(style));
|
||||
copy.setConditionExpression(condition == null ? null : condition.copy(style));
|
||||
copy.setThenClause(thenClause == null ? null : thenClause.copy(style));
|
||||
|
@ -137,7 +141,10 @@ public class CPPASTIfStatement extends CPPASTAttributeOwner implements ICPPASTIf
|
|||
|
||||
if (!((CPPASTIfStatement) stmt).acceptByAttributeSpecifiers(action)) return false;
|
||||
|
||||
IASTNode child = stmt.getConditionExpression();
|
||||
IASTNode child = stmt.getInitializerStatement();
|
||||
if (child != null && !child.accept(action))
|
||||
return false;
|
||||
child = stmt.getConditionExpression();
|
||||
if (child != null && !child.accept(action))
|
||||
return false;
|
||||
child= stmt.getConditionDeclaration();
|
||||
|
@ -175,17 +182,28 @@ public class CPPASTIfStatement extends CPPASTAttributeOwner implements ICPPASTIf
|
|||
|
||||
@Override
|
||||
public void replace(IASTNode child, IASTNode other) {
|
||||
if (initStatement == child) {
|
||||
other.setParent(child.getParent());
|
||||
other.setPropertyInParent(child.getPropertyInParent());
|
||||
initStatement = (IASTStatement) other;
|
||||
return;
|
||||
}
|
||||
|
||||
if (thenClause == child) {
|
||||
other.setParent(child.getParent());
|
||||
other.setPropertyInParent(child.getPropertyInParent());
|
||||
thenClause = (IASTStatement) other;
|
||||
return;
|
||||
} else if (elseClause == child) {
|
||||
}
|
||||
|
||||
if (elseClause == child) {
|
||||
other.setParent(child.getParent());
|
||||
other.setPropertyInParent(child.getPropertyInParent());
|
||||
elseClause = (IASTStatement) other;
|
||||
return;
|
||||
} else if (condition == child || condDecl == child) {
|
||||
}
|
||||
|
||||
if (condition == child || condDecl == child) {
|
||||
if (other instanceof IASTExpression) {
|
||||
setConditionExpression((IASTExpression) other);
|
||||
} else if (other instanceof IASTDeclaration) {
|
||||
|
@ -193,6 +211,7 @@ public class CPPASTIfStatement extends CPPASTAttributeOwner implements ICPPASTIf
|
|||
}
|
||||
return;
|
||||
}
|
||||
|
||||
super.replace(child, other);
|
||||
}
|
||||
|
||||
|
@ -212,6 +231,33 @@ public class CPPASTIfStatement extends CPPASTAttributeOwner implements ICPPASTIf
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConstexpr() {
|
||||
return isConstexpr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIsConstexpr(boolean isConstexpr) {
|
||||
assertNotFrozen();
|
||||
this.isConstexpr = isConstexpr;
|
||||
}
|
||||
|
||||
@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
|
||||
public IScope getScope() {
|
||||
if (scope == null)
|
||||
|
@ -221,12 +267,13 @@ public class CPPASTIfStatement extends CPPASTAttributeOwner implements ICPPASTIf
|
|||
|
||||
@Override
|
||||
public ICPPExecution getExecution() {
|
||||
ICPPExecution initStmtExec = EvalUtil.getExecutionFromStatement(getInitializerStatement());
|
||||
ICPPASTExpression conditionExpr = (ICPPASTExpression) getConditionExpression();
|
||||
ICPPExecutionOwner conditionDecl = (ICPPExecutionOwner) getConditionDeclaration();
|
||||
ICPPEvaluation conditionExprEval = conditionExpr != null ? conditionExpr.getEvaluation() : null;
|
||||
ExecSimpleDeclaration conditionDeclExec = conditionDecl != null ? (ExecSimpleDeclaration) conditionDecl.getExecution() : null;
|
||||
ICPPExecution thenClauseExec = EvalUtil.getExecutionFromStatement(getThenClause());
|
||||
ICPPExecution elseClauseExec = getElseClause() != null ? EvalUtil.getExecutionFromStatement(getElseClause()) : null;
|
||||
return new ExecIf(conditionExprEval, conditionDeclExec, thenClauseExec, elseClauseExec);
|
||||
ICPPExecution elseClauseExec = EvalUtil.getExecutionFromStatement(getElseClause());
|
||||
return new ExecIf(isConstexpr, initStmtExec, conditionExprEval, conditionDeclExec, thenClauseExec, elseClauseExec);
|
||||
}
|
||||
}
|
|
@ -5270,26 +5270,38 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
int start = LA(1).getOffset();
|
||||
if_loop: while (true) {
|
||||
int so = consume(IToken.t_if).getOffset();
|
||||
ICPPASTIfStatement new_if_statement = getNodeFactory().newIfStatement();
|
||||
// constexpr if
|
||||
if (LT(1) == IToken.t_constexpr) {
|
||||
consume();
|
||||
new_if_statement.setIsConstexpr(true);
|
||||
}
|
||||
consume(IToken.tLPAREN);
|
||||
// init-statement
|
||||
IToken mark= mark();
|
||||
try {
|
||||
IASTStatement statement = initStatement();
|
||||
new_if_statement.setInitializerStatement(statement);
|
||||
} catch (BacktrackException e) {
|
||||
backup(mark);
|
||||
}
|
||||
// condition
|
||||
IASTNode condition= cppStyleCondition(IToken.tRPAREN);
|
||||
if (LT(1) == IToken.tEOC) {
|
||||
// Completing in the condition
|
||||
ICPPASTIfStatement new_if = getNodeFactory().newIfStatement();
|
||||
if (condition instanceof IASTExpression)
|
||||
new_if.setConditionExpression((IASTExpression) condition);
|
||||
new_if_statement.setConditionExpression((IASTExpression) condition);
|
||||
else if (condition instanceof IASTDeclaration)
|
||||
new_if.setConditionDeclaration((IASTDeclaration) condition);
|
||||
new_if_statement.setConditionDeclaration((IASTDeclaration) condition);
|
||||
|
||||
if (if_statement != null) {
|
||||
if_statement.setElseClause(new_if);
|
||||
if_statement.setElseClause(new_if_statement);
|
||||
}
|
||||
return result != null ? result : new_if;
|
||||
return result != null ? result : new_if_statement;
|
||||
}
|
||||
consume(IToken.tRPAREN);
|
||||
|
||||
IASTStatement thenClause = statement();
|
||||
ICPPASTIfStatement new_if_statement = getNodeFactory().newIfStatement();
|
||||
((ASTNode) new_if_statement).setOffset(so);
|
||||
if (condition != null && (condition instanceof IASTExpression || condition instanceof IASTDeclaration))
|
||||
// shouldn't be possible but failure in condition() makes it so
|
||||
|
@ -5447,7 +5459,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
}
|
||||
|
||||
private IASTForStatement startTraditionalForLoop() throws BacktrackException, EndOfFileException {
|
||||
final IASTStatement initStmt = forInitStatement();
|
||||
final IASTStatement initStmt = initStatement();
|
||||
IASTNode condition= null;
|
||||
IASTExpression iterExpr= null;
|
||||
|
||||
|
|
|
@ -1624,7 +1624,14 @@ public class CPPSemantics {
|
|||
} else if (parent instanceof ICPPASTSwitchStatement) {
|
||||
nodes = new IASTNode[] { ((ICPPASTSwitchStatement) parent).getControllerDeclaration() };
|
||||
} else if (parent instanceof ICPPASTIfStatement) {
|
||||
nodes = new IASTNode[] { ((ICPPASTIfStatement) parent).getConditionDeclaration() };
|
||||
ICPPASTIfStatement ifStatement = (ICPPASTIfStatement) parent;
|
||||
final IASTStatement initStatement = ifStatement.getInitializerStatement();
|
||||
final IASTDeclaration conditionDeclaration = ifStatement.getConditionDeclaration();
|
||||
if (initStatement != null) {
|
||||
nodes = new IASTNode[] {initStatement, conditionDeclaration};
|
||||
} else {
|
||||
nodes = new IASTNode[] {conditionDeclaration};
|
||||
}
|
||||
} else if (parent instanceof ICPPASTWhileStatement) {
|
||||
nodes = new IASTNode[] { ((ICPPASTWhileStatement) parent).getConditionDeclaration() };
|
||||
} else if (parent instanceof ICPPASTRangeBasedForStatement) {
|
||||
|
|
|
@ -16,28 +16,41 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.InstantiationContext;
|
|||
import org.eclipse.core.runtime.CoreException;
|
||||
|
||||
public class ExecIf implements ICPPExecution {
|
||||
private final boolean isConstexpr;
|
||||
private final ICPPExecution initStmtExec;
|
||||
private final ICPPEvaluation conditionExprEval;
|
||||
private final ExecSimpleDeclaration conditionDeclExec;
|
||||
private final ICPPExecution thenClauseExec;
|
||||
private final ICPPExecution elseClauseExec;
|
||||
|
||||
public ExecIf(ICPPEvaluation conditionExprEval, ExecSimpleDeclaration conditionDeclExec, ICPPExecution thenClauseExec, ICPPExecution elseClauseExec) {
|
||||
public ExecIf(boolean isConstexpr, ICPPExecution initStmtExec, ICPPEvaluation conditionExprEval, ExecSimpleDeclaration conditionDeclExec, ICPPExecution thenClauseExec, ICPPExecution elseClauseExec) {
|
||||
this.isConstexpr = isConstexpr;
|
||||
this.initStmtExec = initStmtExec;
|
||||
this.conditionExprEval = conditionExprEval;
|
||||
this.conditionDeclExec = conditionDeclExec;
|
||||
this.thenClauseExec = thenClauseExec;
|
||||
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) {
|
||||
if (conditionExprEval != null) {
|
||||
return EvalUtil.conditionExprSatisfied(conditionExprEval, record, context);
|
||||
} else if (conditionDeclExec != null) {
|
||||
return EvalUtil.conditionDeclSatisfied(conditionDeclExec, record, context);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICPPExecution executeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context) {
|
||||
boolean conditionSatisfied = false;
|
||||
if (conditionExprEval != null) {
|
||||
conditionSatisfied = EvalUtil.conditionExprSatisfied(conditionExprEval, record, context);
|
||||
} else if (conditionDeclExec != null) {
|
||||
conditionSatisfied = EvalUtil.conditionDeclSatisfied(conditionDeclExec, record, context);
|
||||
}
|
||||
|
||||
if (conditionSatisfied) {
|
||||
executeInitStatement(record, context);
|
||||
if (conditionSatisfied(record, context)) {
|
||||
return EvalUtil.executeStatement(thenClauseExec, record, context);
|
||||
} else if (elseClauseExec != null) {
|
||||
return EvalUtil.executeStatement(elseClauseExec, record, context);
|
||||
|
@ -47,19 +60,44 @@ public class ExecIf implements ICPPExecution {
|
|||
|
||||
@Override
|
||||
public ICPPExecution instantiate(InstantiationContext context, int maxDepth) {
|
||||
ICPPExecution newInitStmtExec = initStmtExec != null ? initStmtExec.instantiate(context, maxDepth) : null;
|
||||
ICPPEvaluation newConditionExprEval = conditionExprEval != null ? conditionExprEval.instantiate(context, maxDepth) : null;
|
||||
ExecSimpleDeclaration newConditionDeclExec = conditionDeclExec != null ? (ExecSimpleDeclaration) conditionDeclExec.instantiate(context, maxDepth) : null;
|
||||
ICPPExecution newThenClauseExec = thenClauseExec.instantiate(context, maxDepth);
|
||||
ICPPExecution newElseClauseExec = elseClauseExec != null ? elseClauseExec.instantiate(context, maxDepth) : null;
|
||||
if (newConditionExprEval == conditionExprEval && newConditionDeclExec == conditionDeclExec && newThenClauseExec == thenClauseExec && newElseClauseExec == elseClauseExec) {
|
||||
|
||||
ICPPExecution newThenClauseExec = null;
|
||||
ICPPExecution newElseClauseExec = null;
|
||||
|
||||
if (isConstexpr && newConditionExprEval != null && newConditionExprEval.getValue().numberValue() != null) {
|
||||
if (newConditionExprEval.getValue().numberValue().intValue() != 0) {
|
||||
/*
|
||||
* We can't just "return newThenClauseExec" here, because the condition
|
||||
* might have side effects so it needs to be preserved in the instantiated
|
||||
* execution even if one of its branch has become null
|
||||
*/
|
||||
newThenClauseExec = thenClauseExec.instantiate(context, maxDepth);
|
||||
} else {
|
||||
newElseClauseExec = elseClauseExec != null ? elseClauseExec.instantiate(context, maxDepth) : null;
|
||||
}
|
||||
} else {
|
||||
newThenClauseExec = thenClauseExec.instantiate(context, maxDepth);
|
||||
newElseClauseExec = elseClauseExec != null ? elseClauseExec.instantiate(context, maxDepth) : null;
|
||||
}
|
||||
|
||||
if (newInitStmtExec == initStmtExec && newConditionExprEval == conditionExprEval && newConditionDeclExec == conditionDeclExec
|
||||
&& newThenClauseExec == thenClauseExec && newElseClauseExec == elseClauseExec) {
|
||||
return this;
|
||||
}
|
||||
return new ExecIf(newConditionExprEval, newConditionDeclExec, newThenClauseExec, newElseClauseExec);
|
||||
return new ExecIf(isConstexpr, newInitStmtExec, newConditionExprEval, newConditionDeclExec, newThenClauseExec, newElseClauseExec);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void marshal(ITypeMarshalBuffer buffer, boolean includeValue) throws CoreException {
|
||||
buffer.putShort(ITypeMarshalBuffer.EXEC_IF);
|
||||
short firstBytes = ITypeMarshalBuffer.EXEC_IF;
|
||||
if (isConstexpr) {
|
||||
firstBytes |= ITypeMarshalBuffer.FLAG1;
|
||||
}
|
||||
buffer.putShort(firstBytes);
|
||||
buffer.marshalExecution(initStmtExec, includeValue);
|
||||
buffer.marshalEvaluation(conditionExprEval, includeValue);
|
||||
buffer.marshalExecution(conditionDeclExec, includeValue);
|
||||
buffer.marshalExecution(thenClauseExec, includeValue);
|
||||
|
@ -67,10 +105,12 @@ public class ExecIf implements ICPPExecution {
|
|||
}
|
||||
|
||||
public static ICPPExecution unmarshal(short firstBytes, ITypeMarshalBuffer buffer) throws CoreException {
|
||||
boolean isConstexpr = (firstBytes & ITypeMarshalBuffer.FLAG1) != 0;
|
||||
ICPPExecution initStmtExec = buffer.unmarshalExecution();
|
||||
ICPPEvaluation conditionExprEval = buffer.unmarshalEvaluation();
|
||||
ExecSimpleDeclaration conditionDeclExec = (ExecSimpleDeclaration) buffer.unmarshalExecution();
|
||||
ICPPExecution thenClauseExec = buffer.unmarshalExecution();
|
||||
ICPPExecution elseClauseExec = buffer.unmarshalExecution();
|
||||
return new ExecIf(conditionExprEval, conditionDeclExec, thenClauseExec, elseClauseExec);
|
||||
return new ExecIf(isConstexpr, initStmtExec, conditionExprEval, conditionDeclExec, thenClauseExec, elseClauseExec);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,7 +65,8 @@ public class StatementWriter extends NodeWriter {
|
|||
private static final String CONTINUE = "continue"; //$NON-NLS-1$
|
||||
private static final String BREAK = "break"; //$NON-NLS-1$
|
||||
private static final String ELSE = "else"; //$NON-NLS-1$
|
||||
private static final String IF = "if ("; //$NON-NLS-1$
|
||||
private static final String IF = "if "; //$NON-NLS-1$
|
||||
private static final String CONSTEXPR = "constexpr "; //$NON-NLS-1$
|
||||
private static final String FOR = "for ("; //$NON-NLS-1$
|
||||
private static final String DO_WHILE = " while ("; //$NON-NLS-1$
|
||||
private static final String DO = "do"; //$NON-NLS-1$
|
||||
|
@ -216,10 +217,18 @@ public class StatementWriter extends NodeWriter {
|
|||
|
||||
private void writeIfStatement(IASTIfStatement ifStatement) {
|
||||
scribe.print(IF);
|
||||
final boolean isCPPIfStatement = ifStatement instanceof ICPPASTIfStatement;
|
||||
if (isCPPIfStatement && ((ICPPASTIfStatement) ifStatement).isConstexpr()) {
|
||||
scribe.print(CONSTEXPR);
|
||||
}
|
||||
scribe.print('(');
|
||||
scribe.noNewLines();
|
||||
if (ifStatement instanceof ICPPASTIfStatement) {
|
||||
if (isCPPIfStatement) {
|
||||
ICPPASTIfStatement cppIfStatment = (ICPPASTIfStatement) ifStatement;
|
||||
|
||||
IASTStatement initStatement = cppIfStatment.getInitializerStatement();
|
||||
if (initStatement != null) {
|
||||
writeStatement(initStatement, false);
|
||||
}
|
||||
if (cppIfStatment.getConditionDeclaration() == null) {
|
||||
cppIfStatment.getConditionExpression().accept(visitor);
|
||||
} else {
|
||||
|
|
|
@ -289,10 +289,13 @@ public class PDOM extends PlatformObject implements IPDOM {
|
|||
* 209.0 - Alias templates and their instances take up more space than required, bug 516385.
|
||||
* 210.0 - Return type deduction, bug 408470.
|
||||
* 211.0 - Change representation of alias template instances, bug 516338.
|
||||
*
|
||||
* CDT 9.5 development (version not supported on the 9.4.x branch)
|
||||
* 212.0 - C++ constexpr if and if init-statement evaluation
|
||||
*/
|
||||
private static final int MIN_SUPPORTED_VERSION= version(211, 0);
|
||||
private static final int MAX_SUPPORTED_VERSION= version(211, Short.MAX_VALUE);
|
||||
private static final int DEFAULT_VERSION = version(211, 0);
|
||||
private static final int MIN_SUPPORTED_VERSION= version(212, 0);
|
||||
private static final int MAX_SUPPORTED_VERSION= version(212, Short.MAX_VALUE);
|
||||
private static final int DEFAULT_VERSION = version(212, 0);
|
||||
|
||||
private static int version(int major, int minor) {
|
||||
return (major << 16) + minor;
|
||||
|
|
|
@ -268,7 +268,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
|
|||
private class TrailingSemicolonFormatter extends TrailingTokenFormatter {
|
||||
TrailingSemicolonFormatter(IASTNode node) {
|
||||
super(Token.tSEMI, getLastNodeCharacterPosition(node),
|
||||
fInsideFor ? preferences.insert_space_before_semicolon_in_for :
|
||||
fHasClauseInitStatement ? preferences.insert_space_before_semicolon_in_for :
|
||||
preferences.insert_space_before_semicolon,
|
||||
false);
|
||||
}
|
||||
|
@ -396,7 +396,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
|
|||
final DefaultCodeFormatterOptions preferences;
|
||||
private final Scribe scribe;
|
||||
|
||||
private boolean fInsideFor;
|
||||
private boolean fHasClauseInitStatement;
|
||||
private boolean fInsideMacroArguments;
|
||||
private boolean fExpectSemicolonAfterDeclaration= true;
|
||||
|
||||
|
@ -3134,7 +3134,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
|
|||
}
|
||||
|
||||
private int visit(IASTNullStatement node) {
|
||||
if (!fInsideFor && nodeOffset(node) == getCurrentPosition()) {
|
||||
if (!fHasClauseInitStatement && nodeOffset(node) == getCurrentPosition()) {
|
||||
scribe.printNextToken(Token.tSEMI, preferences.insert_space_before_semicolon);
|
||||
scribe.printTrailingComment();
|
||||
}
|
||||
|
@ -3143,7 +3143,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
|
|||
|
||||
private int visit(IASTDeclarationStatement node) {
|
||||
node.getDeclaration().accept(this);
|
||||
if (!fInsideFor) {
|
||||
if (!fHasClauseInitStatement) {
|
||||
scribe.startNewLine();
|
||||
}
|
||||
return PROCESS_SKIP;
|
||||
|
@ -3151,7 +3151,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
|
|||
|
||||
private int visit(IASTExpressionStatement node) {
|
||||
Runnable semicolonFormatter = null;
|
||||
if (!fInsideFor) {
|
||||
if (!fHasClauseInitStatement) {
|
||||
semicolonFormatter = new TrailingSemicolonFormatter(node);
|
||||
scribe.setTailFormatter(semicolonFormatter);
|
||||
}
|
||||
|
@ -3160,7 +3160,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
|
|||
semicolonFormatter.run();
|
||||
scribe.setTailFormatter(null);
|
||||
}
|
||||
if (!fInsideFor) {
|
||||
if (!fHasClauseInitStatement) {
|
||||
scribe.startNewLine();
|
||||
}
|
||||
return PROCESS_SKIP;
|
||||
|
@ -3176,7 +3176,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
|
|||
Runnable tailFormatter = null;
|
||||
if (!doNodesHaveSameOffset(node, initializerStmt)) {
|
||||
scribe.printNextToken(Token.tLPAREN, preferences.insert_space_before_opening_paren_in_for);
|
||||
fInsideFor= true;
|
||||
fHasClauseInitStatement = true;
|
||||
if (preferences.insert_space_after_opening_paren_in_for) {
|
||||
scribe.space();
|
||||
}
|
||||
|
@ -3240,7 +3240,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
|
|||
scribe.setTailFormatter(null);
|
||||
}
|
||||
} finally {
|
||||
fInsideFor= false;
|
||||
fHasClauseInitStatement= false;
|
||||
}
|
||||
ok = true;
|
||||
} catch (AlignmentException e) {
|
||||
|
@ -3271,7 +3271,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
|
|||
scribe.printNextToken(Token.t_for);
|
||||
final int line = scribe.line;
|
||||
scribe.printNextToken(Token.tLPAREN, preferences.insert_space_before_opening_paren_in_for);
|
||||
fInsideFor= true;
|
||||
fHasClauseInitStatement= true;
|
||||
try {
|
||||
if (preferences.insert_space_after_opening_paren_in_for) {
|
||||
scribe.space();
|
||||
|
@ -3285,7 +3285,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
|
|||
}
|
||||
initializer.accept(this);
|
||||
} finally {
|
||||
fInsideFor= false;
|
||||
fHasClauseInitStatement= false;
|
||||
}
|
||||
if (peekNextToken() == Token.tRPAREN) {
|
||||
scribe.printNextToken(Token.tRPAREN, preferences.insert_space_before_closing_paren_in_for);
|
||||
|
@ -3295,24 +3295,46 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
|
|||
return PROCESS_SKIP;
|
||||
}
|
||||
|
||||
private void beginIfClause() {
|
||||
scribe.printNextToken(Token.tLPAREN, preferences.insert_space_before_opening_paren_in_if);
|
||||
if (preferences.insert_space_after_opening_paren_in_if) {
|
||||
scribe.space();
|
||||
}
|
||||
}
|
||||
|
||||
private int visit(IASTIfStatement node) {
|
||||
if (!startsWithMacroExpansion(node)) {
|
||||
scribe.printNextToken(Token.t_if);
|
||||
}
|
||||
final int line = scribe.line;
|
||||
IASTNode condition = node.getConditionExpression();
|
||||
if (condition == null && node instanceof ICPPASTIfStatement) {
|
||||
condition = ((ICPPASTIfStatement) node).getConditionDeclaration();
|
||||
}
|
||||
final IASTStatement thenStatement = node.getThenClause();
|
||||
final IASTStatement elseStatement = node.getElseClause();
|
||||
|
||||
fExpectSemicolonAfterDeclaration= false;
|
||||
|
||||
fExpectSemicolonAfterDeclaration = false;
|
||||
try {
|
||||
if (condition == null || !doNodesHaveSameOffset(node, condition)) {
|
||||
scribe.printNextToken(Token.tLPAREN, preferences.insert_space_before_opening_paren_in_if);
|
||||
if (preferences.insert_space_after_opening_paren_in_if) {
|
||||
if (node instanceof ICPPASTIfStatement) {
|
||||
ICPPASTIfStatement cppIfStatment = (ICPPASTIfStatement) node;
|
||||
if (cppIfStatment.isConstexpr()) {
|
||||
scribe.space();
|
||||
scribe.printNextToken(Token.t_constexpr);
|
||||
scribe.space();
|
||||
}
|
||||
IASTStatement initStatement = cppIfStatment.getInitializerStatement();
|
||||
if (initStatement != null) {
|
||||
beginIfClause();
|
||||
fHasClauseInitStatement = true;
|
||||
initStatement.accept(this);
|
||||
if (preferences.insert_space_after_semicolon_in_for) {
|
||||
scribe.space();
|
||||
}
|
||||
}
|
||||
if (condition == null) {
|
||||
condition = ((ICPPASTIfStatement) node).getConditionDeclaration();
|
||||
}
|
||||
}
|
||||
if (condition == null || !doNodesHaveSameOffset(node, condition)) {
|
||||
if (!fHasClauseInitStatement) {
|
||||
beginIfClause();
|
||||
}
|
||||
Runnable tailFormatter = null;
|
||||
if (DefaultCodeFormatterConstants.END_OF_LINE.equals(preferences.brace_position_for_block) &&
|
||||
|
@ -3334,7 +3356,8 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
|
|||
condition.accept(this);
|
||||
}
|
||||
} finally {
|
||||
fExpectSemicolonAfterDeclaration= true;
|
||||
fHasClauseInitStatement = false;
|
||||
fExpectSemicolonAfterDeclaration = true;
|
||||
}
|
||||
|
||||
boolean thenStatementIsBlock = false;
|
||||
|
@ -3357,7 +3380,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
|
|||
scribe.printTrailingComment();
|
||||
} else {
|
||||
if (getCurrentPosition() <= nodeOffset(thenStatement)) {
|
||||
formatLeftCurlyBrace(line, preferences.brace_position_for_block);
|
||||
formatLeftCurlyBrace(scribe.line, preferences.brace_position_for_block);
|
||||
}
|
||||
thenStatement.accept(this);
|
||||
if (elseStatement != null && preferences.insert_new_line_before_else_in_if_statement) {
|
||||
|
|
|
@ -888,6 +888,7 @@ public class SimpleScanner {
|
|||
fgKeywords.put("compl", Integer.valueOf(Token.t_compl)); //$NON-NLS-1$
|
||||
fgKeywords.put("const", Integer.valueOf(Token.t_const)); //$NON-NLS-1$
|
||||
fgKeywords.put("const_cast", Integer.valueOf(Token.t_const_cast)); //$NON-NLS-1$
|
||||
fgKeywords.put("constexpr", Integer.valueOf(Token.t_constexpr)); //$NON-NLS-1$
|
||||
fgKeywords.put("continue", Integer.valueOf(Token.t_continue)); //$NON-NLS-1$
|
||||
fgKeywords.put("default", Integer.valueOf(Token.t_default)); //$NON-NLS-1$
|
||||
fgKeywords.put("delete", Integer.valueOf(Token.t_delete)); //$NON-NLS-1$
|
||||
|
|
|
@ -505,4 +505,5 @@ public class Token {
|
|||
static public final int t_byte = 214;
|
||||
static public final int t_transient = 215;
|
||||
static public final int t_native = 216;
|
||||
static public final int t_constexpr = 5400;
|
||||
}
|
||||
|
|
|
@ -3209,4 +3209,107 @@ public class CodeFormatterTest extends BaseUITestCase {
|
|||
public void testSizeofParameterPackFormat_464498() throws Exception {
|
||||
assertFormatterResult();
|
||||
}
|
||||
|
||||
//void foo() {
|
||||
// if constexpr (constexpr bool k = true) {
|
||||
// }
|
||||
//}
|
||||
|
||||
//void foo() {
|
||||
// if constexpr (constexpr bool k = true) {
|
||||
// }
|
||||
//}
|
||||
public void testConstexprIfFormat_1() throws Exception {
|
||||
assertFormatterResult();
|
||||
}
|
||||
|
||||
//void foo() {
|
||||
// if
|
||||
// constexpr (constexpr bool k = true) {
|
||||
// }
|
||||
//}
|
||||
|
||||
//void foo() {
|
||||
// if constexpr (constexpr bool k = true) {
|
||||
// }
|
||||
//}
|
||||
public void testConstexprIfFormat_2() throws Exception {
|
||||
assertFormatterResult();
|
||||
}
|
||||
|
||||
//void foo() {
|
||||
// if
|
||||
//
|
||||
// constexpr
|
||||
// (constexpr bool k = true) {
|
||||
// }
|
||||
//}
|
||||
|
||||
//void foo() {
|
||||
// if
|
||||
//
|
||||
// constexpr (constexpr bool k = true) {
|
||||
// }
|
||||
//}
|
||||
public void testConstexprIfFormat_3() throws Exception {
|
||||
assertFormatterResult();
|
||||
}
|
||||
|
||||
//void foo() {
|
||||
// if constexpr (constexpr bool k = true; k) {
|
||||
// }
|
||||
//}
|
||||
|
||||
//void foo() {
|
||||
// if constexpr (constexpr bool k = true; k) {
|
||||
// }
|
||||
//}
|
||||
public void testIfInitStatementFormat_1() throws Exception {
|
||||
assertFormatterResult();
|
||||
}
|
||||
|
||||
//void foo() {
|
||||
// if
|
||||
// constexpr (constexpr bool k = true; k) {
|
||||
// }
|
||||
//}
|
||||
|
||||
//void foo() {
|
||||
// if constexpr (constexpr bool k = true; k) {
|
||||
// }
|
||||
//}
|
||||
public void testIfInitStatementFormat_2() throws Exception {
|
||||
assertFormatterResult();
|
||||
}
|
||||
|
||||
//void foo() {
|
||||
// if
|
||||
//
|
||||
// constexpr
|
||||
// (constexpr bool k = true; k) {
|
||||
// }
|
||||
//}
|
||||
|
||||
//void foo() {
|
||||
// if
|
||||
//
|
||||
// constexpr (constexpr bool k = true; k) {
|
||||
// }
|
||||
//}
|
||||
public void testIfInitStatementFormat_3() throws Exception {
|
||||
assertFormatterResult();
|
||||
}
|
||||
|
||||
//void foo() {
|
||||
// if (constexpr bool k = true;k) {
|
||||
// }
|
||||
//}
|
||||
|
||||
//void foo() {
|
||||
// if (constexpr bool k = true; k) {
|
||||
// }
|
||||
//}
|
||||
public void testIfInitStatementFormat_4() throws Exception {
|
||||
assertFormatterResult();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue