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

Richard Smith richard at metafoo.co.uk
Mon Dec 2 18:38:15 PST 2013


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
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20131202/be8875c9/attachment.html>


More information about the cfe-commits mailing list