changeset 5:7a2c806705bf

Enable CbC goto parse. But tail call flag was not set yet, so it's not jmp but call.
author Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
date Fri, 07 Jun 2013 20:03:58 +0900
parents e68854097132
children c8782e147cac
files tools/clang/include/clang/Parse/Parser.h tools/clang/lib/Parse/ParseStmt.cpp
diffstat 2 files changed, 67 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/tools/clang/include/clang/Parse/Parser.h	Thu Jun 06 15:05:00 2013 +0900
+++ b/tools/clang/include/clang/Parse/Parser.h	Fri Jun 07 20:03:58 2013 +0900
@@ -1497,6 +1497,7 @@
   StmtResult ParseDoStatement();
   StmtResult ParseForStatement(SourceLocation *TrailingElseLoc);
   StmtResult ParseGotoStatement();
+  StmtResult ParseCbCGotoStatement();
   StmtResult ParseContinueStatement();
   StmtResult ParseBreakStatement();
   StmtResult ParseReturnStatement();
--- a/tools/clang/lib/Parse/ParseStmt.cpp	Thu Jun 06 15:05:00 2013 +0900
+++ b/tools/clang/lib/Parse/ParseStmt.cpp	Fri Jun 07 20:03:58 2013 +0900
@@ -223,7 +223,13 @@
   case tok::kw_for:                 // C99 6.8.5.3: for-statement
     return ParseForStatement(TrailingElseLoc);
 
-  case tok::kw_goto:                // C99 6.8.6.1: goto-statement
+  case tok::kw_goto:                // C99 6.8.6.1: goto-statement or CbC goto
+#ifndef noCbC
+    if (PP.LookAhead(1).is(tok::l_paren)) { // is CbC goto : 'goto' codeSegment() ';'
+      return ParseCbCGotoStatement();
+      SemiError = "goto code segment";
+    }
+#endif
     Res = ParseGotoStatement();
     SemiError = "goto";
     break;
@@ -1596,32 +1602,72 @@
 ///
 StmtResult Parser::ParseGotoStatement() {
   assert(Tok.is(tok::kw_goto) && "Not a goto stmt!");
-  SourceLocation GotoLoc = ConsumeToken();  // eat the 'goto'.
-
-  StmtResult Res;
-  if (Tok.is(tok::identifier)) {
-    LabelDecl *LD = Actions.LookupOrCreateLabel(Tok.getIdentifierInfo(),
-                                                Tok.getLocation());
-    Res = Actions.ActOnGotoStmt(GotoLoc, Tok.getLocation(), LD);
-    ConsumeToken();
-  } else if (Tok.is(tok::star)) {
-    // GNU indirect goto extension.
-    Diag(Tok, diag::ext_gnu_indirect_goto);
-    SourceLocation StarLoc = ConsumeToken();
-    ExprResult R(ParseExpression());
-    if (R.isInvalid()) {  // Skip to the semicolon, but don't consume it.
-      SkipUntil(tok::semi, false, true);
-      return StmtError();
+    SourceLocation GotoLoc = ConsumeToken();  // eat the 'goto'.
+    
+    StmtResult Res;
+    
+    if (Tok.is(tok::identifier)) {
+      LabelDecl *LD = Actions.LookupOrCreateLabel(Tok.getIdentifierInfo(),
+						  Tok.getLocation());
+      Res = Actions.ActOnGotoStmt(GotoLoc, Tok.getLocation(), LD);
+      ConsumeToken();
+    } else if (Tok.is(tok::star)) {
+      // GNU indirect goto extension.
+      Diag(Tok, diag::ext_gnu_indirect_goto);
+      SourceLocation StarLoc = ConsumeToken();
+      ExprResult R(ParseExpression());
+      if (R.isInvalid()) {  // Skip to the semicolon, but don't consume it.
+	SkipUntil(tok::semi, false, true);
+	return StmtError();
+      }
+      Res = Actions.ActOnIndirectGotoStmt(GotoLoc, StarLoc, R.take());
     }
-    Res = Actions.ActOnIndirectGotoStmt(GotoLoc, StarLoc, R.take());
-  } else {
+  else {
     Diag(Tok, diag::err_expected_ident);
     return StmtError();
   }
-
   return Res;
 }
 
+#ifndef noCbC
+/// ParseCbCGotoStatement
+///       jump-statement:
+///         'goto' codeSegment ';'
+///
+///
+StmtResult Parser::ParseCbCGotoStatement() {
+  assert(Tok.is(tok::kw_goto) && "Not a goto stmt!");
+  ConsumeToken();  // eat the 'goto'.
+    
+  StmtResult Res;
+    
+  if (Tok.is(tok::identifier) && NextToken().is(tok::l_paren)) { // 'goto' codeSegment() ';'
+    // TODO : set code segment flag (tail call elim flag). 
+    CorrectionCandidateCallback DefaultValidator;
+    DefaultValidator.WantTypeSpecifiers = true;
+    DefaultValidator.WantExpressionKeywords = true;
+    DefaultValidator.WantRemainingKeywords = true;
+    DefaultValidator.WantCXXNamedCasts = false;
+    
+    if (TryAnnotateName(/*IsAddressOfOperand*/false, &DefaultValidator)
+	== ANK_Error) {
+      // Handle errors here by skipping up to the next semicolon or '}', and
+      // eat the semicolon if that's what stopped us.
+      SkipUntil(tok::r_brace, /*StopAtSemi=*/true, /*DontConsume=*/true);
+      if (Tok.is(tok::semi))
+	ConsumeToken();
+      return StmtError();
+    }
+    Res = ParseExprStatement();
+  }
+  else {
+    Diag(Tok, diag::err_expected_ident);
+    return StmtError();
+  }
+  return Res;
+}
+#endif
+
 /// ParseContinueStatement
 ///       jump-statement:
 ///         'continue' ';'