r195543 - Generate a marker token when entering or leaving a submodule when building a

Richard Smith richard-llvm at metafoo.co.uk
Fri Nov 22 20:06:10 PST 2013


Author: rsmith
Date: Fri Nov 22 22:06:09 2013
New Revision: 195543

URL: http://llvm.org/viewvc/llvm-project?rev=195543&view=rev
Log:
Generate a marker token when entering or leaving a submodule when building a
module. Use the marker to diagnose cases where we try to transition between
submodules when not at the top level (most likely because a closing brace was
missing at the end of a header file, but is also possible if submodule headers
attempt to do something fundamentally non-modular, like our .def files).

Added:
    cfe/trunk/test/Modules/Inputs/malformed/
    cfe/trunk/test/Modules/Inputs/malformed/a1.h
    cfe/trunk/test/Modules/Inputs/malformed/a2.h
    cfe/trunk/test/Modules/Inputs/malformed/b1.h
    cfe/trunk/test/Modules/Inputs/malformed/b2.h
    cfe/trunk/test/Modules/Inputs/malformed/module.map
    cfe/trunk/test/Modules/malformed.cpp
Modified:
    cfe/trunk/include/clang/Basic/TokenKinds.def
    cfe/trunk/include/clang/Lex/Preprocessor.h
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/lib/Frontend/PrintPreprocessedOutput.cpp
    cfe/trunk/lib/Lex/PPDirectives.cpp
    cfe/trunk/lib/Lex/PPLexerChange.cpp
    cfe/trunk/lib/Lex/Preprocessor.cpp
    cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Parse/ParseDeclCXX.cpp
    cfe/trunk/lib/Parse/ParseInit.cpp
    cfe/trunk/lib/Parse/ParseObjc.cpp
    cfe/trunk/lib/Parse/ParseStmt.cpp
    cfe/trunk/lib/Parse/Parser.cpp
    cfe/trunk/test/Modules/auto-module-import.m

Modified: cfe/trunk/include/clang/Basic/TokenKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TokenKinds.def?rev=195543&r1=195542&r2=195543&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/TokenKinds.def (original)
+++ cfe/trunk/include/clang/Basic/TokenKinds.def Fri Nov 22 22:06:09 2013
@@ -667,8 +667,10 @@ ANNOTATION(pragma_opencl_extension)
 ANNOTATION(pragma_openmp)
 ANNOTATION(pragma_openmp_end)
 
-// Annotation for module import translated from #include etc.
+// Annotations for module import translated from #include etc.
 ANNOTATION(module_include)
+ANNOTATION(module_begin)
+ANNOTATION(module_end)
 
 #undef ANNOTATION
 #undef TESTING_KEYWORD

Modified: cfe/trunk/include/clang/Lex/Preprocessor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/Preprocessor.h?rev=195543&r1=195542&r2=195543&view=diff
==============================================================================
--- cfe/trunk/include/clang/Lex/Preprocessor.h (original)
+++ cfe/trunk/include/clang/Lex/Preprocessor.h Fri Nov 22 22:06:09 2013
@@ -276,22 +276,26 @@ class Preprocessor : public RefCountedBa
     CLK_LexAfterModuleImport
   } CurLexerKind;
 
+  /// \brief True if the current lexer is for a submodule.
+  bool CurIsSubmodule;
+
   /// IncludeMacroStack - This keeps track of the stack of files currently
   /// \#included, and macros currently being expanded from, not counting
   /// CurLexer/CurTokenLexer.
   struct IncludeStackInfo {
     enum CurLexerKind     CurLexerKind;
+    bool                  IsSubmodule;
     Lexer                 *TheLexer;
     PTHLexer              *ThePTHLexer;
     PreprocessorLexer     *ThePPLexer;
     TokenLexer            *TheTokenLexer;
     const DirectoryLookup *TheDirLookup;
 
-    IncludeStackInfo(enum CurLexerKind K, Lexer *L, PTHLexer* P,
-                     PreprocessorLexer* PPL,
-                     TokenLexer* TL, const DirectoryLookup *D)
-      : CurLexerKind(K), TheLexer(L), ThePTHLexer(P), ThePPLexer(PPL),
-        TheTokenLexer(TL), TheDirLookup(D) {}
+    IncludeStackInfo(enum CurLexerKind K, bool SM, Lexer *L, PTHLexer *P,
+                     PreprocessorLexer *PPL, TokenLexer *TL,
+                     const DirectoryLookup *D)
+        : CurLexerKind(K), IsSubmodule(SM), TheLexer(L), ThePTHLexer(P),
+          ThePPLexer(PPL), TheTokenLexer(TL), TheDirLookup(D) {}
   };
   std::vector<IncludeStackInfo> IncludeMacroStack;
 
@@ -662,7 +666,7 @@ public:
   /// start lexing tokens from it instead of the current buffer.  Emit an error
   /// and don't enter the file on error.
   void EnterSourceFile(FileID CurFileID, const DirectoryLookup *Dir,
-                       SourceLocation Loc);
+                       SourceLocation Loc, bool IsSubmodule = false);
 
   /// EnterMacro - Add a Macro to the top of the include stack and start lexing
   /// tokens from it instead of the current buffer.  Args specifies the
@@ -1155,6 +1159,9 @@ private:
   IdentifierInfo *Ident__abnormal_termination,
                  *Ident___abnormal_termination,
                  *Ident_AbnormalTermination;
+
+  const char *getCurLexerEndPos();
+
 public:
   void PoisonSEHIdentifiers(bool Poison = true); // Borland
 
@@ -1265,6 +1272,7 @@ private:
 
   void PushIncludeMacroStack() {
     IncludeMacroStack.push_back(IncludeStackInfo(CurLexerKind,
+                                                 CurIsSubmodule,
                                                  CurLexer.take(),
                                                  CurPTHLexer.take(),
                                                  CurPPLexer,
@@ -1280,6 +1288,7 @@ private:
     CurTokenLexer.reset(IncludeMacroStack.back().TheTokenLexer);
     CurDirLookup  = IncludeMacroStack.back().TheDirLookup;
     CurLexerKind = IncludeMacroStack.back().CurLexerKind;
+    CurIsSubmodule = IncludeMacroStack.back().IsSubmodule;
     IncludeMacroStack.pop_back();
   }
 
@@ -1380,11 +1389,13 @@ private:
 
   /// EnterSourceFileWithLexer - Add a lexer to the top of the include stack and
   /// start lexing tokens from it instead of the current buffer.
-  void EnterSourceFileWithLexer(Lexer *TheLexer, const DirectoryLookup *Dir);
+  void EnterSourceFileWithLexer(Lexer *TheLexer, const DirectoryLookup *Dir,
+                                bool IsSubmodule = false);
 
   /// EnterSourceFileWithPTH - Add a lexer to the top of the include stack and
   /// start getting tokens from it using the PTH cache.
-  void EnterSourceFileWithPTH(PTHLexer *PL, const DirectoryLookup *Dir);
+  void EnterSourceFileWithPTH(PTHLexer *PL, const DirectoryLookup *Dir,
+                              bool IsSubmodule = false);
 
   /// \brief Set the file ID for the preprocessor predefines.
   void setPredefinesFileID(FileID FID) {

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=195543&r1=195542&r2=195543&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Fri Nov 22 22:06:09 2013
@@ -73,7 +73,7 @@ class Parser : public CodeCompletionHand
   SourceLocation PrevTokLocation;
 
   unsigned short ParenCount, BracketCount, BraceCount;
-  
+
   /// Actions - These are the callbacks we invoke as we parse various constructs
   /// in the file.
   Sema &Actions;
@@ -408,6 +408,14 @@ private:
     Tok.setKind(tok::eof);
   }
 
+  /// \brief Determine if we're at the end of the file or at a transition
+  /// between modules.
+  bool isEofOrEom() {
+    tok::TokenKind Kind = Tok.getKind();
+    return Kind == tok::eof || Kind == tok::annot_module_begin ||
+           Kind == tok::annot_module_end || Kind == tok::annot_module_include;
+  }
+
   /// \brief Handle the annotation token produced for #pragma unused(...)
   void HandlePragmaUnused();
 

Modified: cfe/trunk/lib/Frontend/PrintPreprocessedOutput.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PrintPreprocessedOutput.cpp?rev=195543&r1=195542&r2=195543&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PrintPreprocessedOutput.cpp (original)
+++ cfe/trunk/lib/Frontend/PrintPreprocessedOutput.cpp Fri Nov 22 22:06:09 2013
@@ -657,7 +657,9 @@ static void PrintPreprocessedTokens(Prep
       // -traditional-cpp the lexer keeps /all/ whitespace, including comments.
       SourceLocation StartLoc = Tok.getLocation();
       Callbacks->MoveToLine(StartLoc.getLocWithOffset(Tok.getLength()));
-    } else if (Tok.is(tok::annot_module_include)) {
+    } else if (Tok.is(tok::annot_module_include) ||
+               Tok.is(tok::annot_module_begin) ||
+               Tok.is(tok::annot_module_end)) {
       // PrintPPOutputPPCallbacks::InclusionDirective handles producing
       // appropriate output here. Ignore this token entirely.
       PP.Lex(Tok);

Modified: cfe/trunk/lib/Lex/PPDirectives.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPDirectives.cpp?rev=195543&r1=195542&r2=195543&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/PPDirectives.cpp (original)
+++ cfe/trunk/lib/Lex/PPDirectives.cpp Fri Nov 22 22:06:09 2013
@@ -1389,6 +1389,19 @@ bool Preprocessor::ConcatenateIncludeNam
   return true;
 }
 
+/// \brief Push a token onto the token stream containing an annotation.
+static void EnterAnnotationToken(Preprocessor &PP,
+                                 SourceLocation Begin, SourceLocation End,
+                                 tok::TokenKind Kind, void *AnnotationVal) {
+  Token *Tok = new Token[1];
+  Tok[0].startToken();
+  Tok[0].setKind(Kind);
+  Tok[0].setLocation(Begin);
+  Tok[0].setAnnotationEndLoc(End);
+  Tok[0].setAnnotationValue(AnnotationVal);
+  PP.EnterTokenStream(Tok, 1, true, true);
+}
+
 /// HandleIncludeDirective - The "\#include" tokens have just been read, read
 /// the file to be included from the lexer, then include it!  This is a common
 /// routine with functionality shared between \#include, \#include_next and
@@ -1590,7 +1603,7 @@ void Preprocessor::HandleIncludeDirectiv
     // include directive maps to.
     bool BuildingImportedModule
       = Path[0].first->getName() == getLangOpts().CurrentModule;
-    
+
     if (!BuildingImportedModule && getLangOpts().ObjC2) {
       // If we're not building the imported module, warn that we're going
       // to automatically turn this inclusion directive into a module import.
@@ -1639,13 +1652,8 @@ void Preprocessor::HandleIncludeDirectiv
         // make the module visible.
         // FIXME: Produce this as the current token directly, rather than
         // allocating a new token for it.
-        Token *Tok = new Token[1];
-        Tok[0].startToken();
-        Tok[0].setKind(tok::annot_module_include);
-        Tok[0].setLocation(HashLoc);
-        Tok[0].setAnnotationEndLoc(End);
-        Tok[0].setAnnotationValue(Imported);
-        EnterTokenStream(Tok, 1, true, true);
+        EnterAnnotationToken(*this, HashLoc, End, tok::annot_module_include,
+                             Imported);
       }
       return;
     }
@@ -1692,8 +1700,23 @@ void Preprocessor::HandleIncludeDirectiv
   FileID FID = SourceMgr.createFileID(File, IncludePos, FileCharacter);
   assert(!FID.isInvalid() && "Expected valid file ID");
 
-  // Finally, if all is good, enter the new file!
-  EnterSourceFile(FID, CurDir, FilenameTok.getLocation());
+  // Determine if we're switching to building a new submodule, and which one.
+  ModuleMap::KnownHeader BuildingModule;
+  if (getLangOpts().Modules && !getLangOpts().CurrentModule.empty()) {
+    Module *RequestingModule = getModuleForLocation(FilenameLoc);
+    BuildingModule =
+        HeaderInfo.getModuleMap().findModuleForHeader(File, RequestingModule);
+  }
+
+  // If all is good, enter the new file!
+  EnterSourceFile(FID, CurDir, FilenameTok.getLocation(),
+                  static_cast<bool>(BuildingModule));
+
+  // If we're walking into another part of the same module, let the parser
+  // know that any future declarations are within that other submodule.
+  if (BuildingModule)
+    EnterAnnotationToken(*this, HashLoc, End, tok::annot_module_begin,
+                         BuildingModule.getModule());
 }
 
 /// HandleIncludeNextDirective - Implements \#include_next.

Modified: cfe/trunk/lib/Lex/PPLexerChange.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPLexerChange.cpp?rev=195543&r1=195542&r2=195543&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/PPLexerChange.cpp (original)
+++ cfe/trunk/lib/Lex/PPLexerChange.cpp Fri Nov 22 22:06:09 2013
@@ -69,7 +69,7 @@ PreprocessorLexer *Preprocessor::getCurr
 /// EnterSourceFile - Add a source file to the top of the include stack and
 /// start lexing tokens from it instead of the current buffer.
 void Preprocessor::EnterSourceFile(FileID FID, const DirectoryLookup *CurDir,
-                                   SourceLocation Loc) {
+                                   SourceLocation Loc, bool IsSubmodule) {
   assert(!CurTokenLexer && "Cannot #include a file inside a macro!");
   ++NumEnteredSourceFiles;
 
@@ -78,7 +78,7 @@ void Preprocessor::EnterSourceFile(FileI
 
   if (PTH) {
     if (PTHLexer *PL = PTH->CreateLexer(FID)) {
-      EnterSourceFileWithPTH(PL, CurDir);
+      EnterSourceFileWithPTH(PL, CurDir, IsSubmodule);
       return;
     }
   }
@@ -101,14 +101,16 @@ void Preprocessor::EnterSourceFile(FileI
         CodeCompletionFileLoc.getLocWithOffset(CodeCompletionOffset);
   }
 
-  EnterSourceFileWithLexer(new Lexer(FID, InputFile, *this), CurDir);
+  EnterSourceFileWithLexer(new Lexer(FID, InputFile, *this), CurDir,
+                           IsSubmodule);
   return;
 }
 
 /// EnterSourceFileWithLexer - Add a source file to the top of the include stack
 ///  and start lexing tokens from it instead of the current buffer.
 void Preprocessor::EnterSourceFileWithLexer(Lexer *TheLexer,
-                                            const DirectoryLookup *CurDir) {
+                                            const DirectoryLookup *CurDir,
+                                            bool IsSubmodule) {
 
   // Add the current lexer to the include stack.
   if (CurPPLexer || CurTokenLexer)
@@ -117,6 +119,7 @@ void Preprocessor::EnterSourceFileWithLe
   CurLexer.reset(TheLexer);
   CurPPLexer = TheLexer;
   CurDirLookup = CurDir;
+  CurIsSubmodule = IsSubmodule;
   if (CurLexerKind != CLK_LexAfterModuleImport)
     CurLexerKind = CLK_Lexer;
   
@@ -133,7 +136,8 @@ void Preprocessor::EnterSourceFileWithLe
 /// EnterSourceFileWithPTH - Add a source file to the top of the include stack
 /// and start getting tokens from it using the PTH cache.
 void Preprocessor::EnterSourceFileWithPTH(PTHLexer *PL,
-                                          const DirectoryLookup *CurDir) {
+                                          const DirectoryLookup *CurDir,
+                                          bool IsSubmodule) {
 
   if (CurPPLexer || CurTokenLexer)
     PushIncludeMacroStack();
@@ -141,6 +145,7 @@ void Preprocessor::EnterSourceFileWithPT
   CurDirLookup = CurDir;
   CurPTHLexer.reset(PL);
   CurPPLexer = CurPTHLexer.get();
+  CurIsSubmodule = IsSubmodule;
   if (CurLexerKind != CLK_LexAfterModuleImport)
     CurLexerKind = CLK_PTHLexer;
   
@@ -244,6 +249,29 @@ void Preprocessor::PropagateLineStartLea
   // but it might if they're empty?
 }
 
+/// \brief Determine the location to use as the end of the buffer for a lexer.
+///
+/// If the file ends with a newline, form the EOF token on the newline itself,
+/// rather than "on the line following it", which doesn't exist.  This makes
+/// diagnostics relating to the end of file include the last file that the user
+/// actually typed, which is goodness.
+const char *Preprocessor::getCurLexerEndPos() {
+  const char *EndPos = CurLexer->BufferEnd;
+  if (EndPos != CurLexer->BufferStart &&
+      (EndPos[-1] == '\n' || EndPos[-1] == '\r')) {
+    --EndPos;
+
+    // Handle \n\r and \r\n:
+    if (EndPos != CurLexer->BufferStart &&
+        (EndPos[-1] == '\n' || EndPos[-1] == '\r') &&
+        EndPos[-1] != EndPos[0])
+      --EndPos;
+  }
+
+  return EndPos;
+}
+
+
 /// HandleEndOfFile - This callback is invoked when the lexer hits the end of
 /// the current file.  This either returns the EOF token or pops a level off
 /// the include stack and keeps going.
@@ -342,7 +370,19 @@ bool Preprocessor::HandleEndOfFile(Token
     FileID ExitedFID;
     if (Callbacks && !isEndOfMacro && CurPPLexer)
       ExitedFID = CurPPLexer->getFileID();
-    
+
+    // If this file corresponded to a submodule, notify the parser that we've
+    // left that submodule.
+    bool LeavingSubmodule = CurIsSubmodule && CurLexer;
+    if (LeavingSubmodule) {
+      const char *EndPos = getCurLexerEndPos();
+      Result.startToken();
+      CurLexer->BufferPtr = EndPos;
+      CurLexer->FormTokenWithChars(Result, EndPos, tok::annot_module_end);
+      Result.setAnnotationEndLoc(Result.getLocation());
+      Result.setAnnotationValue(0);
+    }
+
     // We're done with the #included file.
     RemoveTopOfLexerStack();
 
@@ -357,27 +397,13 @@ bool Preprocessor::HandleEndOfFile(Token
                              PPCallbacks::ExitFile, FileType, ExitedFID);
     }
 
-    // Client should lex another token.
-    return false;
+    // Client should lex another token unless we generated an EOM.
+    return LeavingSubmodule;
   }
 
-  // If the file ends with a newline, form the EOF token on the newline itself,
-  // rather than "on the line following it", which doesn't exist.  This makes
-  // diagnostics relating to the end of file include the last file that the user
-  // actually typed, which is goodness.
+  // If this is the end of the main file, form an EOF token.
   if (CurLexer) {
-    const char *EndPos = CurLexer->BufferEnd;
-    if (EndPos != CurLexer->BufferStart &&
-        (EndPos[-1] == '\n' || EndPos[-1] == '\r')) {
-      --EndPos;
-
-      // Handle \n\r and \r\n:
-      if (EndPos != CurLexer->BufferStart &&
-          (EndPos[-1] == '\n' || EndPos[-1] == '\r') &&
-          EndPos[-1] != EndPos[0])
-        --EndPos;
-    }
-
+    const char *EndPos = getCurLexerEndPos();
     Result.startToken();
     CurLexer->BufferPtr = EndPos;
     CurLexer->FormTokenWithChars(Result, EndPos, tok::eof);

Modified: cfe/trunk/lib/Lex/Preprocessor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/Preprocessor.cpp?rev=195543&r1=195542&r2=195543&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/Preprocessor.cpp (original)
+++ cfe/trunk/lib/Lex/Preprocessor.cpp Fri Nov 22 22:06:09 2013
@@ -67,8 +67,8 @@ Preprocessor::Preprocessor(IntrusiveRefC
       CodeComplete(0), CodeCompletionFile(0), CodeCompletionOffset(0),
       LastTokenWasAt(false), ModuleImportExpectsIdentifier(false),
       CodeCompletionReached(0), SkipMainFilePreamble(0, true), CurPPLexer(0),
-      CurDirLookup(0), CurLexerKind(CLK_Lexer), Callbacks(0),
-      MacroArgCache(0), Record(0), MIChainHead(0), MICache(0),
+      CurDirLookup(0), CurLexerKind(CLK_Lexer), CurIsSubmodule(false),
+      Callbacks(0), MacroArgCache(0), Record(0), MIChainHead(0), MICache(0),
       DeserialMIChainHead(0) {
   OwnsHeaderSearch = OwnsHeaders;
   

Modified: cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp?rev=195543&r1=195542&r2=195543&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp (original)
+++ cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp Fri Nov 22 22:06:09 2013
@@ -580,6 +580,9 @@ bool Parser::ConsumeAndStoreUntil(tok::T
 
     switch (Tok.getKind()) {
     case tok::eof:
+    case tok::annot_module_begin:
+    case tok::annot_module_end:
+    case tok::annot_module_include:
       // Ran out of tokens.
       return false;
 
@@ -965,6 +968,9 @@ bool Parser::ConsumeAndStoreInitializer(
       goto consume_token;
 
     case tok::eof:
+    case tok::annot_module_begin:
+    case tok::annot_module_end:
+    case tok::annot_module_include:
       // Ran out of tokens.
       return false;
 

Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=195543&r1=195542&r2=195543&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Fri Nov 22 22:06:09 2013
@@ -1561,6 +1561,9 @@ void Parser::SkipMalformedDecl() {
       break;
 
     case tok::eof:
+    case tok::annot_module_begin:
+    case tok::annot_module_end:
+    case tok::annot_module_include:
       return;
 
     default:
@@ -3371,7 +3374,7 @@ void Parser::ParseStructUnionBody(Source
   SmallVector<Decl *, 32> FieldDecls;
 
   // While we still have something to read, read the declarations in the struct.
-  while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
+  while (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
     // Each iteration of this loop reads one struct-declaration.
 
     // Check for extraneous top-level semicolon.

Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=195543&r1=195542&r2=195543&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Fri Nov 22 22:06:09 2013
@@ -195,7 +195,7 @@ void Parser::ParseInnerNamespace(std::ve
                                  ParsedAttributes& attrs,
                                  BalancedDelimiterTracker &Tracker) {
   if (index == Ident.size()) {
-    while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
+    while (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
       ParsedAttributesWithRange attrs(AttrFactory);
       MaybeParseCXX11Attributes(attrs);
       MaybeParseMicrosoftAttributes(attrs);
@@ -318,7 +318,7 @@ Decl *Parser::ParseLinkage(ParsingDeclSp
 
   BalancedDelimiterTracker T(*this, tok::l_brace);
   T.consumeOpen();
-  while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
+  while (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
     ParsedAttributesWithRange attrs(AttrFactory);
     MaybeParseCXX11Attributes(attrs);
     MaybeParseMicrosoftAttributes(attrs);
@@ -2452,7 +2452,7 @@ ExprResult Parser::ParseCXXMemberInitial
       // a top-level comma always ends the initializer expression.
       const Token &Next = NextToken();
       if (IsFunction || Next.is(tok::semi) || Next.is(tok::comma) ||
-           Next.is(tok::eof)) {
+          Next.is(tok::eof)) {
         if (IsFunction)
           Diag(ConsumeToken(), diag::err_default_delete_in_multiple_declaration)
             << 1 /* delete */;
@@ -2597,7 +2597,7 @@ void Parser::ParseCXXMemberSpecification
 
   if (TagDecl) {
     // While we still have something to read, read the member-declarations.
-    while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
+    while (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
       // Each iteration of this loop reads one member-declaration.
 
       if (getLangOpts().MicrosoftExt && (Tok.is(tok::kw___if_exists) ||
@@ -3420,7 +3420,7 @@ void Parser::ParseMicrosoftIfExistsClass
     return;
   }
 
-  while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
+  while (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
     // __if_exists, __if_not_exists can nest.
     if ((Tok.is(tok::kw___if_exists) || Tok.is(tok::kw___if_not_exists))) {
       ParseMicrosoftIfExistsClassDeclaration((DeclSpec::TST)TagType, CurAS);

Modified: cfe/trunk/lib/Parse/ParseInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseInit.cpp?rev=195543&r1=195542&r2=195543&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseInit.cpp (original)
+++ cfe/trunk/lib/Parse/ParseInit.cpp Fri Nov 22 22:06:09 2013
@@ -512,7 +512,7 @@ bool Parser::ParseMicrosoftIfExistsBrace
     return false;
   }
 
-  while (Tok.isNot(tok::eof)) {
+  while (!isEofOrEom()) {
     trailingComma = false;
     // If we know that this cannot be a designation, just parse the nested
     // initializer directly.

Modified: cfe/trunk/lib/Parse/ParseObjc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseObjc.cpp?rev=195543&r1=195542&r2=195543&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseObjc.cpp (original)
+++ cfe/trunk/lib/Parse/ParseObjc.cpp Fri Nov 22 22:06:09 2013
@@ -423,7 +423,7 @@ void Parser::ParseObjCInterfaceDeclList(
     }
 
     // If we got to the end of the file, exit the loop.
-    if (Tok.is(tok::eof))
+    if (isEofOrEom())
       break;
 
     // Code completion within an Objective-C interface.
@@ -1289,7 +1289,7 @@ void Parser::ParseObjCClassInstanceVaria
   BalancedDelimiterTracker T(*this, tok::l_brace);
   T.consumeOpen();
   // While we still have something to read, read the instance variables.
-  while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
+  while (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
     // Each iteration of this loop reads one objc-instance-variable-decl.
 
     // Check for extraneous top-level semicolon.
@@ -1582,7 +1582,7 @@ Parser::ParseObjCAtImplementationDeclara
 
   {
     ObjCImplParsingDataRAII ObjCImplParsing(*this, ObjCImpDecl);
-    while (!ObjCImplParsing.isFinished() && Tok.isNot(tok::eof)) {
+    while (!ObjCImplParsing.isFinished() && !isEofOrEom()) {
       ParsedAttributesWithRange attrs(AttrFactory);
       MaybeParseCXX11Attributes(attrs);
       MaybeParseMicrosoftAttributes(attrs);
@@ -1612,7 +1612,7 @@ Parser::ParseObjCAtEndDeclaration(Source
 Parser::ObjCImplParsingDataRAII::~ObjCImplParsingDataRAII() {
   if (!Finished) {
     finish(P.Tok.getLocation());
-    if (P.Tok.is(tok::eof)) {
+    if (P.isEofOrEom()) {
       P.Diag(P.Tok, diag::err_objc_missing_end)
           << FixItHint::CreateInsertion(P.Tok.getLocation(), "\n at end\n");
       P.Diag(Dcl->getLocStart(), diag::note_objc_container_start)

Modified: cfe/trunk/lib/Parse/ParseStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseStmt.cpp?rev=195543&r1=195542&r2=195543&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseStmt.cpp (original)
+++ cfe/trunk/lib/Parse/ParseStmt.cpp Fri Nov 22 22:06:09 2013
@@ -890,7 +890,7 @@ StmtResult Parser::ParseCompoundStatemen
       Stmts.push_back(R.release());
   }
 
-  while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
+  while (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
     if (Tok.is(tok::annot_pragma_unused)) {
       HandlePragmaUnused();
       continue;
@@ -2058,7 +2058,7 @@ StmtResult Parser::ParseMicrosoftAsmStat
   SourceLocation TokLoc = Tok.getLocation();
   do {
     // If we hit EOF, we're done, period.
-    if (Tok.is(tok::eof))
+    if (isEofOrEom())
       break;
 
     if (!InAsmComment && Tok.is(tok::semi)) {

Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=195543&r1=195542&r2=195543&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Fri Nov 22 22:06:09 2013
@@ -288,7 +288,7 @@ bool Parser::SkipUntil(ArrayRef<tok::Tok
     if (Toks.size() == 1 && Toks[0] == tok::eof &&
         !HasFlagsSet(Flags, StopAtSemi) &&
         !HasFlagsSet(Flags, StopAtCodeCompletion)) {
-      while (Tok.getKind() != tok::eof)
+      while (Tok.isNot(tok::eof))
         ConsumeAnyToken();
       return true;
     }
@@ -297,7 +297,15 @@ bool Parser::SkipUntil(ArrayRef<tok::Tok
     case tok::eof:
       // Ran out of tokens.
       return false;
-        
+
+    case tok::annot_module_begin:
+    case tok::annot_module_end:
+    case tok::annot_module_include:
+      // Stop before we change submodules. They generally indicate a "good"
+      // place to pick up parsing again (except in the special case where
+      // we're trying to skip to EOF).
+      return false;
+
     case tok::code_completion:
       if (!HasFlagsSet(Flags, StopAtCodeCompletion))
         ConsumeToken();
@@ -574,10 +582,12 @@ namespace {
 bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) {
   DestroyTemplateIdAnnotationsRAIIObj CleanupRAII(TemplateIds);
 
-  // Skip over the EOF token, flagging end of previous input for incremental 
+  // Skip over the EOF token, flagging end of previous input for incremental
   // processing
-  if (PP.isIncrementalProcessingEnabled() && Tok.is(tok::eof))
+  if (PP.isIncrementalProcessingEnabled() && Tok.is(tok::eof)) {
     ConsumeToken();
+    return false;
+  }
 
   Result = DeclGroupPtrTy();
   switch (Tok.getKind()) {
@@ -592,6 +602,12 @@ bool Parser::ParseTopLevelDecl(DeclGroup
     ConsumeToken();
     return false;
 
+  case tok::annot_module_begin:
+  case tok::annot_module_end:
+    // FIXME: Update visibility based on the submodule we're in.
+    ConsumeToken();
+    return false;
+
   case tok::eof:
     // Late template parsing can begin.
     if (getLangOpts().DelayedTemplateParsing)
@@ -1917,14 +1933,15 @@ void Parser::ParseMicrosoftIfExistsExter
   }
 
   // Parse the declarations.
-  while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
+  // FIXME: Support module import within __if_exists?
+  while (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
     ParsedAttributesWithRange attrs(AttrFactory);
     MaybeParseCXX11Attributes(attrs);
     MaybeParseMicrosoftAttributes(attrs);
     DeclGroupPtrTy Result = ParseExternalDeclaration(attrs);
     if (Result && !getCurScope()->getParent())
       Actions.getASTConsumer().HandleTopLevelDecl(Result.get());
-  }     
+  }
   Braces.consumeClose();
 }
 
@@ -1980,8 +1997,8 @@ bool BalancedDelimiterTracker::diagnoseO
   P.Diag(P.Tok, diag::err_bracket_depth_exceeded)
     << P.getLangOpts().BracketDepth;
   P.Diag(P.Tok, diag::note_bracket_depth);
-  P.SkipUntil(tok::eof);
-  return true;  
+  P.cutOffParsing();
+  return true;
 }
 
 bool BalancedDelimiterTracker::expectAndConsume(unsigned DiagID,

Added: cfe/trunk/test/Modules/Inputs/malformed/a1.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/malformed/a1.h?rev=195543&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/malformed/a1.h (added)
+++ cfe/trunk/test/Modules/Inputs/malformed/a1.h Fri Nov 22 22:06:09 2013
@@ -0,0 +1 @@
+void f() {

Added: cfe/trunk/test/Modules/Inputs/malformed/a2.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/malformed/a2.h?rev=195543&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/malformed/a2.h (added)
+++ cfe/trunk/test/Modules/Inputs/malformed/a2.h Fri Nov 22 22:06:09 2013
@@ -0,0 +1 @@
+}

Added: cfe/trunk/test/Modules/Inputs/malformed/b1.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/malformed/b1.h?rev=195543&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/malformed/b1.h (added)
+++ cfe/trunk/test/Modules/Inputs/malformed/b1.h Fri Nov 22 22:06:09 2013
@@ -0,0 +1,3 @@
+struct S {
+  #include "b2.h"
+};

Added: cfe/trunk/test/Modules/Inputs/malformed/b2.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/malformed/b2.h?rev=195543&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/malformed/b2.h (added)
+++ cfe/trunk/test/Modules/Inputs/malformed/b2.h Fri Nov 22 22:06:09 2013
@@ -0,0 +1 @@
+void g() {}

Added: cfe/trunk/test/Modules/Inputs/malformed/module.map
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/malformed/module.map?rev=195543&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/malformed/module.map (added)
+++ cfe/trunk/test/Modules/Inputs/malformed/module.map Fri Nov 22 22:06:09 2013
@@ -0,0 +1,8 @@
+module a {
+  module a1 { header "a1.h" }
+  module a2 { header "a2.h" }
+}
+module b {
+  module b1 { header "b1.h" }
+  module b2 { header "b2.h" }
+}

Modified: cfe/trunk/test/Modules/auto-module-import.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/auto-module-import.m?rev=195543&r1=195542&r2=195543&view=diff
==============================================================================
--- cfe/trunk/test/Modules/auto-module-import.m (original)
+++ cfe/trunk/test/Modules/auto-module-import.m Fri Nov 22 22:06:09 2013
@@ -83,6 +83,6 @@ int getNotInModule() {
   return not_in_module;
 }
 
-void includeNotAtTopLevel() {
-  #include <NoUmbrella/A.h> // expected-warning {{treating #include as an import}} expected-error {{expected expression}}
-}
+void includeNotAtTopLevel() { // expected-note {{to match this '{'}}
+  #include <NoUmbrella/A.h> // expected-warning {{treating #include as an import}} expected-error {{expected '}'}}
+} // expected-error {{extraneous closing brace}}

Added: cfe/trunk/test/Modules/malformed.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/malformed.cpp?rev=195543&view=auto
==============================================================================
--- cfe/trunk/test/Modules/malformed.cpp (added)
+++ cfe/trunk/test/Modules/malformed.cpp Fri Nov 22 22:06:09 2013
@@ -0,0 +1,23 @@
+// RUN: rm -rf %t
+// RUN: not %clang_cc1 -fmodules -fmodules-cache-path=%t -I %S/Inputs/malformed -DHEADER="a1.h" %s 2>&1 | FileCheck %s --check-prefix=CHECK-A
+// RUN: not %clang_cc1 -fmodules -fmodules-cache-path=%t -I %S/Inputs/malformed -DHEADER="b1.h" %s 2>&1 | FileCheck %s --check-prefix=CHECK-B
+
+#define STR2(x) #x
+#define STR(x) STR2(x)
+#include STR(HEADER)
+
+// CHECK-A: While building module 'a'
+// CHECK-A: a1.h:1:{{.*}} error: expected '}'
+// CHECK-A: a1.h:1:{{.*}} note: to match this '{'
+//
+// CHECK-A: While building module 'a'
+// CHECK-A: a2.h:1:{{.*}} error: extraneous closing brace
+
+// CHECK-B: While building module 'b'
+// CHECK-B: b1.h:2:{{.*}} error: expected '}'
+// CHECK-B: b1.h:1:{{.*}} note: to match this '{'
+// CHECK-B: b1.h:3:{{.*}} error: extraneous closing brace ('}')
+//
+// CHECK-B: While building module 'b'
+// CHECK-B: b2.h:1:{{.*}} error: redefinition of 'g'
+// CHECK-B: b2.h:1:{{.*}} note: previous definition is here





More information about the cfe-commits mailing list