summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp88
1 files changed, 82 insertions, 6 deletions
diff --git a/contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp b/contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp
index 25a98ae..b6689df 100644
--- a/contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp
@@ -16,8 +16,12 @@
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/MacroInfo.h"
#include "clang/Lex/LexDiagnostic.h"
+#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
+#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/PathV2.h"
+#include "llvm/ADT/StringSwitch.h"
using namespace clang;
PPCallbacks::~PPCallbacks() {}
@@ -198,6 +202,31 @@ void Preprocessor::EnterTokenStream(const Token *Toks, unsigned NumToks,
CurLexerKind = CLK_TokenLexer;
}
+/// \brief Compute the relative path that names the given file relative to
+/// the given directory.
+static void computeRelativePath(FileManager &FM, const DirectoryEntry *Dir,
+ const FileEntry *File,
+ SmallString<128> &Result) {
+ Result.clear();
+
+ StringRef FilePath = File->getDir()->getName();
+ StringRef Path = FilePath;
+ while (!Path.empty()) {
+ if (const DirectoryEntry *CurDir = FM.getDirectory(Path)) {
+ if (CurDir == Dir) {
+ Result = FilePath.substr(Path.size());
+ llvm::sys::path::append(Result,
+ llvm::sys::path::filename(File->getName()));
+ return;
+ }
+ }
+
+ Path = llvm::sys::path::parent_path(Path);
+ }
+
+ Result = File->getName();
+}
+
/// 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.
@@ -216,8 +245,11 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) {
}
}
- // Complain about reaching an EOF within arc_cf_code_audited.
- if (PragmaARCCFCodeAuditedLoc.isValid()) {
+ // Complain about reaching a true EOF within arc_cf_code_audited.
+ // We don't want to complain about reaching the end of a macro
+ // instantiation or a _Pragma.
+ if (PragmaARCCFCodeAuditedLoc.isValid() &&
+ !isEndOfMacro && !(CurLexer && CurLexer->Is_PragmaLexer)) {
Diag(PragmaARCCFCodeAuditedLoc, diag::err_pp_eof_in_arc_cf_code_audited);
// Recover by leaving immediately.
@@ -296,15 +328,17 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) {
CurLexer->BufferPtr = EndPos;
CurLexer->FormTokenWithChars(Result, EndPos, tok::eof);
- // We're done with the #included file.
- CurLexer.reset();
+ if (!isIncrementalProcessingEnabled())
+ // We're done with lexing.
+ CurLexer.reset();
} else {
assert(CurPTHLexer && "Got EOF but no current lexer set!");
CurPTHLexer->getEOF(Result);
CurPTHLexer.reset();
}
-
- CurPPLexer = 0;
+
+ if (!isIncrementalProcessingEnabled())
+ CurPPLexer = 0;
// This is the end of the top-level file. 'WarnUnusedMacroLocs' has collected
// all macro locations that we need to warn because they are not used.
@@ -312,6 +346,48 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) {
I=WarnUnusedMacroLocs.begin(), E=WarnUnusedMacroLocs.end(); I!=E; ++I)
Diag(*I, diag::pp_macro_not_used);
+ // If we are building a module that has an umbrella header, make sure that
+ // each of the headers within the directory covered by the umbrella header
+ // was actually included by the umbrella header.
+ if (Module *Mod = getCurrentModule()) {
+ if (Mod->getUmbrellaHeader()) {
+ SourceLocation StartLoc
+ = SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
+
+ if (getDiagnostics().getDiagnosticLevel(
+ diag::warn_uncovered_module_header,
+ StartLoc) != DiagnosticsEngine::Ignored) {
+ ModuleMap &ModMap = getHeaderSearchInfo().getModuleMap();
+ typedef llvm::sys::fs::recursive_directory_iterator
+ recursive_directory_iterator;
+ const DirectoryEntry *Dir = Mod->getUmbrellaDir();
+ llvm::error_code EC;
+ for (recursive_directory_iterator Entry(Dir->getName(), EC), End;
+ Entry != End && !EC; Entry.increment(EC)) {
+ using llvm::StringSwitch;
+
+ // Check whether this entry has an extension typically associated with
+ // headers.
+ if (!StringSwitch<bool>(llvm::sys::path::extension(Entry->path()))
+ .Cases(".h", ".H", ".hh", ".hpp", true)
+ .Default(false))
+ continue;
+
+ if (const FileEntry *Header = getFileManager().getFile(Entry->path()))
+ if (!getSourceManager().hasFileInfo(Header)) {
+ if (!ModMap.isHeaderInUnavailableModule(Header)) {
+ // Find the relative path that would access this header.
+ SmallString<128> RelativePath;
+ computeRelativePath(FileMgr, Dir, Header, RelativePath);
+ Diag(StartLoc, diag::warn_uncovered_module_header)
+ << RelativePath;
+ }
+ }
+ }
+ }
+ }
+ }
+
return true;
}
OpenPOWER on IntegriCloud