aboutsummaryrefslogtreecommitdiff
path: root/lib/Frontend
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Frontend')
-rw-r--r--lib/Frontend/ASTConsumers.cpp4
-rw-r--r--lib/Frontend/ASTMerge.cpp7
-rw-r--r--lib/Frontend/ASTUnit.cpp58
-rw-r--r--lib/Frontend/ChainedIncludesSource.cpp4
-rw-r--r--lib/Frontend/CompilerInstance.cpp388
-rw-r--r--lib/Frontend/CompilerInvocation.cpp59
-rw-r--r--lib/Frontend/DependencyFile.cpp8
-rw-r--r--lib/Frontend/DiagnosticRenderer.cpp5
-rw-r--r--lib/Frontend/FrontendAction.cpp8
-rw-r--r--lib/Frontend/FrontendActions.cpp131
-rw-r--r--lib/Frontend/FrontendOptions.cpp2
-rw-r--r--lib/Frontend/InitHeaderSearch.cpp9
-rw-r--r--lib/Frontend/InitPreprocessor.cpp8
-rw-r--r--lib/Frontend/LogDiagnosticPrinter.cpp5
-rw-r--r--lib/Frontend/PrintPreprocessedOutput.cpp91
-rw-r--r--lib/Frontend/SerializedDiagnosticPrinter.cpp4
-rw-r--r--lib/Frontend/TextDiagnostic.cpp6
-rw-r--r--lib/Frontend/TextDiagnosticBuffer.cpp3
-rw-r--r--lib/Frontend/TextDiagnosticPrinter.cpp5
-rw-r--r--lib/Frontend/VerifyDiagnosticConsumer.cpp90
20 files changed, 657 insertions, 238 deletions
diff --git a/lib/Frontend/ASTConsumers.cpp b/lib/Frontend/ASTConsumers.cpp
index 936bd2f8a4..4a63d76a73 100644
--- a/lib/Frontend/ASTConsumers.cpp
+++ b/lib/Frontend/ASTConsumers.cpp
@@ -463,6 +463,10 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC,
Out << "<class template> " << *CTD << '\n';
break;
}
+ case Decl::OMPThreadPrivate: {
+ Out << "<omp threadprivate> " << '"' << *I << "\"\n";
+ break;
+ }
default:
Out << "DeclKind: " << DK << '"' << *I << "\"\n";
llvm_unreachable("decl unhandled");
diff --git a/lib/Frontend/ASTMerge.cpp b/lib/Frontend/ASTMerge.cpp
index bfb30836d8..b6c644eba7 100644
--- a/lib/Frontend/ASTMerge.cpp
+++ b/lib/Frontend/ASTMerge.cpp
@@ -34,7 +34,7 @@ bool ASTMergeAction::BeginSourceFileAction(CompilerInstance &CI,
void ASTMergeAction::ExecuteAction() {
CompilerInstance &CI = getCompilerInstance();
CI.getDiagnostics().getClient()->BeginSourceFile(
- CI.getASTContext().getLangOpts());
+ CI.getASTContext().getLangOpts());
CI.getDiagnostics().SetArgToStringFn(&FormatASTNodeDiagnosticArgument,
&CI.getASTContext());
IntrusiveRefCntPtr<DiagnosticIDs>
@@ -42,8 +42,9 @@ void ASTMergeAction::ExecuteAction() {
for (unsigned I = 0, N = ASTFiles.size(); I != N; ++I) {
IntrusiveRefCntPtr<DiagnosticsEngine>
Diags(new DiagnosticsEngine(DiagIDs, &CI.getDiagnosticOpts(),
- CI.getDiagnostics().getClient(),
- /*ShouldOwnClient=*/false));
+ new ForwardingDiagnosticConsumer(
+ *CI.getDiagnostics().getClient()),
+ /*ShouldOwnClient=*/true));
ASTUnit *Unit = ASTUnit::LoadFromASTFile(ASTFiles[I], Diags,
CI.getFileSystemOpts(), false);
if (!Unit)
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
index 4a956ff3ab..8bd5172454 100644
--- a/lib/Frontend/ASTUnit.cpp
+++ b/lib/Frontend/ASTUnit.cpp
@@ -236,6 +236,11 @@ ASTUnit::ASTUnit(bool _MainFileIsAST)
}
ASTUnit::~ASTUnit() {
+ // If we loaded from an AST file, balance out the BeginSourceFile call.
+ if (MainFileIsAST && getDiagnostics().getClient()) {
+ getDiagnostics().getClient()->EndSourceFile();
+ }
+
clearFileLevelDecls();
// Clean up the temporary files and the preamble file.
@@ -581,25 +586,24 @@ private:
}
};
+ /// \brief Diagnostic consumer that saves each diagnostic it is given.
class StoredDiagnosticConsumer : public DiagnosticConsumer {
SmallVectorImpl<StoredDiagnostic> &StoredDiags;
-
+ SourceManager *SourceMgr;
+
public:
explicit StoredDiagnosticConsumer(
SmallVectorImpl<StoredDiagnostic> &StoredDiags)
- : StoredDiags(StoredDiags) { }
-
+ : StoredDiags(StoredDiags), SourceMgr(0) { }
+
+ virtual void BeginSourceFile(const LangOptions &LangOpts,
+ const Preprocessor *PP = 0) {
+ if (PP)
+ SourceMgr = &PP->getSourceManager();
+ }
+
virtual void HandleDiagnostic(DiagnosticsEngine::Level Level,
const Diagnostic &Info);
-
- DiagnosticConsumer *clone(DiagnosticsEngine &Diags) const {
- // Just drop any diagnostics that come from cloned consumers; they'll
- // have different source managers anyway.
- // FIXME: We'd like to be able to capture these somehow, even if it's just
- // file/line/column, because they could occur when parsing module maps or
- // building modules on-demand.
- return new IgnoringDiagConsumer();
- }
};
/// \brief RAII object that optionally captures diagnostics, if
@@ -635,7 +639,11 @@ void StoredDiagnosticConsumer::HandleDiagnostic(DiagnosticsEngine::Level Level,
// Default implementation (Warnings/errors count).
DiagnosticConsumer::HandleDiagnostic(Level, Info);
- StoredDiags.push_back(StoredDiagnostic(Level, Info));
+ // Only record the diagnostic if it's part of the source manager we know
+ // about. This effectively drops diagnostics from modules we're building.
+ // FIXME: In the long run, ee don't want to drop source managers from modules.
+ if (!Info.hasSourceManager() || &Info.getSourceManager() == SourceMgr)
+ StoredDiags.push_back(StoredDiagnostic(Level, Info));
}
ASTDeserializationListener *ASTUnit::getDeserializationListener() {
@@ -662,8 +670,7 @@ void ASTUnit::ConfigureDiags(IntrusiveRefCntPtr<DiagnosticsEngine> &Diags,
Client = new StoredDiagnosticConsumer(AST.StoredDiagnostics);
Diags = CompilerInstance::createDiagnostics(new DiagnosticOptions(),
Client,
- /*ShouldOwnClient=*/true,
- /*ShouldCloneClient=*/false);
+ /*ShouldOwnClient=*/true);
} else if (CaptureDiagnostics) {
Diags->setClient(new StoredDiagnosticConsumer(AST.StoredDiagnostics));
}
@@ -801,6 +808,7 @@ ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename,
break;
case ASTReader::Failure:
+ case ASTReader::Missing:
case ASTReader::OutOfDate:
case ASTReader::VersionMismatch:
case ASTReader::ConfigurationMismatch:
@@ -834,6 +842,9 @@ ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename,
ReaderPtr->InitializeSema(*AST->TheSema);
AST->Reader = ReaderPtr;
+ // Tell the diagnostic client that we have started a source file.
+ AST->getDiagnostics().getClient()->BeginSourceFile(Context.getLangOpts(),&PP);
+
return AST.take();
}
@@ -1026,16 +1037,17 @@ public:
}
-static void checkAndRemoveNonDriverDiags(SmallVectorImpl<StoredDiagnostic> &
- StoredDiagnostics) {
+static bool isNonDriverDiag(const StoredDiagnostic &StoredDiag) {
+ return StoredDiag.getLocation().isValid();
+}
+
+static void
+checkAndRemoveNonDriverDiags(SmallVectorImpl<StoredDiagnostic> &StoredDiags) {
// Get rid of stored diagnostics except the ones from the driver which do not
// have a source location.
- for (unsigned I = 0; I < StoredDiagnostics.size(); ++I) {
- if (StoredDiagnostics[I].getLocation().isValid()) {
- StoredDiagnostics.erase(StoredDiagnostics.begin()+I);
- --I;
- }
- }
+ StoredDiags.erase(
+ std::remove_if(StoredDiags.begin(), StoredDiags.end(), isNonDriverDiag),
+ StoredDiags.end());
}
static void checkAndSanitizeDiags(SmallVectorImpl<StoredDiagnostic> &
diff --git a/lib/Frontend/ChainedIncludesSource.cpp b/lib/Frontend/ChainedIncludesSource.cpp
index f414f93812..cde84caade 100644
--- a/lib/Frontend/ChainedIncludesSource.cpp
+++ b/lib/Frontend/ChainedIncludesSource.cpp
@@ -47,6 +47,7 @@ static ASTReader *createASTReader(CompilerInstance &CI,
return Reader.take();
case ASTReader::Failure:
+ case ASTReader::Missing:
case ASTReader::OutOfDate:
case ASTReader::VersionMismatch:
case ASTReader::ConfigurationMismatch:
@@ -112,8 +113,6 @@ ChainedIncludesSource *ChainedIncludesSource::create(CompilerInstance &CI) {
OwningPtr<ASTConsumer> consumer;
consumer.reset(new PCHGenerator(Clang->getPreprocessor(), "-", 0,
/*isysroot=*/"", &OS));
- Clang->getPreprocessor().setPPMutationListener(
- consumer->GetPPMutationListener());
Clang->getASTContext().setASTMutationListener(
consumer->GetASTMutationListener());
Clang->setASTConsumer(consumer.take());
@@ -144,6 +143,7 @@ ChainedIncludesSource *ChainedIncludesSource::create(CompilerInstance &CI) {
Clang->getASTConsumer().GetASTDeserializationListener()));
if (!Reader)
return 0;
+ Clang->setModuleManager(static_cast<ASTReader*>(Reader.get()));
Clang->getASTContext().setExternalSource(Reader);
}
diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp
index ce6572aa1b..cf856fc2ab 100644
--- a/lib/Frontend/CompilerInstance.cpp
+++ b/lib/Frontend/CompilerInstance.cpp
@@ -44,6 +44,8 @@
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/system_error.h"
+#include <sys/stat.h>
+#include <time.h>
using namespace clang;
@@ -62,7 +64,8 @@ void CompilerInstance::setInvocation(CompilerInvocation *Value) {
bool CompilerInstance::shouldBuildGlobalModuleIndex() const {
return (BuildGlobalModuleIndex ||
- (ModuleManager && ModuleManager->isGlobalIndexUnavailable())) &&
+ (ModuleManager && ModuleManager->isGlobalIndexUnavailable() &&
+ getFrontendOpts().GenerateGlobalModuleIndex)) &&
!ModuleBuildFailed;
}
@@ -152,18 +155,15 @@ static void SetupSerializedDiagnostics(DiagnosticOptions *DiagOpts,
}
void CompilerInstance::createDiagnostics(DiagnosticConsumer *Client,
- bool ShouldOwnClient,
- bool ShouldCloneClient) {
+ bool ShouldOwnClient) {
Diagnostics = createDiagnostics(&getDiagnosticOpts(), Client,
- ShouldOwnClient, ShouldCloneClient,
- &getCodeGenOpts());
+ ShouldOwnClient, &getCodeGenOpts());
}
IntrusiveRefCntPtr<DiagnosticsEngine>
CompilerInstance::createDiagnostics(DiagnosticOptions *Opts,
DiagnosticConsumer *Client,
bool ShouldOwnClient,
- bool ShouldCloneClient,
const CodeGenOptions *CodeGenOpts) {
IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
IntrusiveRefCntPtr<DiagnosticsEngine>
@@ -172,10 +172,7 @@ CompilerInstance::createDiagnostics(DiagnosticOptions *Opts,
// Create the diagnostic client for reporting errors or for
// implementing -verify.
if (Client) {
- if (ShouldCloneClient)
- Diags->setClient(Client->clone(*Diags), ShouldOwnClient);
- else
- Diags->setClient(Client, ShouldOwnClient);
+ Diags->setClient(Client, ShouldOwnClient);
} else
Diags->setClient(new TextDiagnosticPrinter(llvm::errs(), Opts));
@@ -338,6 +335,7 @@ CompilerInstance::createPCHExternalASTSource(StringRef Path,
// Unrecoverable failure: don't even try to process the input file.
break;
+ case ASTReader::Missing:
case ASTReader::OutOfDate:
case ASTReader::VersionMismatch:
case ASTReader::ConfigurationMismatch:
@@ -864,9 +862,10 @@ static void compileModule(CompilerInstance &ImportingInstance,
// module.
CompilerInstance Instance;
Instance.setInvocation(&*Invocation);
- Instance.createDiagnostics(&ImportingInstance.getDiagnosticClient(),
- /*ShouldOwnClient=*/true,
- /*ShouldCloneClient=*/true);
+
+ Instance.createDiagnostics(new ForwardingDiagnosticConsumer(
+ ImportingInstance.getDiagnosticClient()),
+ /*ShouldOwnClient=*/true);
// Note that this module is part of the module build stack, so that we
// can detect cycles in the module graph.
@@ -888,6 +887,7 @@ static void compileModule(CompilerInstance &ImportingInstance,
llvm::CrashRecoveryContext CRC;
CompileModuleMapData Data = { Instance, CreateModuleAction };
CRC.RunSafelyOnThread(&doCompileMapModule, &Data, ThreadStackSize);
+
// Delete the temporary module map file.
// FIXME: Even though we're executing under crash protection, it would still
@@ -904,6 +904,183 @@ static void compileModule(CompilerInstance &ImportingInstance,
}
}
+/// \brief Diagnose differences between the current definition of the given
+/// configuration macro and the definition provided on the command line.
+static void checkConfigMacro(Preprocessor &PP, StringRef ConfigMacro,
+ Module *Mod, SourceLocation ImportLoc) {
+ IdentifierInfo *Id = PP.getIdentifierInfo(ConfigMacro);
+ SourceManager &SourceMgr = PP.getSourceManager();
+
+ // If this identifier has never had a macro definition, then it could
+ // not have changed.
+ if (!Id->hadMacroDefinition())
+ return;
+
+ // If this identifier does not currently have a macro definition,
+ // check whether it had one on the command line.
+ if (!Id->hasMacroDefinition()) {
+ MacroDirective::DefInfo LatestDef =
+ PP.getMacroDirectiveHistory(Id)->getDefinition();
+ for (MacroDirective::DefInfo Def = LatestDef; Def;
+ Def = Def.getPreviousDefinition()) {
+ FileID FID = SourceMgr.getFileID(Def.getLocation());
+ if (FID.isInvalid())
+ continue;
+
+ // We only care about the predefines buffer.
+ if (FID != PP.getPredefinesFileID())
+ continue;
+
+ // This macro was defined on the command line, then #undef'd later.
+ // Complain.
+ PP.Diag(ImportLoc, diag::warn_module_config_macro_undef)
+ << true << ConfigMacro << Mod->getFullModuleName();
+ if (LatestDef.isUndefined())
+ PP.Diag(LatestDef.getUndefLocation(), diag::note_module_def_undef_here)
+ << true;
+ return;
+ }
+
+ // Okay: no definition in the predefines buffer.
+ return;
+ }
+
+ // This identifier has a macro definition. Check whether we had a definition
+ // on the command line.
+ MacroDirective::DefInfo LatestDef =
+ PP.getMacroDirectiveHistory(Id)->getDefinition();
+ MacroDirective::DefInfo PredefinedDef;
+ for (MacroDirective::DefInfo Def = LatestDef; Def;
+ Def = Def.getPreviousDefinition()) {
+ FileID FID = SourceMgr.getFileID(Def.getLocation());
+ if (FID.isInvalid())
+ continue;
+
+ // We only care about the predefines buffer.
+ if (FID != PP.getPredefinesFileID())
+ continue;
+
+ PredefinedDef = Def;
+ break;
+ }
+
+ // If there was no definition for this macro in the predefines buffer,
+ // complain.
+ if (!PredefinedDef ||
+ (!PredefinedDef.getLocation().isValid() &&
+ PredefinedDef.getUndefLocation().isValid())) {
+ PP.Diag(ImportLoc, diag::warn_module_config_macro_undef)
+ << false << ConfigMacro << Mod->getFullModuleName();
+ PP.Diag(LatestDef.getLocation(), diag::note_module_def_undef_here)
+ << false;
+ return;
+ }
+
+ // If the current macro definition is the same as the predefined macro
+ // definition, it's okay.
+ if (LatestDef.getMacroInfo() == PredefinedDef.getMacroInfo() ||
+ LatestDef.getMacroInfo()->isIdenticalTo(*PredefinedDef.getMacroInfo(),PP,
+ /*Syntactically=*/true))
+ return;
+
+ // The macro definitions differ.
+ PP.Diag(ImportLoc, diag::warn_module_config_macro_undef)
+ << false << ConfigMacro << Mod->getFullModuleName();
+ PP.Diag(LatestDef.getLocation(), diag::note_module_def_undef_here)
+ << false;
+}
+
+/// \brief Write a new timestamp file with the given path.
+static void writeTimestampFile(StringRef TimestampFile) {
+ std::string ErrorInfo;
+ llvm::raw_fd_ostream Out(TimestampFile.str().c_str(), ErrorInfo,
+ llvm::raw_fd_ostream::F_Binary);
+}
+
+/// \brief Prune the module cache of modules that haven't been accessed in
+/// a long time.
+static void pruneModuleCache(const HeaderSearchOptions &HSOpts) {
+ struct stat StatBuf;
+ llvm::SmallString<128> TimestampFile;
+ TimestampFile = HSOpts.ModuleCachePath;
+ llvm::sys::path::append(TimestampFile, "modules.timestamp");
+
+ // Try to stat() the timestamp file.
+ if (::stat(TimestampFile.c_str(), &StatBuf)) {
+ // If the timestamp file wasn't there, create one now.
+ if (errno == ENOENT) {
+ writeTimestampFile(TimestampFile);
+ }
+ return;
+ }
+
+ // Check whether the time stamp is older than our pruning interval.
+ // If not, do nothing.
+ time_t TimeStampModTime = StatBuf.st_mtime;
+ time_t CurrentTime = time(0);
+ if (CurrentTime - TimeStampModTime <= time_t(HSOpts.ModuleCachePruneInterval))
+ return;
+
+ // Write a new timestamp file so that nobody else attempts to prune.
+ // There is a benign race condition here, if two Clang instances happen to
+ // notice at the same time that the timestamp is out-of-date.
+ writeTimestampFile(TimestampFile);
+
+ // Walk the entire module cache, looking for unused module files and module
+ // indices.
+ llvm::error_code EC;
+ SmallString<128> ModuleCachePathNative;
+ llvm::sys::path::native(HSOpts.ModuleCachePath, ModuleCachePathNative);
+ for (llvm::sys::fs::directory_iterator
+ Dir(ModuleCachePathNative.str(), EC), DirEnd;
+ Dir != DirEnd && !EC; Dir.increment(EC)) {
+ // If we don't have a directory, there's nothing to look into.
+ bool IsDirectory;
+ if (llvm::sys::fs::is_directory(Dir->path(), IsDirectory) || !IsDirectory)
+ continue;
+
+ // Walk all of the files within this directory.
+ bool RemovedAllFiles = true;
+ for (llvm::sys::fs::directory_iterator File(Dir->path(), EC), FileEnd;
+ File != FileEnd && !EC; File.increment(EC)) {
+ // We only care about module and global module index files.
+ if (llvm::sys::path::extension(File->path()) != ".pcm" &&
+ llvm::sys::path::filename(File->path()) != "modules.idx") {
+ RemovedAllFiles = false;
+ continue;
+ }
+
+ // Look at this file. If we can't stat it, there's nothing interesting
+ // there.
+ if (::stat(File->path().c_str(), &StatBuf)) {
+ RemovedAllFiles = false;
+ continue;
+ }
+
+ // If the file has been used recently enough, leave it there.
+ time_t FileAccessTime = StatBuf.st_atime;
+ if (CurrentTime - FileAccessTime <=
+ time_t(HSOpts.ModuleCachePruneAfter)) {
+ RemovedAllFiles = false;
+ continue;
+ }
+
+ // Remove the file.
+ bool Existed;
+ if (llvm::sys::fs::remove(File->path(), Existed) || !Existed) {
+ RemovedAllFiles = false;
+ }
+ }
+
+ // If we removed all of the files in the directory, remove the directory
+ // itself.
+ if (RemovedAllFiles) {
+ bool Existed;
+ llvm::sys::fs::remove(Dir->path(), Existed);
+ }
+ }
+}
+
ModuleLoadResult
CompilerInstance::loadModule(SourceLocation ImportLoc,
ModuleIdPath Path,
@@ -916,7 +1093,7 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
// Make the named module visible.
if (LastModuleImportResult)
ModuleManager->makeModuleVisible(LastModuleImportResult, Visibility,
- ImportLoc);
+ ImportLoc, /*Complain=*/false);
return LastModuleImportResult;
}
@@ -945,93 +1122,19 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
} else
ModuleFileName = PP->getHeaderSearchInfo().getModuleFileName(ModuleName);
- if (ModuleFileName.empty()) {
- getDiagnostics().Report(ModuleNameLoc, diag::err_module_not_found)
- << ModuleName
- << SourceRange(ImportLoc, ModuleNameLoc);
- LastModuleImportLoc = ImportLoc;
- LastModuleImportResult = ModuleLoadResult();
- return LastModuleImportResult;
- }
-
- const FileEntry *ModuleFile
- = getFileManager().getFile(ModuleFileName, /*OpenFile=*/false,
- /*CacheFailure=*/false);
- bool BuildingModule = false;
- if (!ModuleFile && Module) {
- // The module is not cached, but we have a module map from which we can
- // build the module.
-
- // Check whether there is a cycle in the module graph.
- ModuleBuildStack Path = getSourceManager().getModuleBuildStack();
- ModuleBuildStack::iterator Pos = Path.begin(), PosEnd = Path.end();
- for (; Pos != PosEnd; ++Pos) {
- if (Pos->first == ModuleName)
- break;
- }
-
- if (Pos != PosEnd) {
- SmallString<256> CyclePath;
- for (; Pos != PosEnd; ++Pos) {
- CyclePath += Pos->first;
- CyclePath += " -> ";
- }
- CyclePath += ModuleName;
-
- getDiagnostics().Report(ModuleNameLoc, diag::err_module_cycle)
- << ModuleName << CyclePath;
- return ModuleLoadResult();
- }
-
- // Check whether we have already attempted to build this module (but
- // failed).
- if (getPreprocessorOpts().FailedModules &&
- getPreprocessorOpts().FailedModules->hasAlreadyFailed(ModuleName)) {
- getDiagnostics().Report(ModuleNameLoc, diag::err_module_not_built)
- << ModuleName
- << SourceRange(ImportLoc, ModuleNameLoc);
- ModuleBuildFailed = true;
- return ModuleLoadResult();
- }
-
- BuildingModule = true;
- compileModule(*this, ModuleNameLoc, Module, ModuleFileName);
- ModuleFile = FileMgr->getFile(ModuleFileName, /*OpenFile=*/false,
- /*CacheFailure=*/false);
-
- if (!ModuleFile && getPreprocessorOpts().FailedModules)
- getPreprocessorOpts().FailedModules->addFailed(ModuleName);
- }
-
- if (!ModuleFile) {
- getDiagnostics().Report(ModuleNameLoc,
- BuildingModule? diag::err_module_not_built
- : diag::err_module_not_found)
- << ModuleName
- << SourceRange(ImportLoc, ModuleNameLoc);
- ModuleBuildFailed = true;
- return ModuleLoadResult();
- }
-
- // If there is already a module file associated with this module, make sure
- // it is the same as the module file we're looking for. Otherwise, we
- // have two module files for the same module.
- if (const FileEntry *CurModuleFile = Module? Module->getASTFile() : 0) {
- if (CurModuleFile != ModuleFile) {
- getDiagnostics().Report(ModuleNameLoc, diag::err_module_file_conflict)
- << ModuleName
- << CurModuleFile->getName()
- << ModuleFile->getName();
- ModuleBuildFailed = true;
- return ModuleLoadResult();
- }
- }
-
// If we don't already have an ASTReader, create one now.
if (!ModuleManager) {
if (!hasASTContext())
createASTContext();
+ // If we're not recursively building a module, check whether we
+ // need to prune the module cache.
+ if (getSourceManager().getModuleBuildStack().empty() &&
+ getHeaderSearchOpts().ModuleCachePruneInterval > 0 &&
+ getHeaderSearchOpts().ModuleCachePruneAfter > 0) {
+ pruneModuleCache(getHeaderSearchOpts());
+ }
+
std::string Sysroot = getHeaderSearchOpts().Sysroot;
const PreprocessorOptions &PPOpts = getPreprocessorOpts();
ModuleManager = new ASTReader(getPreprocessor(), *Context,
@@ -1044,8 +1147,6 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
getASTConsumer().GetASTDeserializationListener());
getASTContext().setASTMutationListener(
getASTConsumer().GetASTMutationListener());
- getPreprocessor().setPPMutationListener(
- getASTConsumer().GetPPMutationListener());
}
OwningPtr<ExternalASTSource> Source;
Source.reset(ModuleManager);
@@ -1056,21 +1157,53 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
ModuleManager->StartTranslationUnit(&getASTConsumer());
}
- // Try to load the module we found.
- unsigned ARRFlags = ASTReader::ARR_None;
- if (Module)
- ARRFlags |= ASTReader::ARR_OutOfDate;
- switch (ModuleManager->ReadAST(ModuleFile->getName(),
- serialization::MK_Module, ImportLoc,
- ARRFlags)) {
+ // Try to load the module file.
+ unsigned ARRFlags = ASTReader::ARR_OutOfDate | ASTReader::ARR_Missing;
+ switch (ModuleManager->ReadAST(ModuleFileName, serialization::MK_Module,
+ ImportLoc, ARRFlags)) {
case ASTReader::Success:
break;
case ASTReader::OutOfDate: {
- // The module file is out-of-date. Rebuild it.
- getFileManager().invalidateCache(ModuleFile);
+ // The module file is out-of-date. Remove it, then rebuild it.
bool Existed;
llvm::sys::fs::remove(ModuleFileName, Existed);
+ }
+ // Fall through to build the module again.
+
+ case ASTReader::Missing: {
+ // The module file is (now) missing. Build it.
+
+ // If we don't have a module, we don't know how to build the module file.
+ // Complain and return.
+ if (!Module) {
+ getDiagnostics().Report(ModuleNameLoc, diag::err_module_not_found)
+ << ModuleName
+ << SourceRange(ImportLoc, ModuleNameLoc);
+ ModuleBuildFailed = true;
+ return ModuleLoadResult();
+ }
+
+ // Check whether there is a cycle in the module graph.
+ ModuleBuildStack ModPath = getSourceManager().getModuleBuildStack();
+ ModuleBuildStack::iterator Pos = ModPath.begin(), PosEnd = ModPath.end();
+ for (; Pos != PosEnd; ++Pos) {
+ if (Pos->first == ModuleName)
+ break;
+ }
+
+ if (Pos != PosEnd) {
+ SmallString<256> CyclePath;
+ for (; Pos != PosEnd; ++Pos) {
+ CyclePath += Pos->first;
+ CyclePath += " -> ";
+ }
+ CyclePath += ModuleName;
+
+ getDiagnostics().Report(ModuleNameLoc, diag::err_module_cycle)
+ << ModuleName << CyclePath;
+ return ModuleLoadResult();
+ }
// Check whether we have already attempted to build this module (but
// failed).
@@ -1083,15 +1216,23 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
return ModuleLoadResult();
}
+ // Try to compile the module.
compileModule(*this, ModuleNameLoc, Module, ModuleFileName);
- // Try loading the module again.
- ModuleFile = FileMgr->getFile(ModuleFileName, /*OpenFile=*/false,
- /*CacheFailure=*/false);
- if (!ModuleFile ||
- ModuleManager->ReadAST(ModuleFileName,
+ // Try to read the module file, now that we've compiled it.
+ ASTReader::ASTReadResult ReadResult
+ = ModuleManager->ReadAST(ModuleFileName,
serialization::MK_Module, ImportLoc,
- ASTReader::ARR_None) != ASTReader::Success) {
+ ASTReader::ARR_Missing);
+ if (ReadResult != ASTReader::Success) {
+ if (ReadResult == ASTReader::Missing) {
+ getDiagnostics().Report(ModuleNameLoc,
+ Module? diag::err_module_not_built
+ : diag::err_module_not_found)
+ << ModuleName
+ << SourceRange(ImportLoc, ModuleNameLoc);
+ }
+
if (getPreprocessorOpts().FailedModules)
getPreprocessorOpts().FailedModules->addFailed(ModuleName);
KnownModules[Path[0].first] = 0;
@@ -1125,10 +1266,6 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
.findModule((Path[0].first->getName()));
}
- if (Module) {
- Module->setASTFile(ModuleFile);
- }
-
// Cache the result of this top-level module lookup for later.
Known = KnownModules.insert(std::make_pair(Path[0].first, Module)).first;
}
@@ -1220,9 +1357,17 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
return ModuleLoadResult();
}
- ModuleManager->makeModuleVisible(Module, Visibility, ImportLoc);
+ ModuleManager->makeModuleVisible(Module, Visibility, ImportLoc,
+ /*Complain=*/true);
}
-
+
+ // Check for any configuration macros that have changed.
+ clang::Module *TopModule = Module->getTopLevelModule();
+ for (unsigned I = 0, N = TopModule->ConfigMacros.size(); I != N; ++I) {
+ checkConfigMacro(getPreprocessor(), TopModule->ConfigMacros[I],
+ Module, ImportLoc);
+ }
+
// If this module import was due to an inclusion directive, create an
// implicit import declaration to capture it in the AST.
if (IsInclusionDirective && hasASTContext()) {
@@ -1242,7 +1387,8 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
void CompilerInstance::makeModuleVisible(Module *Mod,
Module::NameVisibilityKind Visibility,
- SourceLocation ImportLoc){
- ModuleManager->makeModuleVisible(Mod, Visibility, ImportLoc);
+ SourceLocation ImportLoc,
+ bool Complain){
+ ModuleManager->makeModuleVisible(Mod, Visibility, ImportLoc, Complain);
}
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 3c5954a696..42ea96f0f2 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -29,6 +29,7 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/system_error.h"
using namespace clang;
//===----------------------------------------------------------------------===//
@@ -68,6 +69,9 @@ static unsigned getOptimizationLevel(ArgList &Args, InputKind IK,
if (A->getOption().matches(options::OPT_O0))
return 0;
+ if (A->getOption().matches(options::OPT_Ofast))
+ return 3;
+
assert (A->getOption().matches(options::OPT_O));
StringRef S(A->getValue());
@@ -80,8 +84,7 @@ static unsigned getOptimizationLevel(ArgList &Args, InputKind IK,
return DefaultOpt;
}
-static unsigned getOptimizationLevelSize(ArgList &Args, InputKind IK,
- DiagnosticsEngine &Diags) {
+static unsigned getOptimizationLevelSize(ArgList &Args) {
if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
if (A->getOption().matches(options::OPT_O)) {
switch (A->getValue()[0]) {
@@ -281,6 +284,7 @@ static bool ParseMigratorArgs(MigratorOptions &Opts, ArgList &Args) {
static void ParseCommentArgs(CommentOptions &Opts, ArgList &Args) {
Opts.BlockCommandNames = Args.getAllArgValues(OPT_fcomment_block_commands);
+ Opts.ParseAllComments = Args.hasArg(OPT_fparse_all_comments);
}
static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
@@ -317,23 +321,24 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.DebugColumnInfo = Args.hasArg(OPT_dwarf_column_info);
Opts.SplitDwarfFile = Args.getLastArgValue(OPT_split_dwarf_file);
- Opts.ModulesAutolink = Args.hasArg(OPT_fmodules_autolink);
Opts.DisableLLVMOpts = Args.hasArg(OPT_disable_llvm_optzns);
Opts.DisableRedZone = Args.hasArg(OPT_disable_red_zone);
Opts.ForbidGuardVariables = Args.hasArg(OPT_fforbid_guard_variables);
Opts.UseRegisterSizedBitfieldAccess = Args.hasArg(
OPT_fuse_register_sized_bitfield_access);
Opts.RelaxedAliasing = Args.hasArg(OPT_relaxed_aliasing);
+ Opts.StructPathTBAA = Args.hasArg(OPT_struct_path_tbaa);
Opts.DwarfDebugFlags = Args.getLastArgValue(OPT_dwarf_debug_flags);
Opts.MergeAllConstants = !Args.hasArg(OPT_fno_merge_all_constants);
Opts.NoCommon = Args.hasArg(OPT_fno_common);
Opts.NoImplicitFloat = Args.hasArg(OPT_no_implicit_float);
- Opts.OptimizeSize = getOptimizationLevelSize(Args, IK, Diags);
+ Opts.OptimizeSize = getOptimizationLevelSize(Args);
Opts.SimplifyLibCalls = !(Args.hasArg(OPT_fno_builtin) ||
Args.hasArg(OPT_ffreestanding));
Opts.UnrollLoops = Args.hasArg(OPT_funroll_loops) ||
(Opts.OptimizationLevel > 1 && !Opts.OptimizeSize);
+ Opts.Autolink = !Args.hasArg(OPT_fno_autolink);
Opts.AsmVerbose = Args.hasArg(OPT_masm_verbose);
Opts.ObjCAutoRefCountExceptions = Args.hasArg(OPT_fobjc_arc_exceptions);
Opts.CUDAIsDevice = Args.hasArg(OPT_fcuda_is_device);
@@ -358,6 +363,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.NumRegisterParameters = Args.getLastArgIntValue(OPT_mregparm, 0, Diags);
Opts.NoGlobalMerge = Args.hasArg(OPT_mno_global_merge);
Opts.NoExecStack = Args.hasArg(OPT_mno_exec_stack);
+ Opts.EnableSegmentedStacks = Args.hasArg(OPT_split_stacks);
Opts.RelaxAll = Args.hasArg(OPT_mrelax_all);
Opts.OmitLeafFramePointer = Args.hasArg(OPT_momit_leaf_frame_pointer);
Opts.SaveTempLabels = Args.hasArg(OPT_msave_temp_labels);
@@ -380,13 +386,14 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.VerifyModule = !Args.hasArg(OPT_disable_llvm_verifier);
Opts.SanitizeRecover = !Args.hasArg(OPT_fno_sanitize_recover);
+ Opts.DisableGCov = Args.hasArg(OPT_test_coverage);
Opts.EmitGcovArcs = Args.hasArg(OPT_femit_coverage_data);
Opts.EmitGcovNotes = Args.hasArg(OPT_femit_coverage_notes);
if (Opts.EmitGcovArcs || Opts.EmitGcovNotes) {
Opts.CoverageFile = Args.getLastArgValue(OPT_coverage_file);
Opts.CoverageExtraChecksum = Args.hasArg(OPT_coverage_cfg_checksum);
- Opts.CoverageFunctionNamesInData =
- Args.hasArg(OPT_coverage_function_names_in_data);
+ Opts.CoverageNoFunctionNamesInData =
+ Args.hasArg(OPT_coverage_no_function_names_in_data);
if (Args.hasArg(OPT_coverage_version_EQ)) {
StringRef CoverageVersion = Args.getLastArgValue(OPT_coverage_version_EQ);
if (CoverageVersion.size() != 4) {
@@ -394,10 +401,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
<< Args.getLastArg(OPT_coverage_version_EQ)->getAsString(Args)
<< CoverageVersion;
} else {
- Opts.CoverageVersion[0] = CoverageVersion[3];
- Opts.CoverageVersion[1] = CoverageVersion[2];
- Opts.CoverageVersion[2] = CoverageVersion[1];
- Opts.CoverageVersion[3] = CoverageVersion[0];
+ memcpy(Opts.CoverageVersion, CoverageVersion.data(), 4);
}
}
}
@@ -645,6 +649,8 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
Opts.ProgramAction = frontend::InitOnly; break;
case OPT_fsyntax_only:
Opts.ProgramAction = frontend::ParseSyntaxOnly; break;
+ case OPT_module_file_info:
+ Opts.ProgramAction = frontend::ModuleFileInfo; break;
case OPT_print_decl_contexts:
Opts.ProgramAction = frontend::PrintDeclContext; break;
case OPT_print_preamble:
@@ -780,7 +786,7 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
.Case("objective-c-header", IK_ObjC)
.Case("c++-header", IK_CXX)
.Case("objective-c++-header", IK_ObjCXX)
- .Case("ast", IK_AST)
+ .Cases("ast", "pcm", IK_AST)
.Case("ir", IK_LLVM_IR)
.Default(IK_None);
if (DashX == IK_None)
@@ -837,7 +843,10 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) {
Opts.ResourceDir = Args.getLastArgValue(OPT_resource_dir);
Opts.ModuleCachePath = Args.getLastArgValue(OPT_fmodules_cache_path);
Opts.DisableModuleHash = Args.hasArg(OPT_fdisable_module_hash);
-
+ Opts.ModuleCachePruneInterval
+ = Args.getLastArgIntValue(OPT_fmodules_prune_interval, 7*24*60*60);
+ Opts.ModuleCachePruneAfter
+ = Args.getLastArgIntValue(OPT_fmodules_prune_after, 31*24*60*60);
for (arg_iterator it = Args.filtered_begin(OPT_fmodules_ignore_macro),
ie = Args.filtered_end(); it != ie; ++it) {
StringRef MacroDef = (*it)->getValue();
@@ -1171,9 +1180,6 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
if (Args.hasArg(OPT_pthread))
Opts.POSIXThreads = 1;
- if (Args.hasArg(OPT_fdelayed_template_parsing))
- Opts.DelayedTemplateParsing = 1;
-
// The value-visibility mode defaults to "default".
if (Arg *visOpt = Args.getLastArg(OPT_fvisibility)) {
Opts.setValueVisibilityMode(parseVisibility(visOpt, Args, Diags));
@@ -1241,7 +1247,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.AccessControl = !Args.hasArg(OPT_fno_access_control);
Opts.ElideConstructors = !Args.hasArg(OPT_fno_elide_constructors);
Opts.MathErrno = Args.hasArg(OPT_fmath_errno);
- Opts.InstantiationDepth = Args.getLastArgIntValue(OPT_ftemplate_depth, 512,
+ Opts.InstantiationDepth = Args.getLastArgIntValue(OPT_ftemplate_depth, 256,
Diags);
Opts.ConstexprCallDepth = Args.getLastArgIntValue(OPT_fconstexpr_depth, 512,
Diags);
@@ -1289,7 +1295,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
// FIXME: Eliminate this dependency.
unsigned Opt = getOptimizationLevel(Args, IK, Diags),
- OptSize = getOptimizationLevelSize(Args, IK, Diags);
+ OptSize = getOptimizationLevelSize(Args);
Opts.Optimize = Opt != 0;
Opts.OptimizeSize = OptSize != 0;
@@ -1463,6 +1469,7 @@ static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts,
case frontend::GeneratePCH:
case frontend::GeneratePTH:
case frontend::ParseSyntaxOnly:
+ case frontend::ModuleFileInfo:
case frontend::PluginAction:
case frontend::PrintDeclContext:
case frontend::RewriteObjC:
@@ -1625,6 +1632,8 @@ llvm::APInt ModuleSignature::getAsInteger() const {
}
std::string CompilerInvocation::getModuleHash() const {
+ // Note: For QoI reasons, the things we use as a hash here should all be
+ // dumped via the -module-info flag.
using llvm::hash_code;
using llvm::hash_value;
using llvm::hash_combine;
@@ -1678,5 +1687,21 @@ std::string CompilerInvocation::getModuleHash() const {
hsOpts.UseStandardCXXIncludes,
hsOpts.UseLibcxx);
+ // Darwin-specific hack: if we have a sysroot, use the contents of
+ // $sysroot/System/Library/CoreServices/SystemVersion.plist
+ // as part of the module hash.
+ if (!hsOpts.Sysroot.empty()) {
+ llvm::OwningPtr<llvm::MemoryBuffer> buffer;
+ SmallString<128> systemVersionFile;
+ systemVersionFile += hsOpts.Sysroot;
+ llvm::sys::path::append(systemVersionFile, "System");
+ llvm::sys::path::append(systemVersionFile, "Library");
+ llvm::sys::path::append(systemVersionFile, "CoreServices");
+ llvm::sys::path::append(systemVersionFile, "SystemVersion.plist");
+ if (!llvm::MemoryBuffer::getFile(systemVersionFile, buffer)) {
+ code = hash_combine(code, buffer.get()->getBuffer());
+ }
+ }
+
return llvm::APInt(64, code).toString(36, /*Signed=*/false);
}
diff --git a/lib/Frontend/DependencyFile.cpp b/lib/Frontend/DependencyFile.cpp
index 53ea8befbc..628def68e5 100644
--- a/lib/Frontend/DependencyFile.cpp
+++ b/lib/Frontend/DependencyFile.cpp
@@ -151,12 +151,14 @@ void DependencyFileCallback::AddFilename(StringRef Filename) {
Files.push_back(Filename);
}
-/// PrintFilename - GCC escapes spaces, but apparently not ' or " or other
-/// scary characters.
+/// PrintFilename - GCC escapes spaces, # and $, but apparently not ' or " or
+/// other scary characters.
static void PrintFilename(raw_ostream &OS, StringRef Filename) {
for (unsigned i = 0, e = Filename.size(); i != e; ++i) {
- if (Filename[i] == ' ')
+ if (Filename[i] == ' ' || Filename[i] == '#')
OS << '\\';
+ else if (Filename[i] == '$') // $ is escaped by $$.
+ OS << '$';
OS << Filename[i];
}
}
diff --git a/lib/Frontend/DiagnosticRenderer.cpp b/lib/Frontend/DiagnosticRenderer.cpp
index 3b4f55c6c4..4eee59548c 100644
--- a/lib/Frontend/DiagnosticRenderer.cpp
+++ b/lib/Frontend/DiagnosticRenderer.cpp
@@ -462,9 +462,8 @@ void DiagnosticRenderer::emitMacroExpansions(SourceLocation Loc,
Message << "expanded from here";
else
Message << "expanded from macro '" << MacroName << "'";
- emitDiagnostic(SpellingLoc, DiagnosticsEngine::Note,
- Message.str(),
- SpellingRanges, ArrayRef<FixItHint>(), &SM);
+ emitDiagnostic(SpellingLoc, DiagnosticsEngine::Note, Message.str(),
+ SpellingRanges, None, &SM);
}
DiagnosticNoteRenderer::~DiagnosticNoteRenderer() {}
diff --git a/lib/Frontend/FrontendAction.cpp b/lib/Frontend/FrontendAction.cpp
index 6d31c315b4..ece51a3570 100644
--- a/lib/Frontend/FrontendAction.cpp
+++ b/lib/Frontend/FrontendAction.cpp
@@ -188,6 +188,10 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
setCurrentInput(Input, AST);
+ // Inform the diagnostic client we are processing a source file.
+ CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), 0);
+ HasBegunSourceFile = true;
+
// Set the shared objects, these are reset when we finish processing the
// file, otherwise the CompilerInstance will happily destroy them.
CI.setFileManager(&AST->getFileManager());
@@ -283,8 +287,6 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
goto failure;
CI.getASTContext().setASTMutationListener(Consumer->GetASTMutationListener());
- CI.getPreprocessor().setPPMutationListener(
- Consumer->GetPPMutationListener());
if (!CI.getPreprocessorOpts().ChainedIncludes.empty()) {
// Convert headers to PCH and chain them.
@@ -292,6 +294,8 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
source.reset(ChainedIncludesSource::create(CI));
if (!source)
goto failure;
+ CI.setModuleManager(static_cast<ASTReader*>(
+ &static_cast<ChainedIncludesSource*>(source.get())->getFinalReader()));
CI.getASTContext().setExternalSource(source);
} else if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) {
diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp
index 965e762d79..5c7567fa8c 100644
--- a/lib/Frontend/FrontendActions.cpp
+++ b/lib/Frontend/FrontendActions.cpp
@@ -19,6 +19,7 @@
#include "clang/Lex/Pragma.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Parse/Parser.h"
+#include "clang/Serialization/ASTReader.h"
#include "clang/Serialization/ASTWriter.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/Support/FileSystem.h"
@@ -173,12 +174,12 @@ static void collectModuleHeaderIncludes(const LangOptions &LangOpts,
// Add includes for each of these headers.
for (unsigned I = 0, N = Module->Headers.size(); I != N; ++I) {
const FileEntry *Header = Module->Headers[I];
- Module->TopHeaders.insert(Header);
+ Module->addTopHeader(Header);
addHeaderInclude(Header, Includes, LangOpts);
}
if (const FileEntry *UmbrellaHeader = Module->getUmbrellaHeader()) {
- Module->TopHeaders.insert(UmbrellaHeader);
+ Module->addTopHeader(UmbrellaHeader);
if (Module->Parent) {
// Include the umbrella header for submodules.
addHeaderInclude(UmbrellaHeader, Includes, LangOpts);
@@ -203,7 +204,7 @@ static void collectModuleHeaderIncludes(const LangOptions &LangOpts,
if (const FileEntry *Header = FileMgr.getFile(Dir->path())) {
if (ModMap.isHeaderInUnavailableModule(Header))
continue;
- Module->TopHeaders.insert(Header);
+ Module->addTopHeader(Header);
}
// Include this header umbrella header for submodules.
@@ -316,6 +317,130 @@ ASTConsumer *SyntaxOnlyAction::CreateASTConsumer(CompilerInstance &CI,
return new ASTConsumer();
}
+ASTConsumer *DumpModuleInfoAction::CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) {
+ return new ASTConsumer();
+}
+
+namespace {
+ /// \brief AST reader listener that dumps module information for a module
+ /// file.
+ class DumpModuleInfoListener : public ASTReaderListener {
+ llvm::raw_ostream &Out;
+
+ public:
+ DumpModuleInfoListener(llvm::raw_ostream &Out) : Out(Out) { }
+
+#define DUMP_BOOLEAN(Value, Text) \
+ Out.indent(4) << Text << ": " << (Value? "Yes" : "No") << "\n"
+
+ virtual bool ReadFullVersionInformation(StringRef FullVersion) {
+ Out.indent(2)
+ << "Generated by "
+ << (FullVersion == getClangFullRepositoryVersion()? "this"
+ : "a different")
+ << " Clang: " << FullVersion << "\n";
+ return ASTReaderListener::ReadFullVersionInformation(FullVersion);
+ }
+
+ virtual bool ReadLanguageOptions(const LangOptions &LangOpts,
+ bool Complain) {
+ Out.indent(2) << "Language options:\n";
+#define LANGOPT(Name, Bits, Default, Description) \
+ DUMP_BOOLEAN(LangOpts.Name, Description);
+#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \
+ Out.indent(4) << Description << ": " \
+ << static_cast<unsigned>(LangOpts.get##Name()) << "\n";
+#define VALUE_LANGOPT(Name, Bits, Default, Description) \
+ Out.indent(4) << Description << ": " << LangOpts.Name << "\n";
+#define BENIGN_LANGOPT(Name, Bits, Default, Description)
+#define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description)
+#include "clang/Basic/LangOptions.def"
+ return false;
+ }
+
+ virtual bool ReadTargetOptions(const TargetOptions &TargetOpts,
+ bool Complain) {
+ Out.indent(2) << "Target options:\n";
+ Out.indent(4) << " Triple: " << TargetOpts.Triple << "\n";
+ Out.indent(4) << " CPU: " << TargetOpts.CPU << "\n";
+ Out.indent(4) << " ABI: " << TargetOpts.ABI << "\n";
+ Out.indent(4) << " C++ ABI: " << TargetOpts.CXXABI << "\n";
+ Out.indent(4) << " Linker version: " << TargetOpts.LinkerVersion << "\n";
+
+ if (!TargetOpts.FeaturesAsWritten.empty()) {
+ Out.indent(4) << "Target features:\n";
+ for (unsigned I = 0, N = TargetOpts.FeaturesAsWritten.size();
+ I != N; ++I) {
+ Out.indent(6) << TargetOpts.FeaturesAsWritten[I] << "\n";
+ }
+ }
+
+ return false;
+ }
+
+ virtual bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts,
+ bool Complain) {
+ Out.indent(2) << "Header search options:\n";
+ Out.indent(4) << "System root [-isysroot=]: '" << HSOpts.Sysroot << "'\n";
+ DUMP_BOOLEAN(HSOpts.UseBuiltinIncludes,
+ "Use builtin include directories [-nobuiltininc]");
+ DUMP_BOOLEAN(HSOpts.UseStandardSystemIncludes,
+ "Use standard system include directories [-nostdinc]");
+ DUMP_BOOLEAN(HSOpts.UseStandardCXXIncludes,
+ "Use standard C++ include directories [-nostdinc++]");
+ DUMP_BOOLEAN(HSOpts.UseLibcxx,
+ "Use libc++ (rather than libstdc++) [-stdlib=]");
+ return false;
+ }
+
+ virtual bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,
+ bool Complain,
+ std::string &SuggestedPredefines) {
+ Out.indent(2) << "Preprocessor options:\n";
+ DUMP_BOOLEAN(PPOpts.UsePredefines,
+ "Uses compiler/target-specific predefines [-undef]");
+ DUMP_BOOLEAN(PPOpts.DetailedRecord,
+ "Uses detailed preprocessing record (for indexing)");
+
+ if (!PPOpts.Macros.empty()) {
+ Out.indent(4) << "Predefined macros:\n";
+ }
+
+ for (std::vector<std::pair<std::string, bool/*isUndef*/> >::const_iterator
+ I = PPOpts.Macros.begin(), IEnd = PPOpts.Macros.end();
+ I != IEnd; ++I) {
+ Out.indent(6);
+ if (I->second)
+ Out << "-U";
+ else
+ Out << "-D";
+ Out << I->first << "\n";
+ }
+ return false;
+ }
+#undef DUMP_BOOLEAN
+ };
+}
+
+void DumpModuleInfoAction::ExecuteAction() {
+ // Set up the output file.
+ llvm::OwningPtr<llvm::raw_fd_ostream> OutFile;
+ StringRef OutputFileName = getCompilerInstance().getFrontendOpts().OutputFile;
+ if (!OutputFileName.empty() && OutputFileName != "-") {
+ std::string ErrorInfo;
+ OutFile.reset(new llvm::raw_fd_ostream(OutputFileName.str().c_str(),
+ ErrorInfo));
+ }
+ llvm::raw_ostream &Out = OutFile.get()? *OutFile.get() : llvm::outs();
+
+ Out << "Information for module file '" << getCurrentFile() << "':\n";
+ DumpModuleInfoListener Listener(Out);
+ ASTReader::readASTFileControlBlock(getCurrentFile(),
+ getCompilerInstance().getFileManager(),
+ Listener);
+}
+
//===----------------------------------------------------------------------===//
// Preprocessor Actions
//===----------------------------------------------------------------------===//
diff --git a/lib/Frontend/FrontendOptions.cpp b/lib/Frontend/FrontendOptions.cpp
index ea4005f7c9..f1823c69e9 100644
--- a/lib/Frontend/FrontendOptions.cpp
+++ b/lib/Frontend/FrontendOptions.cpp
@@ -13,7 +13,7 @@ using namespace clang;
InputKind FrontendOptions::getInputKindForExtension(StringRef Extension) {
return llvm::StringSwitch<InputKind>(Extension)
- .Case("ast", IK_AST)
+ .Cases("ast", "pcm", IK_AST)
.Case("c", IK_C)
.Cases("S", "s", IK_Asm)
.Case("i", IK_PreprocessedC)
diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp
index 35eec565f7..f4ca4d498a 100644
--- a/lib/Frontend/InitHeaderSearch.cpp
+++ b/lib/Frontend/InitHeaderSearch.cpp
@@ -24,6 +24,7 @@
#include "llvm/ADT/Triple.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
@@ -410,16 +411,16 @@ AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple, const HeaderSearchOp
#endif
break;
case llvm::Triple::DragonFly:
- AddPath("/usr/include/c++/4.1", CXXSystem, false);
+ if (llvm::sys::fs::exists("/usr/lib/gcc47"))
+ AddPath("/usr/include/c++/4.7", CXXSystem, false);
+ else
+ AddPath("/usr/include/c++/4.4", CXXSystem, false);
break;
case llvm::Triple::FreeBSD:
// FreeBSD 8.0
// FreeBSD 7.3
AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2", "", "", "", triple);
break;
- case llvm::Triple::NetBSD:
- AddGnuCPlusPlusIncludePaths("/usr/include/g++", "", "", "", triple);
- break;
case llvm::Triple::OpenBSD: {
std::string t = triple.getTriple();
if (t.substr(0, 6) == "x86_64")
diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp
index b74c3c0b1c..dc3ab53eda 100644
--- a/lib/Frontend/InitPreprocessor.cpp
+++ b/lib/Frontend/InitPreprocessor.cpp
@@ -302,12 +302,13 @@ static void InitializeStandardPredefinedMacros(const TargetInfo &TI,
else if (!LangOpts.GNUMode && LangOpts.Digraphs)
Builder.defineMacro("__STDC_VERSION__", "199409L");
} else {
- // FIXME: LangOpts.CPlusPlus1y
-
+ // FIXME: Use the right value for __cplusplus for C++1y once one is chosen.
+ if (LangOpts.CPlusPlus1y)
+ Builder.defineMacro("__cplusplus", "201305L");
// C++11 [cpp.predefined]p1:
// The name __cplusplus is defined to the value 201103L when compiling a
// C++ translation unit.
- if (LangOpts.CPlusPlus11)
+ else if (LangOpts.CPlusPlus11)
Builder.defineMacro("__cplusplus", "201103L");
// C++03 [cpp.predefined]p1:
// The name __cplusplus is defined to the value 199711L when compiling a
@@ -490,6 +491,7 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
DefineTypeSize("__LONG_LONG_MAX__", TargetInfo::SignedLongLong, TI, Builder);
DefineTypeSize("__WCHAR_MAX__", TI.getWCharType(), TI, Builder);
DefineTypeSize("__INTMAX_MAX__", TI.getIntMaxType(), TI, Builder);
+ DefineTypeSize("__SIZE_MAX__", TI.getSizeType(), TI, Builder);
DefineTypeSizeof("__SIZEOF_DOUBLE__", TI.getDoubleWidth(), TI, Builder);
DefineTypeSizeof("__SIZEOF_FLOAT__", TI.getFloatWidth(), TI, Builder);
diff --git a/lib/Frontend/LogDiagnosticPrinter.cpp b/lib/Frontend/LogDiagnosticPrinter.cpp
index 0a22481cb6..2189b8658e 100644
--- a/lib/Frontend/LogDiagnosticPrinter.cpp
+++ b/lib/Frontend/LogDiagnosticPrinter.cpp
@@ -171,8 +171,3 @@ void LogDiagnosticPrinter::HandleDiagnostic(DiagnosticsEngine::Level Level,
Entries.push_back(DE);
}
-DiagnosticConsumer *
-LogDiagnosticPrinter::clone(DiagnosticsEngine &Diags) const {
- return new LogDiagnosticPrinter(OS, &*DiagOpts, /*OwnsOutputStream=*/false);
-}
-
diff --git a/lib/Frontend/PrintPreprocessedOutput.cpp b/lib/Frontend/PrintPreprocessedOutput.cpp
index d894939b4b..9fd3649435 100644
--- a/lib/Frontend/PrintPreprocessedOutput.cpp
+++ b/lib/Frontend/PrintPreprocessedOutput.cpp
@@ -127,10 +127,22 @@ public:
virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason,
SrcMgr::CharacteristicKind FileType,
FileID PrevFID);
+ virtual void InclusionDirective(SourceLocation HashLoc,
+ const Token &IncludeTok,
+ StringRef FileName,
+ bool IsAngled,
+ CharSourceRange FilenameRange,
+ const FileEntry *File,
+ StringRef SearchPath,
+ StringRef RelativePath,
+ const Module *Imported);
virtual void Ident(SourceLocation Loc, const std::string &str);
+ virtual void PragmaCaptured(SourceLocation Loc, StringRef Str);
virtual void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind,
const std::string &Str);
- virtual void PragmaMessage(SourceLocation Loc, StringRef Str);
+ virtual void PragmaMessage(SourceLocation Loc, StringRef Namespace,
+ PragmaMessageKind Kind, StringRef Str);
+ virtual void PragmaDebug(SourceLocation Loc, StringRef DebugType);
virtual void PragmaDiagnosticPush(SourceLocation Loc,
StringRef Namespace);
virtual void PragmaDiagnosticPop(SourceLocation Loc,
@@ -258,11 +270,12 @@ void PrintPPOutputPPCallbacks::FileChanged(SourceLocation Loc,
if (IncludeLoc.isValid())
MoveToLine(IncludeLoc);
} else if (Reason == PPCallbacks::SystemHeaderPragma) {
- MoveToLine(NewLine);
-
- // TODO GCC emits the # directive for this directive on the line AFTER the
- // directive and emits a bunch of spaces that aren't needed. Emulate this
- // strange behavior.
+ // GCC emits the # directive for this directive on the line AFTER the
+ // directive and emits a bunch of spaces that aren't needed. This is because
+ // otherwise we will emit a line marker for THIS line, which requires an
+ // extra blank line after the directive to avoid making all following lines
+ // off by one. We can do better by simply incrementing NewLine here.
+ NewLine += 1;
}
CurLine = NewLine;
@@ -305,6 +318,27 @@ void PrintPPOutputPPCallbacks::FileChanged(SourceLocation Loc,
}
}
+void PrintPPOutputPPCallbacks::InclusionDirective(SourceLocation HashLoc,
+ const Token &IncludeTok,
+ StringRef FileName,
+ bool IsAngled,
+ CharSourceRange FilenameRange,
+ const FileEntry *File,
+ StringRef SearchPath,
+ StringRef RelativePath,
+ const Module *Imported) {
+ // When preprocessing, turn implicit imports into @imports.
+ // FIXME: This is a stop-gap until a more comprehensive "preprocessing with
+ // modules" solution is introduced.
+ if (Imported) {
+ startNewLineIfNeeded();
+ MoveToLine(HashLoc);
+ OS << "@import " << Imported->getFullModuleName() << ";"
+ << " /* clang -E: implicit import for \"" << File->getName() << "\" */";
+ EmittedTokensOnThisLine = true;
+ }
+}
+
/// Ident - Handle #ident directives when read by the preprocessor.
///
void PrintPPOutputPPCallbacks::Ident(SourceLocation Loc, const std::string &S) {
@@ -315,10 +349,19 @@ void PrintPPOutputPPCallbacks::Ident(SourceLocation Loc, const std::string &S) {
EmittedTokensOnThisLine = true;
}
+void PrintPPOutputPPCallbacks::PragmaCaptured(SourceLocation Loc,
+ StringRef Str) {
+ startNewLineIfNeeded();
+ MoveToLine(Loc);
+ OS << "#pragma captured";
+
+ setEmittedDirectiveOnThisLine();
+}
+
/// MacroDefined - This hook is called whenever a macro definition is seen.
void PrintPPOutputPPCallbacks::MacroDefined(const Token &MacroNameTok,
const MacroDirective *MD) {
- const MacroInfo *MI = MD->getInfo();
+ const MacroInfo *MI = MD->getMacroInfo();
// Only print out macro definitions in -dD mode.
if (!DumpDefines ||
// Ignore __FILE__ etc.
@@ -367,12 +410,25 @@ void PrintPPOutputPPCallbacks::PragmaComment(SourceLocation Loc,
}
void PrintPPOutputPPCallbacks::PragmaMessage(SourceLocation Loc,
+ StringRef Namespace,
+ PragmaMessageKind Kind,
StringRef Str) {
startNewLineIfNeeded();
MoveToLine(Loc);
- OS << "#pragma message(";
-
- OS << '"';
+ OS << "#pragma ";
+ if (!Namespace.empty())
+ OS << Namespace << ' ';
+ switch (Kind) {
+ case PMK_Message:
+ OS << "message(\"";
+ break;
+ case PMK_Warning:
+ OS << "warning \"";
+ break;
+ case PMK_Error:
+ OS << "error \"";
+ break;
+ }
for (unsigned i = 0, e = Str.size(); i != e; ++i) {
unsigned char Char = Str[i];
@@ -385,8 +441,19 @@ void PrintPPOutputPPCallbacks::PragmaMessage(SourceLocation Loc,
<< (char)('0'+ ((Char >> 0) & 7));
}
OS << '"';
+ if (Kind == PMK_Message)
+ OS << ')';
+ setEmittedDirectiveOnThisLine();
+}
+
+void PrintPPOutputPPCallbacks::PragmaDebug(SourceLocation Loc,
+ StringRef DebugType) {
+ startNewLineIfNeeded();
+ MoveToLine(Loc);
+
+ OS << "#pragma clang __debug ";
+ OS << DebugType;
- OS << ')';
setEmittedDirectiveOnThisLine();
}
@@ -602,7 +669,7 @@ static void DoPrintMacros(Preprocessor &PP, raw_ostream *OS) {
for (Preprocessor::macro_iterator I = PP.macro_begin(), E = PP.macro_end();
I != E; ++I) {
if (I->first->hasMacroDefinition())
- MacrosByID.push_back(id_macro_pair(I->first, I->second->getInfo()));
+ MacrosByID.push_back(id_macro_pair(I->first, I->second->getMacroInfo()));
}
llvm::array_pod_sort(MacrosByID.begin(), MacrosByID.end(), MacroIDCompare);
diff --git a/lib/Frontend/SerializedDiagnosticPrinter.cpp b/lib/Frontend/SerializedDiagnosticPrinter.cpp
index 4bb662bb26..6514321f22 100644
--- a/lib/Frontend/SerializedDiagnosticPrinter.cpp
+++ b/lib/Frontend/SerializedDiagnosticPrinter.cpp
@@ -114,10 +114,6 @@ public:
virtual void finish();
- DiagnosticConsumer *clone(DiagnosticsEngine &Diags) const {
- return new SDiagsWriter(State);
- }
-
private:
/// \brief Emit the preamble for the serialized diagnostics.
void EmitPreamble();
diff --git a/lib/Frontend/TextDiagnostic.cpp b/lib/Frontend/TextDiagnostic.cpp
index c972461241..1572d0f1d0 100644
--- a/lib/Frontend/TextDiagnostic.cpp
+++ b/lib/Frontend/TextDiagnostic.cpp
@@ -958,7 +958,7 @@ static void highlightRange(const CharSourceRange &R,
// Pick the last non-whitespace column.
if (EndColNo > map.getSourceLine().size())
EndColNo = map.getSourceLine().size();
- while (EndColNo-1 &&
+ while (EndColNo &&
(map.getSourceLine()[EndColNo-1] == ' ' ||
map.getSourceLine()[EndColNo-1] == '\t'))
EndColNo = map.startOfPreviousColumn(EndColNo);
@@ -1095,7 +1095,7 @@ void TextDiagnostic::emitSnippetAndCaret(
unsigned ColNo = SM.getColumnNumber(FID, FileOffset);
// Arbitrarily stop showing snippets when the line is too long.
- static const ptrdiff_t MaxLineLengthToPrint = 4096;
+ static const size_t MaxLineLengthToPrint = 4096;
if (ColNo > MaxLineLengthToPrint)
return;
@@ -1110,7 +1110,7 @@ void TextDiagnostic::emitSnippetAndCaret(
++LineEnd;
// Arbitrarily stop showing snippets when the line is too long.
- if (LineEnd - LineStart > MaxLineLengthToPrint)
+ if (size_t(LineEnd - LineStart) > MaxLineLengthToPrint)
return;
// Copy the line of code into an std::string for ease of manipulation.
diff --git a/lib/Frontend/TextDiagnosticBuffer.cpp b/lib/Frontend/TextDiagnosticBuffer.cpp
index 039475a2e0..5821436a30 100644
--- a/lib/Frontend/TextDiagnosticBuffer.cpp
+++ b/lib/Frontend/TextDiagnosticBuffer.cpp
@@ -75,6 +75,3 @@ void TextDiagnosticBuffer::FlushDiagnostics(DiagnosticsEngine &Diags) const {
escapeDiag(it->second, Buf)));
}
-DiagnosticConsumer *TextDiagnosticBuffer::clone(DiagnosticsEngine &) const {
- return new TextDiagnosticBuffer();
-}
diff --git a/lib/Frontend/TextDiagnosticPrinter.cpp b/lib/Frontend/TextDiagnosticPrinter.cpp
index 010f649e6b..c22798af60 100644
--- a/lib/Frontend/TextDiagnosticPrinter.cpp
+++ b/lib/Frontend/TextDiagnosticPrinter.cpp
@@ -155,8 +155,3 @@ void TextDiagnosticPrinter::HandleDiagnostic(DiagnosticsEngine::Level Level,
OS.flush();
}
-
-DiagnosticConsumer *
-TextDiagnosticPrinter::clone(DiagnosticsEngine &Diags) const {
- return new TextDiagnosticPrinter(OS, &*DiagOpts, /*OwnsOutputStream=*/false);
-}
diff --git a/lib/Frontend/VerifyDiagnosticConsumer.cpp b/lib/Frontend/VerifyDiagnosticConsumer.cpp
index 82f6e916e5..46745b6b9a 100644
--- a/lib/Frontend/VerifyDiagnosticConsumer.cpp
+++ b/lib/Frontend/VerifyDiagnosticConsumer.cpp
@@ -111,8 +111,13 @@ void VerifyDiagnosticConsumer::EndSourceFile() {
void VerifyDiagnosticConsumer::HandleDiagnostic(
DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info) {
- if (Info.hasSourceManager())
+ if (Info.hasSourceManager()) {
+ // If this diagnostic is for a different source manager, ignore it.
+ if (SrcManager && &Info.getSourceManager() != SrcManager)
+ return;
+
setSourceManager(Info.getSourceManager());
+ }
#ifndef NDEBUG
// Debug build tracks unparsed files for possible
@@ -278,8 +283,10 @@ private:
///
/// Returns true if any valid directives were found.
static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM,
- SourceLocation Pos, DiagnosticsEngine &Diags,
+ Preprocessor *PP, SourceLocation Pos,
VerifyDiagnosticConsumer::DirectiveStatus &Status) {
+ DiagnosticsEngine &Diags = PP ? PP->getDiagnostics() : SM.getDiagnostics();
+
// A single comment may contain multiple directives.
bool FoundDirective = false;
for (ParseHelper PH(S); !PH.Done();) {
@@ -353,10 +360,30 @@ static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM,
else ExpectedLine -= Line;
ExpectedLoc = SM.translateLineCol(SM.getFileID(Pos), ExpectedLine, 1);
}
- } else {
+ } else if (PH.Next(Line)) {
// Absolute line number.
- if (PH.Next(Line) && Line > 0)
+ if (Line > 0)
ExpectedLoc = SM.translateLineCol(SM.getFileID(Pos), Line, 1);
+ } else if (PP && PH.Search(":")) {
+ // Specific source file.
+ StringRef Filename(PH.C, PH.P-PH.C);
+ PH.Advance();
+
+ // Lookup file via Preprocessor, like a #include.
+ const DirectoryLookup *CurDir;
+ const FileEntry *FE = PP->LookupFile(Filename, false, NULL, CurDir,
+ NULL, NULL, 0);
+ if (!FE) {
+ Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin),
+ diag::err_verify_missing_file) << Filename << KindStr;
+ continue;
+ }
+
+ if (SM.translateFile(FE).isInvalid())
+ SM.createFileID(FE, Pos, SrcMgr::C_User);
+
+ if (PH.Next(Line) && Line > 0)
+ ExpectedLoc = SM.translateFileLineCol(FE, Line, 1);
}
if (ExpectedLoc.isInvalid()) {
@@ -454,6 +481,11 @@ static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM,
bool VerifyDiagnosticConsumer::HandleComment(Preprocessor &PP,
SourceRange Comment) {
SourceManager &SM = PP.getSourceManager();
+
+ // If this comment is for a different source manager, ignore it.
+ if (SrcManager && &SM != SrcManager)
+ return false;
+
SourceLocation CommentBegin = Comment.getBegin();
const char *CommentRaw = SM.getCharacterData(CommentBegin);
@@ -465,7 +497,7 @@ bool VerifyDiagnosticConsumer::HandleComment(Preprocessor &PP,
// Fold any "\<EOL>" sequences
size_t loc = C.find('\\');
if (loc == StringRef::npos) {
- ParseDirective(C, &ED, SM, CommentBegin, PP.getDiagnostics(), Status);
+ ParseDirective(C, &ED, SM, &PP, CommentBegin, Status);
return false;
}
@@ -495,7 +527,7 @@ bool VerifyDiagnosticConsumer::HandleComment(Preprocessor &PP,
}
if (!C2.empty())
- ParseDirective(C2, &ED, SM, CommentBegin, PP.getDiagnostics(), Status);
+ ParseDirective(C2, &ED, SM, &PP, CommentBegin, Status);
return false;
}
@@ -530,8 +562,7 @@ static bool findDirectives(SourceManager &SM, FileID FID,
if (Comment.empty()) continue;
// Find first directive.
- if (ParseDirective(Comment, 0, SM, Tok.getLocation(),
- SM.getDiagnostics(), Status))
+ if (ParseDirective(Comment, 0, SM, 0, Tok.getLocation(), Status))
return true;
}
return false;
@@ -551,8 +582,13 @@ static unsigned PrintUnexpected(DiagnosticsEngine &Diags, SourceManager *SourceM
for (const_diag_iterator I = diag_begin, E = diag_end; I != E; ++I) {
if (I->first.isInvalid() || !SourceMgr)
OS << "\n (frontend)";
- else
- OS << "\n Line " << SourceMgr->getPresumedLineNumber(I->first);
+ else {
+ OS << "\n ";
+ if (const FileEntry *File = SourceMgr->getFileEntryForID(
+ SourceMgr->getFileID(I->first)))
+ OS << " File " << File->getName();
+ OS << " Line " << SourceMgr->getPresumedLineNumber(I->first);
+ }
OS << ": " << I->second;
}
@@ -572,11 +608,12 @@ static unsigned PrintExpected(DiagnosticsEngine &Diags, SourceManager &SourceMgr
llvm::raw_svector_ostream OS(Fmt);
for (DirectiveList::iterator I = DL.begin(), E = DL.end(); I != E; ++I) {
Directive &D = **I;
- OS << "\n Line " << SourceMgr.getPresumedLineNumber(D.DiagnosticLoc);
+ OS << "\n File " << SourceMgr.getFilename(D.DiagnosticLoc)
+ << " Line " << SourceMgr.getPresumedLineNumber(D.DiagnosticLoc);
if (D.DirectiveLoc != D.DiagnosticLoc)
OS << " (directive at "
- << SourceMgr.getFilename(D.DirectiveLoc) << ":"
- << SourceMgr.getPresumedLineNumber(D.DirectiveLoc) << ")";
+ << SourceMgr.getFilename(D.DirectiveLoc) << ':'
+ << SourceMgr.getPresumedLineNumber(D.DirectiveLoc) << ')';
OS << ": " << D.Text;
}
@@ -585,6 +622,22 @@ static unsigned PrintExpected(DiagnosticsEngine &Diags, SourceManager &SourceMgr
return DL.size();
}
+/// \brief Determine whether two source locations come from the same file.
+static bool IsFromSameFile(SourceManager &SM, SourceLocation DirectiveLoc,
+ SourceLocation DiagnosticLoc) {
+ while (DiagnosticLoc.isMacroID())
+ DiagnosticLoc = SM.getImmediateMacroCallerLoc(DiagnosticLoc);
+
+ if (SM.isFromSameFile(DirectiveLoc, DiagnosticLoc))
+ return true;
+
+ const FileEntry *DiagFile = SM.getFileEntryForID(SM.getFileID(DiagnosticLoc));
+ if (!DiagFile && SM.isFromMainFile(DirectiveLoc))
+ return true;
+
+ return (DiagFile == SM.getFileEntryForID(SM.getFileID(DirectiveLoc)));
+}
+
/// CheckLists - Compare expected to seen diagnostic lists and return the
/// the difference between them.
///
@@ -607,6 +660,9 @@ static unsigned CheckLists(DiagnosticsEngine &Diags, SourceManager &SourceMgr,
if (LineNo1 != LineNo2)
continue;
+ if (!IsFromSameFile(SourceMgr, D.DiagnosticLoc, II->first))
+ continue;
+
const std::string &RightText = II->second;
if (D.match(RightText))
break;
@@ -764,14 +820,6 @@ void VerifyDiagnosticConsumer::CheckDiagnostics() {
ED.Notes.clear();
}
-DiagnosticConsumer *
-VerifyDiagnosticConsumer::clone(DiagnosticsEngine &Diags) const {
- if (!Diags.getClient())
- Diags.setClient(PrimaryClient->clone(Diags));
-
- return new VerifyDiagnosticConsumer(Diags);
-}
-
Directive *Directive::create(bool RegexKind, SourceLocation DirectiveLoc,
SourceLocation DiagnosticLoc, StringRef Text,
unsigned Min, unsigned Max) {