Created
July 30, 2020 01:08
-
-
Save geohot/97e56eb6a0725b54db661d8a91705d4d to your computer and use it in GitHub Desktop.
Add support for "fore" loops to clang
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h | |
index 13f265223..61b0a83c6 100644 | |
--- a/clang/include/clang/AST/Stmt.h | |
+++ b/clang/include/clang/AST/Stmt.h | |
@@ -2459,13 +2459,16 @@ class ForStmt : public Stmt { | |
public: | |
ForStmt(const ASTContext &C, Stmt *Init, Expr *Cond, VarDecl *condVar, | |
Expr *Inc, Stmt *Body, SourceLocation FL, SourceLocation LP, | |
- SourceLocation RP); | |
+ SourceLocation RP, bool is_fore_statement=false); | |
/// Build an empty for statement. | |
explicit ForStmt(EmptyShell Empty) : Stmt(ForStmtClass, Empty) {} | |
Stmt *getInit() { return SubExprs[INIT]; } | |
+ bool isForeStatement() const { return ForeStatement; } | |
+ bool ForeStatement = false; | |
+ | |
/// Retrieve the variable declared in this "for" statement, if any. | |
/// | |
/// In the following example, "y" is the condition variable. | |
diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def | |
index daaa54c3d..3dbe9871a 100644 | |
--- a/clang/include/clang/Basic/TokenKinds.def | |
+++ b/clang/include/clang/Basic/TokenKinds.def | |
@@ -293,6 +293,7 @@ KEYWORD(enum , KEYALL) | |
KEYWORD(extern , KEYALL) | |
KEYWORD(float , KEYALL) | |
KEYWORD(for , KEYALL) | |
+KEYWORD(fore , KEYALL) | |
KEYWORD(goto , KEYALL) | |
KEYWORD(if , KEYALL) | |
KEYWORD(inline , KEYC99|KEYCXX|KEYGNU) | |
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h | |
index 4068e6a44..487cf0ba2 100644 | |
--- a/clang/include/clang/Parse/Parser.h | |
+++ b/clang/include/clang/Parse/Parser.h | |
@@ -2078,7 +2078,7 @@ private: | |
StmtResult ParseSwitchStatement(SourceLocation *TrailingElseLoc); | |
StmtResult ParseWhileStatement(SourceLocation *TrailingElseLoc); | |
StmtResult ParseDoStatement(); | |
- StmtResult ParseForStatement(SourceLocation *TrailingElseLoc); | |
+ StmtResult ParseForStatement(SourceLocation *TrailingElseLoc, bool is_fore_statement=false); | |
StmtResult ParseGotoStatement(); | |
StmtResult ParseContinueStatement(); | |
StmtResult ParseBreakStatement(); | |
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h | |
index 4721ccdf1..ed7e2f948 100644 | |
--- a/clang/include/clang/Sema/Sema.h | |
+++ b/clang/include/clang/Sema/Sema.h | |
@@ -4400,7 +4400,8 @@ public: | |
ConditionResult Second, | |
FullExprArg Third, | |
SourceLocation RParenLoc, | |
- Stmt *Body); | |
+ Stmt *Body, | |
+ bool is_fore_statement=false); | |
ExprResult CheckObjCForCollectionOperand(SourceLocation forLoc, | |
Expr *collection); | |
StmtResult ActOnObjCForCollectionStmt(SourceLocation ForColLoc, | |
diff --git a/clang/lib/AST/Stmt.cpp b/clang/lib/AST/Stmt.cpp | |
index 25e685be3..0e7307fc3 100644 | |
--- a/clang/lib/AST/Stmt.cpp | |
+++ b/clang/lib/AST/Stmt.cpp | |
@@ -916,7 +916,7 @@ Optional<const Stmt*> IfStmt::getNondiscardedCase(const ASTContext &Ctx) const { | |
ForStmt::ForStmt(const ASTContext &C, Stmt *Init, Expr *Cond, VarDecl *condVar, | |
Expr *Inc, Stmt *Body, SourceLocation FL, SourceLocation LP, | |
- SourceLocation RP) | |
+ SourceLocation RP, bool is_fore_statement) | |
: Stmt(ForStmtClass), LParenLoc(LP), RParenLoc(RP) | |
{ | |
SubExprs[INIT] = Init; | |
@@ -925,6 +925,7 @@ ForStmt::ForStmt(const ASTContext &C, Stmt *Init, Expr *Cond, VarDecl *condVar, | |
SubExprs[INC] = Inc; | |
SubExprs[BODY] = Body; | |
ForStmtBits.ForLoc = FL; | |
+ ForeStatement = is_fore_statement; | |
} | |
VarDecl *ForStmt::getConditionVariable() const { | |
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp | |
index c2bd17a23..69acaa110 100644 | |
--- a/clang/lib/CodeGen/CGStmt.cpp | |
+++ b/clang/lib/CodeGen/CGStmt.cpp | |
@@ -960,6 +960,12 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S, | |
if (S.getInc()) { | |
EmitBlock(Continue.getBlock()); | |
EmitStmt(S.getInc()); | |
+ | |
+ if (S.isForeStatement()) { | |
+ EmitStmt(S.getInc()); | |
+ EmitStmt(S.getInc()); | |
+ EmitStmt(S.getInc()); | |
+ } | |
} | |
BreakContinueStack.pop_back(); | |
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp | |
index 89a6a2b82..befefbc64 100644 | |
--- a/clang/lib/Parse/ParseStmt.cpp | |
+++ b/clang/lib/Parse/ParseStmt.cpp | |
@@ -265,6 +265,8 @@ Retry: | |
break; | |
case tok::kw_for: // C99 6.8.5.3: for-statement | |
return ParseForStatement(TrailingElseLoc); | |
+ case tok::kw_fore: // C99 lol.ed1: fore-statement | |
+ return ParseForStatement(TrailingElseLoc, true); | |
case tok::kw_goto: // C99 6.8.6.1: goto-statement | |
Res = ParseGotoStatement(); | |
@@ -1742,8 +1744,12 @@ bool Parser::isForRangeIdentifier() { | |
/// [C++0x] for-range-initializer: | |
/// [C++0x] expression | |
/// [C++0x] braced-init-list [TODO] | |
-StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { | |
- assert(Tok.is(tok::kw_for) && "Not a for stmt!"); | |
+StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc, bool is_fore_statement) { | |
+ if (is_fore_statement) { | |
+ assert(Tok.is(tok::kw_fore) && "Not a fore stmt!"); | |
+ } else { | |
+ assert(Tok.is(tok::kw_for) && "Not a for stmt!"); | |
+ } | |
SourceLocation ForLoc = ConsumeToken(); // eat the 'for'. | |
SourceLocation CoawaitLoc; | |
@@ -1985,8 +1991,6 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { | |
if (Tok.isNot(tok::r_paren)) { // for (...;...;) | |
ExprResult Third = ParseExpression(); | |
- // FIXME: The C++11 standard doesn't actually say that this is a | |
- // discarded-value expression, but it clearly should be. | |
ThirdPart = Actions.MakeFullDiscardedValueExpr(Third.get()); | |
} | |
} | |
@@ -2076,7 +2080,7 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { | |
return Actions.ActOnForStmt(ForLoc, T.getOpenLocation(), FirstPart.get(), | |
SecondPart, ThirdPart, T.getCloseLocation(), | |
- Body.get()); | |
+ Body.get(), is_fore_statement); | |
} | |
/// ParseGotoStatement | |
diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp | |
index 9ca2411b3..a0e5b6692 100644 | |
--- a/clang/lib/Sema/SemaStmt.cpp | |
+++ b/clang/lib/Sema/SemaStmt.cpp | |
@@ -1778,7 +1778,7 @@ void Sema::CheckBreakContinueBinding(Expr *E) { | |
StmtResult Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc, | |
Stmt *First, ConditionResult Second, | |
FullExprArg third, SourceLocation RParenLoc, | |
- Stmt *Body) { | |
+ Stmt *Body, bool is_fore_statement) { | |
if (Second.isInvalid()) | |
return StmtError(); | |
@@ -1818,7 +1818,7 @@ StmtResult Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc, | |
return new (Context) | |
ForStmt(Context, First, Second.get().second, Second.get().first, Third, | |
- Body, ForLoc, LParenLoc, RParenLoc); | |
+ Body, ForLoc, LParenLoc, RParenLoc, is_fore_statement); | |
} | |
/// In an Objective C collection iteration statement: |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment