Update Clang for rebase to r212749.
This also fixes a small issue with arm_neon.h not being generated always.
Includes a cherry-pick of:
r213450 - fixes mac-specific header issue
r213126 - removes a default -Bsymbolic on Android
Change-Id: I2a790a0f5d3b2aab11de596fc3a74e7cbc99081d
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
index 49487d9..fc44d9f 100644
--- a/lib/Frontend/ASTUnit.cpp
+++ b/lib/Frontend/ASTUnit.cpp
@@ -47,7 +47,6 @@
#include <atomic>
#include <cstdio>
#include <cstdlib>
-#include <sys/stat.h>
using namespace clang;
using llvm::TimeRecord;
@@ -247,14 +246,10 @@
// perform this operation here because we explicitly request that the
// compiler instance *not* free these buffers for each invocation of the
// parser.
- if (Invocation.getPtr() && OwnsRemappedFileBuffers) {
+ if (Invocation.get() && OwnsRemappedFileBuffers) {
PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts();
- for (PreprocessorOptions::remapped_file_buffer_iterator
- FB = PPOpts.remapped_file_buffer_begin(),
- FBEnd = PPOpts.remapped_file_buffer_end();
- FB != FBEnd;
- ++FB)
- delete FB->second;
+ for (const auto &RB : PPOpts.RemappedFileBuffers)
+ delete RB.second;
}
delete SavedMainFileBuffer;
@@ -504,20 +499,17 @@
Preprocessor &PP;
ASTContext &Context;
LangOptions &LangOpt;
- IntrusiveRefCntPtr<TargetOptions> &TargetOpts;
+ std::shared_ptr<TargetOptions> &TargetOpts;
IntrusiveRefCntPtr<TargetInfo> &Target;
unsigned &Counter;
bool InitializedLanguage;
public:
- ASTInfoCollector(Preprocessor &PP, ASTContext &Context, LangOptions &LangOpt,
- IntrusiveRefCntPtr<TargetOptions> &TargetOpts,
- IntrusiveRefCntPtr<TargetInfo> &Target,
- unsigned &Counter)
- : PP(PP), Context(Context), LangOpt(LangOpt),
- TargetOpts(TargetOpts), Target(Target),
- Counter(Counter),
- InitializedLanguage(false) {}
+ ASTInfoCollector(Preprocessor &PP, ASTContext &Context, LangOptions &LangOpt,
+ std::shared_ptr<TargetOptions> &TargetOpts,
+ IntrusiveRefCntPtr<TargetInfo> &Target, unsigned &Counter)
+ : PP(PP), Context(Context), LangOpt(LangOpt), TargetOpts(TargetOpts),
+ Target(Target), Counter(Counter), InitializedLanguage(false) {}
bool ReadLanguageOptions(const LangOptions &LangOpts,
bool Complain) override {
@@ -536,10 +528,10 @@
// If we've already initialized the target, don't do it again.
if (Target)
return false;
-
- this->TargetOpts = new TargetOptions(TargetOpts);
- Target = TargetInfo::CreateTargetInfo(PP.getDiagnostics(),
- &*this->TargetOpts);
+
+ this->TargetOpts = std::make_shared<TargetOptions>(TargetOpts);
+ Target =
+ TargetInfo::CreateTargetInfo(PP.getDiagnostics(), this->TargetOpts);
updated();
return false;
@@ -559,7 +551,7 @@
//
// FIXME: We shouldn't need to do this, the target should be immutable once
// created. This complexity should be lifted elsewhere.
- Target->setForcedLangOptions(LangOpt);
+ Target->adjust(LangOpt);
// Initialize the preprocessor.
PP.Initialize(*Target);
@@ -656,7 +648,7 @@
void ASTUnit::ConfigureDiags(IntrusiveRefCntPtr<DiagnosticsEngine> &Diags,
const char **ArgBegin, const char **ArgEnd,
ASTUnit &AST, bool CaptureDiagnostics) {
- if (!Diags.getPtr()) {
+ if (!Diags.get()) {
// No diagnostics engine was provided, so create our own diagnostics object
// with the default options.
DiagnosticConsumer *Client = nullptr;
@@ -685,7 +677,7 @@
ASTUnitCleanup(AST.get());
llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine,
llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine> >
- DiagCleanup(Diags.getPtr());
+ DiagCleanup(Diags.get());
ConfigureDiags(Diags, nullptr, nullptr, *AST, CaptureDiagnostics);
@@ -1058,7 +1050,7 @@
IntrusiveRefCntPtr<CompilerInvocation>
CCInvocation(new CompilerInvocation(*Invocation));
- Clang->setInvocation(CCInvocation.getPtr());
+ Clang->setInvocation(CCInvocation.get());
OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].getFile();
// Set up diagnostics, capturing any diagnostics that would
@@ -1066,8 +1058,8 @@
Clang->setDiagnostics(&getDiagnostics());
// Create the target instance.
- Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(),
- &Clang->getTargetOpts()));
+ Clang->setTarget(TargetInfo::CreateTargetInfo(
+ Clang->getDiagnostics(), Clang->getInvocation().TargetOpts));
if (!Clang->hasTarget()) {
delete OverrideMainBuffer;
return true;
@@ -1077,7 +1069,7 @@
//
// FIXME: We shouldn't need to do this, the target should be immutable once
// created. This complexity should be lifted elsewhere.
- Clang->getTarget().setForcedLangOptions(Clang->getLangOpts());
+ Clang->getTarget().adjust(Clang->getLangOpts());
assert(Clang->getFrontendOpts().Inputs.size() == 1 &&
"Invocation must have exactly one source file!");
@@ -1087,9 +1079,15 @@
"IR inputs not support here!");
// Configure the various subsystems.
- LangOpts = &Clang->getLangOpts();
+ LangOpts = Clang->getInvocation().LangOpts;
FileSystemOpts = Clang->getFileSystemOpts();
- // Re-use the existing FileManager
+ IntrusiveRefCntPtr<vfs::FileSystem> VFS =
+ createVFSFromCompilerInvocation(Clang->getInvocation(), getDiagnostics());
+ if (!VFS) {
+ delete OverrideMainBuffer;
+ return true;
+ }
+ FileMgr = new FileManager(FileSystemOpts, VFS);
SourceMgr = new SourceManager(getDiagnostics(), *FileMgr,
UserFilesAreVolatile);
TheSema.reset();
@@ -1211,12 +1209,8 @@
llvm::sys::fs::UniqueID MainFileID;
if (!llvm::sys::fs::getUniqueID(MainFilePath, MainFileID)) {
// Check whether there is a file-file remapping of the main file
- for (PreprocessorOptions::remapped_file_iterator
- M = PreprocessorOpts.remapped_file_begin(),
- E = PreprocessorOpts.remapped_file_end();
- M != E;
- ++M) {
- std::string MPath(M->first);
+ for (const auto &RF : PreprocessorOpts.RemappedFiles) {
+ std::string MPath(RF.first);
llvm::sys::fs::UniqueID MID;
if (!llvm::sys::fs::getUniqueID(MPath, MID)) {
if (MainFileID == MID) {
@@ -1225,8 +1219,8 @@
delete Buffer;
CreatedBuffer = false;
}
-
- Buffer = getBufferForFile(M->second);
+
+ Buffer = getBufferForFile(RF.second);
if (!Buffer)
return std::make_pair(nullptr, std::make_pair(0, true));
CreatedBuffer = true;
@@ -1236,12 +1230,8 @@
// Check whether there is a file-buffer remapping. It supercedes the
// file-file remapping.
- for (PreprocessorOptions::remapped_file_buffer_iterator
- M = PreprocessorOpts.remapped_file_buffer_begin(),
- E = PreprocessorOpts.remapped_file_buffer_end();
- M != E;
- ++M) {
- std::string MPath(M->first);
+ for (const auto &RB : PreprocessorOpts.RemappedFileBuffers) {
+ std::string MPath(RB.first);
llvm::sys::fs::UniqueID MID;
if (!llvm::sys::fs::getUniqueID(MPath, MID)) {
if (MainFileID == MID) {
@@ -1250,8 +1240,8 @@
delete Buffer;
CreatedBuffer = false;
}
-
- Buffer = const_cast<llvm::MemoryBuffer *>(M->second);
+
+ Buffer = const_cast<llvm::MemoryBuffer *>(RB.second);
}
}
}
@@ -1417,29 +1407,27 @@
// First, make a record of those files that have been overridden via
// remapping or unsaved_files.
llvm::StringMap<PreambleFileHash> OverriddenFiles;
- for (PreprocessorOptions::remapped_file_iterator
- R = PreprocessorOpts.remapped_file_begin(),
- REnd = PreprocessorOpts.remapped_file_end();
- !AnyFileChanged && R != REnd;
- ++R) {
+ for (const auto &R : PreprocessorOpts.RemappedFiles) {
+ if (AnyFileChanged)
+ break;
+
vfs::Status Status;
- if (FileMgr->getNoncachedStatValue(R->second, Status)) {
+ if (FileMgr->getNoncachedStatValue(R.second, Status)) {
// If we can't stat the file we're remapping to, assume that something
// horrible happened.
AnyFileChanged = true;
break;
}
- OverriddenFiles[R->first] = PreambleFileHash::createForFile(
+ OverriddenFiles[R.first] = PreambleFileHash::createForFile(
Status.getSize(), Status.getLastModificationTime().toEpochTime());
}
- for (PreprocessorOptions::remapped_file_buffer_iterator
- R = PreprocessorOpts.remapped_file_buffer_begin(),
- REnd = PreprocessorOpts.remapped_file_buffer_end();
- !AnyFileChanged && R != REnd;
- ++R) {
- OverriddenFiles[R->first] =
- PreambleFileHash::createForMemoryBuffer(R->second);
+
+ for (const auto &RB : PreprocessorOpts.RemappedFileBuffers) {
+ if (AnyFileChanged)
+ break;
+ OverriddenFiles[RB.first] =
+ PreambleFileHash::createForMemoryBuffer(RB.second);
}
// Check whether anything has changed.
@@ -1559,14 +1547,13 @@
Clang->setDiagnostics(&getDiagnostics());
// Create the target instance.
- Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(),
- &Clang->getTargetOpts()));
+ Clang->setTarget(TargetInfo::CreateTargetInfo(
+ Clang->getDiagnostics(), Clang->getInvocation().TargetOpts));
if (!Clang->hasTarget()) {
llvm::sys::fs::remove(FrontendOpts.OutputFile);
Preamble.clear();
PreambleRebuildCounter = DefaultPreambleRebuildInterval;
- PreprocessorOpts.eraseRemappedFile(
- PreprocessorOpts.remapped_file_buffer_end() - 1);
+ PreprocessorOpts.RemappedFileBuffers.pop_back();
return nullptr;
}
@@ -1574,7 +1561,7 @@
//
// FIXME: We shouldn't need to do this, the target should be immutable once
// created. This complexity should be lifted elsewhere.
- Clang->getTarget().setForcedLangOptions(Clang->getLangOpts());
+ Clang->getTarget().adjust(Clang->getLangOpts());
assert(Clang->getFrontendOpts().Inputs.size() == 1 &&
"Invocation must have exactly one source file!");
@@ -1603,14 +1590,16 @@
Clang->setSourceManager(new SourceManager(getDiagnostics(),
Clang->getFileManager()));
+ auto PreambleDepCollector = std::make_shared<DependencyCollector>();
+ Clang->addDependencyCollector(PreambleDepCollector);
+
std::unique_ptr<PrecompilePreambleAction> Act;
Act.reset(new PrecompilePreambleAction(*this));
if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0])) {
llvm::sys::fs::remove(FrontendOpts.OutputFile);
Preamble.clear();
PreambleRebuildCounter = DefaultPreambleRebuildInterval;
- PreprocessorOpts.eraseRemappedFile(
- PreprocessorOpts.remapped_file_buffer_end() - 1);
+ PreprocessorOpts.RemappedFileBuffers.pop_back();
return nullptr;
}
@@ -1638,8 +1627,7 @@
Preamble.clear();
TopLevelDeclsInPreamble.clear();
PreambleRebuildCounter = DefaultPreambleRebuildInterval;
- PreprocessorOpts.eraseRemappedFile(
- PreprocessorOpts.remapped_file_buffer_end() - 1);
+ PreprocessorOpts.RemappedFileBuffers.pop_back();
return nullptr;
}
@@ -1651,33 +1639,23 @@
// so we can verify whether they have changed or not.
FilesInPreamble.clear();
SourceManager &SourceMgr = Clang->getSourceManager();
- const llvm::MemoryBuffer *MainFileBuffer
- = SourceMgr.getBuffer(SourceMgr.getMainFileID());
- for (SourceManager::fileinfo_iterator F = SourceMgr.fileinfo_begin(),
- FEnd = SourceMgr.fileinfo_end();
- F != FEnd;
- ++F) {
- const FileEntry *File = F->second->OrigEntry;
- if (!File)
+ for (auto &Filename : PreambleDepCollector->getDependencies()) {
+ const FileEntry *File = Clang->getFileManager().getFile(Filename);
+ if (!File || File == SourceMgr.getFileEntryForID(SourceMgr.getMainFileID()))
continue;
- const llvm::MemoryBuffer *Buffer = F->second->getRawBuffer();
- if (Buffer == MainFileBuffer)
- continue;
-
if (time_t ModTime = File->getModificationTime()) {
FilesInPreamble[File->getName()] = PreambleFileHash::createForFile(
- F->second->getSize(), ModTime);
+ File->getSize(), ModTime);
} else {
- assert(F->second->getSize() == Buffer->getBufferSize());
+ llvm::MemoryBuffer *Buffer = SourceMgr.getMemoryBufferForFile(File);
FilesInPreamble[File->getName()] =
PreambleFileHash::createForMemoryBuffer(Buffer);
}
}
-
+
PreambleRebuildCounter = 1;
- PreprocessorOpts.eraseRemappedFile(
- PreprocessorOpts.remapped_file_buffer_end() - 1);
-
+ PreprocessorOpts.RemappedFileBuffers.pop_back();
+
// If the hash of top-level entities differs from the hash of the top-level
// entities the last time we rebuilt the preamble, clear out the completion
// cache.
@@ -1709,7 +1687,7 @@
// Steal the created target, context, and preprocessor if they have been
// created.
assert(CI.hasInvocation() && "missing invocation");
- LangOpts = CI.getInvocation().getLangOpts();
+ LangOpts = CI.getInvocation().LangOpts;
TheSema.reset(CI.takeSema());
Consumer.reset(CI.takeASTConsumer());
if (CI.hasASTContext())
@@ -1810,7 +1788,7 @@
ASTUnitCleanup(OwnAST.get());
llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine,
llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine> >
- DiagCleanup(Diags.getPtr());
+ DiagCleanup(Diags.get());
// We'll manage file buffers ourselves.
CI->getPreprocessorOpts().RetainRemappedFileBuffers = true;
@@ -1832,8 +1810,8 @@
Clang->setDiagnostics(&AST->getDiagnostics());
// Create the target instance.
- Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(),
- &Clang->getTargetOpts()));
+ Clang->setTarget(TargetInfo::CreateTargetInfo(
+ Clang->getDiagnostics(), Clang->getInvocation().TargetOpts));
if (!Clang->hasTarget())
return nullptr;
@@ -1841,7 +1819,7 @@
//
// FIXME: We shouldn't need to do this, the target should be immutable once
// created. This complexity should be lifted elsewhere.
- Clang->getTarget().setForcedLangOptions(Clang->getLangOpts());
+ Clang->getTarget().adjust(Clang->getLangOpts());
assert(Clang->getFrontendOpts().Inputs.size() == 1 &&
"Invocation must have exactly one source file!");
@@ -1966,7 +1944,7 @@
ASTUnitCleanup(AST.get());
llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine,
llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine> >
- DiagCleanup(Diags.getPtr());
+ DiagCleanup(Diags.get());
if (AST->LoadFromCompilerInvocation(PrecompilePreamble))
return nullptr;
@@ -1983,7 +1961,7 @@
bool AllowPCHWithCompilerErrors, bool SkipFunctionBodies,
bool UserFilesAreVolatile, bool ForSerialization,
std::unique_ptr<ASTUnit> *ErrAST) {
- if (!Diags.getPtr()) {
+ if (!Diags.get()) {
// No diagnostics engine was provided, so create our own diagnostics object
// with the default options.
Diags = CompilerInstance::createDiagnostics(new DiagnosticOptions());
@@ -2073,13 +2051,9 @@
// Remap files.
PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts();
- for (PreprocessorOptions::remapped_file_buffer_iterator
- R = PPOpts.remapped_file_buffer_begin(),
- REnd = PPOpts.remapped_file_buffer_end();
- R != REnd;
- ++R) {
- delete R->second;
- }
+ for (const auto &RB : PPOpts.RemappedFileBuffers)
+ delete RB.second;
+
Invocation->getPreprocessorOpts().clearRemappedFiles();
for (unsigned I = 0, N = RemappedFiles.size(); I != N; ++I) {
Invocation->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first,
@@ -2409,8 +2383,8 @@
ProcessWarningOptions(Diag, CCInvocation->getDiagnosticOpts());
// Create the target instance.
- Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(),
- &Clang->getTargetOpts()));
+ Clang->setTarget(TargetInfo::CreateTargetInfo(
+ Clang->getDiagnostics(), Clang->getInvocation().TargetOpts));
if (!Clang->hasTarget()) {
Clang->setInvocation(nullptr);
return;
@@ -2420,7 +2394,7 @@
//
// FIXME: We shouldn't need to do this, the target should be immutable once
// created. This complexity should be lifted elsewhere.
- Clang->getTarget().setForcedLangOptions(Clang->getLangOpts());
+ Clang->getTarget().adjust(Clang->getLangOpts());
assert(Clang->getFrontendOpts().Inputs.size() == 1 &&
"Invocation must have exactly one source file!");
diff --git a/lib/Frontend/Android.mk b/lib/Frontend/Android.mk
index ec6489a..e93ba21 100644
--- a/lib/Frontend/Android.mk
+++ b/lib/Frontend/Android.mk
@@ -44,6 +44,7 @@
LangStandards.cpp \
LayoutOverrideSource.cpp \
LogDiagnosticPrinter.cpp \
+ ModuleDependencyCollector.cpp \
MultiplexConsumer.cpp \
PrintPreprocessedOutput.cpp \
SerializedDiagnosticPrinter.cpp \
diff --git a/lib/Frontend/CMakeLists.txt b/lib/Frontend/CMakeLists.txt
index b67e0ae..3fa7a2c 100644
--- a/lib/Frontend/CMakeLists.txt
+++ b/lib/Frontend/CMakeLists.txt
@@ -25,6 +25,7 @@
LangStandards.cpp
LayoutOverrideSource.cpp
LogDiagnosticPrinter.cpp
+ ModuleDependencyCollector.cpp
MultiplexConsumer.cpp
PrintPreprocessedOutput.cpp
SerializedDiagnosticPrinter.cpp
diff --git a/lib/Frontend/CacheTokens.cpp b/lib/Frontend/CacheTokens.cpp
index d30196d..14f7027 100644
--- a/lib/Frontend/CacheTokens.cpp
+++ b/lib/Frontend/CacheTokens.cpp
@@ -540,7 +540,8 @@
~StatListener() {}
LookupResult getStat(const char *Path, FileData &Data, bool isFile,
- vfs::File **F, vfs::FileSystem &FS) override {
+ std::unique_ptr<vfs::File> *F,
+ vfs::FileSystem &FS) override {
LookupResult Result = statChained(Path, Data, isFile, F, FS);
if (Result == CacheMissing) // Failed 'stat'.
diff --git a/lib/Frontend/ChainedIncludesSource.cpp b/lib/Frontend/ChainedIncludesSource.cpp
index 6dc3fd4..e6e73ac 100644
--- a/lib/Frontend/ChainedIncludesSource.cpp
+++ b/lib/Frontend/ChainedIncludesSource.cpp
@@ -12,7 +12,6 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Frontend/ChainedIncludesSource.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/CompilerInstance.h"
@@ -25,6 +24,54 @@
using namespace clang;
+namespace {
+class ChainedIncludesSource : public ExternalSemaSource {
+public:
+ virtual ~ChainedIncludesSource();
+
+ ExternalSemaSource &getFinalReader() const { return *FinalReader; }
+
+ std::vector<CompilerInstance *> CIs;
+ IntrusiveRefCntPtr<ExternalSemaSource> FinalReader;
+
+protected:
+ //===----------------------------------------------------------------------===//
+ // ExternalASTSource interface.
+ //===----------------------------------------------------------------------===//
+
+ Decl *GetExternalDecl(uint32_t ID) override;
+ Selector GetExternalSelector(uint32_t ID) override;
+ uint32_t GetNumExternalSelectors() override;
+ Stmt *GetExternalDeclStmt(uint64_t Offset) override;
+ CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset) override;
+ bool FindExternalVisibleDeclsByName(const DeclContext *DC,
+ DeclarationName Name) override;
+ ExternalLoadResult
+ FindExternalLexicalDecls(const DeclContext *DC,
+ bool (*isKindWeWant)(Decl::Kind),
+ SmallVectorImpl<Decl *> &Result) override;
+ void CompleteType(TagDecl *Tag) override;
+ void CompleteType(ObjCInterfaceDecl *Class) override;
+ void StartedDeserializing() override;
+ void FinishedDeserializing() override;
+ void StartTranslationUnit(ASTConsumer *Consumer) override;
+ void PrintStats() override;
+
+ /// Return the amount of memory used by memory buffers, breaking down
+ /// by heap-backed versus mmap'ed memory.
+ void getMemoryBufferSizes(MemoryBufferSizes &sizes) const override;
+
+ //===----------------------------------------------------------------------===//
+ // ExternalSemaSource interface.
+ //===----------------------------------------------------------------------===//
+
+ void InitializeSema(Sema &S) override;
+ void ForgetSema() override;
+ void ReadMethodPool(Selector Sel) override;
+ bool LookupUnqualified(LookupResult &R, Scope *S) override;
+};
+}
+
static ASTReader *
createASTReader(CompilerInstance &CI, StringRef pchFile,
SmallVectorImpl<llvm::MemoryBuffer *> &memBufs,
@@ -62,8 +109,8 @@
delete CIs[i];
}
-IntrusiveRefCntPtr<ChainedIncludesSource>
-ChainedIncludesSource::create(CompilerInstance &CI) {
+IntrusiveRefCntPtr<ExternalSemaSource> clang::createChainedIncludesSource(
+ CompilerInstance &CI, IntrusiveRefCntPtr<ExternalSemaSource> &Reader) {
std::vector<std::string> &includes = CI.getPreprocessorOpts().ChainedIncludes;
assert(!includes.empty() && "No '-chain-include' in options!");
@@ -99,9 +146,9 @@
std::unique_ptr<CompilerInstance> Clang(new CompilerInstance());
Clang->setInvocation(CInvok.release());
- Clang->setDiagnostics(Diags.getPtr());
- Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(),
- &Clang->getTargetOpts()));
+ Clang->setDiagnostics(Diags.get());
+ Clang->setTarget(TargetInfo::CreateTargetInfo(
+ Clang->getDiagnostics(), Clang->getInvocation().TargetOpts));
Clang->createFileManager();
Clang->createSourceManager(Clang->getFileManager());
Clang->createPreprocessor(TU_Prefix);
@@ -126,17 +173,14 @@
} else {
assert(!serialBufs.empty());
SmallVector<llvm::MemoryBuffer *, 4> bufs;
- for (unsigned si = 0, se = serialBufs.size(); si != se; ++si) {
- bufs.push_back(llvm::MemoryBuffer::getMemBufferCopy(
- StringRef(serialBufs[si]->getBufferStart(),
- serialBufs[si]->getBufferSize())));
- }
+ // TODO: Pass through the existing MemoryBuffer instances instead of
+ // allocating new ones.
+ for (auto *SB : serialBufs)
+ bufs.push_back(llvm::MemoryBuffer::getMemBuffer(SB->getBuffer()));
std::string pchName = includes[i-1];
llvm::raw_string_ostream os(pchName);
os << ".pch" << i-1;
- os.flush();
-
- serialBufNames.push_back(pchName);
+ serialBufNames.push_back(os.str());
IntrusiveRefCntPtr<ASTReader> Reader;
Reader = createASTReader(*Clang, pchName, bufs, serialBufNames,
@@ -151,18 +195,14 @@
return nullptr;
ParseAST(Clang->getSema());
- OS.flush();
Clang->getDiagnosticClient().EndSourceFile();
- serialBufs.push_back(
- llvm::MemoryBuffer::getMemBufferCopy(StringRef(serialAST.data(),
- serialAST.size())));
+ serialBufs.push_back(llvm::MemoryBuffer::getMemBufferCopy(OS.str()));
source->CIs.push_back(Clang.release());
}
assert(!serialBufs.empty());
std::string pchName = includes.back() + ".pch-final";
serialBufNames.push_back(pchName);
- IntrusiveRefCntPtr<ASTReader> Reader;
Reader = createASTReader(CI, pchName, serialBufs, serialBufNames);
if (!Reader)
return nullptr;
diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp
index c65d34b..7cea9e4 100644
--- a/lib/Frontend/CompilerInstance.cpp
+++ b/lib/Frontend/CompilerInstance.cpp
@@ -16,6 +16,7 @@
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/Version.h"
+#include "clang/Config/config.h"
#include "clang/Frontend/ChainedDiagnosticConsumer.h"
#include "clang/Frontend/FrontendAction.h"
#include "clang/Frontend/FrontendActions.h"
@@ -33,8 +34,8 @@
#include "clang/Serialization/ASTReader.h"
#include "clang/Serialization/GlobalModuleIndex.h"
#include "llvm/ADT/Statistic.h"
-#include "llvm/Config/config.h"
#include "llvm/Support/CrashRecoveryContext.h"
+#include "llvm/Support/Errc.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/LockFileManager.h"
@@ -44,8 +45,8 @@
#include "llvm/Support/Signals.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/Support/system_error.h"
#include <sys/stat.h>
+#include <system_error>
#include <time.h>
using namespace clang;
@@ -115,6 +116,16 @@
ModuleManager = Reader;
}
+std::shared_ptr<ModuleDependencyCollector>
+CompilerInstance::getModuleDepCollector() const {
+ return ModuleDepCollector;
+}
+
+void CompilerInstance::setModuleDepCollector(
+ std::shared_ptr<ModuleDependencyCollector> Collector) {
+ ModuleDepCollector = Collector;
+}
+
// Diagnostics
static void SetUpDiagnosticLog(DiagnosticOptions *DiagOpts,
const CodeGenOptions *CodeGenOpts,
@@ -223,6 +234,56 @@
SourceMgr = new SourceManager(getDiagnostics(), FileMgr);
}
+// Initialize the remapping of files to alternative contents, e.g.,
+// those specified through other files.
+static void InitializeFileRemapping(DiagnosticsEngine &Diags,
+ SourceManager &SourceMgr,
+ FileManager &FileMgr,
+ const PreprocessorOptions &InitOpts) {
+ // Remap files in the source manager (with buffers).
+ for (const auto &RB : InitOpts.RemappedFileBuffers) {
+ // Create the file entry for the file that we're mapping from.
+ const FileEntry *FromFile =
+ FileMgr.getVirtualFile(RB.first, RB.second->getBufferSize(), 0);
+ if (!FromFile) {
+ Diags.Report(diag::err_fe_remap_missing_from_file) << RB.first;
+ if (!InitOpts.RetainRemappedFileBuffers)
+ delete RB.second;
+ continue;
+ }
+
+ // Override the contents of the "from" file with the contents of
+ // the "to" file.
+ SourceMgr.overrideFileContents(FromFile, RB.second,
+ InitOpts.RetainRemappedFileBuffers);
+ }
+
+ // Remap files in the source manager (with other files).
+ for (const auto &RF : InitOpts.RemappedFiles) {
+ // Find the file that we're mapping to.
+ const FileEntry *ToFile = FileMgr.getFile(RF.second);
+ if (!ToFile) {
+ Diags.Report(diag::err_fe_remap_missing_to_file) << RF.first << RF.second;
+ continue;
+ }
+
+ // Create the file entry for the file that we're mapping from.
+ const FileEntry *FromFile =
+ FileMgr.getVirtualFile(RF.first, ToFile->getSize(), 0);
+ if (!FromFile) {
+ Diags.Report(diag::err_fe_remap_missing_from_file) << RF.first;
+ continue;
+ }
+
+ // Override the contents of the "from" file with the contents of
+ // the "to" file.
+ SourceMgr.overrideFileContents(FromFile, ToFile);
+ }
+
+ SourceMgr.setOverridenFilesKeepOriginalName(
+ InitOpts.RemappedFilesKeepOriginalName);
+}
+
// Preprocessor
void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) {
@@ -255,7 +316,16 @@
if (PPOpts.DetailedRecord)
PP->createPreprocessingRecord();
- InitializePreprocessor(*PP, PPOpts, getHeaderSearchOpts(), getFrontendOpts());
+ // Apply remappings to the source manager.
+ InitializeFileRemapping(PP->getDiagnostics(), PP->getSourceManager(),
+ PP->getFileManager(), PPOpts);
+
+ // Predefine macros and configure the preprocessor.
+ InitializePreprocessor(*PP, PPOpts, getFrontendOpts());
+
+ // Initialize the header search object.
+ ApplyHeaderSearchOptions(PP->getHeaderSearchInfo(), getHeaderSearchOpts(),
+ PP->getLangOpts(), PP->getTargetInfo().getTriple());
PP->setPreprocessedOutput(getPreprocessorOutputOpts().ShowCPP);
@@ -277,6 +347,14 @@
AttachDependencyGraphGen(*PP, DepOpts.DOTOutputFile,
getHeaderSearchOpts().Sysroot);
+ for (auto &Listener : DependencyCollectors)
+ Listener->attachToPreprocessor(*PP);
+
+ // If we don't have a collector, but we are collecting module dependencies,
+ // then we're the top level compiler instance and need to create one.
+ if (!ModuleDepCollector && !DepOpts.ModuleDependencyOutputDir.empty())
+ ModuleDepCollector = std::make_shared<ModuleDependencyCollector>(
+ DepOpts.ModuleDependencyOutputDir);
// Handle generating header include information, if requested.
if (DepOpts.ShowHeaderIncludes)
@@ -317,7 +395,7 @@
AllowPCHWithCompilerErrors, getPreprocessor(), getASTContext(),
DeserializationListener, OwnDeserializationListener, Preamble,
getFrontendOpts().UseGlobalModuleIndex);
- ModuleManager = static_cast<ASTReader*>(Source.getPtr());
+ ModuleManager = static_cast<ASTReader*>(Source.get());
getASTContext().setExternalSource(Source);
}
@@ -454,8 +532,8 @@
// If '-working-directory' was passed, the output filename should be
// relative to that.
FileMgr->FixupRelativePath(NewOutFile);
- if (llvm::error_code ec = llvm::sys::fs::rename(it->TempFilename,
- NewOutFile.str())) {
+ if (std::error_code ec =
+ llvm::sys::fs::rename(it->TempFilename, NewOutFile.str())) {
getDiagnostics().Report(diag::err_unable_to_rename_temp)
<< it->TempFilename << it->Filename << ec.message();
@@ -478,6 +556,12 @@
/*UseTemporary=*/true);
}
+llvm::raw_null_ostream *CompilerInstance::createNullOutputFile() {
+ llvm::raw_null_ostream *OS = new llvm::raw_null_ostream();
+ addOutputFile(OutputFile("", "", OS));
+ return OS;
+}
+
llvm::raw_fd_ostream *
CompilerInstance::createOutputFile(StringRef OutputPath,
bool Binary, bool RemoveFileOnSignal,
@@ -562,7 +646,7 @@
TempPath = OutFile;
TempPath += "-%%%%%%%%";
int fd;
- llvm::error_code EC =
+ std::error_code EC =
llvm::sys::fs::createUniqueFile(TempPath.str(), fd, TempPath);
if (CreateMissingDirectories &&
@@ -658,11 +742,14 @@
SourceMgr.setMainFileID(
SourceMgr.createFileID(File, SourceLocation(), Kind));
} else {
- std::unique_ptr<llvm::MemoryBuffer> SB;
- if (llvm::error_code ec = llvm::MemoryBuffer::getSTDIN(SB)) {
- Diags.Report(diag::err_fe_error_reading_stdin) << ec.message();
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> SBOrErr =
+ llvm::MemoryBuffer::getSTDIN();
+ if (std::error_code EC = SBOrErr.getError()) {
+ Diags.Report(diag::err_fe_error_reading_stdin) << EC.message();
return false;
}
+ std::unique_ptr<llvm::MemoryBuffer> SB = std::move(SBOrErr.get());
+
const FileEntry *File = FileMgr.getVirtualFile(SB->getBufferIdentifier(),
SB->getBufferSize(), 0);
SourceMgr.setMainFileID(
@@ -687,7 +774,8 @@
raw_ostream &OS = llvm::errs();
// Create the target instance.
- setTarget(TargetInfo::CreateTargetInfo(getDiagnostics(), &getTargetOpts()));
+ setTarget(TargetInfo::CreateTargetInfo(getDiagnostics(),
+ getInvocation().TargetOpts));
if (!hasTarget())
return false;
@@ -695,7 +783,7 @@
//
// FIXME: We shouldn't need to do this, the target should be immutable once
// created. This complexity should be lifted elsewhere.
- getTarget().setForcedLangOptions(getLangOpts());
+ getTarget().adjust(getLangOpts());
// rewriter project will change target built-in bool type from its default.
if (getFrontendOpts().ProgramAction == frontend::RewriteObjC)
@@ -704,7 +792,7 @@
// Validate/process some options.
if (getHeaderSearchOpts().Verbose)
OS << "clang -cc1 version " CLANG_VERSION_STRING
- << " based upon " << PACKAGE_STRING
+ << " based upon " << BACKEND_PACKAGE_STRING
<< " default target " << llvm::sys::getDefaultTargetTriple() << "\n";
if (getFrontendOpts().ShowTimers)
@@ -844,6 +932,10 @@
SourceMgr.pushModuleBuildStack(Module->getTopLevelModuleName(),
FullSourceLoc(ImportLoc, ImportingInstance.getSourceManager()));
+ // If we're collecting module dependencies, we need to share a collector
+ // between all of the module CompilerInstances.
+ Instance.setModuleDepCollector(ImportingInstance.getModuleDepCollector());
+
// Get or create the module map that we'll use to build this module.
std::string InferredModuleMapContent;
if (const FileEntry *ModuleMapFile =
@@ -858,7 +950,7 @@
FrontendOpts.Inputs.push_back(
FrontendInputFile("__inferred_module.map", IK));
- const llvm::MemoryBuffer *ModuleMapBuffer =
+ llvm::MemoryBuffer *ModuleMapBuffer =
llvm::MemoryBuffer::getMemBuffer(InferredModuleMapContent);
ModuleMapFile = Instance.getFileManager().getVirtualFile(
"__inferred_module.map", InferredModuleMapContent.size(), 0);
@@ -889,23 +981,28 @@
}
}
-static void compileModule(CompilerInstance &ImportingInstance,
- SourceLocation ImportLoc,
- Module *Module,
- StringRef ModuleFileName) {
+static bool compileAndLoadModule(CompilerInstance &ImportingInstance,
+ SourceLocation ImportLoc,
+ SourceLocation ModuleNameLoc,
+ Module *Module,
+ StringRef ModuleFileName) {
// FIXME: have LockFileManager return an error_code so that we can
// avoid the mkdir when the directory already exists.
StringRef Dir = llvm::sys::path::parent_path(ModuleFileName);
llvm::sys::fs::create_directories(Dir);
while (1) {
+ unsigned ModuleLoadCapabilities = ASTReader::ARR_Missing;
llvm::LockFileManager Locked(ModuleFileName);
switch (Locked) {
case llvm::LockFileManager::LFS_Error:
- return;
+ return false;
case llvm::LockFileManager::LFS_Owned:
- // We're responsible for building the module ourselves. Do so below.
+ // We're responsible for building the module ourselves.
+ // FIXME: if there are errors, don't attempt to load the module.
+ compileModuleImpl(ImportingInstance, ModuleNameLoc, Module,
+ ModuleFileName);
break;
case llvm::LockFileManager::LFS_Shared:
@@ -913,11 +1010,28 @@
// finish.
if (Locked.waitForUnlock() == llvm::LockFileManager::Res_OwnerDied)
continue; // try again to get the lock.
- return;
+ ModuleLoadCapabilities |= ASTReader::ARR_OutOfDate;
+ break;
}
- return compileModuleImpl(ImportingInstance, ImportLoc, Module,
- ModuleFileName);
+ // Try to read the module file, now that we've compiled it.
+ ASTReader::ASTReadResult ReadResult =
+ ImportingInstance.getModuleManager()->ReadAST(
+ ModuleFileName, serialization::MK_Module, ImportLoc,
+ ModuleLoadCapabilities);
+
+ if (ReadResult == ASTReader::OutOfDate &&
+ Locked == llvm::LockFileManager::LFS_Shared) {
+ // The module may be out of date in the presence of file system races,
+ // or if one of its imports depends on header search paths that are not
+ // consistent with this ImportingInstance. Try again...
+ continue;
+ } else if (ReadResult == ASTReader::Missing) {
+ ImportingInstance.getDiagnostics().Report(ModuleNameLoc,
+ diag::err_module_not_built)
+ << Module->Name << SourceRange(ImportLoc, ModuleNameLoc);
+ }
+ return ReadResult == ASTReader::Success;
}
}
@@ -1045,7 +1159,7 @@
// Walk the entire module cache, looking for unused module files and module
// indices.
- llvm::error_code EC;
+ std::error_code EC;
SmallString<128> ModuleCachePathNative;
llvm::sys::path::native(HSOpts.ModuleCachePath, ModuleCachePathNative);
for (llvm::sys::fs::directory_iterator
@@ -1182,6 +1296,12 @@
if (TheDependencyFileGenerator)
TheDependencyFileGenerator->AttachToASTReader(*ModuleManager);
+ if (ModuleDepCollector)
+ ModuleDepCollector->attachToASTReader(*ModuleManager);
+
+ for (auto &Listener : DependencyCollectors)
+ Listener->attachToASTReader(*ModuleManager);
+
// Try to load the module file.
unsigned ARRFlags = ASTReader::ARR_OutOfDate | ASTReader::ARR_Missing;
switch (ModuleManager->ReadAST(ModuleFileName, serialization::MK_Module,
@@ -1228,23 +1348,9 @@
return ModuleLoadResult();
}
- // Try to compile the module.
- compileModule(*this, ModuleNameLoc, Module, 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_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);
- }
-
+ // Try to compile and then load the module.
+ if (!compileAndLoadModule(*this, ImportLoc, ModuleNameLoc, Module,
+ ModuleFileName)) {
if (getPreprocessorOpts().FailedModules)
getPreprocessorOpts().FailedModules->addFailed(ModuleName);
KnownModules[Path[0].first] = nullptr;
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 2ba9450..3d79ac7 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -20,6 +20,7 @@
#include "clang/Serialization/ASTReader.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Triple.h"
@@ -33,10 +34,10 @@
#include "llvm/Support/Host.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
-#include "llvm/Support/system_error.h"
#include <atomic>
#include <memory>
#include <sys/stat.h>
+#include <system_error>
using namespace clang;
//===----------------------------------------------------------------------===//
@@ -309,6 +310,22 @@
return "default";
}
+/// \brief Create a new Regex instance out of the string value in \p RpassArg.
+/// It returns a pointer to the newly generated Regex instance.
+static std::shared_ptr<llvm::Regex>
+GenerateOptimizationRemarkRegex(DiagnosticsEngine &Diags, ArgList &Args,
+ Arg *RpassArg) {
+ StringRef Val = RpassArg->getValue();
+ std::string RegexError;
+ std::shared_ptr<llvm::Regex> Pattern = std::make_shared<llvm::Regex>(Val);
+ if (!Pattern->isValid(RegexError)) {
+ Diags.Report(diag::err_drv_optimization_remark_pattern)
+ << RegexError << RpassArg->getAsString(Args);
+ Pattern.reset();
+ }
+ return Pattern;
+}
+
static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
DiagnosticsEngine &Diags,
const TargetOptions &TargetOpts) {
@@ -533,18 +550,31 @@
}
Opts.DependentLibraries = Args.getAllArgValues(OPT_dependent_lib);
+ bool NeedLocTracking = false;
if (Arg *A = Args.getLastArg(OPT_Rpass_EQ)) {
- StringRef Val = A->getValue();
- std::string RegexError;
- Opts.OptimizationRemarkPattern = std::make_shared<llvm::Regex>(Val);
- if (!Opts.OptimizationRemarkPattern->isValid(RegexError)) {
- Diags.Report(diag::err_drv_optimization_remark_pattern)
- << RegexError << A->getAsString(Args);
- Opts.OptimizationRemarkPattern.reset();
- }
+ Opts.OptimizationRemarkPattern =
+ GenerateOptimizationRemarkRegex(Diags, Args, A);
+ NeedLocTracking = true;
}
+ if (Arg *A = Args.getLastArg(OPT_Rpass_missed_EQ)) {
+ Opts.OptimizationRemarkMissedPattern =
+ GenerateOptimizationRemarkRegex(Diags, Args, A);
+ NeedLocTracking = true;
+ }
+
+ if (Arg *A = Args.getLastArg(OPT_Rpass_analysis_EQ)) {
+ Opts.OptimizationRemarkAnalysisPattern =
+ GenerateOptimizationRemarkRegex(Diags, Args, A);
+ NeedLocTracking = true;
+ }
+
+ // If the user requested one of the flags in the -Rpass family, make sure
+ // that the backend tracks source location information.
+ if (NeedLocTracking && Opts.getDebugInfo() == CodeGenOptions::NoDebugInfo)
+ Opts.setDebugInfo(CodeGenOptions::LocTrackingOnly);
+
return Success;
}
@@ -561,6 +591,8 @@
Opts.AddMissingHeaderDeps = Args.hasArg(OPT_MG);
Opts.PrintShowIncludes = Args.hasArg(OPT_show_includes);
Opts.DOTOutputFile = Args.getLastArgValue(OPT_dependency_dot);
+ Opts.ModuleDependencyOutputDir =
+ Args.getLastArgValue(OPT_module_dependency_dir);
}
bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
@@ -1107,6 +1139,7 @@
Opts.CPlusPlus = Std.isCPlusPlus();
Opts.CPlusPlus11 = Std.isCPlusPlus11();
Opts.CPlusPlus1y = Std.isCPlusPlus1y();
+ Opts.CPlusPlus1z = Std.isCPlusPlus1z();
Opts.Digraphs = Std.hasDigraphs();
Opts.GNUMode = Std.isGNUMode();
Opts.GNUInline = !Std.isC99();
@@ -1114,18 +1147,13 @@
Opts.ImplicitInt = Std.hasImplicitInt();
// Set OpenCL Version.
- if (LangStd == LangStandard::lang_opencl) {
- Opts.OpenCL = 1;
+ Opts.OpenCL = LangStd == LangStandard::lang_opencl || IK == IK_OpenCL;
+ if (LangStd == LangStandard::lang_opencl)
Opts.OpenCLVersion = 100;
- }
- else if (LangStd == LangStandard::lang_opencl11) {
- Opts.OpenCL = 1;
+ else if (LangStd == LangStandard::lang_opencl11)
Opts.OpenCLVersion = 110;
- }
- else if (LangStd == LangStandard::lang_opencl12) {
- Opts.OpenCL = 1;
+ else if (LangStd == LangStandard::lang_opencl12)
Opts.OpenCLVersion = 120;
- }
// OpenCL has some additional defaults.
if (Opts.OpenCL) {
@@ -1136,8 +1164,7 @@
Opts.NativeHalfType = 1;
}
- if (LangStd == LangStandard::lang_cuda)
- Opts.CUDA = 1;
+ Opts.CUDA = LangStd == LangStandard::lang_cuda || IK == IK_CUDA;
// OpenCL and C++ both have bool, true, false keywords.
Opts.Bool = Opts.OpenCL || Opts.CPlusPlus;
@@ -1153,7 +1180,8 @@
// Mimicing gcc's behavior, trigraphs are only enabled if -trigraphs
// is specified, or -std is set to a conforming mode.
- Opts.Trigraphs = !Opts.GNUMode;
+ // Trigraphs are disabled by default in c++1z onwards.
+ Opts.Trigraphs = !Opts.GNUMode && !Opts.CPlusPlus1z;
Opts.DollarIdents = !Opts.AsmPreprocessor;
@@ -1179,6 +1207,60 @@
return DefaultVisibility;
}
+static unsigned parseMSCVersion(ArgList &Args, DiagnosticsEngine &Diags) {
+ auto Arg = Args.getLastArg(OPT_fmsc_version);
+ if (!Arg)
+ return 0;
+
+ // The MSC versioning scheme involves four versioning components:
+ // - Major
+ // - Minor
+ // - Build
+ // - Patch
+ //
+ // We accept either the old style (_MSC_VER) value, or a _MSC_FULL_VER value.
+ // Additionally, the value may be provided in the form of a more readable
+ // MM.mm.bbbbb.pp version.
+ //
+ // Unfortunately, due to the bit-width limitations, we cannot currently encode
+ // the value for the patch level.
+
+ StringRef Value = Arg->getValue();
+
+ // parse the compatible old form of _MSC_VER or the newer _MSC_FULL_VER
+ if (Value.find('.') == StringRef::npos) {
+ unsigned Version = 0;
+ if (Value.getAsInteger(10, Version)) {
+ Diags.Report(diag::err_drv_invalid_value)
+ << Arg->getAsString(Args) << Value;
+ return 0;
+ }
+ if (Version < 100)
+ Version = Version * 100; // major -> major.minor
+ if (Version < 100000)
+ Version = Version * 100000; // major.minor -> major.minor.build
+ return Version;
+ }
+
+ // parse the dot-delimited component version
+ unsigned VC[4] = {0};
+ SmallVector<StringRef, 4> Components;
+
+ Value.split(Components, ".", llvm::array_lengthof(VC));
+ for (unsigned CI = 0,
+ CE = std::min(Components.size(), llvm::array_lengthof(VC));
+ CI < CE; ++CI) {
+ if (Components[CI].getAsInteger(10, VC[CI])) {
+ Diags.Report(diag::err_drv_invalid_value)
+ << Arg->getAsString(Args) << Value;
+ return 0;
+ }
+ }
+
+ // FIXME we cannot encode the patch level
+ return VC[0] * 10000000 + VC[1] * 100000 + VC[2];
+}
+
static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
DiagnosticsEngine &Diags) {
// FIXME: Cleanup per-file based stuff.
@@ -1348,7 +1430,7 @@
Opts.MSVCCompat = Args.hasArg(OPT_fms_compatibility);
Opts.MicrosoftExt = Opts.MSVCCompat || Args.hasArg(OPT_fms_extensions);
Opts.AsmBlocks = Args.hasArg(OPT_fasm_blocks) || Opts.MicrosoftExt;
- Opts.MSCVersion = getLastArgIntValue(Args, OPT_fmsc_version, 0, Diags);
+ Opts.MSCVersion = parseMSCVersion(Args, Diags);
Opts.VtorDispMode = getLastArgIntValue(Args, OPT_vtordisp_mode_EQ, 1, Diags);
Opts.Borland = Args.hasArg(OPT_fborland_extensions);
Opts.WritableStrings = Args.hasArg(OPT_fwritable_strings);
@@ -1365,6 +1447,7 @@
Opts.TraditionalCPP = Args.hasArg(OPT_traditional_cpp);
Opts.RTTI = !Args.hasArg(OPT_fno_rtti);
+ Opts.RTTIData = Opts.RTTI && !Args.hasArg(OPT_fno_rtti_data);
Opts.Blocks = Args.hasArg(OPT_fblocks);
Opts.BlocksRuntimeOptional = Args.hasArg(OPT_fblocks_runtime_optional);
Opts.Modules = Args.hasArg(OPT_fmodules);
@@ -1874,14 +1957,16 @@
// $sysroot/System/Library/CoreServices/SystemVersion.plist
// as part of the module hash.
if (!hsOpts.Sysroot.empty()) {
- std::unique_ptr<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.str(), buffer)) {
+
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> buffer =
+ llvm::MemoryBuffer::getFile(systemVersionFile.str());
+ if (buffer) {
code = hash_combine(code, buffer.get()->getBuffer());
struct stat statBuf;
@@ -1948,15 +2033,16 @@
Overlay(new vfs::OverlayFileSystem(vfs::getRealFileSystem()));
// earlier vfs files are on the bottom
for (const std::string &File : CI.getHeaderSearchOpts().VFSOverlayFiles) {
- std::unique_ptr<llvm::MemoryBuffer> Buffer;
- if (llvm::errc::success != llvm::MemoryBuffer::getFile(File, Buffer)) {
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buffer =
+ llvm::MemoryBuffer::getFile(File);
+ if (!Buffer) {
Diags.Report(diag::err_missing_vfs_overlay_file) << File;
return IntrusiveRefCntPtr<vfs::FileSystem>();
}
IntrusiveRefCntPtr<vfs::FileSystem> FS =
- vfs::getVFSFromYAML(Buffer.release(), /*DiagHandler*/nullptr);
- if (!FS.getPtr()) {
+ vfs::getVFSFromYAML(Buffer->release(), /*DiagHandler*/ nullptr);
+ if (!FS.get()) {
Diags.Report(diag::err_invalid_vfs_overlay) << File;
return IntrusiveRefCntPtr<vfs::FileSystem>();
}
diff --git a/lib/Frontend/CreateInvocationFromCommandLine.cpp b/lib/Frontend/CreateInvocationFromCommandLine.cpp
index 45f7aa3..f2f36e4 100644
--- a/lib/Frontend/CreateInvocationFromCommandLine.cpp
+++ b/lib/Frontend/CreateInvocationFromCommandLine.cpp
@@ -32,7 +32,7 @@
CompilerInvocation *
clang::createInvocationFromCommandLine(ArrayRef<const char *> ArgList,
IntrusiveRefCntPtr<DiagnosticsEngine> Diags) {
- if (!Diags.getPtr()) {
+ if (!Diags.get()) {
// No diagnostics engine was provided, so create our own diagnostics object
// with the default options.
Diags = CompilerInstance::createDiagnostics(new DiagnosticOptions);
diff --git a/lib/Frontend/DependencyFile.cpp b/lib/Frontend/DependencyFile.cpp
index e72be89..0b9c0d4 100644
--- a/lib/Frontend/DependencyFile.cpp
+++ b/lib/Frontend/DependencyFile.cpp
@@ -29,6 +29,105 @@
using namespace clang;
namespace {
+struct DepCollectorPPCallbacks : public PPCallbacks {
+ DependencyCollector &DepCollector;
+ SourceManager &SM;
+ DepCollectorPPCallbacks(DependencyCollector &L, SourceManager &SM)
+ : DepCollector(L), SM(SM) { }
+
+ void FileChanged(SourceLocation Loc, FileChangeReason Reason,
+ SrcMgr::CharacteristicKind FileType,
+ FileID PrevFID) override {
+ if (Reason != PPCallbacks::EnterFile)
+ return;
+
+ // Dependency generation really does want to go all the way to the
+ // file entry for a source location to find out what is depended on.
+ // We do not want #line markers to affect dependency generation!
+ const FileEntry *FE =
+ SM.getFileEntryForID(SM.getFileID(SM.getExpansionLoc(Loc)));
+ if (!FE)
+ return;
+
+ StringRef Filename = FE->getName();
+
+ // Remove leading "./" (or ".//" or "././" etc.)
+ while (Filename.size() > 2 && Filename[0] == '.' &&
+ llvm::sys::path::is_separator(Filename[1])) {
+ Filename = Filename.substr(1);
+ while (llvm::sys::path::is_separator(Filename[0]))
+ Filename = Filename.substr(1);
+ }
+
+ DepCollector.maybeAddDependency(Filename, /*FromModule*/false,
+ FileType != SrcMgr::C_User,
+ /*IsModuleFile*/false, /*IsMissing*/false);
+ }
+
+ void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
+ StringRef FileName, bool IsAngled,
+ CharSourceRange FilenameRange, const FileEntry *File,
+ StringRef SearchPath, StringRef RelativePath,
+ const Module *Imported) override {
+ if (!File)
+ DepCollector.maybeAddDependency(FileName, /*FromModule*/false,
+ /*IsSystem*/false, /*IsModuleFile*/false,
+ /*IsMissing*/true);
+ // Files that actually exist are handled by FileChanged.
+ }
+
+ void EndOfMainFile() override {
+ DepCollector.finishedMainFile();
+ }
+};
+
+struct DepCollectorASTListener : public ASTReaderListener {
+ DependencyCollector &DepCollector;
+ DepCollectorASTListener(DependencyCollector &L) : DepCollector(L) { }
+ bool needsInputFileVisitation() override { return true; }
+ bool needsSystemInputFileVisitation() override {
+ return DepCollector.needSystemDependencies();
+ }
+ void visitModuleFile(StringRef Filename) override {
+ DepCollector.maybeAddDependency(Filename, /*FromModule*/true,
+ /*IsSystem*/false, /*IsModuleFile*/true,
+ /*IsMissing*/false);
+ }
+ bool visitInputFile(StringRef Filename, bool IsSystem,
+ bool IsOverridden) override {
+ if (IsOverridden)
+ return true;
+
+ DepCollector.maybeAddDependency(Filename, /*FromModule*/true, IsSystem,
+ /*IsModuleFile*/false, /*IsMissing*/false);
+ return true;
+ }
+};
+} // end anonymous namespace
+
+void DependencyCollector::maybeAddDependency(StringRef Filename, bool FromModule,
+ bool IsSystem, bool IsModuleFile,
+ bool IsMissing) {
+ if (Seen.insert(Filename) &&
+ sawDependency(Filename, FromModule, IsSystem, IsModuleFile, IsMissing))
+ Dependencies.push_back(Filename);
+}
+
+bool DependencyCollector::sawDependency(StringRef Filename, bool FromModule,
+ bool IsSystem, bool IsModuleFile,
+ bool IsMissing) {
+ return Filename != "<built-in>" && (needSystemDependencies() || !IsSystem);
+}
+
+DependencyCollector::~DependencyCollector() { }
+void DependencyCollector::attachToPreprocessor(Preprocessor &PP) {
+ PP.addPPCallbacks(new DepCollectorPPCallbacks(*this, PP.getSourceManager()));
+}
+void DependencyCollector::attachToASTReader(ASTReader &R) {
+ R.addListener(new DepCollectorASTListener(*this));
+}
+
+namespace {
/// Private implementation for DependencyFileGenerator
class DFGImpl : public PPCallbacks {
std::vector<std::string> Files;
diff --git a/lib/Frontend/DiagnosticRenderer.cpp b/lib/Frontend/DiagnosticRenderer.cpp
index ce9fc05..cff32b8 100644
--- a/lib/Frontend/DiagnosticRenderer.cpp
+++ b/lib/Frontend/DiagnosticRenderer.cpp
@@ -190,6 +190,12 @@
&Diag);
}
+void DiagnosticRenderer::emitBasicNote(StringRef Message) {
+ emitDiagnosticMessage(
+ SourceLocation(), PresumedLoc(), DiagnosticsEngine::Note, Message,
+ ArrayRef<CharSourceRange>(), nullptr, DiagOrStoredDiag());
+}
+
/// \brief Prints an include stack when appropriate for a particular
/// diagnostic level and location.
///
@@ -506,8 +512,3 @@
Message << "while building module '" << ModuleName << ":";
emitNote(Loc, Message.str(), &SM);
}
-
-
-void DiagnosticNoteRenderer::emitBasicNote(StringRef Message) {
- emitNote(SourceLocation(), Message, nullptr);
-}
diff --git a/lib/Frontend/FrontendAction.cpp b/lib/Frontend/FrontendAction.cpp
index b085749..c274ba7 100644
--- a/lib/Frontend/FrontendAction.cpp
+++ b/lib/Frontend/FrontendAction.cpp
@@ -12,7 +12,6 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclGroup.h"
#include "clang/Frontend/ASTUnit.h"
-#include "clang/Frontend/ChainedIncludesSource.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/FrontendPluginRegistry.h"
@@ -30,7 +29,7 @@
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/Support/system_error.h"
+#include <system_error>
using namespace clang;
namespace {
@@ -260,7 +259,7 @@
PreprocessorOptions &PPOpts = CI.getPreprocessorOpts();
StringRef PCHInclude = PPOpts.ImplicitPCHInclude;
if (const DirectoryEntry *PCHDir = FileMgr.getDirectory(PCHInclude)) {
- llvm::error_code EC;
+ std::error_code EC;
SmallString<128> DirNative;
llvm::sys::path::native(PCHDir->getName(), DirNative);
bool Found = false;
@@ -315,13 +314,12 @@
if (!CI.getPreprocessorOpts().ChainedIncludes.empty()) {
// Convert headers to PCH and chain them.
- IntrusiveRefCntPtr<ChainedIncludesSource> source;
- source = ChainedIncludesSource::create(CI);
+ IntrusiveRefCntPtr<ExternalSemaSource> source, FinalReader;
+ source = createChainedIncludesSource(CI, FinalReader);
if (!source)
goto failure;
- CI.setModuleManager(static_cast<ASTReader*>(&source->getFinalReader()));
+ CI.setModuleManager(static_cast<ASTReader *>(FinalReader.get()));
CI.getASTContext().setExternalSource(source);
-
} else if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) {
// Use PCH.
assert(hasPCHSupport() && "This action does not have PCH support!");
diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp
index 5c56ee3..ef6bfec 100644
--- a/lib/Frontend/FrontendActions.cpp
+++ b/lib/Frontend/FrontendActions.cpp
@@ -24,8 +24,8 @@
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/Support/system_error.h"
#include <memory>
+#include <system_error>
using namespace clang;
@@ -129,10 +129,10 @@
return Includes;
}
-static llvm::error_code addHeaderInclude(StringRef HeaderName,
- SmallVectorImpl<char> &Includes,
- const LangOptions &LangOpts,
- bool IsExternC) {
+static std::error_code addHeaderInclude(StringRef HeaderName,
+ SmallVectorImpl<char> &Includes,
+ const LangOptions &LangOpts,
+ bool IsExternC) {
if (IsExternC && LangOpts.CPlusPlus)
Includes += "extern \"C\" {\n";
if (LangOpts.ObjC1)
@@ -146,20 +146,20 @@
Includes += HeaderName;
} else {
SmallString<256> Header = HeaderName;
- if (llvm::error_code Err = llvm::sys::fs::make_absolute(Header))
+ if (std::error_code Err = llvm::sys::fs::make_absolute(Header))
return Err;
Includes += Header;
}
Includes += "\"\n";
if (IsExternC && LangOpts.CPlusPlus)
Includes += "}\n";
- return llvm::error_code::success();
+ return std::error_code();
}
-static llvm::error_code addHeaderInclude(const FileEntry *Header,
- SmallVectorImpl<char> &Includes,
- const LangOptions &LangOpts,
- bool IsExternC) {
+static std::error_code addHeaderInclude(const FileEntry *Header,
+ SmallVectorImpl<char> &Includes,
+ const LangOptions &LangOpts,
+ bool IsExternC) {
return addHeaderInclude(Header->getName(), Includes, LangOpts, IsExternC);
}
@@ -170,19 +170,19 @@
///
/// \param Includes Will be augmented with the set of \#includes or \#imports
/// needed to load all of the named headers.
-static llvm::error_code
+static std::error_code
collectModuleHeaderIncludes(const LangOptions &LangOpts, FileManager &FileMgr,
ModuleMap &ModMap, clang::Module *Module,
SmallVectorImpl<char> &Includes) {
// Don't collect any headers for unavailable modules.
if (!Module->isAvailable())
- return llvm::error_code::success();
+ return std::error_code();
// Add includes for each of these headers.
for (unsigned I = 0, N = Module->NormalHeaders.size(); I != N; ++I) {
const FileEntry *Header = Module->NormalHeaders[I];
Module->addTopHeader(Header);
- if (llvm::error_code Err =
+ if (std::error_code Err =
addHeaderInclude(Header, Includes, LangOpts, Module->IsExternC))
return Err;
}
@@ -192,13 +192,13 @@
Module->addTopHeader(UmbrellaHeader);
if (Module->Parent) {
// Include the umbrella header for submodules.
- if (llvm::error_code Err = addHeaderInclude(UmbrellaHeader, Includes,
- LangOpts, Module->IsExternC))
+ if (std::error_code Err = addHeaderInclude(UmbrellaHeader, Includes,
+ LangOpts, Module->IsExternC))
return Err;
}
} else if (const DirectoryEntry *UmbrellaDir = Module->getUmbrellaDir()) {
// Add all of the headers we find in this subdirectory.
- llvm::error_code EC;
+ std::error_code EC;
SmallString<128> DirNative;
llvm::sys::path::native(UmbrellaDir->getName(), DirNative);
for (llvm::sys::fs::recursive_directory_iterator Dir(DirNative.str(), EC),
@@ -220,8 +220,8 @@
}
// Include this header as part of the umbrella directory.
- if (llvm::error_code Err = addHeaderInclude(Dir->path(), Includes,
- LangOpts, Module->IsExternC))
+ if (std::error_code Err = addHeaderInclude(Dir->path(), Includes,
+ LangOpts, Module->IsExternC))
return Err;
}
@@ -233,11 +233,11 @@
for (clang::Module::submodule_iterator Sub = Module->submodule_begin(),
SubEnd = Module->submodule_end();
Sub != SubEnd; ++Sub)
- if (llvm::error_code Err = collectModuleHeaderIncludes(
+ if (std::error_code Err = collectModuleHeaderIncludes(
LangOpts, FileMgr, ModMap, *Sub, Includes))
return Err;
- return llvm::error_code::success();
+ return std::error_code();
}
bool GenerateModuleAction::BeginSourceFileAction(CompilerInstance &CI,
@@ -310,7 +310,7 @@
// Collect the set of #includes we need to build the module.
SmallString<256> HeaderContents;
- llvm::error_code Err = llvm::error_code::success();
+ std::error_code Err = std::error_code();
if (const FileEntry *UmbrellaHeader = Module->getUmbrellaHeader())
Err = addHeaderInclude(UmbrellaHeader, HeaderContents, CI.getLangOpts(),
Module->IsExternC);
diff --git a/lib/Frontend/HeaderIncludeGen.cpp b/lib/Frontend/HeaderIncludeGen.cpp
index 6d2e378..8b2435b 100644
--- a/lib/Frontend/HeaderIncludeGen.cpp
+++ b/lib/Frontend/HeaderIncludeGen.cpp
@@ -49,7 +49,7 @@
void clang::AttachHeaderIncludeGen(Preprocessor &PP, bool ShowAllHeaders,
StringRef OutputPath, bool ShowDepth,
bool MSStyle) {
- raw_ostream *OutputFile = &llvm::errs();
+ raw_ostream *OutputFile = MSStyle ? &llvm::outs() : &llvm::errs();
bool OwnsOutputFile = false;
// Open the output file, if used.
diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp
index d2890f0..d2edc94 100644
--- a/lib/Frontend/InitHeaderSearch.cpp
+++ b/lib/Frontend/InitHeaderSearch.cpp
@@ -472,7 +472,8 @@
case llvm::Triple::Win32:
if (triple.getEnvironment() == llvm::Triple::MSVC ||
- triple.getEnvironment() == llvm::Triple::Itanium)
+ triple.getEnvironment() == llvm::Triple::Itanium ||
+ triple.getObjectFormat() == llvm::Triple::MachO)
return;
break;
}
diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp
index fb52eb4..f03348d 100644
--- a/lib/Frontend/InitPreprocessor.cpp
+++ b/lib/Frontend/InitPreprocessor.cpp
@@ -180,7 +180,7 @@
/// DefineTypeSize - Emit a macro to the predefines buffer that declares a macro
/// named MacroName with the max value for a type with width 'TypeWidth' a
/// signedness of 'isSigned' and with a value suffix of 'ValSuffix' (e.g. LL).
-static void DefineTypeSize(StringRef MacroName, unsigned TypeWidth,
+static void DefineTypeSize(const Twine &MacroName, unsigned TypeWidth,
StringRef ValSuffix, bool isSigned,
MacroBuilder &Builder) {
llvm::APInt MaxVal = isSigned ? llvm::APInt::getSignedMaxValue(TypeWidth)
@@ -190,7 +190,7 @@
/// DefineTypeSize - An overloaded helper that uses TargetInfo to determine
/// the width, suffix, and signedness of the given type
-static void DefineTypeSize(StringRef MacroName, TargetInfo::IntType Ty,
+static void DefineTypeSize(const Twine &MacroName, TargetInfo::IntType Ty,
const TargetInfo &TI, MacroBuilder &Builder) {
DefineTypeSize(MacroName, TI.getTypeWidth(Ty), TI.getTypeConstantSuffix(Ty),
TI.isTypeSigned(Ty), Builder);
@@ -212,23 +212,68 @@
Twine(BitWidth / TI.getCharWidth()));
}
-static void DefineExactWidthIntType(TargetInfo::IntType Ty,
- const TargetInfo &TI, MacroBuilder &Builder) {
+static void DefineExactWidthIntType(TargetInfo::IntType Ty,
+ const TargetInfo &TI,
+ MacroBuilder &Builder) {
int TypeWidth = TI.getTypeWidth(Ty);
+ bool IsSigned = TI.isTypeSigned(Ty);
// Use the target specified int64 type, when appropriate, so that [u]int64_t
// ends up being defined in terms of the correct type.
if (TypeWidth == 64)
- Ty = TI.getInt64Type();
+ Ty = IsSigned ? TI.getInt64Type() : TI.getIntTypeByWidth(64, false);
- DefineType("__INT" + Twine(TypeWidth) + "_TYPE__", Ty, Builder);
+ const char *Prefix = IsSigned ? "__INT" : "__UINT";
+
+ DefineType(Prefix + Twine(TypeWidth) + "_TYPE__", Ty, Builder);
StringRef ConstSuffix(TargetInfo::getTypeConstantSuffix(Ty));
if (!ConstSuffix.empty())
- Builder.defineMacro("__INT" + Twine(TypeWidth) + "_C_SUFFIX__",
- ConstSuffix);
+ Builder.defineMacro(Prefix + Twine(TypeWidth) + "_C_SUFFIX__", ConstSuffix);
+
}
+static void DefineExactWidthIntTypeSize(TargetInfo::IntType Ty,
+ const TargetInfo &TI,
+ MacroBuilder &Builder) {
+ int TypeWidth = TI.getTypeWidth(Ty);
+ bool IsSigned = TI.isTypeSigned(Ty);
+
+ // Use the target specified int64 type, when appropriate, so that [u]int64_t
+ // ends up being defined in terms of the correct type.
+ if (TypeWidth == 64)
+ Ty = IsSigned ? TI.getInt64Type() : TI.getIntTypeByWidth(64, false);
+
+ const char *Prefix = IsSigned ? "__INT" : "__UINT";
+ DefineTypeSize(Prefix + Twine(TypeWidth) + "_MAX__", Ty, TI, Builder);
+}
+
+static void DefineLeastWidthIntType(unsigned TypeWidth, bool IsSigned,
+ const TargetInfo &TI,
+ MacroBuilder &Builder) {
+ TargetInfo::IntType Ty = TI.getLeastIntTypeByWidth(TypeWidth, IsSigned);
+ if (Ty == TargetInfo::NoInt)
+ return;
+
+ const char *Prefix = IsSigned ? "__INT_LEAST" : "__UINT_LEAST";
+ DefineType(Prefix + Twine(TypeWidth) + "_TYPE__", Ty, Builder);
+ DefineTypeSize(Prefix + Twine(TypeWidth) + "_MAX__", Ty, TI, Builder);
+}
+
+static void DefineFastIntType(unsigned TypeWidth, bool IsSigned,
+ const TargetInfo &TI, MacroBuilder &Builder) {
+ // stdint.h currently defines the fast int types as equivalent to the least
+ // types.
+ TargetInfo::IntType Ty = TI.getLeastIntTypeByWidth(TypeWidth, IsSigned);
+ if (Ty == TargetInfo::NoInt)
+ return;
+
+ const char *Prefix = IsSigned ? "__INT_FAST" : "__UINT_FAST";
+ DefineType(Prefix + Twine(TypeWidth) + "_TYPE__", Ty, Builder);
+ DefineTypeSize(Prefix + Twine(TypeWidth) + "_MAX__", Ty, TI, Builder);
+}
+
+
/// Get the value the ATOMIC_*_LOCK_FREE macro should have for a type with
/// the specified properties.
static const char *getLockFreeValue(unsigned TypeWidth, unsigned TypeAlign,
@@ -315,10 +360,13 @@
else if (!LangOpts.GNUMode && LangOpts.Digraphs)
Builder.defineMacro("__STDC_VERSION__", "199409L");
} else {
+ // FIXME: Use correct value for C++17.
+ if (LangOpts.CPlusPlus1z)
+ Builder.defineMacro("__cplusplus", "201406L");
// C++1y [cpp.predefined]p1:
// The name __cplusplus is defined to the value 201402L when compiling a
// C++ translation unit.
- if (LangOpts.CPlusPlus1y)
+ else if (LangOpts.CPlusPlus1y)
Builder.defineMacro("__cplusplus", "201402L");
// C++11 [cpp.predefined]p1:
// The name __cplusplus is defined to the value 201103L when compiling a
@@ -430,7 +478,7 @@
// Initialize language-specific preprocessor defines.
// Standard conforming mode?
- if (!LangOpts.GNUMode)
+ if (!LangOpts.GNUMode && !LangOpts.MSVCCompat)
Builder.defineMacro("__STRICT_ANSI__");
if (LangOpts.CPlusPlus11)
@@ -491,7 +539,7 @@
Builder.defineMacro("__BLOCKS__");
}
- if (LangOpts.CXXExceptions)
+ if (!LangOpts.MSVCCompat && LangOpts.CXXExceptions)
Builder.defineMacro("__EXCEPTIONS");
if (LangOpts.RTTI)
Builder.defineMacro("__GXX_RTTI");
@@ -560,6 +608,13 @@
DefineTypeSize("__INTMAX_MAX__", TI.getIntMaxType(), TI, Builder);
DefineTypeSize("__SIZE_MAX__", TI.getSizeType(), TI, Builder);
+ if (!LangOpts.MSVCCompat) {
+ DefineTypeSize("__UINTMAX_MAX__", TI.getUIntMaxType(), TI, Builder);
+ DefineTypeSize("__PTRDIFF_MAX__", TI.getPtrDiffType(0), TI, Builder);
+ DefineTypeSize("__INTPTR_MAX__", TI.getIntPtrType(), TI, Builder);
+ DefineTypeSize("__UINTPTR_MAX__", TI.getUIntPtrType(), TI, Builder);
+ }
+
DefineTypeSizeof("__SIZEOF_DOUBLE__", TI.getDoubleWidth(), TI, Builder);
DefineTypeSizeof("__SIZEOF_FLOAT__", TI.getFloatWidth(), TI, Builder);
DefineTypeSizeof("__SIZEOF_INT__", TI.getIntWidth(), TI, Builder);
@@ -596,6 +651,12 @@
DefineType("__CHAR16_TYPE__", TI.getChar16Type(), Builder);
DefineType("__CHAR32_TYPE__", TI.getChar32Type(), Builder);
+ if (!LangOpts.MSVCCompat) {
+ DefineTypeWidth("__UINTMAX_WIDTH__", TI.getUIntMaxType(), TI, Builder);
+ DefineType("__UINTPTR_TYPE__", TI.getUIntPtrType(), Builder);
+ DefineTypeWidth("__UINTPTR_WIDTH__", TI.getUIntPtrType(), TI, Builder);
+ }
+
DefineFloatMacros(Builder, "FLT", &TI.getFloatFormat(), "F");
DefineFloatMacros(Builder, "DBL", &TI.getDoubleFormat(), "");
DefineFloatMacros(Builder, "LDBL", &TI.getLongDoubleFormat(), "L");
@@ -629,6 +690,54 @@
if (TI.getLongLongWidth() > TI.getLongWidth())
DefineExactWidthIntType(TargetInfo::SignedLongLong, TI, Builder);
+ if (!LangOpts.MSVCCompat) {
+ DefineExactWidthIntType(TargetInfo::UnsignedChar, TI, Builder);
+ DefineExactWidthIntTypeSize(TargetInfo::UnsignedChar, TI, Builder);
+ DefineExactWidthIntTypeSize(TargetInfo::SignedChar, TI, Builder);
+
+ if (TI.getShortWidth() > TI.getCharWidth()) {
+ DefineExactWidthIntType(TargetInfo::UnsignedShort, TI, Builder);
+ DefineExactWidthIntTypeSize(TargetInfo::UnsignedShort, TI, Builder);
+ DefineExactWidthIntTypeSize(TargetInfo::SignedShort, TI, Builder);
+ }
+
+ if (TI.getIntWidth() > TI.getShortWidth()) {
+ DefineExactWidthIntType(TargetInfo::UnsignedInt, TI, Builder);
+ DefineExactWidthIntTypeSize(TargetInfo::UnsignedInt, TI, Builder);
+ DefineExactWidthIntTypeSize(TargetInfo::SignedInt, TI, Builder);
+ }
+
+ if (TI.getLongWidth() > TI.getIntWidth()) {
+ DefineExactWidthIntType(TargetInfo::UnsignedLong, TI, Builder);
+ DefineExactWidthIntTypeSize(TargetInfo::UnsignedLong, TI, Builder);
+ DefineExactWidthIntTypeSize(TargetInfo::SignedLong, TI, Builder);
+ }
+
+ if (TI.getLongLongWidth() > TI.getLongWidth()) {
+ DefineExactWidthIntType(TargetInfo::UnsignedLongLong, TI, Builder);
+ DefineExactWidthIntTypeSize(TargetInfo::UnsignedLongLong, TI, Builder);
+ DefineExactWidthIntTypeSize(TargetInfo::SignedLongLong, TI, Builder);
+ }
+
+ DefineLeastWidthIntType(8, true, TI, Builder);
+ DefineLeastWidthIntType(8, false, TI, Builder);
+ DefineLeastWidthIntType(16, true, TI, Builder);
+ DefineLeastWidthIntType(16, false, TI, Builder);
+ DefineLeastWidthIntType(32, true, TI, Builder);
+ DefineLeastWidthIntType(32, false, TI, Builder);
+ DefineLeastWidthIntType(64, true, TI, Builder);
+ DefineLeastWidthIntType(64, false, TI, Builder);
+
+ DefineFastIntType(8, true, TI, Builder);
+ DefineFastIntType(8, false, TI, Builder);
+ DefineFastIntType(16, true, TI, Builder);
+ DefineFastIntType(16, false, TI, Builder);
+ DefineFastIntType(32, true, TI, Builder);
+ DefineFastIntType(32, false, TI, Builder);
+ DefineFastIntType(64, true, TI, Builder);
+ DefineFastIntType(64, false, TI, Builder);
+ }
+
if (const char *Prefix = TI.getUserLabelPrefix())
Builder.defineMacro("__USER_LABEL_PREFIX__", Prefix);
@@ -726,74 +835,11 @@
TI.getTargetDefines(LangOpts, Builder);
}
-// Initialize the remapping of files to alternative contents, e.g.,
-// those specified through other files.
-static void InitializeFileRemapping(DiagnosticsEngine &Diags,
- SourceManager &SourceMgr,
- FileManager &FileMgr,
- const PreprocessorOptions &InitOpts) {
- // Remap files in the source manager (with buffers).
- for (PreprocessorOptions::const_remapped_file_buffer_iterator
- Remap = InitOpts.remapped_file_buffer_begin(),
- RemapEnd = InitOpts.remapped_file_buffer_end();
- Remap != RemapEnd;
- ++Remap) {
- // Create the file entry for the file that we're mapping from.
- const FileEntry *FromFile = FileMgr.getVirtualFile(Remap->first,
- Remap->second->getBufferSize(),
- 0);
- if (!FromFile) {
- Diags.Report(diag::err_fe_remap_missing_from_file)
- << Remap->first;
- if (!InitOpts.RetainRemappedFileBuffers)
- delete Remap->second;
- continue;
- }
-
- // Override the contents of the "from" file with the contents of
- // the "to" file.
- SourceMgr.overrideFileContents(FromFile, Remap->second,
- InitOpts.RetainRemappedFileBuffers);
- }
-
- // Remap files in the source manager (with other files).
- for (PreprocessorOptions::const_remapped_file_iterator
- Remap = InitOpts.remapped_file_begin(),
- RemapEnd = InitOpts.remapped_file_end();
- Remap != RemapEnd;
- ++Remap) {
- // Find the file that we're mapping to.
- const FileEntry *ToFile = FileMgr.getFile(Remap->second);
- if (!ToFile) {
- Diags.Report(diag::err_fe_remap_missing_to_file)
- << Remap->first << Remap->second;
- continue;
- }
-
- // Create the file entry for the file that we're mapping from.
- const FileEntry *FromFile = FileMgr.getVirtualFile(Remap->first,
- ToFile->getSize(), 0);
- if (!FromFile) {
- Diags.Report(diag::err_fe_remap_missing_from_file)
- << Remap->first;
- continue;
- }
-
- // Override the contents of the "from" file with the contents of
- // the "to" file.
- SourceMgr.overrideFileContents(FromFile, ToFile);
- }
-
- SourceMgr.setOverridenFilesKeepOriginalName(
- InitOpts.RemappedFilesKeepOriginalName);
-}
-
/// InitializePreprocessor - Initialize the preprocessor getting it and the
/// environment ready to process a single file. This returns true on error.
///
void clang::InitializePreprocessor(Preprocessor &PP,
const PreprocessorOptions &InitOpts,
- const HeaderSearchOptions &HSOpts,
const FrontendOptions &FEOpts) {
const LangOptions &LangOpts = PP.getLangOpts();
std::string PredefineBuffer;
@@ -801,9 +847,6 @@
llvm::raw_string_ostream Predefines(PredefineBuffer);
MacroBuilder Builder(Predefines);
- InitializeFileRemapping(PP.getDiagnostics(), PP.getSourceManager(),
- PP.getFileManager(), InitOpts);
-
// Emit line markers for various builtin sections of the file. We don't do
// this in asm preprocessor mode, because "# 4" is not a line marker directive
// in this mode.
@@ -877,9 +920,4 @@
// Copy PredefinedBuffer into the Preprocessor.
PP.setPredefines(Predefines.str());
-
- // Initialize the header search object.
- ApplyHeaderSearchOptions(PP.getHeaderSearchInfo(), HSOpts,
- PP.getLangOpts(),
- PP.getTargetInfo().getTriple());
}
diff --git a/lib/Frontend/LogDiagnosticPrinter.cpp b/lib/Frontend/LogDiagnosticPrinter.cpp
index 917c13f..19539e0 100644
--- a/lib/Frontend/LogDiagnosticPrinter.cpp
+++ b/lib/Frontend/LogDiagnosticPrinter.cpp
@@ -10,11 +10,13 @@
#include "clang/Frontend/LogDiagnosticPrinter.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/FileManager.h"
+#include "clang/Basic/PlistSupport.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
+using namespace markup;
LogDiagnosticPrinter::LogDiagnosticPrinter(raw_ostream &os,
DiagnosticOptions *diags,
@@ -40,19 +42,34 @@
llvm_unreachable("Invalid DiagnosticsEngine level!");
}
-// Escape XML characters inside the raw string.
-static void emitString(llvm::raw_svector_ostream &OS, const StringRef Raw) {
- for (StringRef::iterator I = Raw.begin(), E = Raw.end(); I != E; ++I) {
- char c = *I;
- switch (c) {
- default: OS << c; break;
- case '&': OS << "&"; break;
- case '<': OS << "<"; break;
- case '>': OS << ">"; break;
- case '\'': OS << "'"; break;
- case '\"': OS << """; break;
- }
+void
+LogDiagnosticPrinter::EmitDiagEntry(llvm::raw_ostream &OS,
+ const LogDiagnosticPrinter::DiagEntry &DE) {
+ OS << " <dict>\n";
+ OS << " <key>level</key>\n"
+ << " ";
+ EmitString(OS, getLevelName(DE.DiagnosticLevel)) << '\n';
+ if (!DE.Filename.empty()) {
+ OS << " <key>filename</key>\n"
+ << " ";
+ EmitString(OS, DE.Filename) << '\n';
}
+ if (DE.Line != 0) {
+ OS << " <key>line</key>\n"
+ << " ";
+ EmitInteger(OS, DE.Line) << '\n';
+ }
+ if (DE.Column != 0) {
+ OS << " <key>column</key>\n"
+ << " ";
+ EmitInteger(OS, DE.Column) << '\n';
+ }
+ if (!DE.Message.empty()) {
+ OS << " <key>message</key>\n"
+ << " ";
+ EmitString(OS, DE.Message) << '\n';
+ }
+ OS << " </dict>\n";
}
void LogDiagnosticPrinter::EndSourceFile() {
@@ -72,48 +89,18 @@
OS << "<dict>\n";
if (!MainFilename.empty()) {
OS << " <key>main-file</key>\n"
- << " <string>";
- emitString(OS, MainFilename);
- OS << "</string>\n";
+ << " ";
+ EmitString(OS, MainFilename) << '\n';
}
if (!DwarfDebugFlags.empty()) {
OS << " <key>dwarf-debug-flags</key>\n"
- << " <string>";
- emitString(OS, DwarfDebugFlags);
- OS << "</string>\n";
+ << " ";
+ EmitString(OS, DwarfDebugFlags) << '\n';
}
OS << " <key>diagnostics</key>\n";
OS << " <array>\n";
- for (unsigned i = 0, e = Entries.size(); i != e; ++i) {
- DiagEntry &DE = Entries[i];
-
- OS << " <dict>\n";
- OS << " <key>level</key>\n"
- << " <string>";
- emitString(OS, getLevelName(DE.DiagnosticLevel));
- OS << "</string>\n";
- if (!DE.Filename.empty()) {
- OS << " <key>filename</key>\n"
- << " <string>";
- emitString(OS, DE.Filename);
- OS << "</string>\n";
- }
- if (DE.Line != 0) {
- OS << " <key>line</key>\n"
- << " <integer>" << DE.Line << "</integer>\n";
- }
- if (DE.Column != 0) {
- OS << " <key>column</key>\n"
- << " <integer>" << DE.Column << "</integer>\n";
- }
- if (!DE.Message.empty()) {
- OS << " <key>message</key>\n"
- << " <string>";
- emitString(OS, DE.Message);
- OS << "</string>\n";
- }
- OS << " </dict>\n";
- }
+ for (auto &DE : Entries)
+ EmitDiagEntry(OS, DE);
OS << " </array>\n";
OS << "</dict>\n";
diff --git a/lib/Frontend/ModuleDependencyCollector.cpp b/lib/Frontend/ModuleDependencyCollector.cpp
new file mode 100644
index 0000000..d30f921
--- /dev/null
+++ b/lib/Frontend/ModuleDependencyCollector.cpp
@@ -0,0 +1,116 @@
+//===--- ModuleDependencyCollector.cpp - Collect module dependencies ------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Collect the dependencies of a set of modules.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/Utils.h"
+#include "clang/Serialization/ASTReader.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
+
+namespace {
+/// Private implementation for ModuleDependencyCollector
+class ModuleDependencyListener : public ASTReaderListener {
+ ModuleDependencyCollector &Collector;
+
+ std::error_code copyToRoot(StringRef Src);
+public:
+ ModuleDependencyListener(ModuleDependencyCollector &Collector)
+ : Collector(Collector) {}
+ bool needsInputFileVisitation() override { return true; }
+ bool needsSystemInputFileVisitation() override { return true; }
+ bool visitInputFile(StringRef Filename, bool IsSystem,
+ bool IsOverridden) override;
+};
+}
+
+void ModuleDependencyCollector::attachToASTReader(ASTReader &R) {
+ R.addListener(new ModuleDependencyListener(*this));
+}
+
+void ModuleDependencyCollector::writeFileMap() {
+ if (Seen.empty())
+ return;
+
+ SmallString<256> Dest = getDest();
+ llvm::sys::path::append(Dest, "vfs.yaml");
+
+ std::string ErrorInfo;
+ llvm::raw_fd_ostream OS(Dest.c_str(), ErrorInfo, llvm::sys::fs::F_Text);
+ if (!ErrorInfo.empty()) {
+ setHasErrors();
+ return;
+ }
+ VFSWriter.write(OS);
+}
+
+/// Remove traversal (ie, . or ..) from the given absolute path.
+static void removePathTraversal(SmallVectorImpl<char> &Path) {
+ using namespace llvm::sys;
+ SmallVector<StringRef, 16> ComponentStack;
+ StringRef P(Path.data(), Path.size());
+
+ // Skip the root path, then look for traversal in the components.
+ StringRef Rel = path::relative_path(P);
+ for (StringRef C : llvm::make_range(path::begin(Rel), path::end(Rel))) {
+ if (C == ".")
+ continue;
+ if (C == "..") {
+ assert(ComponentStack.size() && "Path traverses out of parent");
+ ComponentStack.pop_back();
+ } else
+ ComponentStack.push_back(C);
+ }
+
+ // The stack is now the path without any directory traversal.
+ SmallString<256> Buffer = path::root_path(P);
+ for (StringRef C : ComponentStack)
+ path::append(Buffer, C);
+
+ // Put the result in Path.
+ Path.swap(Buffer);
+}
+
+std::error_code ModuleDependencyListener::copyToRoot(StringRef Src) {
+ using namespace llvm::sys;
+
+ // We need an absolute path to append to the root.
+ SmallString<256> AbsoluteSrc = Src;
+ fs::make_absolute(AbsoluteSrc);
+ removePathTraversal(AbsoluteSrc);
+
+ // Build the destination path.
+ SmallString<256> Dest = Collector.getDest();
+ path::append(Dest, path::relative_path(AbsoluteSrc));
+
+ // Copy the file into place.
+ if (std::error_code EC = fs::create_directories(path::parent_path(Dest),
+ /*IgnoreExisting=*/true))
+ return EC;
+ if (std::error_code EC = fs::copy_file(AbsoluteSrc.str(), Dest.str()))
+ return EC;
+ // Use the absolute path under the root for the file mapping.
+ Collector.addFileMapping(AbsoluteSrc.str(), Dest.str());
+ return std::error_code();
+}
+
+bool ModuleDependencyListener::visitInputFile(StringRef Filename, bool IsSystem,
+ bool IsOverridden) {
+ if (Collector.insertSeen(Filename))
+ if (copyToRoot(Filename))
+ Collector.setHasErrors();
+ return true;
+}
diff --git a/lib/Frontend/PrintPreprocessedOutput.cpp b/lib/Frontend/PrintPreprocessedOutput.cpp
index 8c32c24..4a6f8db 100644
--- a/lib/Frontend/PrintPreprocessedOutput.cpp
+++ b/lib/Frontend/PrintPreprocessedOutput.cpp
@@ -139,7 +139,7 @@
void PragmaDiagnosticPush(SourceLocation Loc, StringRef Namespace) override;
void PragmaDiagnosticPop(SourceLocation Loc, StringRef Namespace) override;
void PragmaDiagnostic(SourceLocation Loc, StringRef Namespace,
- diag::Mapping Map, StringRef Str) override;
+ diag::Severity Map, StringRef Str) override;
void PragmaWarning(SourceLocation Loc, StringRef WarningSpec,
ArrayRef<int> Ids) override;
void PragmaWarningPush(SourceLocation Loc, int Level) override;
@@ -439,26 +439,27 @@
setEmittedDirectiveOnThisLine();
}
-void PrintPPOutputPPCallbacks::
-PragmaDiagnostic(SourceLocation Loc, StringRef Namespace,
- diag::Mapping Map, StringRef Str) {
+void PrintPPOutputPPCallbacks::PragmaDiagnostic(SourceLocation Loc,
+ StringRef Namespace,
+ diag::Severity Map,
+ StringRef Str) {
startNewLineIfNeeded();
MoveToLine(Loc);
OS << "#pragma " << Namespace << " diagnostic ";
switch (Map) {
- case diag::MAP_REMARK:
+ case diag::Severity::Remark:
OS << "remark";
break;
- case diag::MAP_WARNING:
+ case diag::Severity::Warning:
OS << "warning";
break;
- case diag::MAP_ERROR:
+ case diag::Severity::Error:
OS << "error";
break;
- case diag::MAP_IGNORE:
+ case diag::Severity::Ignored:
OS << "ignored";
break;
- case diag::MAP_FATAL:
+ case diag::Severity::Fatal:
OS << "fatal";
break;
}
diff --git a/lib/Frontend/TextDiagnostic.cpp b/lib/Frontend/TextDiagnostic.cpp
index 4c90d01..dc67d68 100644
--- a/lib/Frontend/TextDiagnostic.cpp
+++ b/lib/Frontend/TextDiagnostic.cpp
@@ -689,8 +689,9 @@
printDiagnosticLevel(OS, Level, DiagOpts->ShowColors,
DiagOpts->CLFallbackMode);
- printDiagnosticMessage(OS, Level, Message,
- OS.tell() - StartOfLocationInfo,
+ printDiagnosticMessage(OS,
+ /*IsSupplemental*/ Level == DiagnosticsEngine::Note,
+ Message, OS.tell() - StartOfLocationInfo,
DiagOpts->MessageLength, DiagOpts->ShowColors);
}
@@ -735,24 +736,18 @@
OS.resetColor();
}
-/*static*/ void
-TextDiagnostic::printDiagnosticMessage(raw_ostream &OS,
- DiagnosticsEngine::Level Level,
- StringRef Message,
- unsigned CurrentColumn, unsigned Columns,
- bool ShowColors) {
+/*static*/
+void TextDiagnostic::printDiagnosticMessage(raw_ostream &OS,
+ bool IsSupplemental,
+ StringRef Message,
+ unsigned CurrentColumn,
+ unsigned Columns, bool ShowColors) {
bool Bold = false;
- if (ShowColors) {
- // Print warnings, errors and fatal errors in bold, no color
- switch (Level) {
- case DiagnosticsEngine::Warning:
- case DiagnosticsEngine::Error:
- case DiagnosticsEngine::Fatal:
- OS.changeColor(savedColor, true);
- Bold = true;
- break;
- default: break; //don't bold notes
- }
+ if (ShowColors && !IsSupplemental) {
+ // Print primary diagnostic messages in bold and without color, to visually
+ // indicate the transition from continuation notes and other output.
+ OS.changeColor(savedColor, true);
+ Bold = true;
}
if (Columns)
@@ -813,7 +808,7 @@
if (DiagOpts->getFormat() == DiagnosticOptions::Msvc) {
OS << ',';
// Visual Studio 2010 or earlier expects column number to be off by one
- if (LangOpts.MSCVersion && LangOpts.MSCVersion < 1700)
+ if (LangOpts.MSCVersion && LangOpts.MSCVersion < 170000000)
ColNo--;
} else
OS << ':';
@@ -875,12 +870,6 @@
OS << ' ';
}
-void TextDiagnostic::emitBasicNote(StringRef Message) {
- // FIXME: Emit this as a real note diagnostic.
- // FIXME: Format an actual diagnostic rather than a hard coded string.
- OS << "note: " << Message << "\n";
-}
-
void TextDiagnostic::emitIncludeLocation(SourceLocation Loc,
PresumedLoc PLoc,
const SourceManager &SM) {
@@ -1141,7 +1130,7 @@
std::string FixItInsertionLine = buildFixItInsertionLine(LineNo,
sourceColMap,
Hints, SM,
- DiagOpts.getPtr());
+ DiagOpts.get());
// If the source line is too long for our terminal, select only the
// "interesting" source region within that line.
diff --git a/lib/Frontend/TextDiagnosticPrinter.cpp b/lib/Frontend/TextDiagnosticPrinter.cpp
index d6df655..6271509 100644
--- a/lib/Frontend/TextDiagnosticPrinter.cpp
+++ b/lib/Frontend/TextDiagnosticPrinter.cpp
@@ -82,8 +82,8 @@
StringRef Opt = DiagnosticIDs::getWarningOptionForDiag(Info.getID());
if (!Opt.empty()) {
OS << (Started ? "," : " [")
- << (DiagnosticIDs::isRemark(Info.getID()) ? "-R" : "-W") << Opt;
- StringRef OptValue = Info.getDiags()->getFlagNameValue();
+ << (Level == DiagnosticsEngine::Remark ? "-R" : "-W") << Opt;
+ StringRef OptValue = Info.getDiags()->getFlagValue();
if (!OptValue.empty())
OS << "=" << OptValue;
Started = true;
diff --git a/lib/Frontend/VerifyDiagnosticConsumer.cpp b/lib/Frontend/VerifyDiagnosticConsumer.cpp
index 856b51d..b50950e 100644
--- a/lib/Frontend/VerifyDiagnosticConsumer.cpp
+++ b/lib/Frontend/VerifyDiagnosticConsumer.cpp
@@ -164,8 +164,9 @@
class StandardDirective : public Directive {
public:
StandardDirective(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc,
- StringRef Text, unsigned Min, unsigned Max)
- : Directive(DirectiveLoc, DiagnosticLoc, Text, Min, Max) { }
+ bool MatchAnyLine, StringRef Text, unsigned Min,
+ unsigned Max)
+ : Directive(DirectiveLoc, DiagnosticLoc, MatchAnyLine, Text, Min, Max) { }
bool isValid(std::string &Error) override {
// all strings are considered valid; even empty ones
@@ -182,8 +183,10 @@
class RegexDirective : public Directive {
public:
RegexDirective(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc,
- StringRef Text, unsigned Min, unsigned Max, StringRef RegexStr)
- : Directive(DirectiveLoc, DiagnosticLoc, Text, Min, Max), Regex(RegexStr) { }
+ bool MatchAnyLine, StringRef Text, unsigned Min, unsigned Max,
+ StringRef RegexStr)
+ : Directive(DirectiveLoc, DiagnosticLoc, MatchAnyLine, Text, Min, Max),
+ Regex(RegexStr) { }
bool isValid(std::string &Error) override {
if (Regex.isValid(Error))
@@ -371,6 +374,7 @@
// Next optional token: @
SourceLocation ExpectedLoc;
+ bool MatchAnyLine = false;
if (!PH.Next("@")) {
ExpectedLoc = Pos;
} else {
@@ -411,6 +415,10 @@
if (PH.Next(Line) && Line > 0)
ExpectedLoc = SM.translateFileLineCol(FE, Line, 1);
+ else if (PH.Next("*")) {
+ MatchAnyLine = true;
+ ExpectedLoc = SM.translateFileLineCol(FE, 1, 1);
+ }
}
if (ExpectedLoc.isInvalid()) {
@@ -495,7 +503,8 @@
// Construct new directive.
std::unique_ptr<Directive> D(
- Directive::create(RegexKind, Pos, ExpectedLoc, Text, Min, Max));
+ Directive::create(RegexKind, Pos, ExpectedLoc, MatchAnyLine, Text,
+ Min, Max));
std::string Error;
if (D->isValid(Error)) {
@@ -644,8 +653,11 @@
llvm::raw_svector_ostream OS(Fmt);
for (DirectiveList::iterator I = DL.begin(), E = DL.end(); I != E; ++I) {
Directive &D = **I;
- OS << "\n File " << SourceMgr.getFilename(D.DiagnosticLoc)
- << " Line " << SourceMgr.getPresumedLineNumber(D.DiagnosticLoc);
+ OS << "\n File " << SourceMgr.getFilename(D.DiagnosticLoc);
+ if (D.MatchAnyLine)
+ OS << " Line *";
+ else
+ OS << " Line " << SourceMgr.getPresumedLineNumber(D.DiagnosticLoc);
if (D.DirectiveLoc != D.DiagnosticLoc)
OS << " (directive at "
<< SourceMgr.getFilename(D.DirectiveLoc) << ':'
@@ -692,9 +704,11 @@
for (unsigned i = 0; i < D.Max; ++i) {
DiagList::iterator II, IE;
for (II = Right.begin(), IE = Right.end(); II != IE; ++II) {
- unsigned LineNo2 = SourceMgr.getPresumedLineNumber(II->first);
- if (LineNo1 != LineNo2)
- continue;
+ if (!D.MatchAnyLine) {
+ unsigned LineNo2 = SourceMgr.getPresumedLineNumber(II->first);
+ if (LineNo1 != LineNo2)
+ continue;
+ }
if (!IsFromSameFile(SourceMgr, D.DiagnosticLoc, II->first))
continue;
@@ -859,10 +873,11 @@
}
Directive *Directive::create(bool RegexKind, SourceLocation DirectiveLoc,
- SourceLocation DiagnosticLoc, StringRef Text,
- unsigned Min, unsigned Max) {
+ SourceLocation DiagnosticLoc, bool MatchAnyLine,
+ StringRef Text, unsigned Min, unsigned Max) {
if (!RegexKind)
- return new StandardDirective(DirectiveLoc, DiagnosticLoc, Text, Min, Max);
+ return new StandardDirective(DirectiveLoc, DiagnosticLoc, MatchAnyLine,
+ Text, Min, Max);
// Parse the directive into a regular expression.
std::string RegexStr;
@@ -887,6 +902,6 @@
}
}
- return new RegexDirective(DirectiveLoc, DiagnosticLoc, Text, Min, Max,
- RegexStr);
+ return new RegexDirective(DirectiveLoc, DiagnosticLoc, MatchAnyLine, Text,
+ Min, Max, RegexStr);
}