diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-11-23 04:06:09 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-11-23 04:06:09 +0000 |
commit | 34f30516aa7f32cbff61dc9066f0b332dfd88c2b (patch) | |
tree | 3761579a8a9c29f366a7f5a6c805567dfecef066 /clang/lib/Lex/PPLexerChange.cpp | |
parent | 5c6eab21ebaf93c68b5d1df8b845518ea6f54b63 (diff) | |
download | bcm5719-llvm-34f30516aa7f32cbff61dc9066f0b332dfd88c2b.tar.gz bcm5719-llvm-34f30516aa7f32cbff61dc9066f0b332dfd88c2b.zip |
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).
llvm-svn: 195543
Diffstat (limited to 'clang/lib/Lex/PPLexerChange.cpp')
-rw-r--r-- | clang/lib/Lex/PPLexerChange.cpp | 74 |
1 files changed, 50 insertions, 24 deletions
diff --git a/clang/lib/Lex/PPLexerChange.cpp b/clang/lib/Lex/PPLexerChange.cpp index 1f970a4450d..3b3c5a91920 100644 --- a/clang/lib/Lex/PPLexerChange.cpp +++ b/clang/lib/Lex/PPLexerChange.cpp @@ -69,7 +69,7 @@ PreprocessorLexer *Preprocessor::getCurrentFileLexer() const { /// 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(FileID FID, const DirectoryLookup *CurDir, if (PTH) { if (PTHLexer *PL = PTH->CreateLexer(FID)) { - EnterSourceFileWithPTH(PL, CurDir); + EnterSourceFileWithPTH(PL, CurDir, IsSubmodule); return; } } @@ -101,14 +101,16 @@ void Preprocessor::EnterSourceFile(FileID FID, const DirectoryLookup *CurDir, 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::EnterSourceFileWithLexer(Lexer *TheLexer, CurLexer.reset(TheLexer); CurPPLexer = TheLexer; CurDirLookup = CurDir; + CurIsSubmodule = IsSubmodule; if (CurLexerKind != CLK_LexAfterModuleImport) CurLexerKind = CLK_Lexer; @@ -133,7 +136,8 @@ void Preprocessor::EnterSourceFileWithLexer(Lexer *TheLexer, /// 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::EnterSourceFileWithPTH(PTHLexer *PL, CurDirLookup = CurDir; CurPTHLexer.reset(PL); CurPPLexer = CurPTHLexer.get(); + CurIsSubmodule = IsSubmodule; if (CurLexerKind != CLK_LexAfterModuleImport) CurLexerKind = CLK_PTHLexer; @@ -244,6 +249,29 @@ void Preprocessor::PropagateLineStartLeadingSpaceInfo(Token &Result) { // 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 &Result, bool isEndOfMacro) { 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 &Result, bool isEndOfMacro) { 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); |