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

Rafael EspĂ­ndola rafael.espindola at gmail.com
Mon Dec 2 17:58:52 PST 2013


looks like this found a real issue with OS X 10.9's headers. Should we
just xfail the test?  Including a system header (<stdint.h>) in a
clang test seems like a bad idea, no? I am getting:

Command Output (stderr):

--

While building module 'Darwin' imported from
/Users/respindola/llvm/clang/test/Headers/cxx11.cpp:18:

In file included from <module-includes>:10:

/usr/include/inttypes.h:252:1: error: expected '}'

#include <sys/_types/_wchar_t.h>

^

/usr/include/inttypes.h:235:1: note: to match this '{'

__BEGIN_DECLS

^

/usr/include/sys/cdefs.h:71:34: note: expanded from macro '__BEGIN_DECLS'

#define __BEGIN_DECLS   extern "C" {

                                   ^

While building module 'Darwin' imported from
/Users/respindola/llvm/clang/test/Headers/cxx11.cpp:18:

In file included from <module-includes>:10:

/usr/include/inttypes.h:263:1: error: extraneous closing brace ('}')

__END_DECLS

^

/usr/include/sys/cdefs.h:72:21: note: expanded from macro '__END_DECLS'

#define __END_DECLS     }

                        ^

While building module 'Darwin' imported from
/Users/respindola/llvm/clang/test/Headers/cxx11.cpp:18:

In file included from <module-includes>:25:

/usr/include/stdlib.h:238:1: error: expected '}'

#include <machine/types.h>

^

/usr/include/stdlib.h:127:1: note: to match this '{'

__BEGIN_DECLS

^

/usr/include/sys/cdefs.h:71:34: note: expanded from macro '__BEGIN_DECLS'

#define __BEGIN_DECLS   extern "C" {

                                   ^

While building module 'Darwin' imported from
/Users/respindola/llvm/clang/test/Headers/cxx11.cpp:18:

In file included from <module-includes>:25:

/usr/include/stdlib.h:323:1: error: extraneous closing brace ('}')

__END_DECLS

^

/usr/include/sys/cdefs.h:72:21: note: expanded from macro '__END_DECLS'

#define __END_DECLS     }

                        ^

While building module 'Darwin' imported from
/Users/respindola/llvm/clang/test/Headers/cxx11.cpp:18:

In file included from <module-includes>:49:

/usr/include/iconv.h:80:1: error: expected '}'

#include <sys/_types/_wchar_t.h>

^

/usr/include/iconv.h:56:12: note: to match this '{'

extern "C" {

           ^

/usr/include/iconv.h:185:1: error: extraneous closing brace ('}')

}

^

While building module 'Darwin' imported from
/Users/respindola/llvm/clang/test/Headers/cxx11.cpp:18:

In file included from <module-includes>:56:

In file included from /usr/include/net/if.h:106:

In file included from /usr/include/net/if_var.h:70:

/usr/include/sys/time.h:193:1: error: expected '}'

#include <sys/_select.h>        /* select() prototype */

^

/usr/include/sys/time.h:181:1: note: to match this '{'

__BEGIN_DECLS

^

/usr/include/sys/cdefs.h:71:34: note: expanded from macro '__BEGIN_DECLS'

#define __BEGIN_DECLS   extern "C" {

                                   ^

While building module 'Darwin' imported from
/Users/respindola/llvm/clang/test/Headers/cxx11.cpp:18:

In file included from <module-includes>:56:

In file included from /usr/include/net/if.h:106:

In file included from /usr/include/net/if_var.h:70:

/usr/include/sys/time.h:199:1: error: extraneous closing brace ('}')

__END_DECLS

^

/usr/include/sys/cdefs.h:72:21: note: expanded from macro '__END_DECLS'

#define __END_DECLS     }

                        ^

While building module 'Darwin' imported from
/Users/respindola/llvm/clang/test/Headers/cxx11.cpp:18:

In file included from <module-includes>:185:

/usr/include/unistd.h:707:7: error: declaration of 'valloc' has a
different language linkage

void    *valloc(size_t);

         ^

/usr/include/stdlib.h:316:7: note: previous declaration is here

void    *valloc(size_t);

         ^

While building module 'Darwin' imported from
/Users/respindola/llvm/clang/test/Headers/cxx11.cpp:18:

In file included from <module-includes>:185:

/usr/include/unistd.h:709:14: error: declaration of 'suboptarg' has a
different language linkage

extern char *suboptarg;                 /* getsubopt(3) external variable */

             ^

/usr/include/stdlib.h:315:14: note: previous definition is here

extern char *suboptarg;         /* getsubopt(3) external variable */

             ^

While building module 'Darwin' imported from
/Users/respindola/llvm/clang/test/Headers/cxx11.cpp:18:

In file included from <module-includes>:325:

In file included from /usr/include/ncurses.h:141:

/usr/include/unctrl.h:54:1: error: expected '}'

#include <curses.h>

^

/usr/include/unctrl.h:51:12: note: to match this '{'

extern "C" {

           ^

/usr/include/unctrl.h:60:1: error: extraneous closing brace ('}')

}

^

/Users/respindola/llvm/clang/test/Headers/cxx11.cpp:18:10: fatal
error: could not build module 'Darwin'

#include <stdint.h>

 ~~~~~~~~^

13 errors generated.

On 22 November 2013 23:06, Richard Smith <richard-llvm at metafoo.co.uk> wrote:
> 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
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits



More information about the cfe-commits mailing list