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

Nico Weber thakis at chromium.org
Tue Dec 24 12:53:30 PST 2013


I filed PR18322 for this and added a FIXME to this test pointing to it for
now.


On Mon, Dec 2, 2013 at 6:38 PM, Richard Smith <richard at metafoo.co.uk> wrote:

> On Mon, Dec 2, 2013 at 5:58 PM, Rafael EspĂ­ndola <
> rafael.espindola at gmail.com> wrote:
>
>> looks like this found a real issue with OS X 10.9's headers.
>
>
> I agree that this looks like a bug in the headers; it looks like
> sys/_types/_wchar_t.h should probably not be specified as a separate
> submodule, since including it in an 'extern "C" {' suggests that it's just
> a fragment of text rather than an actual submodule.
>
> Should we just xfail the test?
>
>
> That fixes the test, but does nothing for people who are using Clang SVN
> on Mac OS with older (incompatible) modules. We need to figure out how to
> handle that case. Maybe we should include a version number in module.map
> files, and ignore module.maps that don't specify the right version?
>
>
>> Including a system header (<stdint.h>) in a
>> clang test seems like a bad idea, no?
>
>
> Well... the point of this test is to ensure that we do the right thing
> when our own <stdint.h> #include_next's the system one. We should probably
> change the test to get that effect a different way (for instance, by
> providing a fake sysroot with a fake <stdint.h>).
>
>
>> 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
>>
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20131224/69acf8f4/attachment.html>


More information about the cfe-commits mailing list