Skip to content

Instantly share code, notes, and snippets.

@geohot
Created July 30, 2020 01:08
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save geohot/97e56eb6a0725b54db661d8a91705d4d to your computer and use it in GitHub Desktop.
Save geohot/97e56eb6a0725b54db661d8a91705d4d to your computer and use it in GitHub Desktop.
Add support for "fore" loops to clang
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