return visitDoStmt(cast<DoStmt>(S));
case Stmt::ForStmtClass:
return visitForStmt(cast<ForStmt>(S));
+ case Stmt::CXXForRangeStmtClass:
+ return visitCXXForRangeStmt(cast<CXXForRangeStmt>(S));
case Stmt::BreakStmtClass:
return visitBreakStmt(cast<BreakStmt>(S));
case Stmt::ContinueStmtClass:
}
template <class Emitter>
+bool ByteCodeStmtGen<Emitter>::visitCXXForRangeStmt(const CXXForRangeStmt *S) {
+ const Stmt *Init = S->getInit();
+ const Expr *Cond = S->getCond();
+ const Expr *Inc = S->getInc();
+ const Stmt *Body = S->getBody();
+ const Stmt *BeginStmt = S->getBeginStmt();
+ const Stmt *RangeStmt = S->getRangeStmt();
+ const Stmt *EndStmt = S->getEndStmt();
+ const VarDecl *LoopVar = S->getLoopVariable();
+
+ LabelTy EndLabel = this->getLabel();
+ LabelTy CondLabel = this->getLabel();
+ LabelTy IncLabel = this->getLabel();
+ ExprScope<Emitter> ES(this);
+ LoopScope<Emitter> LS(this, EndLabel, IncLabel);
+
+ // Emit declarations needed in the loop.
+ if (Init && !this->visitStmt(Init))
+ return false;
+ if (!this->visitStmt(RangeStmt))
+ return false;
+ if (!this->visitStmt(BeginStmt))
+ return false;
+ if (!this->visitStmt(EndStmt))
+ return false;
+
+ // Now the condition as well as the loop variable assignment.
+ this->emitLabel(CondLabel);
+ if (!this->visitBool(Cond))
+ return false;
+ if (!this->jumpFalse(EndLabel))
+ return false;
+
+ if (!this->visitVarDecl(LoopVar))
+ return false;
+
+ // Body.
+ if (!this->visitStmt(Body))
+ return false;
+ this->emitLabel(IncLabel);
+ if (!this->discard(Inc))
+ return false;
+ if (!this->jump(CondLabel))
+ return false;
+
+ this->emitLabel(EndLabel);
+ return true;
+}
+
+template <class Emitter>
bool ByteCodeStmtGen<Emitter>::visitBreakStmt(const BreakStmt *S) {
if (!BreakLabel)
return false;
// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -std=c++20 -verify=expected-cpp20 %s
// RUN: %clang_cc1 -std=c++20 -verify=ref %s
-// ref-no-diagnostics
-// expected-no-diagnostics
-// expected-cpp20-no-diagnostics
-
namespace WhileLoop {
constexpr int f() {
int i = 0;
#endif
};
+
+namespace RangeForLoop {
+ constexpr int localArray() {
+ int a[] = {1,2,3,4};
+ int s = 0;
+ for(int i : a) {
+ s += i;
+ }
+ return s;
+ }
+ static_assert(localArray() == 10, "");
+
+ constexpr int localArray2() {
+ int a[] = {1,2,3,4};
+ int s = 0;
+ for(const int &i : a) {
+ s += i;
+ }
+ return s;
+ }
+ static_assert(localArray2() == 10, "");
+
+ constexpr int nested() {
+ int s = 0;
+ for (const int i : (int[]){1,2,3,4}) {
+ int a[] = {i, i};
+ for(int m : a) {
+ s += m;
+ }
+ }
+ return s;
+ }
+ static_assert(nested() == 20, "");
+
+ constexpr int withBreak() {
+ int s = 0;
+ for (const int &i: (bool[]){false, true}) {
+ if (i)
+ break;
+ s++;
+ }
+ return s;
+ }
+ static_assert(withBreak() == 1, "");
+
+ constexpr void NoBody() {
+ for (const int &i: (bool[]){false, true}); // expected-warning {{empty body}} \
+ // expected-note {{semicolon on a separate line}} \
+ // expected-cpp20-warning {{empty body}} \
+ // expected-cpp20-note {{semicolon on a separate line}} \
+ // ref-warning {{empty body}} \
+ // ref-note {{semicolon on a separate line}}
+ }
+}