diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java index 7afb03ee66f..41617c39b38 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java @@ -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 + // struct meta { + // static constexpr int value = 1 + meta::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 + // constexpr int foo() { + // if constexpr (N % 2 != 0) { + // return meta::value; + // } else { + // return meta::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 + // struct meta { + // static constexpr int value = 1 + meta::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 + // constexpr int foo() { + // if constexpr (N % 2 == 0) { + // return meta::value; + // } else { + // return meta::value; + // } + // } + // + // // Call the function + // constexpr int waldo = foo<7>(); + public void testConditionalInstantiationOfConstexprIfFalseBranch_527427() throws Exception { + BindingAssertionHelper helper = getAssertionHelper(); + helper.assertVariableValue("waldo", 3); + } + + // template + // constexpr int fib() { + // if constexpr (N == 0) { + // return 0; + // } else if constexpr (N == 1) { + // return 1; + // } else { + // return fib() + fib(); + // } + // } + // + // // 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 + // 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 + // 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); + } } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMLocationTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMLocationTests.java index 1b9512e9ccc..c26b65b589a 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMLocationTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMLocationTests.java @@ -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; diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/cxx14/constexpr/IfStatementTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/cxx14/constexpr/IfStatementTests.java index b150653c6a1..956d655d00c 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/cxx14/constexpr/IfStatementTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/cxx14/constexpr/IfStatementTests.java @@ -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); + } } diff --git a/core/org.eclipse.cdt.core.tests/resources/rewrite/ASTWriterStatementTestSource.awts b/core/org.eclipse.cdt.core.tests/resources/rewrite/ASTWriterStatementTestSource.awts index 603eaf61fe1..766d3c6e588 100644 --- a/core/org.eclipse.cdt.core.tests/resources/rewrite/ASTWriterStatementTestSource.awts +++ b/core/org.eclipse.cdt.core.tests/resources/rewrite/ASTWriterStatementTestSource.awts @@ -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){ + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTIfStatement.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTIfStatement.java index 372b9dec6f4..6ef782f4350 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTIfStatement.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTIfStatement.java @@ -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 null 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 IASTSimpleDeclaration or a + * IASTExpressionStatement. + * + * @since 6.5 + */ + public void setInitializerStatement(IASTStatement statement); + /** * Returns the implicit IScope represented by this if statement * diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java index 1a9ed31648a..54633ceccef 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java @@ -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()); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GNUCSourceParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GNUCSourceParser.java index 2622b978491..515c6ee5d60 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GNUCSourceParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GNUCSourceParser.java @@ -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: diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTIfStatement.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTIfStatement.java index 1de85dcfc72..db928914f2e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTIfStatement.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTIfStatement.java @@ -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); } } \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java index 0169f1e521b..d3717ffe206 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java @@ -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; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java index 84f7b656cb4..53ab4f75f1c 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java @@ -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) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecIf.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecIf.java index d0ba059f28b..4c12afdafa3 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecIf.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecIf.java @@ -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); } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/astwriter/StatementWriter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/astwriter/StatementWriter.java index 69d9c11dac5..ce6713198a7 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/astwriter/StatementWriter.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/astwriter/StatementWriter.java @@ -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 { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java index c99dccbdd56..127f9bf3628 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java @@ -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; diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/CodeFormatterVisitor.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/CodeFormatterVisitor.java index 99d2d0d7349..37c34403a62 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/CodeFormatterVisitor.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/CodeFormatterVisitor.java @@ -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) { diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/scanner/SimpleScanner.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/scanner/SimpleScanner.java index 801e9ed2db9..eead44e613c 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/scanner/SimpleScanner.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/scanner/SimpleScanner.java @@ -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$ diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/scanner/Token.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/scanner/Token.java index 9cbe4a5918f..8226a36e5aa 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/scanner/Token.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/scanner/Token.java @@ -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; } diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CodeFormatterTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CodeFormatterTest.java index f9e30efddb1..7477575c0f8 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CodeFormatterTest.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CodeFormatterTest.java @@ -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(); + } }