diff options
author | Vedant Kumar <vsk@apple.com> | 2017-09-11 20:47:42 +0000 |
---|---|---|
committer | Vedant Kumar <vsk@apple.com> | 2017-09-11 20:47:42 +0000 |
commit | 3919a501f30688f0c4a03156fb672f381f03de5f (patch) | |
tree | ab649c95b8d89362f1dc95961206d117c1a09c4a /clang/lib | |
parent | 5d5aa214d83a7b90c8b8370e9449f32d4d6629b4 (diff) | |
download | bcm5719-llvm-3919a501f30688f0c4a03156fb672f381f03de5f.tar.gz bcm5719-llvm-3919a501f30688f0c4a03156fb672f381f03de5f.zip |
[Lexer] Report more precise skipped regions (PR34166)
This patch teaches the preprocessor to report more precise source ranges for
code that is skipped due to conditional directives.
The new behavior includes the '#' from the opening directive and the full text
of the line containing the closing directive in the skipped area. This matches
up clang's behavior (we don't IRGen the code between the closing "endif" and
the end of a line).
This also affects the code coverage implementation. See llvm.org/PR34166 (this
also happens to be rdar://problem/23224058).
The old behavior (report the end of the skipped range as the end
location of the 'endif' token) is preserved for indexing clients.
Differential Revision: https://reviews.llvm.org/D36642
llvm-svn: 312947
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/CodeGen/CoverageMappingGen.cpp | 2 | ||||
-rw-r--r-- | clang/lib/CodeGen/CoverageMappingGen.h | 2 | ||||
-rw-r--r-- | clang/lib/Lex/PPDirectives.cpp | 59 | ||||
-rw-r--r-- | clang/lib/Lex/PreprocessingRecord.cpp | 5 |
4 files changed, 39 insertions, 29 deletions
diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp index f47dd07f0cc..cf736a484e5 100644 --- a/clang/lib/CodeGen/CoverageMappingGen.cpp +++ b/clang/lib/CodeGen/CoverageMappingGen.cpp @@ -29,7 +29,7 @@ using namespace clang; using namespace CodeGen; using namespace llvm::coverage; -void CoverageSourceInfo::SourceRangeSkipped(SourceRange Range) { +void CoverageSourceInfo::SourceRangeSkipped(SourceRange Range, SourceLocation) { SkippedRanges.push_back(Range); } diff --git a/clang/lib/CodeGen/CoverageMappingGen.h b/clang/lib/CodeGen/CoverageMappingGen.h index b6789c2a79f..d07ed5ebcf2 100644 --- a/clang/lib/CodeGen/CoverageMappingGen.h +++ b/clang/lib/CodeGen/CoverageMappingGen.h @@ -39,7 +39,7 @@ class CoverageSourceInfo : public PPCallbacks { public: ArrayRef<SourceRange> getSkippedRanges() const { return SkippedRanges; } - void SourceRangeSkipped(SourceRange Range) override; + void SourceRangeSkipped(SourceRange Range, SourceLocation EndifLoc) override; }; namespace CodeGen { diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp index 6b09398e468..556e76356da 100644 --- a/clang/lib/Lex/PPDirectives.cpp +++ b/clang/lib/Lex/PPDirectives.cpp @@ -79,7 +79,8 @@ Preprocessor::AllocateVisibilityMacroDirective(SourceLocation Loc, } /// \brief Read and discard all tokens remaining on the current line until -/// the tok::eod token is found. +/// the tok::eod token is found. If the discarded tokens are in a skipped range, +/// complete the range and pass it to the \c SourceRangeSkipped callback. void Preprocessor::DiscardUntilEndOfDirective() { Token Tmp; do { @@ -350,7 +351,8 @@ void Preprocessor::CheckEndOfDirective(const char *DirType, bool EnableMacros) { /// If ElseOk is true, then \#else directives are ok, if not, then we have /// already seen one so a \#else directive is a duplicate. When this returns, /// the caller can lex the first valid token. -void Preprocessor::SkipExcludedConditionalBlock(SourceLocation IfTokenLoc, +void Preprocessor::SkipExcludedConditionalBlock(const Token &HashToken, + SourceLocation IfTokenLoc, bool FoundNonSkipPortion, bool FoundElse, SourceLocation ElseLoc) { @@ -558,10 +560,10 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation IfTokenLoc, // the #if block. CurPPLexer->LexingRawMode = false; - if (Callbacks) { - SourceLocation BeginLoc = ElseLoc.isValid() ? ElseLoc : IfTokenLoc; - Callbacks->SourceRangeSkipped(SourceRange(BeginLoc, Tok.getLocation())); - } + if (Callbacks) + Callbacks->SourceRangeSkipped( + SourceRange(HashToken.getLocation(), CurPPLexer->getSourceLocation()), + Tok.getLocation()); } void Preprocessor::PTHSkipExcludedConditionalBlock() { @@ -949,15 +951,17 @@ void Preprocessor::HandleDirective(Token &Result) { default: break; // C99 6.10.1 - Conditional Inclusion. case tok::pp_if: - return HandleIfDirective(Result, ReadAnyTokensBeforeDirective); + return HandleIfDirective(Result, SavedHash, ReadAnyTokensBeforeDirective); case tok::pp_ifdef: - return HandleIfdefDirective(Result, false, true/*not valid for miopt*/); + return HandleIfdefDirective(Result, SavedHash, false, + true /*not valid for miopt*/); case tok::pp_ifndef: - return HandleIfdefDirective(Result, true, ReadAnyTokensBeforeDirective); + return HandleIfdefDirective(Result, SavedHash, true, + ReadAnyTokensBeforeDirective); case tok::pp_elif: - return HandleElifDirective(Result); + return HandleElifDirective(Result, SavedHash); case tok::pp_else: - return HandleElseDirective(Result); + return HandleElseDirective(Result, SavedHash); case tok::pp_endif: return HandleEndifDirective(Result); @@ -2613,7 +2617,9 @@ void Preprocessor::HandleUndefDirective() { /// true if any tokens have been returned or pp-directives activated before this /// \#ifndef has been lexed. /// -void Preprocessor::HandleIfdefDirective(Token &Result, bool isIfndef, +void Preprocessor::HandleIfdefDirective(Token &Result, + const Token &HashToken, + bool isIfndef, bool ReadAnyTokensBeforeDirective) { ++NumIf; Token DirectiveTok = Result; @@ -2625,8 +2631,8 @@ void Preprocessor::HandleIfdefDirective(Token &Result, bool isIfndef, if (MacroNameTok.is(tok::eod)) { // Skip code until we get to #endif. This helps with recovery by not // emitting an error when the #endif is reached. - SkipExcludedConditionalBlock(DirectiveTok.getLocation(), - /*Foundnonskip*/false, /*FoundElse*/false); + SkipExcludedConditionalBlock(HashToken, DirectiveTok.getLocation(), + /*Foundnonskip*/ false, /*FoundElse*/ false); return; } @@ -2674,15 +2680,16 @@ void Preprocessor::HandleIfdefDirective(Token &Result, bool isIfndef, /*foundelse*/false); } else { // No, skip the contents of this block. - SkipExcludedConditionalBlock(DirectiveTok.getLocation(), - /*Foundnonskip*/false, - /*FoundElse*/false); + SkipExcludedConditionalBlock(HashToken, DirectiveTok.getLocation(), + /*Foundnonskip*/ false, + /*FoundElse*/ false); } } /// HandleIfDirective - Implements the \#if directive. /// void Preprocessor::HandleIfDirective(Token &IfToken, + const Token &HashToken, bool ReadAnyTokensBeforeDirective) { ++NumIf; @@ -2720,8 +2727,9 @@ void Preprocessor::HandleIfDirective(Token &IfToken, /*foundnonskip*/true, /*foundelse*/false); } else { // No, skip the contents of this block. - SkipExcludedConditionalBlock(IfToken.getLocation(), /*Foundnonskip*/false, - /*FoundElse*/false); + SkipExcludedConditionalBlock(HashToken, IfToken.getLocation(), + /*Foundnonskip*/ false, + /*FoundElse*/ false); } } @@ -2753,7 +2761,7 @@ void Preprocessor::HandleEndifDirective(Token &EndifToken) { /// HandleElseDirective - Implements the \#else directive. /// -void Preprocessor::HandleElseDirective(Token &Result) { +void Preprocessor::HandleElseDirective(Token &Result, const Token &HashToken) { ++NumElse; // #else directive in a non-skipping conditional... start skipping. @@ -2784,13 +2792,14 @@ void Preprocessor::HandleElseDirective(Token &Result) { } // Finally, skip the rest of the contents of this block. - SkipExcludedConditionalBlock(CI.IfLoc, /*Foundnonskip*/true, - /*FoundElse*/true, Result.getLocation()); + SkipExcludedConditionalBlock(HashToken, CI.IfLoc, /*Foundnonskip*/ true, + /*FoundElse*/ true, Result.getLocation()); } /// HandleElifDirective - Implements the \#elif directive. /// -void Preprocessor::HandleElifDirective(Token &ElifToken) { +void Preprocessor::HandleElifDirective(Token &ElifToken, + const Token &HashToken) { ++NumElse; // #elif directive in a non-skipping conditional... start skipping. @@ -2827,7 +2836,7 @@ void Preprocessor::HandleElifDirective(Token &ElifToken) { } // Finally, skip the rest of the contents of this block. - SkipExcludedConditionalBlock(CI.IfLoc, /*Foundnonskip*/true, - /*FoundElse*/CI.FoundElse, + SkipExcludedConditionalBlock(HashToken, CI.IfLoc, /*Foundnonskip*/ true, + /*FoundElse*/ CI.FoundElse, ElifToken.getLocation()); } diff --git a/clang/lib/Lex/PreprocessingRecord.cpp b/clang/lib/Lex/PreprocessingRecord.cpp index 03c4cbe589d..954b569bb02 100644 --- a/clang/lib/Lex/PreprocessingRecord.cpp +++ b/clang/lib/Lex/PreprocessingRecord.cpp @@ -400,8 +400,9 @@ void PreprocessingRecord::Defined(const Token &MacroNameTok, MacroNameTok.getLocation()); } -void PreprocessingRecord::SourceRangeSkipped(SourceRange Range) { - SkippedRanges.push_back(Range); +void PreprocessingRecord::SourceRangeSkipped(SourceRange Range, + SourceLocation EndifLoc) { + SkippedRanges.emplace_back(Range.getBegin(), EndifLoc); } void PreprocessingRecord::MacroExpands(const Token &Id, |