changeset 89:9020ffd06b8b

Create prototype declaration automatically (only support direct continuation)
author Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
date Tue, 14 Apr 2015 03:55:39 +0900
parents e471d82fb99b
children 2ddce554fef0
files tools/clang/.git/index tools/clang/include/clang/Lex/Preprocessor.h tools/clang/include/clang/Parse/Parser.h tools/clang/lib/Lex/PPDirectives.cpp tools/clang/lib/Parse/ParseCbC.cpp tools/clang/lib/Parse/ParseDecl.cpp tools/clang/lib/Parse/ParseStmt.cpp
diffstat 7 files changed, 86 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
Binary file tools/clang/.git/index has changed
--- a/tools/clang/include/clang/Lex/Preprocessor.h	Mon Apr 13 18:34:22 2015 +0900
+++ b/tools/clang/include/clang/Lex/Preprocessor.h	Tue Apr 14 03:55:39 2015 +0900
@@ -1615,6 +1615,8 @@
   unsigned int SavedDepth;
   Token SavedToken;
   bool SavedTokenFlag;
+  void ClearCache();
+  void RestoreTokens(Token *Toks, unsigned NumToks);
 #endif
 };
 
--- a/tools/clang/include/clang/Parse/Parser.h	Mon Apr 13 18:34:22 2015 +0900
+++ b/tools/clang/include/clang/Parse/Parser.h	Tue Apr 14 03:55:39 2015 +0900
@@ -1570,6 +1570,7 @@
   StmtVector* Stmtsp;
   const char* curFuncName;
   unsigned int UniqueId;
+  bool ProtoParsing = false;
 #endif
   StmtResult ParseStatement(SourceLocation *TrailingElseLoc = nullptr);
   StmtResult
@@ -1804,6 +1805,7 @@
   ExprResult Prepare__envForGotoWithTheEnvExpr();
   bool isVoidFunction();
   bool SearchCodeSegmentDeclaration(std::string Name);
+  void CreatePrototypeDeclaration(Token IITok);
 #endif
 
   bool isDeclarationSpecifier(bool DisambiguatingWithExpression = false);
--- a/tools/clang/lib/Lex/PPDirectives.cpp	Mon Apr 13 18:34:22 2015 +0900
+++ b/tools/clang/lib/Lex/PPDirectives.cpp	Tue Apr 14 03:55:39 2015 +0900
@@ -2560,4 +2560,14 @@
   EnterSourceFile(FID, CurDir, FilenameTok.getLocation());
   return true;
 }
+
+void Preprocessor::ClearCache(){
+  CachedTokens.clear();
+  CachedLexPos = 0;
+}
+
+void Preprocessor::RestoreTokens(Token *Toks, unsigned NumToks){
+  EnterCachingLexMode();
+  CachedTokens.insert(CachedTokens.begin()+CachedLexPos, Toks, Toks + NumToks);
+}
 #endif
--- a/tools/clang/lib/Parse/ParseCbC.cpp	Mon Apr 13 18:34:22 2015 +0900
+++ b/tools/clang/lib/Parse/ParseCbC.cpp	Tue Apr 14 03:55:39 2015 +0900
@@ -931,9 +931,51 @@
 /// If we can't find it , return false;
 bool Parser::SearchCodeSegmentDeclaration(std::string Name){
   while(SkipUntil(tok::kw___code,StopBeforeMatch)){
-    if(NextToken().getIdentifierInfo()->getName().str() == Name)
+    if(NextToken().is(tok::identifier) && NextToken().getIdentifierInfo()->getName().str() == Name)
       return true;
+    ConsumeToken();
   }
   return false;
 }
+
+/// CreatePrototypeDeclaration - Create prototype declaration by it's definition.
+void Parser::CreatePrototypeDeclaration(Token IITok){
+  // move to the top level scope
+  Scope *SavedScope = getCurScope();
+  DeclContext *SavedContext = Actions.CurContext;
+  sema::FunctionScopeInfo *SavedFSI = Actions.FunctionScopes.pop_back_val();
+  Actions.CurContext = static_cast<DeclContext *>(Actions.Context.getTranslationUnitDecl());
+  Scope *TopScope = getCurScope();
+  while(TopScope->getParent() != NULL)
+    TopScope = TopScope->getParent();
+  Actions.CurScope = TopScope;
+  
+  Token CachedTokens[] = {IITok, PP.LookAhead(1)};
+  Token SavedToken = Tok;
+  PP.ClearCache();
+  ProtoParsing = true;
+  
+  StringRef Filename;
+  Filename = StringRef("proto.h",7);
+  const DirectoryLookup *CurDir;
+  FileID FID = PP.getSourceManager().createFileID(PP.getCurrentFileLexer()->getFileEntry(), IITok.getLocation(), SrcMgr::C_User);
+  PP.EnterSourceFile(FID,CurDir,IITok.getLocation());
+  ConsumeToken();
+  SearchCodeSegmentDeclaration(IITok.getIdentifierInfo()->getName().str());
+  
+  // move to the previous scope.
+  DeclGroupPtrTy ProtoDecl;
+  ParseTopLevelDecl(ProtoDecl);
+  (&Actions.getASTConsumer())->HandleTopLevelDecl(ProtoDecl.get());
+  Actions.CurScope = SavedScope;
+  Actions.CurContext = SavedContext;
+  Actions.FunctionScopes.push_back(SavedFSI);
+  
+  // recover tokens
+  Tok = SavedToken;
+  PP.RestoreTokens(CachedTokens, 2);
+  
+  ProtoParsing = false;
+}
+
 #endif
--- a/tools/clang/lib/Parse/ParseDecl.cpp	Mon Apr 13 18:34:22 2015 +0900
+++ b/tools/clang/lib/Parse/ParseDecl.cpp	Tue Apr 14 03:55:39 2015 +0900
@@ -1668,6 +1668,9 @@
 
   // Check to see if we have a function *definition* which must have a body.
   if (D.isFunctionDeclarator() &&
+#ifndef noCbC
+      !ProtoParsing &&
+#endif 
       // Look at the next token to make sure that this isn't a function
       // declaration.  We have to check this because __attribute__ might be the
       // start of a function definition in GCC-extended K&R C.
@@ -1747,6 +1750,10 @@
     DeclsInGroup.push_back(FirstDecl);
 
   bool ExpectSemi = Context != Declarator::ForContext;
+
+#ifndef noCbC
+  ExpectSemi = ExpectSemi && !ProtoParsing;
+#endif
   
   // If we don't have a comma, it is either the end of the list (a ';') or an
   // error, bail out.
@@ -1804,6 +1811,12 @@
     }
   }
 
+#ifndef noCbC
+  if(ProtoParsing){
+    Token T;
+    PP.HandleEndOfFile(T, false);
+  }
+#endif
   return Actions.FinalizeDeclaratorGroup(getCurScope(), DS, DeclsInGroup);
 }
 
--- a/tools/clang/lib/Parse/ParseStmt.cpp	Mon Apr 13 18:34:22 2015 +0900
+++ b/tools/clang/lib/Parse/ParseStmt.cpp	Tue Apr 14 03:55:39 2015 +0900
@@ -27,6 +27,8 @@
 
 #ifndef noCbC
 #include "clang/Sema/Lookup.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/AST/ASTConsumer.h"
 #endif
 
 using namespace clang;
@@ -253,20 +255,23 @@
 
   case tok::kw_goto:                // C99 6.8.6.1: goto-statement
 #ifndef noCbC
-    if (!(NextToken().is(tok::identifier) && PP.LookAhead(1).is(tok::semi)) && // C: 'goto' identifier ';'
-        NextToken().isNot(tok::star)) {                                        // C: 'goto' '*' expression ';'
-      SemiError = "goto code segment";
-
-      if(NextToken().is(tok::identifier)){ // Probably, direct continuation. goto csName();
-        LookupResult LR(Actions, NextToken().getIdentifierInfo(), NextToken().getLocation(), Actions.LookupOrdinaryName);
-        CXXScopeSpec SS;
-        Actions.LookupParsedName(LR, getCurScope(), &SS, !(Actions.getCurMethodDecl()));
-        if(LR.getResultKind() == LookupResult::NotFound){
+    {
+      Token Next = NextToken();
+      if (!(Next.is(tok::identifier) && PP.LookAhead(1).is(tok::semi)) && // C: 'goto' identifier ';'
+          Next.isNot(tok::star)) {                                        // C: 'goto' '*' expression ';'
+        SemiError = "goto code segment";
+        if(Next.is(tok::identifier)){ // Probably, direct continuation. goto csName();
+          LookupResult LR(Actions, Next.getIdentifierInfo(), Next.getLocation(), Actions.LookupOrdinaryName);
+          CXXScopeSpec SS;
+          Actions.LookupParsedName(LR, getCurScope(), &SS, !(Actions.getCurMethodDecl()));
+          if(LR.getResultKind() == LookupResult::NotFound){
+            CreatePrototypeDeclaration(Next);
+          }
+          
         }
         
+        return ParseCbCGotoStatement(Attrs, Stmts);                              // CbC: goto codesegment statement
       }
-      
-      return ParseCbCGotoStatement(Attrs, Stmts);                              // CbC: goto codesegment statement
     }
 #endif
     Res = ParseGotoStatement();