aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Frontend
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2012-12-02 13:20:44 +0000
committerDimitry Andric <dim@FreeBSD.org>2012-12-02 13:20:44 +0000
commit13cc256e404620c1de0cbcc4e43ce1e2dbbc4898 (patch)
tree2732d02d7d51218d6eed98ac7fcfc5b8794896b5 /lib/Frontend
parent657bc3d9848e3be92029b2416031340988cd0111 (diff)
downloadsrc-13cc256e404620c1de0cbcc4e43ce1e2dbbc4898.tar.gz
src-13cc256e404620c1de0cbcc4e43ce1e2dbbc4898.zip
Vendor import of clang release_32 branch r168974 (effectively, 3.2 RC2):vendor/clang/clang-release_32-r168974
Notes
Notes: svn path=/vendor/clang/dist/; revision=243791 svn path=/vendor/clang/clang-release_32-r168974/; revision=243792; tag=vendor/clang/clang-release_32-r168974
Diffstat (limited to 'lib/Frontend')
-rw-r--r--lib/Frontend/ASTConsumers.cpp5
-rw-r--r--lib/Frontend/ASTMerge.cpp5
-rw-r--r--lib/Frontend/ASTUnit.cpp306
-rw-r--r--lib/Frontend/ChainedDiagnosticConsumer.cpp2
-rw-r--r--lib/Frontend/ChainedIncludesSource.cpp22
-rw-r--r--lib/Frontend/CompilerInstance.cpp139
-rw-r--r--lib/Frontend/CompilerInvocation.cpp1261
-rw-r--r--lib/Frontend/CreateInvocationFromCommandLine.cpp11
-rw-r--r--lib/Frontend/DependencyFile.cpp10
-rw-r--r--lib/Frontend/DependencyGraph.cpp10
-rw-r--r--lib/Frontend/DiagnosticRenderer.cpp94
-rw-r--r--lib/Frontend/FrontendAction.cpp76
-rw-r--r--lib/Frontend/FrontendActions.cpp133
-rw-r--r--lib/Frontend/InitHeaderSearch.cpp6
-rw-r--r--lib/Frontend/InitPreprocessor.cpp86
-rw-r--r--lib/Frontend/LogDiagnosticPrinter.cpp7
-rw-r--r--lib/Frontend/PrintPreprocessedOutput.cpp8
-rw-r--r--lib/Frontend/SerializedDiagnosticPrinter.cpp232
-rw-r--r--lib/Frontend/TextDiagnostic.cpp203
-rw-r--r--lib/Frontend/TextDiagnosticPrinter.cpp10
-rw-r--r--lib/Frontend/VerifyDiagnosticConsumer.cpp213
-rw-r--r--lib/Frontend/Warnings.cpp5
22 files changed, 1211 insertions, 1633 deletions
diff --git a/lib/Frontend/ASTConsumers.cpp b/lib/Frontend/ASTConsumers.cpp
index 0f0d8352046d..882d400c4292 100644
--- a/lib/Frontend/ASTConsumers.cpp
+++ b/lib/Frontend/ASTConsumers.cpp
@@ -58,7 +58,7 @@ namespace {
bool shouldWalkTypesOfTypeLocs() const { return false; }
bool TraverseDecl(Decl *D) {
- if (filterMatches(D)) {
+ if (D != NULL && filterMatches(D)) {
Out.changeColor(llvm::raw_ostream::BLUE) <<
(Dump ? "Dumping " : "Printing ") << getName(D) << ":\n";
Out.resetColor();
@@ -66,6 +66,7 @@ namespace {
D->dump(Out);
else
D->print(Out, /*Indentation=*/0, /*PrintInstantiation=*/true);
+ Out << "\n";
// Don't traverse child nodes to avoid output duplication.
return true;
}
@@ -89,8 +90,6 @@ namespace {
class ASTDeclNodeLister : public ASTConsumer,
public RecursiveASTVisitor<ASTDeclNodeLister> {
- typedef RecursiveASTVisitor<ASTDeclNodeLister> base;
-
public:
ASTDeclNodeLister(raw_ostream *Out = NULL)
: Out(Out ? *Out : llvm::outs()) {}
diff --git a/lib/Frontend/ASTMerge.cpp b/lib/Frontend/ASTMerge.cpp
index 9feb3de4f0db..31b1df43df79 100644
--- a/lib/Frontend/ASTMerge.cpp
+++ b/lib/Frontend/ASTMerge.cpp
@@ -41,8 +41,9 @@ void ASTMergeAction::ExecuteAction() {
DiagIDs(CI.getDiagnostics().getDiagnosticIDs());
for (unsigned I = 0, N = ASTFiles.size(); I != N; ++I) {
IntrusiveRefCntPtr<DiagnosticsEngine>
- Diags(new DiagnosticsEngine(DiagIDs, CI.getDiagnostics().getClient(),
- /*ShouldOwnClient=*/false));
+ Diags(new DiagnosticsEngine(DiagIDs, &CI.getDiagnosticOpts(),
+ CI.getDiagnostics().getClient(),
+ /*ShouldOwnClient=*/false));
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 42a67720c353..5576854a7d8b 100644
--- a/lib/Frontend/ASTUnit.cpp
+++ b/lib/Frontend/ASTUnit.cpp
@@ -27,6 +27,7 @@
#include "clang/Serialization/ASTWriter.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/Diagnostic.h"
@@ -180,6 +181,14 @@ void OnDiskData::Cleanup() {
CleanPreambleFile();
}
+struct ASTUnit::ASTWriterData {
+ SmallString<128> Buffer;
+ llvm::BitstreamWriter Stream;
+ ASTWriter Writer;
+
+ ASTWriterData() : Stream(Buffer), Writer(Stream) { }
+};
+
void ASTUnit::clearFileLevelDecls() {
for (FileDeclsTy::iterator
I = FileDecls.begin(), E = FileDecls.end(); I != E; ++I)
@@ -495,8 +504,8 @@ class ASTInfoCollector : public ASTReaderListener {
ASTContext &Context;
LangOptions &LangOpt;
HeaderSearch &HSI;
+ IntrusiveRefCntPtr<TargetOptions> &TargetOpts;
IntrusiveRefCntPtr<TargetInfo> &Target;
- std::string &Predefines;
unsigned &Counter;
unsigned NumHeaderInfos;
@@ -504,54 +513,38 @@ class ASTInfoCollector : public ASTReaderListener {
bool InitializedLanguage;
public:
ASTInfoCollector(Preprocessor &PP, ASTContext &Context, LangOptions &LangOpt,
- HeaderSearch &HSI,
+ HeaderSearch &HSI,
+ IntrusiveRefCntPtr<TargetOptions> &TargetOpts,
IntrusiveRefCntPtr<TargetInfo> &Target,
- std::string &Predefines,
unsigned &Counter)
- : PP(PP), Context(Context), LangOpt(LangOpt), HSI(HSI), Target(Target),
- Predefines(Predefines), Counter(Counter), NumHeaderInfos(0),
+ : PP(PP), Context(Context), LangOpt(LangOpt), HSI(HSI),
+ TargetOpts(TargetOpts), Target(Target),
+ Counter(Counter), NumHeaderInfos(0),
InitializedLanguage(false) {}
- virtual bool ReadLanguageOptions(const LangOptions &LangOpts) {
+ virtual bool ReadLanguageOptions(const LangOptions &LangOpts,
+ bool Complain) {
if (InitializedLanguage)
return false;
LangOpt = LangOpts;
-
- // Initialize the preprocessor.
- PP.Initialize(*Target);
-
- // Initialize the ASTContext
- Context.InitBuiltinTypes(*Target);
-
InitializedLanguage = true;
+
+ updated();
return false;
}
- virtual bool ReadTargetTriple(StringRef Triple) {
+ virtual bool ReadTargetOptions(const TargetOptions &TargetOpts,
+ bool Complain) {
// If we've already initialized the target, don't do it again.
if (Target)
return false;
- // FIXME: This is broken, we should store the TargetOptions in the AST file.
- TargetOptions TargetOpts;
- TargetOpts.ABI = "";
- TargetOpts.CXXABI = "";
- TargetOpts.CPU = "";
- TargetOpts.Features.clear();
- TargetOpts.Triple = Triple;
- Target = TargetInfo::CreateTargetInfo(PP.getDiagnostics(), TargetOpts);
- return false;
- }
+ this->TargetOpts = new TargetOptions(TargetOpts);
+ Target = TargetInfo::CreateTargetInfo(PP.getDiagnostics(),
+ *this->TargetOpts);
- virtual bool ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers,
- StringRef OriginalFileName,
- std::string &SuggestedPredefines,
- FileManager &FileMgr) {
- Predefines = Buffers[0].Data;
- for (unsigned I = 1, N = Buffers.size(); I != N; ++I) {
- Predefines += Buffers[I].Data;
- }
+ updated();
return false;
}
@@ -559,9 +552,27 @@ public:
HSI.setHeaderFileInfoForUID(HFI, NumHeaderInfos++);
}
- virtual void ReadCounter(unsigned Value) {
+ virtual void ReadCounter(const serialization::ModuleFile &M, unsigned Value) {
Counter = Value;
}
+
+private:
+ void updated() {
+ if (!Target || !InitializedLanguage)
+ return;
+
+ // Inform the target of the language options.
+ //
+ // FIXME: We shouldn't need to do this, the target should be immutable once
+ // created. This complexity should be lifted elsewhere.
+ Target->setForcedLangOptions(LangOpt);
+
+ // Initialize the preprocessor.
+ PP.Initialize(*Target);
+
+ // Initialize the ASTContext
+ Context.InitBuiltinTypes(*Target);
+ }
};
class StoredDiagnosticConsumer : public DiagnosticConsumer {
@@ -621,8 +632,10 @@ void StoredDiagnosticConsumer::HandleDiagnostic(DiagnosticsEngine::Level Level,
StoredDiags.push_back(StoredDiagnostic(Level, Info));
}
-const std::string &ASTUnit::getOriginalSourceFileName() {
- return OriginalSourceFile;
+ASTDeserializationListener *ASTUnit::getDeserializationListener() {
+ if (WriterData)
+ return &WriterData->Writer;
+ return 0;
}
llvm::MemoryBuffer *ASTUnit::getBufferForFile(StringRef Filename,
@@ -638,11 +651,11 @@ void ASTUnit::ConfigureDiags(IntrusiveRefCntPtr<DiagnosticsEngine> &Diags,
if (!Diags.getPtr()) {
// No diagnostics engine was provided, so create our own diagnostics object
// with the default options.
- DiagnosticOptions DiagOpts;
DiagnosticConsumer *Client = 0;
if (CaptureDiagnostics)
Client = new StoredDiagnosticConsumer(AST.StoredDiagnostics);
- Diags = CompilerInstance::createDiagnostics(DiagOpts, ArgEnd-ArgBegin,
+ Diags = CompilerInstance::createDiagnostics(new DiagnosticOptions(),
+ ArgEnd-ArgBegin,
ArgBegin, Client,
/*ShouldOwnClient=*/true,
/*ShouldCloneClient=*/false);
@@ -679,7 +692,10 @@ ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename,
AST->SourceMgr = new SourceManager(AST->getDiagnostics(),
AST->getFileManager(),
UserFilesAreVolatile);
- AST->HeaderInfo.reset(new HeaderSearch(AST->getFileManager(),
+ AST->HSOpts = new HeaderSearchOptions();
+
+ AST->HeaderInfo.reset(new HeaderSearch(AST->HSOpts,
+ AST->getFileManager(),
AST->getDiagnostics(),
AST->ASTFileLangOpts,
/*Target=*/0));
@@ -734,12 +750,12 @@ ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename,
// Gather Info for preprocessor construction later on.
HeaderSearch &HeaderInfo = *AST->HeaderInfo.get();
- std::string Predefines;
unsigned Counter;
OwningPtr<ASTReader> Reader;
- AST->PP = new Preprocessor(AST->getDiagnostics(), AST->ASTFileLangOpts,
+ AST->PP = new Preprocessor(new PreprocessorOptions(),
+ AST->getDiagnostics(), AST->ASTFileLangOpts,
/*Target=*/0, AST->getSourceManager(), HeaderInfo,
*AST,
/*IILookup=*/0,
@@ -757,10 +773,12 @@ ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename,
/*DelayInitialization=*/true);
ASTContext &Context = *AST->Ctx;
+ bool disableValid = false;
+ if (::getenv("LIBCLANG_DISABLE_PCH_VALIDATION"))
+ disableValid = true;
Reader.reset(new ASTReader(PP, Context,
/*isysroot=*/"",
- /*DisableValidation=*/false,
- /*DisableStatCache=*/false,
+ /*DisableValidation=*/disableValid,
AllowPCHWithCompilerErrors));
// Recover resources if we crash before exiting this method.
@@ -769,21 +787,25 @@ ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename,
Reader->setListener(new ASTInfoCollector(*AST->PP, Context,
AST->ASTFileLangOpts, HeaderInfo,
- AST->Target, Predefines, Counter));
+ AST->TargetOpts, AST->Target,
+ Counter));
- switch (Reader->ReadAST(Filename, serialization::MK_MainFile)) {
+ switch (Reader->ReadAST(Filename, serialization::MK_MainFile,
+ ASTReader::ARR_None)) {
case ASTReader::Success:
break;
case ASTReader::Failure:
- case ASTReader::IgnorePCH:
+ case ASTReader::OutOfDate:
+ case ASTReader::VersionMismatch:
+ case ASTReader::ConfigurationMismatch:
+ case ASTReader::HadErrors:
AST->getDiagnostics().Report(diag::err_fe_unable_to_load_pch);
return NULL;
}
AST->OriginalSourceFile = Reader->getOriginalSourceFile();
- PP.setPredefines(Reader->getSuggestedPredefines());
PP.setCounterValue(Counter);
// Attach the AST reader to the AST context as an external AST
@@ -897,6 +919,10 @@ public:
for (DeclGroupRef::iterator it = D.begin(), ie = D.end(); it != ie; ++it)
handleTopLevelDecl(*it);
}
+
+ virtual ASTDeserializationListener *GetASTDeserializationListener() {
+ return Unit.getDeserializationListener();
+ }
};
class TopLevelDeclTrackerAction : public ASTFrontendAction {
@@ -1047,14 +1073,13 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) {
CCInvocation(new CompilerInvocation(*Invocation));
Clang->setInvocation(CCInvocation.getPtr());
- OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].File;
+ OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].getFile();
// Set up diagnostics, capturing any diagnostics that would
// otherwise be dropped.
Clang->setDiagnostics(&getDiagnostics());
// Create the target instance.
- Clang->getTargetOpts().Features = TargetFeatures;
Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(),
Clang->getTargetOpts()));
if (!Clang->hasTarget()) {
@@ -1070,9 +1095,9 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) {
assert(Clang->getFrontendOpts().Inputs.size() == 1 &&
"Invocation must have exactly one source file!");
- assert(Clang->getFrontendOpts().Inputs[0].Kind != IK_AST &&
+ assert(Clang->getFrontendOpts().Inputs[0].getKind() != IK_AST &&
"FIXME: AST inputs not yet supported here!");
- assert(Clang->getFrontendOpts().Inputs[0].Kind != IK_LLVM_IR &&
+ assert(Clang->getFrontendOpts().Inputs[0].getKind() != IK_LLVM_IR &&
"IR inputs not support here!");
// Configure the various subsystems.
@@ -1217,7 +1242,7 @@ ASTUnit::ComputePreamble(CompilerInvocation &Invocation,
// command line (to another file) or directly through the compiler invocation
// (to a memory buffer).
llvm::MemoryBuffer *Buffer = 0;
- llvm::sys::PathWithStatus MainFilePath(FrontendOpts.Inputs[0].File);
+ llvm::sys::PathWithStatus MainFilePath(FrontendOpts.Inputs[0].getFile());
if (const llvm::sys::FileStatus *MainFileStatus = MainFilePath.getFileStatus()) {
// Check whether there is a file-file remapping of the main file
for (PreprocessorOptions::remapped_file_iterator
@@ -1267,7 +1292,7 @@ ASTUnit::ComputePreamble(CompilerInvocation &Invocation,
// If the main source file was not remapped, load it now.
if (!Buffer) {
- Buffer = getBufferForFile(FrontendOpts.Inputs[0].File);
+ Buffer = getBufferForFile(FrontendOpts.Inputs[0].getFile());
if (!Buffer)
return std::make_pair((llvm::MemoryBuffer*)0, std::make_pair(0, true));
@@ -1429,7 +1454,7 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble(
// buffer size we reserved when creating the preamble.
return CreatePaddedMainFileBuffer(NewPreamble.first,
PreambleReservedSize,
- FrontendOpts.Inputs[0].File);
+ FrontendOpts.Inputs[0].getFile());
}
}
@@ -1482,7 +1507,7 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble(
// Save the preamble text for later; we'll need to compare against it for
// subsequent reparses.
- StringRef MainFilename = PreambleInvocation->getFrontendOpts().Inputs[0].File;
+ StringRef MainFilename = PreambleInvocation->getFrontendOpts().Inputs[0].getFile();
Preamble.assign(FileMgr->getFile(MainFilename),
NewPreamble.first->getBufferStart(),
NewPreamble.first->getBufferStart()
@@ -1492,7 +1517,7 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble(
delete PreambleBuffer;
PreambleBuffer
= llvm::MemoryBuffer::getNewUninitMemBuffer(PreambleReservedSize,
- FrontendOpts.Inputs[0].File);
+ FrontendOpts.Inputs[0].getFile());
memcpy(const_cast<char*>(PreambleBuffer->getBufferStart()),
NewPreamble.first->getBufferStart(), Preamble.size());
memset(const_cast<char*>(PreambleBuffer->getBufferStart()) + Preamble.size(),
@@ -1500,7 +1525,7 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble(
const_cast<char*>(PreambleBuffer->getBufferEnd())[-1] = '\n';
// Remap the main source file to the preamble buffer.
- llvm::sys::PathWithStatus MainFilePath(FrontendOpts.Inputs[0].File);
+ llvm::sys::PathWithStatus MainFilePath(FrontendOpts.Inputs[0].getFile());
PreprocessorOpts.addRemappedFile(MainFilePath.str(), PreambleBuffer);
// Tell the compiler invocation to generate a temporary precompiled header.
@@ -1518,15 +1543,14 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble(
CICleanup(Clang.get());
Clang->setInvocation(&*PreambleInvocation);
- OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].File;
+ OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].getFile();
// Set up diagnostics, capturing all of the diagnostics produced.
Clang->setDiagnostics(&getDiagnostics());
// Create the target instance.
- Clang->getTargetOpts().Features = TargetFeatures;
Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(),
- Clang->getTargetOpts()));
+ Clang->getTargetOpts()));
if (!Clang->hasTarget()) {
llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk();
Preamble.clear();
@@ -1544,9 +1568,9 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble(
assert(Clang->getFrontendOpts().Inputs.size() == 1 &&
"Invocation must have exactly one source file!");
- assert(Clang->getFrontendOpts().Inputs[0].Kind != IK_AST &&
+ assert(Clang->getFrontendOpts().Inputs[0].getKind() != IK_AST &&
"FIXME: AST inputs not yet supported here!");
- assert(Clang->getFrontendOpts().Inputs[0].Kind != IK_LLVM_IR &&
+ assert(Clang->getFrontendOpts().Inputs[0].getKind() != IK_LLVM_IR &&
"IR inputs not support here!");
// Clear out old caches and data.
@@ -1633,7 +1657,7 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble(
return CreatePaddedMainFileBuffer(NewPreamble.first,
PreambleReservedSize,
- FrontendOpts.Inputs[0].File);
+ FrontendOpts.Inputs[0].getFile());
}
void ASTUnit::RealizeTopLevelDeclsFromPreamble() {
@@ -1664,7 +1688,7 @@ void ASTUnit::transferASTDataFromCompilerInstance(CompilerInstance &CI) {
}
StringRef ASTUnit::getMainFileName() const {
- return Invocation->getFrontendOpts().Inputs[0].File;
+ return Invocation->getFrontendOpts().Inputs[0].getFile();
}
ASTUnit *ASTUnit::create(CompilerInvocation *CI,
@@ -1733,9 +1757,6 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(CompilerInvocation *CI,
CI->getFrontendOpts().DisableFree = false;
ProcessWarningOptions(AST->getDiagnostics(), CI->getDiagnosticOpts());
- // Save the target features.
- AST->TargetFeatures = CI->getTargetOpts().Features;
-
// Create the compiler instance to use for building the AST.
OwningPtr<CompilerInstance> Clang(new CompilerInstance());
@@ -1744,14 +1765,13 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(CompilerInvocation *CI,
CICleanup(Clang.get());
Clang->setInvocation(CI);
- AST->OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].File;
+ AST->OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].getFile();
// Set up diagnostics, capturing any diagnostics that would
// otherwise be dropped.
Clang->setDiagnostics(&AST->getDiagnostics());
// Create the target instance.
- Clang->getTargetOpts().Features = AST->TargetFeatures;
Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(),
Clang->getTargetOpts()));
if (!Clang->hasTarget())
@@ -1765,9 +1785,9 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(CompilerInvocation *CI,
assert(Clang->getFrontendOpts().Inputs.size() == 1 &&
"Invocation must have exactly one source file!");
- assert(Clang->getFrontendOpts().Inputs[0].Kind != IK_AST &&
+ assert(Clang->getFrontendOpts().Inputs[0].getKind() != IK_AST &&
"FIXME: AST inputs not yet supported here!");
- assert(Clang->getFrontendOpts().Inputs[0].Kind != IK_LLVM_IR &&
+ assert(Clang->getFrontendOpts().Inputs[0].getKind() != IK_LLVM_IR &&
"IR inputs not supported here!");
// Configure the various subsystems.
@@ -1840,9 +1860,6 @@ bool ASTUnit::LoadFromCompilerInvocation(bool PrecompilePreamble) {
Invocation->getFrontendOpts().DisableFree = false;
ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts());
- // Save the target features.
- TargetFeatures = Invocation->getTargetOpts().Features;
-
llvm::MemoryBuffer *OverrideMainBuffer = 0;
if (PrecompilePreamble) {
PreambleRebuildCounter = 2;
@@ -1909,12 +1926,13 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin,
bool AllowPCHWithCompilerErrors,
bool SkipFunctionBodies,
bool UserFilesAreVolatile,
+ bool ForSerialization,
OwningPtr<ASTUnit> *ErrAST) {
if (!Diags.getPtr()) {
// No diagnostics engine was provided, so create our own diagnostics object
// with the default options.
- DiagnosticOptions DiagOpts;
- Diags = CompilerInstance::createDiagnostics(DiagOpts, ArgEnd - ArgBegin,
+ Diags = CompilerInstance::createDiagnostics(new DiagnosticOptions(),
+ ArgEnd - ArgBegin,
ArgBegin);
}
@@ -1972,6 +1990,8 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin,
AST->NumStoredDiagnosticsFromDriver = StoredDiagnostics.size();
AST->StoredDiagnostics.swap(StoredDiagnostics);
AST->Invocation = CI;
+ if (ForSerialization)
+ AST->WriterData.reset(new ASTWriterData());
CI = 0; // Zero out now to ease cleanup during crash recovery.
// Recover resources if we crash before exiting this method.
@@ -2002,7 +2022,6 @@ bool ASTUnit::Reparse(RemappedFile *RemappedFiles, unsigned NumRemappedFiles) {
// Remap files.
PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts();
- PPOpts.DisableStatCache = true;
for (PreprocessorOptions::remapped_file_buffer_iterator
R = PPOpts.remapped_file_buffer_begin(),
REnd = PPOpts.remapped_file_buffer_end();
@@ -2238,7 +2257,6 @@ void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S,
// Adjust priority based on similar type classes.
unsigned Priority = C->Priority;
- CXCursorKind CursorKind = C->Kind;
CodeCompletionString *Completion = C->Completion;
if (!Context.getPreferredType().isNull()) {
if (C->Kind == CXCursor_MacroDefinition) {
@@ -2272,12 +2290,11 @@ void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S,
CodeCompletionBuilder Builder(getAllocator(), getCodeCompletionTUInfo(),
CCP_CodePattern, C->Availability);
Builder.AddTypedTextChunk(C->Completion->getTypedText());
- CursorKind = CXCursor_NotImplemented;
Priority = CCP_CodePattern;
Completion = Builder.TakeString();
}
- AllResults.push_back(Result(Completion, Priority, CursorKind,
+ AllResults.push_back(Result(Completion, Priority, C->Kind,
C->Availability));
}
@@ -2341,7 +2358,7 @@ void ASTUnit::CodeComplete(StringRef File, unsigned Line, unsigned Column,
CICleanup(Clang.get());
Clang->setInvocation(&*CCInvocation);
- OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].File;
+ OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].getFile();
// Set up diagnostics, capturing any diagnostics produced.
Clang->setDiagnostics(&Diag);
@@ -2351,7 +2368,6 @@ void ASTUnit::CodeComplete(StringRef File, unsigned Line, unsigned Column,
StoredDiagnostics);
// Create the target instance.
- Clang->getTargetOpts().Features = TargetFeatures;
Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(),
Clang->getTargetOpts()));
if (!Clang->hasTarget()) {
@@ -2367,9 +2383,9 @@ void ASTUnit::CodeComplete(StringRef File, unsigned Line, unsigned Column,
assert(Clang->getFrontendOpts().Inputs.size() == 1 &&
"Invocation must have exactly one source file!");
- assert(Clang->getFrontendOpts().Inputs[0].Kind != IK_AST &&
+ assert(Clang->getFrontendOpts().Inputs[0].getKind() != IK_AST &&
"FIXME: AST inputs not yet supported here!");
- assert(Clang->getFrontendOpts().Inputs[0].Kind != IK_LLVM_IR &&
+ assert(Clang->getFrontendOpts().Inputs[0].getKind() != IK_LLVM_IR &&
"IR inputs not support here!");
@@ -2398,8 +2414,6 @@ void ASTUnit::CodeComplete(StringRef File, unsigned Line, unsigned Column,
= new AugmentedCodeCompleteConsumer(*this, Consumer, CodeCompleteOpts);
Clang->setCodeCompletionConsumer(AugmentedConsumer);
- Clang->getFrontendOpts().SkipFunctionBodies = true;
-
// If we have a precompiled preamble, try to use it. We only allow
// the use of the precompiled preamble if we're if the completion
// point is within the main file, after the end of the precompiled
@@ -2420,7 +2434,6 @@ void ASTUnit::CodeComplete(StringRef File, unsigned Line, unsigned Column,
// If the main file has been overridden due to the use of a preamble,
// make that override happen and introduce the preamble.
- PreprocessorOpts.DisableStatCache = true;
StoredDiagnostics.insert(StoredDiagnostics.end(),
stored_diag_begin(),
stored_diag_afterDriver_begin());
@@ -2438,8 +2451,9 @@ void ASTUnit::CodeComplete(StringRef File, unsigned Line, unsigned Column,
PreprocessorOpts.PrecompiledPreambleBytes.second = false;
}
- // Disable the preprocessing record
- PreprocessorOpts.DetailedRecord = false;
+ // Disable the preprocessing record if modules are not enabled.
+ if (!Clang->getLangOpts().Modules)
+ PreprocessorOpts.DetailedRecord = false;
OwningPtr<SyntaxOnlyAction> Act;
Act.reset(new SyntaxOnlyAction);
@@ -2457,7 +2471,7 @@ void ASTUnit::CodeComplete(StringRef File, unsigned Line, unsigned Column,
checkAndSanitizeDiags(StoredDiagnostics, getSourceManager());
}
-CXSaveError ASTUnit::Save(StringRef File) {
+bool ASTUnit::Save(StringRef File) {
// Write to a temporary file and later rename it to the actual file, to avoid
// possible race conditions.
SmallString<128> TempPath;
@@ -2466,7 +2480,7 @@ CXSaveError ASTUnit::Save(StringRef File) {
int fd;
if (llvm::sys::fs::unique_file(TempPath.str(), fd, TempPath,
/*makeAbsolute=*/false))
- return CXSaveError_Unknown;
+ return true;
// FIXME: Can we somehow regenerate the stat cache here, or do we need to
// unconditionally create a stat cache when we parse the file?
@@ -2476,32 +2490,43 @@ CXSaveError ASTUnit::Save(StringRef File) {
Out.close();
if (Out.has_error()) {
Out.clear_error();
- return CXSaveError_Unknown;
+ return true;
}
if (llvm::sys::fs::rename(TempPath.str(), File)) {
bool exists;
llvm::sys::fs::remove(TempPath.str(), exists);
- return CXSaveError_Unknown;
+ return true;
}
- return CXSaveError_None;
+ return false;
+}
+
+static bool serializeUnit(ASTWriter &Writer,
+ SmallVectorImpl<char> &Buffer,
+ Sema &S,
+ bool hasErrors,
+ raw_ostream &OS) {
+ Writer.WriteAST(S, std::string(), 0, "", hasErrors);
+
+ // Write the generated bitstream to "Out".
+ if (!Buffer.empty())
+ OS.write(Buffer.data(), Buffer.size());
+
+ return false;
}
bool ASTUnit::serialize(raw_ostream &OS) {
bool hasErrors = getDiagnostics().hasErrorOccurred();
+ if (WriterData)
+ return serializeUnit(WriterData->Writer, WriterData->Buffer,
+ getSema(), hasErrors, OS);
+
SmallString<128> Buffer;
llvm::BitstreamWriter Stream(Buffer);
ASTWriter Writer(Stream);
- // FIXME: Handle modules
- Writer.WriteAST(getSema(), 0, std::string(), 0, "", hasErrors);
-
- // Write the generated bitstream to "Out".
- if (!Buffer.empty())
- OS.write((char *)&Buffer.front(), Buffer.size());
-
- return false;
+ return serializeUnit(Writer, Buffer, getSema(), hasErrors, OS);
}
typedef ContinuousRangeMap<unsigned, int, 2> SLocRemap;
@@ -2761,6 +2786,85 @@ SourceLocation ASTUnit::getStartOfMainFileID() {
return SourceMgr->getLocForStartOfFile(FID);
}
+std::pair<PreprocessingRecord::iterator, PreprocessingRecord::iterator>
+ASTUnit::getLocalPreprocessingEntities() const {
+ if (isMainFileAST()) {
+ serialization::ModuleFile &
+ Mod = Reader->getModuleManager().getPrimaryModule();
+ return Reader->getModulePreprocessedEntities(Mod);
+ }
+
+ if (PreprocessingRecord *PPRec = PP->getPreprocessingRecord())
+ return std::make_pair(PPRec->local_begin(), PPRec->local_end());
+
+ return std::make_pair(PreprocessingRecord::iterator(),
+ PreprocessingRecord::iterator());
+}
+
+bool ASTUnit::visitLocalTopLevelDecls(void *context, DeclVisitorFn Fn) {
+ if (isMainFileAST()) {
+ serialization::ModuleFile &
+ Mod = Reader->getModuleManager().getPrimaryModule();
+ ASTReader::ModuleDeclIterator MDI, MDE;
+ llvm::tie(MDI, MDE) = Reader->getModuleFileLevelDecls(Mod);
+ for (; MDI != MDE; ++MDI) {
+ if (!Fn(context, *MDI))
+ return false;
+ }
+
+ return true;
+ }
+
+ for (ASTUnit::top_level_iterator TL = top_level_begin(),
+ TLEnd = top_level_end();
+ TL != TLEnd; ++TL) {
+ if (!Fn(context, *TL))
+ return false;
+ }
+
+ return true;
+}
+
+namespace {
+struct PCHLocatorInfo {
+ serialization::ModuleFile *Mod;
+ PCHLocatorInfo() : Mod(0) {}
+};
+}
+
+static bool PCHLocator(serialization::ModuleFile &M, void *UserData) {
+ PCHLocatorInfo &Info = *static_cast<PCHLocatorInfo*>(UserData);
+ switch (M.Kind) {
+ case serialization::MK_Module:
+ return true; // skip dependencies.
+ case serialization::MK_PCH:
+ Info.Mod = &M;
+ return true; // found it.
+ case serialization::MK_Preamble:
+ return false; // look in dependencies.
+ case serialization::MK_MainFile:
+ return false; // look in dependencies.
+ }
+
+ return true;
+}
+
+const FileEntry *ASTUnit::getPCHFile() {
+ if (!Reader)
+ return 0;
+
+ PCHLocatorInfo Info;
+ Reader->getModuleManager().visit(PCHLocator, &Info);
+ if (Info.Mod)
+ return Info.Mod->File;
+
+ return 0;
+}
+
+bool ASTUnit::isModuleFile() {
+ return isMainFileAST() && !ASTFileLangOpts.CurrentModule.empty();
+}
+
void ASTUnit::PreambleData::countLines() const {
NumLines = 0;
if (empty())
diff --git a/lib/Frontend/ChainedDiagnosticConsumer.cpp b/lib/Frontend/ChainedDiagnosticConsumer.cpp
index c1d3db873f1f..d77fd180ea0d 100644
--- a/lib/Frontend/ChainedDiagnosticConsumer.cpp
+++ b/lib/Frontend/ChainedDiagnosticConsumer.cpp
@@ -1,4 +1,4 @@
-//===- ChainedDiagnosticConsumer.cpp - Chain Diagnostic Clients -*- C++ -*-===//
+//===- ChainedDiagnosticConsumer.cpp - Chain Diagnostic Clients -----------===//
//
// The LLVM Compiler Infrastructure
//
diff --git a/lib/Frontend/ChainedIncludesSource.cpp b/lib/Frontend/ChainedIncludesSource.cpp
index dbb06bd23cdc..2d586400ec46 100644
--- a/lib/Frontend/ChainedIncludesSource.cpp
+++ b/lib/Frontend/ChainedIncludesSource.cpp
@@ -39,14 +39,18 @@ static ASTReader *createASTReader(CompilerInstance &CI,
Reader->addInMemoryBuffer(sr, memBufs[ti]);
}
Reader->setDeserializationListener(deserialListener);
- switch (Reader->ReadAST(pchFile, serialization::MK_PCH)) {
+ switch (Reader->ReadAST(pchFile, serialization::MK_PCH,
+ ASTReader::ARR_None)) {
case ASTReader::Success:
// Set the predefines buffer as suggested by the PCH reader.
PP.setPredefines(Reader->getSuggestedPredefines());
return Reader.take();
case ASTReader::Failure:
- case ASTReader::IgnorePCH:
+ case ASTReader::OutOfDate:
+ case ASTReader::VersionMismatch:
+ case ASTReader::ConfigurationMismatch:
+ case ASTReader::HadErrors:
break;
}
return 0;
@@ -63,7 +67,7 @@ ChainedIncludesSource *ChainedIncludesSource::create(CompilerInstance &CI) {
assert(!includes.empty() && "No '-chain-include' in options!");
OwningPtr<ChainedIncludesSource> source(new ChainedIncludesSource());
- InputKind IK = CI.getFrontendOpts().Inputs[0].Kind;
+ InputKind IK = CI.getFrontendOpts().Inputs[0].getKind();
SmallVector<llvm::MemoryBuffer *, 4> serialBufs;
SmallVector<std::string, 4> serialBufNames;
@@ -82,14 +86,14 @@ ChainedIncludesSource *ChainedIncludesSource::create(CompilerInstance &CI) {
CInvok->getPreprocessorOpts().Macros.clear();
CInvok->getFrontendOpts().Inputs.clear();
- CInvok->getFrontendOpts().Inputs.push_back(FrontendInputFile(includes[i],
- IK));
+ FrontendInputFile InputFile(includes[i], IK);
+ CInvok->getFrontendOpts().Inputs.push_back(InputFile);
TextDiagnosticPrinter *DiagClient =
- new TextDiagnosticPrinter(llvm::errs(), DiagnosticOptions());
+ new TextDiagnosticPrinter(llvm::errs(), new DiagnosticOptions());
IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
- new DiagnosticsEngine(DiagID, DiagClient));
+ new DiagnosticsEngine(DiagID, &CI.getDiagnosticOpts(), DiagClient));
OwningPtr<CompilerInstance> Clang(new CompilerInstance());
Clang->setInvocation(CInvok.take());
@@ -108,6 +112,8 @@ 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());
@@ -141,7 +147,7 @@ ChainedIncludesSource *ChainedIncludesSource::create(CompilerInstance &CI) {
Clang->getASTContext().setExternalSource(Reader);
}
- if (!Clang->InitializeSourceManager(includes[i]))
+ if (!Clang->InitializeSourceManager(InputFile))
return 0;
ParseAST(Clang->getSema());
diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp
index 6de153107f3b..22a74fcc35d9 100644
--- a/lib/Frontend/CompilerInstance.cpp
+++ b/lib/Frontend/CompilerInstance.cpp
@@ -52,6 +52,7 @@ CompilerInstance::CompilerInstance()
}
CompilerInstance::~CompilerInstance() {
+ assert(OutputFiles.empty() && "Still output files in flight?");
}
void CompilerInstance::setInvocation(CompilerInvocation *Value) {
@@ -88,19 +89,18 @@ void CompilerInstance::setASTConsumer(ASTConsumer *Value) {
void CompilerInstance::setCodeCompletionConsumer(CodeCompleteConsumer *Value) {
CompletionConsumer.reset(Value);
- getFrontendOpts().SkipFunctionBodies = Value != 0;
}
// Diagnostics
-static void SetUpBuildDumpLog(const DiagnosticOptions &DiagOpts,
+static void SetUpBuildDumpLog(DiagnosticOptions *DiagOpts,
unsigned argc, const char* const *argv,
DiagnosticsEngine &Diags) {
std::string ErrorInfo;
OwningPtr<raw_ostream> OS(
- new llvm::raw_fd_ostream(DiagOpts.DumpBuildInformation.c_str(), ErrorInfo));
+ new llvm::raw_fd_ostream(DiagOpts->DumpBuildInformation.c_str(),ErrorInfo));
if (!ErrorInfo.empty()) {
Diags.Report(diag::err_fe_unable_to_open_logfile)
- << DiagOpts.DumpBuildInformation << ErrorInfo;
+ << DiagOpts->DumpBuildInformation << ErrorInfo;
return;
}
@@ -115,20 +115,20 @@ static void SetUpBuildDumpLog(const DiagnosticOptions &DiagOpts,
Diags.setClient(new ChainedDiagnosticConsumer(Diags.takeClient(), Logger));
}
-static void SetUpDiagnosticLog(const DiagnosticOptions &DiagOpts,
+static void SetUpDiagnosticLog(DiagnosticOptions *DiagOpts,
const CodeGenOptions *CodeGenOpts,
DiagnosticsEngine &Diags) {
std::string ErrorInfo;
bool OwnsStream = false;
raw_ostream *OS = &llvm::errs();
- if (DiagOpts.DiagnosticLogFile != "-") {
+ if (DiagOpts->DiagnosticLogFile != "-") {
// Create the output stream.
llvm::raw_fd_ostream *FileOS(
- new llvm::raw_fd_ostream(DiagOpts.DiagnosticLogFile.c_str(),
+ new llvm::raw_fd_ostream(DiagOpts->DiagnosticLogFile.c_str(),
ErrorInfo, llvm::raw_fd_ostream::F_Append));
if (!ErrorInfo.empty()) {
Diags.Report(diag::warn_fe_cc_log_diagnostics_failure)
- << DiagOpts.DumpBuildInformation << ErrorInfo;
+ << DiagOpts->DumpBuildInformation << ErrorInfo;
} else {
FileOS->SetUnbuffered();
FileOS->SetUseAtomicWrites(true);
@@ -145,7 +145,7 @@ static void SetUpDiagnosticLog(const DiagnosticOptions &DiagOpts,
Diags.setClient(new ChainedDiagnosticConsumer(Diags.takeClient(), Logger));
}
-static void SetupSerializedDiagnostics(const DiagnosticOptions &DiagOpts,
+static void SetupSerializedDiagnostics(DiagnosticOptions *DiagOpts,
DiagnosticsEngine &Diags,
StringRef OutputFile) {
std::string ErrorInfo;
@@ -171,13 +171,13 @@ void CompilerInstance::createDiagnostics(int Argc, const char* const *Argv,
DiagnosticConsumer *Client,
bool ShouldOwnClient,
bool ShouldCloneClient) {
- Diagnostics = createDiagnostics(getDiagnosticOpts(), Argc, Argv, Client,
+ Diagnostics = createDiagnostics(&getDiagnosticOpts(), Argc, Argv, Client,
ShouldOwnClient, ShouldCloneClient,
&getCodeGenOpts());
}
IntrusiveRefCntPtr<DiagnosticsEngine>
-CompilerInstance::createDiagnostics(const DiagnosticOptions &Opts,
+CompilerInstance::createDiagnostics(DiagnosticOptions *Opts,
int Argc, const char* const *Argv,
DiagnosticConsumer *Client,
bool ShouldOwnClient,
@@ -185,7 +185,7 @@ CompilerInstance::createDiagnostics(const DiagnosticOptions &Opts,
const CodeGenOptions *CodeGenOpts) {
IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
IntrusiveRefCntPtr<DiagnosticsEngine>
- Diags(new DiagnosticsEngine(DiagID));
+ Diags(new DiagnosticsEngine(DiagID, Opts));
// Create the diagnostic client for reporting errors or for
// implementing -verify.
@@ -198,22 +198,22 @@ CompilerInstance::createDiagnostics(const DiagnosticOptions &Opts,
Diags->setClient(new TextDiagnosticPrinter(llvm::errs(), Opts));
// Chain in -verify checker, if requested.
- if (Opts.VerifyDiagnostics)
+ if (Opts->VerifyDiagnostics)
Diags->setClient(new VerifyDiagnosticConsumer(*Diags));
// Chain in -diagnostic-log-file dumper, if requested.
- if (!Opts.DiagnosticLogFile.empty())
+ if (!Opts->DiagnosticLogFile.empty())
SetUpDiagnosticLog(Opts, CodeGenOpts, *Diags);
- if (!Opts.DumpBuildInformation.empty())
+ if (!Opts->DumpBuildInformation.empty())
SetUpBuildDumpLog(Opts, Argc, Argv, *Diags);
- if (!Opts.DiagnosticSerializationFile.empty())
+ if (!Opts->DiagnosticSerializationFile.empty())
SetupSerializedDiagnostics(Opts, *Diags,
- Opts.DiagnosticSerializationFile);
+ Opts->DiagnosticSerializationFile);
// Configure our handling of diagnostics.
- ProcessWarningOptions(*Diags, Opts);
+ ProcessWarningOptions(*Diags, *Opts);
return Diags;
}
@@ -241,11 +241,13 @@ void CompilerInstance::createPreprocessor() {
PTHMgr = PTHManager::Create(PPOpts.TokenCache, getDiagnostics());
// Create the Preprocessor.
- HeaderSearch *HeaderInfo = new HeaderSearch(getFileManager(),
+ HeaderSearch *HeaderInfo = new HeaderSearch(&getHeaderSearchOpts(),
+ getFileManager(),
getDiagnostics(),
getLangOpts(),
&getTarget());
- PP = new Preprocessor(getDiagnostics(), getLangOpts(), &getTarget(),
+ PP = new Preprocessor(&getPreprocessorOpts(),
+ getDiagnostics(), getLangOpts(), &getTarget(),
getSourceManager(), *HeaderInfo, *this, PTHMgr,
/*OwnsHeaderSearch=*/true);
@@ -306,14 +308,12 @@ void CompilerInstance::createASTContext() {
void CompilerInstance::createPCHExternalASTSource(StringRef Path,
bool DisablePCHValidation,
- bool DisableStatCache,
bool AllowPCHWithCompilerErrors,
void *DeserializationListener){
OwningPtr<ExternalASTSource> Source;
bool Preamble = getPreprocessorOpts().PrecompiledPreambleBytes.first != 0;
Source.reset(createPCHExternalASTSource(Path, getHeaderSearchOpts().Sysroot,
DisablePCHValidation,
- DisableStatCache,
AllowPCHWithCompilerErrors,
getPreprocessor(), getASTContext(),
DeserializationListener,
@@ -326,7 +326,6 @@ ExternalASTSource *
CompilerInstance::createPCHExternalASTSource(StringRef Path,
const std::string &Sysroot,
bool DisablePCHValidation,
- bool DisableStatCache,
bool AllowPCHWithCompilerErrors,
Preprocessor &PP,
ASTContext &Context,
@@ -335,14 +334,15 @@ CompilerInstance::createPCHExternalASTSource(StringRef Path,
OwningPtr<ASTReader> Reader;
Reader.reset(new ASTReader(PP, Context,
Sysroot.empty() ? "" : Sysroot.c_str(),
- DisablePCHValidation, DisableStatCache,
+ DisablePCHValidation,
AllowPCHWithCompilerErrors));
Reader->setDeserializationListener(
static_cast<ASTDeserializationListener *>(DeserializationListener));
switch (Reader->ReadAST(Path,
Preamble ? serialization::MK_Preamble
- : serialization::MK_PCH)) {
+ : serialization::MK_PCH,
+ ASTReader::ARR_None)) {
case ASTReader::Success:
// Set the predefines buffer as suggested by the PCH reader. Typically, the
// predefines buffer will be empty.
@@ -353,7 +353,10 @@ CompilerInstance::createPCHExternalASTSource(StringRef Path,
// Unrecoverable failure: don't even try to process the input file.
break;
- case ASTReader::IgnorePCH:
+ case ASTReader::OutOfDate:
+ case ASTReader::VersionMismatch:
+ case ASTReader::ConfigurationMismatch:
+ case ASTReader::HadErrors:
// No suitable PCH file could be found. Return an error.
break;
}
@@ -586,19 +589,29 @@ CompilerInstance::createOutputFile(StringRef OutputPath,
// Initialization Utilities
-bool CompilerInstance::InitializeSourceManager(StringRef InputFile,
- SrcMgr::CharacteristicKind Kind){
- return InitializeSourceManager(InputFile, Kind, getDiagnostics(),
+bool CompilerInstance::InitializeSourceManager(const FrontendInputFile &Input){
+ return InitializeSourceManager(Input, getDiagnostics(),
getFileManager(), getSourceManager(),
getFrontendOpts());
}
-bool CompilerInstance::InitializeSourceManager(StringRef InputFile,
- SrcMgr::CharacteristicKind Kind,
+bool CompilerInstance::InitializeSourceManager(const FrontendInputFile &Input,
DiagnosticsEngine &Diags,
FileManager &FileMgr,
SourceManager &SourceMgr,
const FrontendOptions &Opts) {
+ SrcMgr::CharacteristicKind
+ Kind = Input.isSystem() ? SrcMgr::C_System : SrcMgr::C_User;
+
+ if (Input.isBuffer()) {
+ SourceMgr.createMainFileIDForMemBuffer(Input.getBuffer(), Kind);
+ assert(!SourceMgr.getMainFileID().isInvalid() &&
+ "Couldn't establish MainFileID!");
+ return true;
+ }
+
+ StringRef InputFile = Input.getFile();
+
// Figure out where to get and map in the main file.
if (InputFile != "-") {
const FileEntry *File = FileMgr.getFile(InputFile);
@@ -607,6 +620,19 @@ bool CompilerInstance::InitializeSourceManager(StringRef InputFile,
return false;
}
SourceMgr.createMainFileID(File, Kind);
+
+ // The natural SourceManager infrastructure can't currently handle named
+ // pipes, but we would at least like to accept them for the main
+ // file. Detect them here, read them with the more generic MemoryBuffer
+ // function, and simply override their contents as we do for STDIN.
+ if (File->isNamedPipe()) {
+ OwningPtr<llvm::MemoryBuffer> MB;
+ if (llvm::error_code ec = llvm::MemoryBuffer::getFile(InputFile, MB)) {
+ Diags.Report(diag::err_cannot_open_file) << InputFile << ec.message();
+ return false;
+ }
+ SourceMgr.overrideFileContents(File, MB.take());
+ }
} else {
OwningPtr<llvm::MemoryBuffer> SB;
if (llvm::MemoryBuffer::getSTDIN(SB)) {
@@ -746,7 +772,7 @@ static void compileModule(CompilerInstance &ImportingInstance,
// Someone else is responsible for building the module. Wait for them to
// finish.
Locked.waitForUnlock();
- break;
+ return;
}
ModuleMap &ModMap
@@ -836,6 +862,7 @@ static void compileModule(CompilerInstance &ImportingInstance,
// FIXME: Even though we're executing under crash protection, it would still
// be nice to do this with RemoveFileOnSignal when we can. However, that
// doesn't make sense for all clients, so clean this up manually.
+ Instance.clearOutputFiles(/*EraseFiles=*/true);
if (!TempModuleMapFileName.empty())
llvm::sys::Path(TempModuleMapFileName).eraseFromDisk();
}
@@ -939,13 +966,14 @@ Module *CompilerInstance::loadModule(SourceLocation ImportLoc,
const PreprocessorOptions &PPOpts = getPreprocessorOpts();
ModuleManager = new ASTReader(getPreprocessor(), *Context,
Sysroot.empty() ? "" : Sysroot.c_str(),
- PPOpts.DisablePCHValidation,
- PPOpts.DisableStatCache);
+ PPOpts.DisablePCHValidation);
if (hasASTConsumer()) {
ModuleManager->setDeserializationListener(
getASTConsumer().GetASTDeserializationListener());
getASTContext().setASTMutationListener(
getASTConsumer().GetASTMutationListener());
+ getPreprocessor().setPPMutationListener(
+ getASTConsumer().GetPPMutationListener());
}
OwningPtr<ExternalASTSource> Source;
Source.reset(ModuleManager);
@@ -957,12 +985,39 @@ Module *CompilerInstance::loadModule(SourceLocation ImportLoc,
}
// 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)) {
+ serialization::MK_Module,
+ ARRFlags)) {
case ASTReader::Success:
break;
- case ASTReader::IgnorePCH:
+ case ASTReader::OutOfDate: {
+ // The module file is out-of-date. Rebuild it.
+ getFileManager().invalidateCache(ModuleFile);
+ bool Existed;
+ llvm::sys::fs::remove(ModuleFileName, Existed);
+ compileModule(*this, Module, ModuleFileName);
+
+ // Try loading the module again.
+ ModuleFile = FileMgr->getFile(ModuleFileName);
+ if (!ModuleFile ||
+ ModuleManager->ReadAST(ModuleFileName,
+ serialization::MK_Module,
+ ASTReader::ARR_None) != ASTReader::Success) {
+ KnownModules[Path[0].first] = 0;
+ return 0;
+ }
+
+ // Okay, we've rebuilt and now loaded the module.
+ break;
+ }
+
+ case ASTReader::VersionMismatch:
+ case ASTReader::ConfigurationMismatch:
+ case ASTReader::HadErrors:
// FIXME: The ASTReader will already have complained, but can we showhorn
// that diagnostic information into a more useful form?
KnownModules[Path[0].first] = 0;
@@ -980,6 +1035,9 @@ Module *CompilerInstance::loadModule(SourceLocation ImportLoc,
Module = PP->getHeaderSearchInfo().getModuleMap()
.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;
@@ -1079,9 +1137,12 @@ Module *CompilerInstance::loadModule(SourceLocation ImportLoc,
// implicit import declaration to capture it in the AST.
if (IsInclusionDirective && hasASTContext()) {
TranslationUnitDecl *TU = getASTContext().getTranslationUnitDecl();
- TU->addDecl(ImportDecl::CreateImplicit(getASTContext(), TU,
- ImportLoc, Module,
- Path.back().second));
+ ImportDecl *ImportD = ImportDecl::CreateImplicit(getASTContext(), TU,
+ ImportLoc, Module,
+ Path.back().second);
+ TU->addDecl(ImportD);
+ if (Consumer)
+ Consumer->HandleImplicitImportDecl(ImportD);
}
LastModuleImportLoc = ImportLoc;
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index d39679caf13e..b9c198b11191 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -11,6 +11,7 @@
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/Version.h"
#include "clang/Basic/FileManager.h"
+#include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Driver/Arg.h"
#include "clang/Driver/ArgList.h"
#include "clang/Driver/Options.h"
@@ -20,6 +21,7 @@
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/LangStandard.h"
#include "clang/Serialization/ASTReader.h"
+#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
@@ -35,917 +37,21 @@ using namespace clang;
//===----------------------------------------------------------------------===//
CompilerInvocationBase::CompilerInvocationBase()
- : LangOpts(new LangOptions()) {}
+ : LangOpts(new LangOptions()), TargetOpts(new TargetOptions()),
+ DiagnosticOpts(new DiagnosticOptions()),
+ HeaderSearchOpts(new HeaderSearchOptions()),
+ PreprocessorOpts(new PreprocessorOptions()) {}
CompilerInvocationBase::CompilerInvocationBase(const CompilerInvocationBase &X)
: RefCountedBase<CompilerInvocation>(),
- LangOpts(new LangOptions(*X.getLangOpts())) {}
+ LangOpts(new LangOptions(*X.getLangOpts())),
+ TargetOpts(new TargetOptions(X.getTargetOpts())),
+ DiagnosticOpts(new DiagnosticOptions(X.getDiagnosticOpts())),
+ HeaderSearchOpts(new HeaderSearchOptions(X.getHeaderSearchOpts())),
+ PreprocessorOpts(new PreprocessorOptions(X.getPreprocessorOpts())) {}
//===----------------------------------------------------------------------===//
-// Utility functions.
-//===----------------------------------------------------------------------===//
-
-static const char *getAnalysisStoreName(AnalysisStores Kind) {
- switch (Kind) {
- default:
- llvm_unreachable("Unknown analysis store!");
-#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN) \
- case NAME##Model: return CMDFLAG;
-#include "clang/Frontend/Analyses.def"
- }
-}
-
-static const char *getAnalysisConstraintName(AnalysisConstraints Kind) {
- switch (Kind) {
- default:
- llvm_unreachable("Unknown analysis constraints!");
-#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN) \
- case NAME##Model: return CMDFLAG;
-#include "clang/Frontend/Analyses.def"
- }
-}
-
-static const char *getAnalysisDiagClientName(AnalysisDiagClients Kind) {
- switch (Kind) {
- default:
- llvm_unreachable("Unknown analysis client!");
-#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN, AUTOCREATE) \
- case PD_##NAME: return CMDFLAG;
-#include "clang/Frontend/Analyses.def"
- }
-}
-
-static const char *getAnalysisPurgeModeName(AnalysisPurgeMode Kind) {
- switch (Kind) {
- default:
- llvm_unreachable("Unknown analysis purge mode!");
-#define ANALYSIS_PURGE(NAME, CMDFLAG, DESC) \
- case NAME: return CMDFLAG;
-#include "clang/Frontend/Analyses.def"
- }
-}
-
-static const char *getAnalysisIPAModeName(AnalysisIPAMode Kind) {
- switch (Kind) {
- default:
- llvm_unreachable("Unknown analysis ipa mode!");
-#define ANALYSIS_IPA(NAME, CMDFLAG, DESC) \
- case NAME: return CMDFLAG;
-#include "clang/Frontend/Analyses.def"
- }
-}
-
-static const char *
- getAnalysisInliningModeName(AnalysisInliningMode Kind) {
- switch (Kind) {
- default:
- llvm_unreachable("Unknown analysis inlining mode!");
-#define ANALYSIS_INLINE_SELECTION(NAME, CMDFLAG, DESC) \
- case NAME: return CMDFLAG;
-#include "clang/Frontend/Analyses.def"
- }
-}
-
-//===----------------------------------------------------------------------===//
-// Serialization (to args)
-//===----------------------------------------------------------------------===//
-
-namespace {
- /// ToArgsList - Helper class to create a list of std::strings.
- class ToArgsList {
- std::vector<std::string> &Res;
- public:
- explicit ToArgsList(std::vector<std::string> &Res) : Res(Res) {}
-
- void push_back(StringRef Str) {
- // Avoid creating a temporary string.
- Res.push_back(std::string());
- Res.back().assign(Str.data(), Str.size());
- }
-
- void push_back(StringRef Str1, StringRef Str2) {
- push_back(Str1);
- push_back(Str2);
- }
- };
-}
-
-static void AnalyzerOptsToArgs(const AnalyzerOptions &Opts, ToArgsList &Res) {
- if (Opts.ShowCheckerHelp)
- Res.push_back("-analyzer-checker-help");
- if (Opts.AnalysisStoreOpt != RegionStoreModel)
- Res.push_back("-analyzer-store",
- getAnalysisStoreName(Opts.AnalysisStoreOpt));
- if (Opts.AnalysisConstraintsOpt != RangeConstraintsModel)
- Res.push_back("-analyzer-constraints",
- getAnalysisConstraintName(Opts.AnalysisConstraintsOpt));
- if (Opts.AnalysisDiagOpt != PD_HTML)
- Res.push_back("-analyzer-output",
- getAnalysisDiagClientName(Opts.AnalysisDiagOpt));
- if (Opts.AnalysisPurgeOpt != PurgeStmt)
- Res.push_back("-analyzer-purge",
- getAnalysisPurgeModeName(Opts.AnalysisPurgeOpt));
- if (!Opts.AnalyzeSpecificFunction.empty())
- Res.push_back("-analyze-function", Opts.AnalyzeSpecificFunction);
- if (Opts.IPAMode != Inlining)
- Res.push_back("-analyzer-ipa", getAnalysisIPAModeName(Opts.IPAMode));
- if (Opts.InliningMode != NoRedundancy)
- Res.push_back("-analyzer-inlining-mode",
- getAnalysisInliningModeName(Opts.InliningMode));
-
- if (Opts.AnalyzeAll)
- Res.push_back("-analyzer-opt-analyze-headers");
- if (Opts.AnalyzerDisplayProgress)
- Res.push_back("-analyzer-display-progress");
- if (Opts.AnalyzeNestedBlocks)
- Res.push_back("-analyzer-opt-analyze-nested-blocks");
- if (Opts.EagerlyAssume)
- Res.push_back("-analyzer-eagerly-assume");
- if (Opts.TrimGraph)
- Res.push_back("-trim-egraph");
- if (Opts.VisualizeEGDot)
- Res.push_back("-analyzer-viz-egraph-graphviz");
- if (Opts.VisualizeEGUbi)
- Res.push_back("-analyzer-viz-egraph-ubigraph");
- if (Opts.NoRetryExhausted)
- Res.push_back("-analyzer-disable-retry-exhausted");
-
- for (unsigned i = 0, e = Opts.CheckersControlList.size(); i != e; ++i) {
- const std::pair<std::string, bool> &opt = Opts.CheckersControlList[i];
- if (opt.second)
- Res.push_back("-analyzer-disable-checker");
- else
- Res.push_back("-analyzer-checker");
- Res.push_back(opt.first);
- }
-}
-
-static void CodeGenOptsToArgs(const CodeGenOptions &Opts, ToArgsList &Res) {
- switch (Opts.DebugInfo) {
- case CodeGenOptions::NoDebugInfo:
- break;
- case CodeGenOptions::DebugLineTablesOnly:
- Res.push_back("-gline-tables-only");
- break;
- case CodeGenOptions::LimitedDebugInfo:
- Res.push_back("-g");
- Res.push_back("-flimit-debug-info");
- break;
- case CodeGenOptions::FullDebugInfo:
- Res.push_back("-g");
- Res.push_back("-fno-limit-debug-info");
- break;
- }
- if (Opts.DisableLLVMOpts)
- Res.push_back("-disable-llvm-optzns");
- if (Opts.DisableRedZone)
- Res.push_back("-disable-red-zone");
- if (Opts.DisableTailCalls)
- Res.push_back("-mdisable-tail-calls");
- if (!Opts.DebugCompilationDir.empty())
- Res.push_back("-fdebug-compilation-dir", Opts.DebugCompilationDir);
- if (!Opts.DwarfDebugFlags.empty())
- Res.push_back("-dwarf-debug-flags", Opts.DwarfDebugFlags);
- if (Opts.EmitGcovArcs)
- Res.push_back("-femit-coverage-data");
- if (Opts.EmitGcovNotes)
- Res.push_back("-femit-coverage-notes");
- if (Opts.EmitOpenCLArgMetadata)
- Res.push_back("-cl-kernel-arg-info");
- if (!Opts.MergeAllConstants)
- Res.push_back("-fno-merge-all-constants");
- if (Opts.NoCommon)
- Res.push_back("-fno-common");
- if (Opts.ForbidGuardVariables)
- Res.push_back("-fforbid-guard-variables");
- if (Opts.UseRegisterSizedBitfieldAccess)
- Res.push_back("-fuse-register-sized-bitfield-access");
- if (Opts.NoImplicitFloat)
- Res.push_back("-no-implicit-float");
- if (Opts.OmitLeafFramePointer)
- Res.push_back("-momit-leaf-frame-pointer");
- if (Opts.OptimizeSize) {
- assert(Opts.OptimizationLevel == 2 && "Invalid options!");
- Opts.OptimizeSize == 1 ? Res.push_back("-Os") : Res.push_back("-Oz");
- } else if (Opts.OptimizationLevel != 0)
- Res.push_back("-O" + llvm::utostr(Opts.OptimizationLevel));
- if (!Opts.MainFileName.empty())
- Res.push_back("-main-file-name", Opts.MainFileName);
- if (Opts.NoInfsFPMath)
- Res.push_back("-menable-no-infinities");
- if (Opts.NoNaNsFPMath)
- Res.push_back("-menable-no-nans");
- // SimplifyLibCalls is only derived.
- // TimePasses is only derived.
- // UnitAtATime is unused.
- // Inlining is only derived.
-
- // UnrollLoops is derived, but also accepts an option, no
- // harm in pushing it back here.
- if (Opts.UnrollLoops)
- Res.push_back("-funroll-loops");
- if (Opts.DataSections)
- Res.push_back("-fdata-sections");
- if (Opts.FunctionSections)
- Res.push_back("-ffunction-sections");
- if (Opts.AsmVerbose)
- Res.push_back("-masm-verbose");
- if (!Opts.CodeModel.empty())
- Res.push_back("-mcode-model", Opts.CodeModel);
- if (Opts.CUDAIsDevice)
- Res.push_back("-fcuda-is-device");
- if (!Opts.CXAAtExit)
- Res.push_back("-fno-use-cxa-atexit");
- if (Opts.CXXCtorDtorAliases)
- Res.push_back("-mconstructor-aliases");
- if (Opts.ObjCAutoRefCountExceptions)
- Res.push_back("-fobjc-arc-eh");
- if (!Opts.DebugPass.empty()) {
- Res.push_back("-mdebug-pass", Opts.DebugPass);
- }
- if (Opts.DisableFPElim)
- Res.push_back("-mdisable-fp-elim");
- if (!Opts.FloatABI.empty())
- Res.push_back("-mfloat-abi", Opts.FloatABI);
- if (!Opts.LimitFloatPrecision.empty())
- Res.push_back("-mlimit-float-precision", Opts.LimitFloatPrecision);
- if (Opts.NoZeroInitializedInBSS)
- Res.push_back("-mno-zero-initialized-bss");
- switch (Opts.getObjCDispatchMethod()) {
- case CodeGenOptions::Legacy:
- break;
- case CodeGenOptions::Mixed:
- Res.push_back("-fobjc-dispatch-method=mixed");
- break;
- case CodeGenOptions::NonLegacy:
- Res.push_back("-fobjc-dispatch-method=non-legacy");
- break;
- }
- if (Opts.BoundsChecking > 0)
- Res.push_back("-fbounds-checking=" + llvm::utostr(Opts.BoundsChecking));
- if (Opts.NumRegisterParameters)
- Res.push_back("-mregparm", llvm::utostr(Opts.NumRegisterParameters));
- if (Opts.NoGlobalMerge)
- Res.push_back("-mno-global-merge");
- if (Opts.NoExecStack)
- Res.push_back("-mnoexecstack");
- if (Opts.RelaxAll)
- Res.push_back("-mrelax-all");
- if (Opts.SaveTempLabels)
- Res.push_back("-msave-temp-labels");
- if (Opts.NoDwarf2CFIAsm)
- Res.push_back("-fno-dwarf2-cfi-asm");
- if (Opts.NoDwarfDirectoryAsm)
- Res.push_back("-fno-dwarf-directory-asm");
- if (Opts.SoftFloat)
- Res.push_back("-msoft-float");
- if (Opts.StrictEnums)
- Res.push_back("-fstrict-enums");
- if (Opts.UnwindTables)
- Res.push_back("-munwind-tables");
- if (Opts.RelocationModel != "pic")
- Res.push_back("-mrelocation-model", Opts.RelocationModel);
- if (!Opts.VerifyModule)
- Res.push_back("-disable-llvm-verifier");
- for (unsigned i = 0, e = Opts.BackendOptions.size(); i != e; ++i)
- Res.push_back("-backend-option", Opts.BackendOptions[i]);
-
- switch (Opts.DefaultTLSModel) {
- case CodeGenOptions::GeneralDynamicTLSModel:
- break;
- case CodeGenOptions::LocalDynamicTLSModel:
- Res.push_back("-ftls-model=local-dynamic");
- break;
- case CodeGenOptions::InitialExecTLSModel:
- Res.push_back("-ftls-model=initial-exec");
- break;
- case CodeGenOptions::LocalExecTLSModel:
- Res.push_back("-ftls-model=local-exec");
- break;
- }
-}
-
-static void DependencyOutputOptsToArgs(const DependencyOutputOptions &Opts,
- ToArgsList &Res) {
- if (Opts.IncludeSystemHeaders)
- Res.push_back("-sys-header-deps");
- if (Opts.ShowHeaderIncludes)
- Res.push_back("-H");
- if (!Opts.HeaderIncludeOutputFile.empty())
- Res.push_back("-header-include-file", Opts.HeaderIncludeOutputFile);
- if (Opts.UsePhonyTargets)
- Res.push_back("-MP");
- if (!Opts.OutputFile.empty())
- Res.push_back("-dependency-file", Opts.OutputFile);
- for (unsigned i = 0, e = Opts.Targets.size(); i != e; ++i)
- Res.push_back("-MT", Opts.Targets[i]);
-}
-
-static void DiagnosticOptsToArgs(const DiagnosticOptions &Opts,
- ToArgsList &Res) {
- if (Opts.IgnoreWarnings)
- Res.push_back("-w");
- if (Opts.NoRewriteMacros)
- Res.push_back("-Wno-rewrite-macros");
- if (Opts.Pedantic)
- Res.push_back("-pedantic");
- if (Opts.PedanticErrors)
- Res.push_back("-pedantic-errors");
- if (!Opts.ShowColumn)
- Res.push_back("-fno-show-column");
- if (!Opts.ShowLocation)
- Res.push_back("-fno-show-source-location");
- if (!Opts.ShowCarets)
- Res.push_back("-fno-caret-diagnostics");
- if (!Opts.ShowFixits)
- Res.push_back("-fno-diagnostics-fixit-info");
- if (Opts.ShowSourceRanges)
- Res.push_back("-fdiagnostics-print-source-range-info");
- if (Opts.ShowParseableFixits)
- Res.push_back("-fdiagnostics-parseable-fixits");
- if (Opts.ShowColors)
- Res.push_back("-fcolor-diagnostics");
- if (Opts.VerifyDiagnostics)
- Res.push_back("-verify");
- if (Opts.ShowOptionNames)
- Res.push_back("-fdiagnostics-show-option");
- if (Opts.ShowCategories == 1)
- Res.push_back("-fdiagnostics-show-category=id");
- else if (Opts.ShowCategories == 2)
- Res.push_back("-fdiagnostics-show-category=name");
- switch (Opts.Format) {
- case DiagnosticOptions::Clang:
- Res.push_back("-fdiagnostics-format=clang"); break;
- case DiagnosticOptions::Msvc:
- Res.push_back("-fdiagnostics-format=msvc"); break;
- case DiagnosticOptions::Vi:
- Res.push_back("-fdiagnostics-format=vi"); break;
- }
- if (Opts.ErrorLimit)
- Res.push_back("-ferror-limit", llvm::utostr(Opts.ErrorLimit));
- if (!Opts.DiagnosticLogFile.empty())
- Res.push_back("-diagnostic-log-file", Opts.DiagnosticLogFile);
- if (Opts.MacroBacktraceLimit
- != DiagnosticOptions::DefaultMacroBacktraceLimit)
- Res.push_back("-fmacro-backtrace-limit",
- llvm::utostr(Opts.MacroBacktraceLimit));
- if (Opts.TemplateBacktraceLimit
- != DiagnosticOptions::DefaultTemplateBacktraceLimit)
- Res.push_back("-ftemplate-backtrace-limit",
- llvm::utostr(Opts.TemplateBacktraceLimit));
- if (Opts.ConstexprBacktraceLimit
- != DiagnosticOptions::DefaultConstexprBacktraceLimit)
- Res.push_back("-fconstexpr-backtrace-limit",
- llvm::utostr(Opts.ConstexprBacktraceLimit));
-
- if (Opts.TabStop != DiagnosticOptions::DefaultTabStop)
- Res.push_back("-ftabstop", llvm::utostr(Opts.TabStop));
- if (Opts.MessageLength)
- Res.push_back("-fmessage-length", llvm::utostr(Opts.MessageLength));
- if (!Opts.DumpBuildInformation.empty())
- Res.push_back("-dump-build-information", Opts.DumpBuildInformation);
- for (unsigned i = 0, e = Opts.Warnings.size(); i != e; ++i)
- Res.push_back("-W" + Opts.Warnings[i]);
-}
-
-static const char *getInputKindName(InputKind Kind) {
- switch (Kind) {
- case IK_None: break;
- case IK_AST: return "ast";
- case IK_Asm: return "assembler-with-cpp";
- case IK_C: return "c";
- case IK_CXX: return "c++";
- case IK_LLVM_IR: return "ir";
- case IK_ObjC: return "objective-c";
- case IK_ObjCXX: return "objective-c++";
- case IK_OpenCL: return "cl";
- case IK_CUDA: return "cuda";
- case IK_PreprocessedC: return "cpp-output";
- case IK_PreprocessedCXX: return "c++-cpp-output";
- case IK_PreprocessedObjC: return "objective-c-cpp-output";
- case IK_PreprocessedObjCXX:return "objective-c++-cpp-output";
- }
-
- llvm_unreachable("Unexpected language kind!");
-}
-
-static const char *getActionName(frontend::ActionKind Kind) {
- switch (Kind) {
- case frontend::PluginAction:
- llvm_unreachable("Invalid kind!");
-
- case frontend::ASTDeclList: return "-ast-list";
- case frontend::ASTDump: return "-ast-dump";
- case frontend::ASTDumpXML: return "-ast-dump-xml";
- case frontend::ASTPrint: return "-ast-print";
- case frontend::ASTView: return "-ast-view";
- case frontend::DumpRawTokens: return "-dump-raw-tokens";
- case frontend::DumpTokens: return "-dump-tokens";
- case frontend::EmitAssembly: return "-S";
- case frontend::EmitBC: return "-emit-llvm-bc";
- case frontend::EmitHTML: return "-emit-html";
- case frontend::EmitLLVM: return "-emit-llvm";
- case frontend::EmitLLVMOnly: return "-emit-llvm-only";
- case frontend::EmitCodeGenOnly: return "-emit-codegen-only";
- case frontend::EmitObj: return "-emit-obj";
- case frontend::FixIt: return "-fixit";
- case frontend::GenerateModule: return "-emit-module";
- case frontend::GeneratePCH: return "-emit-pch";
- case frontend::GeneratePTH: return "-emit-pth";
- case frontend::InitOnly: return "-init-only";
- case frontend::ParseSyntaxOnly: return "-fsyntax-only";
- case frontend::PrintDeclContext: return "-print-decl-contexts";
- case frontend::PrintPreamble: return "-print-preamble";
- case frontend::PrintPreprocessedInput: return "-E";
- case frontend::RewriteMacros: return "-rewrite-macros";
- case frontend::RewriteObjC: return "-rewrite-objc";
- case frontend::RewriteTest: return "-rewrite-test";
- case frontend::RunAnalysis: return "-analyze";
- case frontend::MigrateSource: return "-migrate";
- case frontend::RunPreprocessorOnly: return "-Eonly";
- }
-
- llvm_unreachable("Unexpected language kind!");
-}
-
-static void FileSystemOptsToArgs(const FileSystemOptions &Opts, ToArgsList &Res){
- if (!Opts.WorkingDir.empty())
- Res.push_back("-working-directory", Opts.WorkingDir);
-}
-
-static void CodeCompleteOptionsToArgs(const CodeCompleteOptions &Opts,
- ToArgsList &Res) {
- if (Opts.IncludeMacros)
- Res.push_back("-code-completion-macros");
- if (Opts.IncludeCodePatterns)
- Res.push_back("-code-completion-patterns");
- if (!Opts.IncludeGlobals)
- Res.push_back("-no-code-completion-globals");
- if (Opts.IncludeBriefComments)
- Res.push_back("-code-completion-brief-comments");
-}
-
-static void FrontendOptsToArgs(const FrontendOptions &Opts, ToArgsList &Res) {
- if (Opts.DisableFree)
- Res.push_back("-disable-free");
- if (Opts.RelocatablePCH)
- Res.push_back("-relocatable-pch");
- if (Opts.ShowHelp)
- Res.push_back("-help");
- if (Opts.ShowStats)
- Res.push_back("-print-stats");
- if (Opts.ShowTimers)
- Res.push_back("-ftime-report");
- if (Opts.ShowVersion)
- Res.push_back("-version");
- if (Opts.FixWhatYouCan)
- Res.push_back("-fix-what-you-can");
- if (Opts.FixOnlyWarnings)
- Res.push_back("-fix-only-warnings");
- if (Opts.FixAndRecompile)
- Res.push_back("-fixit-recompile");
- if (Opts.FixToTemporaries)
- Res.push_back("-fixit-to-temporary");
- switch (Opts.ARCMTAction) {
- case FrontendOptions::ARCMT_None:
- break;
- case FrontendOptions::ARCMT_Check:
- Res.push_back("-arcmt-check");
- break;
- case FrontendOptions::ARCMT_Modify:
- Res.push_back("-arcmt-modify");
- break;
- case FrontendOptions::ARCMT_Migrate:
- Res.push_back("-arcmt-migrate");
- break;
- }
- CodeCompleteOptionsToArgs(Opts.CodeCompleteOpts, Res);
- if (!Opts.MTMigrateDir.empty())
- Res.push_back("-mt-migrate-directory", Opts.MTMigrateDir);
- if (!Opts.ARCMTMigrateReportOut.empty())
- Res.push_back("-arcmt-migrate-report-output", Opts.ARCMTMigrateReportOut);
- if (Opts.ARCMTMigrateEmitARCErrors)
- Res.push_back("-arcmt-migrate-emit-errors");
-
- if (Opts.ObjCMTAction & ~FrontendOptions::ObjCMT_Literals)
- Res.push_back("-objcmt-migrate-literals");
- if (Opts.ObjCMTAction & ~FrontendOptions::ObjCMT_Subscripting)
- Res.push_back("-objcmt-migrate-subscripting");
-
- bool NeedLang = false;
- for (unsigned i = 0, e = Opts.Inputs.size(); i != e; ++i)
- if (FrontendOptions::getInputKindForExtension(Opts.Inputs[i].File) !=
- Opts.Inputs[i].Kind)
- NeedLang = true;
- if (NeedLang)
- Res.push_back("-x", getInputKindName(Opts.Inputs[0].Kind));
- for (unsigned i = 0, e = Opts.Inputs.size(); i != e; ++i) {
- assert((!NeedLang || Opts.Inputs[i].Kind == Opts.Inputs[0].Kind) &&
- "Unable to represent this input vector!");
- Res.push_back(Opts.Inputs[i].File);
- }
-
- if (!Opts.OutputFile.empty())
- Res.push_back("-o", Opts.OutputFile);
- if (!Opts.CodeCompletionAt.FileName.empty())
- Res.push_back("-code-completion-at",
- Opts.CodeCompletionAt.FileName + ":" +
- llvm::utostr(Opts.CodeCompletionAt.Line) + ":" +
- llvm::utostr(Opts.CodeCompletionAt.Column));
- if (Opts.ProgramAction != frontend::PluginAction)
- Res.push_back(getActionName(Opts.ProgramAction));
- if (!Opts.ActionName.empty()) {
- Res.push_back("-plugin", Opts.ActionName);
- for(unsigned i = 0, e = Opts.PluginArgs.size(); i != e; ++i)
- Res.push_back("-plugin-arg-" + Opts.ActionName, Opts.PluginArgs[i]);
- }
- if (!Opts.ASTDumpFilter.empty())
- Res.push_back("-ast-dump-filter", Opts.ASTDumpFilter);
- for (unsigned i = 0, e = Opts.Plugins.size(); i != e; ++i)
- Res.push_back("-load", Opts.Plugins[i]);
- for (unsigned i = 0, e = Opts.AddPluginActions.size(); i != e; ++i) {
- Res.push_back("-add-plugin", Opts.AddPluginActions[i]);
- for(unsigned ai = 0, ae = Opts.AddPluginArgs.size(); ai != ae; ++ai)
- Res.push_back("-plugin-arg-" + Opts.AddPluginActions[i],
- Opts.AddPluginArgs[i][ai]);
- }
- for (unsigned i = 0, e = Opts.ASTMergeFiles.size(); i != e; ++i)
- Res.push_back("-ast-merge", Opts.ASTMergeFiles[i]);
- for (unsigned i = 0, e = Opts.LLVMArgs.size(); i != e; ++i)
- Res.push_back("-mllvm", Opts.LLVMArgs[i]);
- if (!Opts.OverrideRecordLayoutsFile.empty())
- Res.push_back("-foverride-record-layout=" + Opts.OverrideRecordLayoutsFile);
-}
-
-static void HeaderSearchOptsToArgs(const HeaderSearchOptions &Opts,
- ToArgsList &Res) {
- if (Opts.Sysroot != "/") {
- Res.push_back("-isysroot");
- Res.push_back(Opts.Sysroot);
- }
-
- /// User specified include entries.
- for (unsigned i = 0, e = Opts.UserEntries.size(); i != e; ++i) {
- const HeaderSearchOptions::Entry &E = Opts.UserEntries[i];
- if (E.IsFramework && (E.Group != frontend::Angled || !E.IsUserSupplied))
- llvm::report_fatal_error("Invalid option set!");
- if (E.IsUserSupplied) {
- switch (E.Group) {
- case frontend::After:
- Res.push_back("-idirafter");
- break;
-
- case frontend::Quoted:
- Res.push_back("-iquote");
- break;
-
- case frontend::System:
- Res.push_back("-isystem");
- break;
-
- case frontend::IndexHeaderMap:
- Res.push_back("-index-header-map");
- Res.push_back(E.IsFramework? "-F" : "-I");
- break;
-
- case frontend::CSystem:
- Res.push_back("-c-isystem");
- break;
-
- case frontend::CXXSystem:
- Res.push_back("-cxx-isystem");
- break;
-
- case frontend::ObjCSystem:
- Res.push_back("-objc-isystem");
- break;
-
- case frontend::ObjCXXSystem:
- Res.push_back("-objcxx-isystem");
- break;
-
- case frontend::Angled:
- Res.push_back(E.IsFramework ? "-F" : "-I");
- break;
- }
- } else {
- if (E.IsInternal) {
- assert(E.Group == frontend::System && "Unexpected header search group");
- if (E.ImplicitExternC)
- Res.push_back("-internal-externc-isystem");
- else
- Res.push_back("-internal-isystem");
- } else {
- if (E.Group != frontend::Angled && E.Group != frontend::System)
- llvm::report_fatal_error("Invalid option set!");
- Res.push_back(E.Group == frontend::Angled ? "-iwithprefixbefore" :
- "-iwithprefix");
- }
- }
- Res.push_back(E.Path);
- }
-
- /// User-specified system header prefixes.
- for (unsigned i = 0, e = Opts.SystemHeaderPrefixes.size(); i != e; ++i) {
- if (Opts.SystemHeaderPrefixes[i].IsSystemHeader)
- Res.push_back("-isystem-prefix");
- else
- Res.push_back("-ino-system-prefix");
-
- Res.push_back(Opts.SystemHeaderPrefixes[i].Prefix);
- }
-
- if (!Opts.ResourceDir.empty())
- Res.push_back("-resource-dir", Opts.ResourceDir);
- if (!Opts.ModuleCachePath.empty())
- Res.push_back("-fmodule-cache-path", Opts.ModuleCachePath);
- if (!Opts.UseStandardSystemIncludes)
- Res.push_back("-nostdsysteminc");
- if (!Opts.UseStandardCXXIncludes)
- Res.push_back("-nostdinc++");
- if (Opts.UseLibcxx)
- Res.push_back("-stdlib=libc++");
- if (Opts.Verbose)
- Res.push_back("-v");
-}
-
-static void LangOptsToArgs(const LangOptions &Opts, ToArgsList &Res) {
- LangOptions DefaultLangOpts;
-
- // FIXME: Need to set -std to get all the implicit options.
-
- // FIXME: We want to only pass options relative to the defaults, which
- // requires constructing a target. :(
- //
- // It would be better to push the all target specific choices into the driver,
- // so that everything below that was more uniform.
-
- if (Opts.Trigraphs)
- Res.push_back("-trigraphs");
- // Implicit based on the input kind:
- // AsmPreprocessor, CPlusPlus, ObjC1, ObjC2, OpenCL
- // Implicit based on the input language standard:
- // BCPLComment, C99, CPlusPlus0x, Digraphs, GNUInline, ImplicitInt, GNUMode
- if (Opts.DollarIdents)
- Res.push_back("-fdollars-in-identifiers");
- if (Opts.GNUMode && !Opts.GNUKeywords)
- Res.push_back("-fno-gnu-keywords");
- if (!Opts.GNUMode && Opts.GNUKeywords)
- Res.push_back("-fgnu-keywords");
- if (Opts.MicrosoftExt)
- Res.push_back("-fms-extensions");
- if (Opts.MicrosoftMode)
- Res.push_back("-fms-compatibility");
- if (Opts.MSCVersion != 0)
- Res.push_back("-fmsc-version=" + llvm::utostr(Opts.MSCVersion));
- if (Opts.Borland)
- Res.push_back("-fborland-extensions");
- if (Opts.ObjCDefaultSynthProperties)
- Res.push_back("-fobjc-default-synthesize-properties");
- // NoInline is implicit.
- if (!Opts.CXXOperatorNames)
- Res.push_back("-fno-operator-names");
- if (Opts.PascalStrings)
- Res.push_back("-fpascal-strings");
- if (Opts.CatchUndefined)
- Res.push_back("-fcatch-undefined-behavior");
- if (Opts.AddressSanitizer)
- Res.push_back("-faddress-sanitizer");
- if (Opts.ThreadSanitizer)
- Res.push_back("-fthread-sanitizer");
- if (Opts.WritableStrings)
- Res.push_back("-fwritable-strings");
- if (Opts.ConstStrings)
- Res.push_back("-fconst-strings");
- if (!Opts.LaxVectorConversions)
- Res.push_back("-fno-lax-vector-conversions");
- if (Opts.AltiVec)
- Res.push_back("-faltivec");
- if (Opts.Exceptions)
- Res.push_back("-fexceptions");
- if (Opts.ObjCExceptions)
- Res.push_back("-fobjc-exceptions");
- if (Opts.CXXExceptions)
- Res.push_back("-fcxx-exceptions");
- if (Opts.SjLjExceptions)
- Res.push_back("-fsjlj-exceptions");
- if (Opts.TraditionalCPP)
- Res.push_back("-traditional-cpp");
- if (!Opts.RTTI)
- Res.push_back("-fno-rtti");
- if (Opts.MSBitfields)
- Res.push_back("-mms-bitfields");
- if (Opts.Freestanding)
- Res.push_back("-ffreestanding");
- if (Opts.NoBuiltin)
- Res.push_back("-fno-builtin");
- if (!Opts.AssumeSaneOperatorNew)
- Res.push_back("-fno-assume-sane-operator-new");
- if (!Opts.ThreadsafeStatics)
- Res.push_back("-fno-threadsafe-statics");
- if (Opts.POSIXThreads)
- Res.push_back("-pthread");
- if (Opts.Blocks)
- Res.push_back("-fblocks");
- if (Opts.BlocksRuntimeOptional)
- Res.push_back("-fblocks-runtime-optional");
- if (Opts.Modules)
- Res.push_back("-fmodules");
- if (Opts.EmitAllDecls)
- Res.push_back("-femit-all-decls");
- if (Opts.MathErrno)
- Res.push_back("-fmath-errno");
- switch (Opts.getSignedOverflowBehavior()) {
- case LangOptions::SOB_Undefined: break;
- case LangOptions::SOB_Defined: Res.push_back("-fwrapv"); break;
- case LangOptions::SOB_Trapping:
- Res.push_back("-ftrapv");
- if (!Opts.OverflowHandler.empty())
- Res.push_back("-ftrapv-handler", Opts.OverflowHandler);
- break;
- }
- switch (Opts.getFPContractMode()) {
- case LangOptions::FPC_Off: Res.push_back("-ffp-contract=off"); break;
- case LangOptions::FPC_On: Res.push_back("-ffp-contract=on"); break;
- case LangOptions::FPC_Fast: Res.push_back("-ffp-contract=fast"); break;
- }
- if (Opts.HeinousExtensions)
- Res.push_back("-fheinous-gnu-extensions");
- // Optimize is implicit.
- // OptimizeSize is implicit.
- if (Opts.FastMath)
- Res.push_back("-ffast-math");
- if (Opts.Static)
- Res.push_back("-static-define");
- if (Opts.DumpRecordLayoutsSimple)
- Res.push_back("-fdump-record-layouts-simple");
- else if (Opts.DumpRecordLayouts)
- Res.push_back("-fdump-record-layouts");
- if (Opts.DumpVTableLayouts)
- Res.push_back("-fdump-vtable-layouts");
- if (Opts.NoBitFieldTypeAlign)
- Res.push_back("-fno-bitfield-type-alignment");
- if (Opts.PICLevel)
- Res.push_back("-pic-level", llvm::utostr(Opts.PICLevel));
- if (Opts.PIELevel)
- Res.push_back("-pie-level", llvm::utostr(Opts.PIELevel));
- if (Opts.ObjCGCBitmapPrint)
- Res.push_back("-print-ivar-layout");
- if (Opts.NoConstantCFStrings)
- Res.push_back("-fno-constant-cfstrings");
- if (!Opts.AccessControl)
- Res.push_back("-fno-access-control");
- if (!Opts.CharIsSigned)
- Res.push_back("-fno-signed-char");
- if (Opts.ShortWChar)
- Res.push_back("-fshort-wchar");
- if (!Opts.ElideConstructors)
- Res.push_back("-fno-elide-constructors");
- if (Opts.getGC() != LangOptions::NonGC) {
- if (Opts.getGC() == LangOptions::HybridGC) {
- Res.push_back("-fobjc-gc");
- } else {
- assert(Opts.getGC() == LangOptions::GCOnly && "Invalid GC mode!");
- Res.push_back("-fobjc-gc-only");
- }
- }
- Res.push_back("-fobjc-runtime=" + Opts.ObjCRuntime.getAsString());
- if (Opts.ObjCAutoRefCount)
- Res.push_back("-fobjc-arc");
- if (Opts.ObjCRuntimeHasWeak)
- Res.push_back("-fobjc-runtime-has-weak");
- if (!Opts.ObjCInferRelatedResultType)
- Res.push_back("-fno-objc-infer-related-result-type");
-
- if (Opts.AppleKext)
- Res.push_back("-fapple-kext");
-
- if (Opts.getVisibilityMode() != DefaultVisibility) {
- Res.push_back("-fvisibility");
- if (Opts.getVisibilityMode() == HiddenVisibility) {
- Res.push_back("hidden");
- } else {
- assert(Opts.getVisibilityMode() == ProtectedVisibility &&
- "Invalid visibility!");
- Res.push_back("protected");
- }
- }
- if (Opts.InlineVisibilityHidden)
- Res.push_back("-fvisibility-inlines-hidden");
-
- if (Opts.getStackProtector() != 0)
- Res.push_back("-stack-protector", llvm::utostr(Opts.getStackProtector()));
- if (Opts.InstantiationDepth != DefaultLangOpts.InstantiationDepth)
- Res.push_back("-ftemplate-depth", llvm::utostr(Opts.InstantiationDepth));
- if (Opts.ConstexprCallDepth != DefaultLangOpts.ConstexprCallDepth)
- Res.push_back("-fconstexpr-depth", llvm::utostr(Opts.ConstexprCallDepth));
- if (!Opts.ObjCConstantStringClass.empty())
- Res.push_back("-fconstant-string-class", Opts.ObjCConstantStringClass);
- if (Opts.FakeAddressSpaceMap)
- Res.push_back("-ffake-address-space-map");
- if (Opts.ParseUnknownAnytype)
- Res.push_back("-funknown-anytype");
- if (Opts.DebuggerSupport)
- Res.push_back("-fdebugger-support");
- if (Opts.DebuggerCastResultToId)
- Res.push_back("-fdebugger-cast-result-to-id");
- if (Opts.DebuggerObjCLiteral)
- Res.push_back("-fdebugger-objc-literal");
- if (Opts.DelayedTemplateParsing)
- Res.push_back("-fdelayed-template-parsing");
- if (Opts.Deprecated)
- Res.push_back("-fdeprecated-macro");
- if (Opts.ApplePragmaPack)
- Res.push_back("-fapple-pragma-pack");
- if (!Opts.CurrentModule.empty())
- Res.push_back("-fmodule-name=" + Opts.CurrentModule);
-}
-
-static void PreprocessorOptsToArgs(const PreprocessorOptions &Opts,
- ToArgsList &Res) {
- for (unsigned i = 0, e = Opts.Macros.size(); i != e; ++i)
- Res.push_back(std::string(Opts.Macros[i].second ? "-U" : "-D") +
- Opts.Macros[i].first);
- for (unsigned i = 0, e = Opts.Includes.size(); i != e; ++i) {
- // FIXME: We need to avoid reincluding the implicit PCH and PTH includes.
- Res.push_back("-include", Opts.Includes[i]);
- }
- for (unsigned i = 0, e = Opts.MacroIncludes.size(); i != e; ++i)
- Res.push_back("-imacros", Opts.MacroIncludes[i]);
- if (!Opts.UsePredefines)
- Res.push_back("-undef");
- if (Opts.DetailedRecord)
- Res.push_back("-detailed-preprocessing-record");
- if (!Opts.ImplicitPCHInclude.empty())
- Res.push_back("-include-pch", Opts.ImplicitPCHInclude);
- if (!Opts.ImplicitPTHInclude.empty())
- Res.push_back("-include-pth", Opts.ImplicitPTHInclude);
- if (!Opts.TokenCache.empty()) {
- if (Opts.ImplicitPTHInclude.empty())
- Res.push_back("-token-cache", Opts.TokenCache);
- else
- assert(Opts.ImplicitPTHInclude == Opts.TokenCache &&
- "Unsupported option combination!");
- }
- for (unsigned i = 0, e = Opts.ChainedIncludes.size(); i != e; ++i)
- Res.push_back("-chain-include", Opts.ChainedIncludes[i]);
- for (unsigned i = 0, e = Opts.RemappedFiles.size(); i != e; ++i) {
- Res.push_back("-remap-file", Opts.RemappedFiles[i].first + ";" +
- Opts.RemappedFiles[i].second);
- }
-}
-
-static void PreprocessorOutputOptsToArgs(const PreprocessorOutputOptions &Opts,
- ToArgsList &Res) {
- if (!Opts.ShowCPP && !Opts.ShowMacros)
- llvm::report_fatal_error("Invalid option combination!");
-
- if (Opts.ShowCPP && Opts.ShowMacros)
- Res.push_back("-dD");
- else if (!Opts.ShowCPP && Opts.ShowMacros)
- Res.push_back("-dM");
-
- if (!Opts.ShowLineMarkers)
- Res.push_back("-P");
- if (Opts.ShowComments)
- Res.push_back("-C");
- if (Opts.ShowMacroComments)
- Res.push_back("-CC");
-}
-
-static void TargetOptsToArgs(const TargetOptions &Opts,
- ToArgsList &Res) {
- Res.push_back("-triple");
- Res.push_back(Opts.Triple);
- if (!Opts.CPU.empty())
- Res.push_back("-target-cpu", Opts.CPU);
- if (!Opts.ABI.empty())
- Res.push_back("-target-abi", Opts.ABI);
- if (!Opts.LinkerVersion.empty())
- Res.push_back("-target-linker-version", Opts.LinkerVersion);
- if (!Opts.CXXABI.empty())
- Res.push_back("-cxx-abi", Opts.CXXABI);
- for (unsigned i = 0, e = Opts.Features.size(); i != e; ++i)
- Res.push_back("-target-feature", Opts.Features[i]);
-}
-
-void CompilerInvocation::toArgs(std::vector<std::string> &Res) const {
- ToArgsList List(Res);
- AnalyzerOptsToArgs(getAnalyzerOpts(), List);
- CodeGenOptsToArgs(getCodeGenOpts(), List);
- DependencyOutputOptsToArgs(getDependencyOutputOpts(), List);
- DiagnosticOptsToArgs(getDiagnosticOpts(), List);
- FileSystemOptsToArgs(getFileSystemOpts(), List);
- FrontendOptsToArgs(getFrontendOpts(), List);
- HeaderSearchOptsToArgs(getHeaderSearchOpts(), List);
- LangOptsToArgs(*getLangOpts(), List);
- PreprocessorOptsToArgs(getPreprocessorOpts(), List);
- PreprocessorOutputOptsToArgs(getPreprocessorOutputOpts(), List);
- TargetOptsToArgs(getTargetOpts(), List);
-}
-
-//===----------------------------------------------------------------------===//
-// Deserialization (to args)
+// Deserialization (from args)
//===----------------------------------------------------------------------===//
using namespace clang::driver;
@@ -965,7 +71,7 @@ static unsigned getOptimizationLevel(ArgList &Args, InputKind IK,
assert (A->getOption().matches(options::OPT_O));
- llvm::StringRef S(A->getValue(Args));
+ llvm::StringRef S(A->getValue());
if (S == "s" || S == "z" || S.empty())
return 2;
@@ -979,7 +85,7 @@ static unsigned getOptimizationLevelSize(ArgList &Args, InputKind IK,
DiagnosticsEngine &Diags) {
if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
if (A->getOption().matches(options::OPT_O)) {
- switch (A->getValue(Args)[0]) {
+ switch (A->getValue()[0]) {
default:
return 0;
case 's':
@@ -996,14 +102,14 @@ static void addWarningArgs(ArgList &Args, std::vector<std::string> &Warnings) {
for (arg_iterator I = Args.filtered_begin(OPT_W_Group),
E = Args.filtered_end(); I != E; ++I) {
Arg *A = *I;
- // If the argument is a pure flag, add its name (minus the "-W" at the beginning)
+ // If the argument is a pure flag, add its name (minus the "W" at the beginning)
// to the warning list. Else, add its value (for the OPT_W case).
if (A->getOption().getKind() == Option::FlagClass) {
- Warnings.push_back(A->getOption().getName().substr(2));
+ Warnings.push_back(A->getOption().getName().substr(1));
} else {
for (unsigned Idx = 0, End = A->getNumValues();
Idx < End; ++Idx) {
- StringRef V = A->getValue(Args, Idx);
+ StringRef V = A->getValue(Idx);
// "-Wl," and such are not warning options.
// FIXME: Should be handled by putting these in separate flags.
if (V.startswith("l,") || V.startswith("a,") || V.startswith("p,"))
@@ -1020,11 +126,11 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
using namespace options;
bool Success = true;
if (Arg *A = Args.getLastArg(OPT_analyzer_store)) {
- StringRef Name = A->getValue(Args);
+ StringRef Name = A->getValue();
AnalysisStores Value = llvm::StringSwitch<AnalysisStores>(Name)
#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN) \
.Case(CMDFLAG, NAME##Model)
-#include "clang/Frontend/Analyses.def"
+#include "clang/StaticAnalyzer/Core/Analyses.def"
.Default(NumStores);
if (Value == NumStores) {
Diags.Report(diag::err_drv_invalid_value)
@@ -1036,11 +142,11 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
}
if (Arg *A = Args.getLastArg(OPT_analyzer_constraints)) {
- StringRef Name = A->getValue(Args);
+ StringRef Name = A->getValue();
AnalysisConstraints Value = llvm::StringSwitch<AnalysisConstraints>(Name)
#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN) \
.Case(CMDFLAG, NAME##Model)
-#include "clang/Frontend/Analyses.def"
+#include "clang/StaticAnalyzer/Core/Analyses.def"
.Default(NumConstraints);
if (Value == NumConstraints) {
Diags.Report(diag::err_drv_invalid_value)
@@ -1052,11 +158,11 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
}
if (Arg *A = Args.getLastArg(OPT_analyzer_output)) {
- StringRef Name = A->getValue(Args);
+ StringRef Name = A->getValue();
AnalysisDiagClients Value = llvm::StringSwitch<AnalysisDiagClients>(Name)
#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN, AUTOCREAT) \
.Case(CMDFLAG, PD_##NAME)
-#include "clang/Frontend/Analyses.def"
+#include "clang/StaticAnalyzer/Core/Analyses.def"
.Default(NUM_ANALYSIS_DIAG_CLIENTS);
if (Value == NUM_ANALYSIS_DIAG_CLIENTS) {
Diags.Report(diag::err_drv_invalid_value)
@@ -1068,11 +174,11 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
}
if (Arg *A = Args.getLastArg(OPT_analyzer_purge)) {
- StringRef Name = A->getValue(Args);
+ StringRef Name = A->getValue();
AnalysisPurgeMode Value = llvm::StringSwitch<AnalysisPurgeMode>(Name)
#define ANALYSIS_PURGE(NAME, CMDFLAG, DESC) \
.Case(CMDFLAG, NAME)
-#include "clang/Frontend/Analyses.def"
+#include "clang/StaticAnalyzer/Core/Analyses.def"
.Default(NumPurgeModes);
if (Value == NumPurgeModes) {
Diags.Report(diag::err_drv_invalid_value)
@@ -1084,11 +190,11 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
}
if (Arg *A = Args.getLastArg(OPT_analyzer_ipa)) {
- StringRef Name = A->getValue(Args);
+ StringRef Name = A->getValue();
AnalysisIPAMode Value = llvm::StringSwitch<AnalysisIPAMode>(Name)
#define ANALYSIS_IPA(NAME, CMDFLAG, DESC) \
.Case(CMDFLAG, NAME)
-#include "clang/Frontend/Analyses.def"
+#include "clang/StaticAnalyzer/Core/Analyses.def"
.Default(NumIPAModes);
if (Value == NumIPAModes) {
Diags.Report(diag::err_drv_invalid_value)
@@ -1100,11 +206,11 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
}
if (Arg *A = Args.getLastArg(OPT_analyzer_inlining_mode)) {
- StringRef Name = A->getValue(Args);
+ StringRef Name = A->getValue();
AnalysisInliningMode Value = llvm::StringSwitch<AnalysisInliningMode>(Name)
#define ANALYSIS_INLINING_MODE(NAME, CMDFLAG, DESC) \
.Case(CMDFLAG, NAME)
-#include "clang/Frontend/Analyses.def"
+#include "clang/StaticAnalyzer/Core/Analyses.def"
.Default(NumInliningModes);
if (Value == NumInliningModes) {
Diags.Report(diag::err_drv_invalid_value)
@@ -1116,21 +222,21 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
}
Opts.ShowCheckerHelp = Args.hasArg(OPT_analyzer_checker_help);
- Opts.VisualizeEGDot = Args.hasArg(OPT_analyzer_viz_egraph_graphviz);
- Opts.VisualizeEGUbi = Args.hasArg(OPT_analyzer_viz_egraph_ubigraph);
+ Opts.visualizeExplodedGraphWithGraphViz =
+ Args.hasArg(OPT_analyzer_viz_egraph_graphviz);
+ Opts.visualizeExplodedGraphWithUbiGraph =
+ Args.hasArg(OPT_analyzer_viz_egraph_ubigraph);
Opts.NoRetryExhausted = Args.hasArg(OPT_analyzer_disable_retry_exhausted);
Opts.AnalyzeAll = Args.hasArg(OPT_analyzer_opt_analyze_headers);
Opts.AnalyzerDisplayProgress = Args.hasArg(OPT_analyzer_display_progress);
Opts.AnalyzeNestedBlocks =
Args.hasArg(OPT_analyzer_opt_analyze_nested_blocks);
- Opts.EagerlyAssume = Args.hasArg(OPT_analyzer_eagerly_assume);
+ Opts.eagerlyAssumeBinOpBifurcation = Args.hasArg(OPT_analyzer_eagerly_assume);
Opts.AnalyzeSpecificFunction = Args.getLastArgValue(OPT_analyze_function);
Opts.UnoptimizedCFG = Args.hasArg(OPT_analysis_UnoptimizedCFG);
- Opts.CFGAddImplicitDtors = Args.hasArg(OPT_analysis_CFGAddImplicitDtors);
Opts.TrimGraph = Args.hasArg(OPT_trim_egraph);
Opts.MaxNodes = Args.getLastArgIntValue(OPT_analyzer_max_nodes, 150000,Diags);
- Opts.MaxLoop = Args.getLastArgIntValue(OPT_analyzer_max_loop, 4, Diags);
- Opts.EagerlyTrimEGraph = !Args.hasArg(OPT_analyzer_no_eagerly_trim_egraph);
+ Opts.maxBlockVisitOnPath = Args.getLastArgIntValue(OPT_analyzer_max_loop, 4, Diags);
Opts.PrintStats = Args.hasArg(OPT_analyzer_stats);
Opts.InlineMaxStackDepth =
Args.getLastArgIntValue(OPT_analyzer_inline_max_stack_depth,
@@ -1148,12 +254,42 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
bool enable = (A->getOption().getID() == OPT_analyzer_checker);
// We can have a list of comma separated checker names, e.g:
// '-analyzer-checker=cocoa,unix'
- StringRef checkerList = A->getValue(Args);
+ StringRef checkerList = A->getValue();
SmallVector<StringRef, 4> checkers;
checkerList.split(checkers, ",");
for (unsigned i = 0, e = checkers.size(); i != e; ++i)
Opts.CheckersControlList.push_back(std::make_pair(checkers[i], enable));
}
+
+ // Go through the analyzer configuration options.
+ for (arg_iterator it = Args.filtered_begin(OPT_analyzer_config),
+ ie = Args.filtered_end(); it != ie; ++it) {
+ const Arg *A = *it;
+ A->claim();
+ // We can have a list of comma separated config names, e.g:
+ // '-analyzer-config key1=val1,key2=val2'
+ StringRef configList = A->getValue();
+ SmallVector<StringRef, 4> configVals;
+ configList.split(configVals, ",");
+ for (unsigned i = 0, e = configVals.size(); i != e; ++i) {
+ StringRef key, val;
+ llvm::tie(key, val) = configVals[i].split("=");
+ if (val.empty()) {
+ Diags.Report(SourceLocation(),
+ diag::err_analyzer_config_no_value) << configVals[i];
+ Success = false;
+ break;
+ }
+ if (val.find('=') != StringRef::npos) {
+ Diags.Report(SourceLocation(),
+ diag::err_analyzer_config_multiple_values)
+ << configVals[i];
+ Success = false;
+ break;
+ }
+ Opts.Config[key] = val;
+ }
+ }
return Success;
}
@@ -1179,21 +315,23 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.OptimizationLevel = OptLevel;
// We must always run at least the always inlining pass.
- Opts.Inlining = (Opts.OptimizationLevel > 1) ? CodeGenOptions::NormalInlining
- : CodeGenOptions::OnlyAlwaysInlining;
+ Opts.setInlining(
+ (Opts.OptimizationLevel > 1) ? CodeGenOptions::NormalInlining
+ : CodeGenOptions::OnlyAlwaysInlining);
// -fno-inline-functions overrides OptimizationLevel > 1.
Opts.NoInline = Args.hasArg(OPT_fno_inline);
- Opts.Inlining = Args.hasArg(OPT_fno_inline_functions) ?
- CodeGenOptions::OnlyAlwaysInlining : Opts.Inlining;
+ Opts.setInlining(Args.hasArg(OPT_fno_inline_functions) ?
+ CodeGenOptions::OnlyAlwaysInlining : Opts.getInlining());
if (Args.hasArg(OPT_gline_tables_only)) {
- Opts.DebugInfo = CodeGenOptions::DebugLineTablesOnly;
+ Opts.setDebugInfo(CodeGenOptions::DebugLineTablesOnly);
} else if (Args.hasArg(OPT_g_Flag)) {
if (Args.hasFlag(OPT_flimit_debug_info, OPT_fno_limit_debug_info, true))
- Opts.DebugInfo = CodeGenOptions::LimitedDebugInfo;
+ Opts.setDebugInfo(CodeGenOptions::LimitedDebugInfo);
else
- Opts.DebugInfo = CodeGenOptions::FullDebugInfo;
+ Opts.setDebugInfo(CodeGenOptions::FullDebugInfo);
}
+ Opts.DebugColumnInfo = Args.hasArg(OPT_dwarf_column_info);
Opts.DisableLLVMOpts = Args.hasArg(OPT_disable_llvm_optzns);
Opts.DisableRedZone = Args.hasArg(OPT_disable_red_zone);
@@ -1263,18 +401,21 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.EmitGcovArcs = Args.hasArg(OPT_femit_coverage_data);
Opts.EmitGcovNotes = Args.hasArg(OPT_femit_coverage_notes);
Opts.EmitOpenCLArgMetadata = Args.hasArg(OPT_cl_kernel_arg_info);
- Opts.EmitMicrosoftInlineAsm = Args.hasArg(OPT_fenable_experimental_ms_inline_asm);
Opts.CoverageFile = Args.getLastArgValue(OPT_coverage_file);
Opts.DebugCompilationDir = Args.getLastArgValue(OPT_fdebug_compilation_dir);
Opts.LinkBitcodeFile = Args.getLastArgValue(OPT_mlink_bitcode_file);
+ Opts.SSPBufferSize =
+ Args.getLastArgIntValue(OPT_stack_protector_buffer_size, 8, Diags);
Opts.StackRealignment = Args.hasArg(OPT_mstackrealign);
if (Arg *A = Args.getLastArg(OPT_mstack_alignment)) {
- StringRef Val = A->getValue(Args);
- Val.getAsInteger(10, Opts.StackAlignment);
+ StringRef Val = A->getValue();
+ unsigned StackAlignment = Opts.StackAlignment;
+ Val.getAsInteger(10, StackAlignment);
+ Opts.StackAlignment = StackAlignment;
}
if (Arg *A = Args.getLastArg(OPT_fobjc_dispatch_method_EQ)) {
- StringRef Name = A->getValue(Args);
+ StringRef Name = A->getValue();
unsigned Method = llvm::StringSwitch<unsigned>(Name)
.Case("legacy", CodeGenOptions::Legacy)
.Case("non-legacy", CodeGenOptions::NonLegacy)
@@ -1284,12 +425,13 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name;
Success = false;
} else {
- Opts.ObjCDispatchMethod = Method;
+ Opts.setObjCDispatchMethod(
+ static_cast<CodeGenOptions::ObjCDispatchMethodKind>(Method));
}
}
if (Arg *A = Args.getLastArg(OPT_ftlsmodel_EQ)) {
- StringRef Name = A->getValue(Args);
+ StringRef Name = A->getValue();
unsigned Model = llvm::StringSwitch<unsigned>(Name)
.Case("global-dynamic", CodeGenOptions::GeneralDynamicTLSModel)
.Case("local-dynamic", CodeGenOptions::LocalDynamicTLSModel)
@@ -1300,7 +442,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name;
Success = false;
} else {
- Opts.DefaultTLSModel = static_cast<CodeGenOptions::TLSModel>(Model);
+ Opts.setDefaultTLSModel(static_cast<CodeGenOptions::TLSModel>(Model));
}
}
@@ -1351,9 +493,9 @@ bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
StringRef ShowOverloads =
Args.getLastArgValue(OPT_fshow_overloads_EQ, "all");
if (ShowOverloads == "best")
- Opts.ShowOverloads = DiagnosticsEngine::Ovl_Best;
+ Opts.setShowOverloads(Ovl_Best);
else if (ShowOverloads == "all")
- Opts.ShowOverloads = DiagnosticsEngine::Ovl_All;
+ Opts.setShowOverloads(Ovl_All);
else {
Success = false;
if (Diags)
@@ -1381,11 +523,11 @@ bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
StringRef Format =
Args.getLastArgValue(OPT_fdiagnostics_format, "clang");
if (Format == "clang")
- Opts.Format = DiagnosticOptions::Clang;
+ Opts.setFormat(DiagnosticOptions::Clang);
else if (Format == "msvc")
- Opts.Format = DiagnosticOptions::Msvc;
+ Opts.setFormat(DiagnosticOptions::Msvc);
else if (Format == "vi")
- Opts.Format = DiagnosticOptions::Vi;
+ Opts.setFormat(DiagnosticOptions::Vi);
else {
Success = false;
if (Diags)
@@ -1467,7 +609,7 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
case OPT_emit_obj:
Opts.ProgramAction = frontend::EmitObj; break;
case OPT_fixit_EQ:
- Opts.FixItSuffix = A->getValue(Args);
+ Opts.FixItSuffix = A->getValue();
// fall-through!
case OPT_fixit:
Opts.ProgramAction = frontend::FixIt; break;
@@ -1503,14 +645,14 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
}
if (const Arg* A = Args.getLastArg(OPT_plugin)) {
- Opts.Plugins.push_back(A->getValue(Args,0));
+ Opts.Plugins.push_back(A->getValue(0));
Opts.ProgramAction = frontend::PluginAction;
- Opts.ActionName = A->getValue(Args);
+ Opts.ActionName = A->getValue();
for (arg_iterator it = Args.filtered_begin(OPT_plugin_arg),
end = Args.filtered_end(); it != end; ++it) {
- if ((*it)->getValue(Args, 0) == Opts.ActionName)
- Opts.PluginArgs.push_back((*it)->getValue(Args, 1));
+ if ((*it)->getValue(0) == Opts.ActionName)
+ Opts.PluginArgs.push_back((*it)->getValue(1));
}
}
@@ -1519,17 +661,17 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
for (int i = 0, e = Opts.AddPluginActions.size(); i != e; ++i) {
for (arg_iterator it = Args.filtered_begin(OPT_plugin_arg),
end = Args.filtered_end(); it != end; ++it) {
- if ((*it)->getValue(Args, 0) == Opts.AddPluginActions[i])
- Opts.AddPluginArgs[i].push_back((*it)->getValue(Args, 1));
+ if ((*it)->getValue(0) == Opts.AddPluginActions[i])
+ Opts.AddPluginArgs[i].push_back((*it)->getValue(1));
}
}
if (const Arg *A = Args.getLastArg(OPT_code_completion_at)) {
Opts.CodeCompletionAt =
- ParsedSourceLocation::FromString(A->getValue(Args));
+ ParsedSourceLocation::FromString(A->getValue());
if (Opts.CodeCompletionAt.FileName.empty())
Diags.Report(diag::err_drv_invalid_value)
- << A->getAsString(Args) << A->getValue(Args);
+ << A->getAsString(Args) << A->getValue();
}
Opts.DisableFree = Args.hasArg(OPT_disable_free);
@@ -1595,7 +737,7 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
InputKind DashX = IK_None;
if (const Arg *A = Args.getLastArg(OPT_x)) {
- DashX = llvm::StringSwitch<InputKind>(A->getValue(Args))
+ DashX = llvm::StringSwitch<InputKind>(A->getValue())
.Case("c", IK_C)
.Case("cl", IK_OpenCL)
.Case("cuda", IK_CUDA)
@@ -1619,7 +761,7 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
.Default(IK_None);
if (DashX == IK_None)
Diags.Report(diag::err_drv_invalid_value)
- << A->getAsString(Args) << A->getValue(Args);
+ << A->getAsString(Args) << A->getValue();
}
// '-' is the default input if none is given.
@@ -1667,7 +809,7 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) {
Opts.UseStandardSystemIncludes = !Args.hasArg(OPT_nostdsysteminc);
Opts.UseStandardCXXIncludes = !Args.hasArg(OPT_nostdincxx);
if (const Arg *A = Args.getLastArg(OPT_stdlib_EQ))
- Opts.UseLibcxx = (strcmp(A->getValue(Args), "libc++") == 0);
+ Opts.UseLibcxx = (strcmp(A->getValue(), "libc++") == 0);
Opts.ResourceDir = Args.getLastArgValue(OPT_resource_dir);
Opts.ModuleCachePath = Args.getLastArgValue(OPT_fmodule_cache_path);
Opts.DisableModuleHash = Args.hasArg(OPT_fdisable_module_hash);
@@ -1686,7 +828,7 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) {
frontend::IncludeDirGroup Group
= IsIndexHeaderMap? frontend::IndexHeaderMap : frontend::Angled;
- Opts.AddPath((*it)->getValue(Args), Group, true,
+ Opts.AddPath((*it)->getValue(), Group, true,
/*IsFramework=*/ (*it)->getOption().matches(OPT_F), false);
IsIndexHeaderMap = false;
}
@@ -1698,43 +840,43 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) {
ie = Args.filtered_end(); it != ie; ++it) {
const Arg *A = *it;
if (A->getOption().matches(OPT_iprefix))
- Prefix = A->getValue(Args);
+ Prefix = A->getValue();
else if (A->getOption().matches(OPT_iwithprefix))
- Opts.AddPath(Prefix.str() + A->getValue(Args),
+ Opts.AddPath(Prefix.str() + A->getValue(),
frontend::System, false, false, false);
else
- Opts.AddPath(Prefix.str() + A->getValue(Args),
+ Opts.AddPath(Prefix.str() + A->getValue(),
frontend::Angled, false, false, false);
}
for (arg_iterator it = Args.filtered_begin(OPT_idirafter),
ie = Args.filtered_end(); it != ie; ++it)
- Opts.AddPath((*it)->getValue(Args), frontend::After, true, false, false);
+ Opts.AddPath((*it)->getValue(), frontend::After, true, false, false);
for (arg_iterator it = Args.filtered_begin(OPT_iquote),
ie = Args.filtered_end(); it != ie; ++it)
- Opts.AddPath((*it)->getValue(Args), frontend::Quoted, true, false, false);
+ Opts.AddPath((*it)->getValue(), frontend::Quoted, true, false, false);
for (arg_iterator it = Args.filtered_begin(OPT_isystem,
OPT_iwithsysroot), ie = Args.filtered_end(); it != ie; ++it)
- Opts.AddPath((*it)->getValue(Args), frontend::System, true, false,
+ Opts.AddPath((*it)->getValue(), frontend::System, true, false,
!(*it)->getOption().matches(OPT_iwithsysroot));
for (arg_iterator it = Args.filtered_begin(OPT_iframework),
ie = Args.filtered_end(); it != ie; ++it)
- Opts.AddPath((*it)->getValue(Args), frontend::System, true, true,
+ Opts.AddPath((*it)->getValue(), frontend::System, true, true,
true);
// Add the paths for the various language specific isystem flags.
for (arg_iterator it = Args.filtered_begin(OPT_c_isystem),
ie = Args.filtered_end(); it != ie; ++it)
- Opts.AddPath((*it)->getValue(Args), frontend::CSystem, true, false, true);
+ Opts.AddPath((*it)->getValue(), frontend::CSystem, true, false, true);
for (arg_iterator it = Args.filtered_begin(OPT_cxx_isystem),
ie = Args.filtered_end(); it != ie; ++it)
- Opts.AddPath((*it)->getValue(Args), frontend::CXXSystem, true, false, true);
+ Opts.AddPath((*it)->getValue(), frontend::CXXSystem, true, false, true);
for (arg_iterator it = Args.filtered_begin(OPT_objc_isystem),
ie = Args.filtered_end(); it != ie; ++it)
- Opts.AddPath((*it)->getValue(Args), frontend::ObjCSystem, true, false,true);
+ Opts.AddPath((*it)->getValue(), frontend::ObjCSystem, true, false,true);
for (arg_iterator it = Args.filtered_begin(OPT_objcxx_isystem),
ie = Args.filtered_end(); it != ie; ++it)
- Opts.AddPath((*it)->getValue(Args), frontend::ObjCXXSystem, true, false,
+ Opts.AddPath((*it)->getValue(), frontend::ObjCXXSystem, true, false,
true);
// Add the internal paths from a driver that detects standard include paths.
@@ -1742,7 +884,7 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) {
OPT_internal_externc_isystem),
E = Args.filtered_end();
I != E; ++I)
- Opts.AddPath((*I)->getValue(Args), frontend::System,
+ Opts.AddPath((*I)->getValue(), frontend::System,
false, false, /*IgnoreSysRoot=*/true, /*IsInternal=*/true,
(*I)->getOption().matches(OPT_internal_externc_isystem));
@@ -1751,7 +893,7 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) {
OPT_ino_system_prefix),
E = Args.filtered_end();
I != E; ++I)
- Opts.AddSystemHeaderPrefix((*I)->getValue(Args),
+ Opts.AddSystemHeaderPrefix((*I)->getValue(),
(*I)->getOption().matches(OPT_isystem_prefix));
}
@@ -1799,11 +941,12 @@ void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK,
}
const LangStandard &Std = LangStandard::getLangStandardForKind(LangStd);
- Opts.BCPLComment = Std.hasBCPLComments();
+ Opts.LineComment = Std.hasLineComments();
Opts.C99 = Std.isC99();
Opts.C11 = Std.isC11();
Opts.CPlusPlus = Std.isCPlusPlus();
Opts.CPlusPlus0x = Std.isCPlusPlus0x();
+ Opts.CPlusPlus1y = Std.isCPlusPlus1y();
Opts.Digraphs = Std.hasDigraphs();
Opts.GNUMode = Std.isGNUMode();
Opts.GNUInline = !Std.isC99();
@@ -1838,6 +981,9 @@ void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK,
// OpenCL and C++ both have bool, true, false keywords.
Opts.Bool = Opts.OpenCL || Opts.CPlusPlus;
+ // C++ has wchar_t keyword.
+ Opts.WChar = Opts.CPlusPlus;
+
Opts.GNUKeywords = Opts.GNUMode;
Opts.CXXOperatorNames = Opts.CPlusPlus;
@@ -1853,14 +999,14 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
// FIXME: Cleanup per-file based stuff.
LangStandard::Kind LangStd = LangStandard::lang_unspecified;
if (const Arg *A = Args.getLastArg(OPT_std_EQ)) {
- LangStd = llvm::StringSwitch<LangStandard::Kind>(A->getValue(Args))
+ LangStd = llvm::StringSwitch<LangStandard::Kind>(A->getValue())
#define LANGSTANDARD(id, name, desc, features) \
.Case(name, LangStandard::lang_##id)
#include "clang/Frontend/LangStandards.def"
.Default(LangStandard::lang_unspecified);
if (LangStd == LangStandard::lang_unspecified)
Diags.Report(diag::err_drv_invalid_value)
- << A->getAsString(Args) << A->getValue(Args);
+ << A->getAsString(Args) << A->getValue();
else {
// Valid standard, check to make sure language and standard are compatable.
const LangStandard &Std = LangStandard::getLangStandardForKind(LangStd);
@@ -1901,7 +1047,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
// Override the -std option in this case.
if (const Arg *A = Args.getLastArg(OPT_cl_std_EQ)) {
LangStandard::Kind OpenCLLangStd
- = llvm::StringSwitch<LangStandard::Kind>(A->getValue(Args))
+ = llvm::StringSwitch<LangStandard::Kind>(A->getValue())
.Case("CL", LangStandard::lang_opencl)
.Case("CL1.1", LangStandard::lang_opencl11)
.Case("CL1.2", LangStandard::lang_opencl12)
@@ -1909,7 +1055,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
if (OpenCLLangStd == LangStandard::lang_unspecified) {
Diags.Report(diag::err_drv_invalid_value)
- << A->getAsString(Args) << A->getValue(Args);
+ << A->getAsString(Args) << A->getValue();
}
else
LangStd = OpenCLLangStd;
@@ -1930,7 +1076,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
if (Opts.ObjC1) {
if (Arg *arg = Args.getLastArg(OPT_fobjc_runtime_EQ)) {
- StringRef value = arg->getValue(Args);
+ StringRef value = arg->getValue();
if (Opts.ObjCRuntime.tryParse(value))
Diags.Report(diag::err_drv_unknown_objc_runtime) << value;
}
@@ -1941,14 +1087,16 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.setGC(LangOptions::HybridGC);
else if (Args.hasArg(OPT_fobjc_arc)) {
Opts.ObjCAutoRefCount = 1;
- if (!Opts.ObjCRuntime.isNonFragile())
- Diags.Report(diag::err_arc_nonfragile_abi);
+ if (!Opts.ObjCRuntime.allowsARC())
+ Diags.Report(diag::err_arc_unsupported_on_runtime);
+
+ // Only set ObjCARCWeak if ARC is enabled.
+ if (Args.hasArg(OPT_fobjc_runtime_has_weak))
+ Opts.ObjCARCWeak = 1;
+ else
+ Opts.ObjCARCWeak = Opts.ObjCRuntime.allowsWeak();
}
- Opts.ObjCRuntimeHasWeak = Opts.ObjCRuntime.hasWeak();
- if (Args.hasArg(OPT_fobjc_runtime_has_weak))
- Opts.ObjCRuntimeHasWeak = 1;
-
if (Args.hasArg(OPT_fno_objc_infer_related_result_type))
Opts.ObjCInferRelatedResultType = 0;
}
@@ -1990,7 +1138,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
<< Args.getLastArg(OPT_fvisibility)->getAsString(Args) << Vis;
if (Arg *A = Args.getLastArg(OPT_ffp_contract)) {
- StringRef Val = A->getValue(Args);
+ StringRef Val = A->getValue();
if (Val == "fast")
Opts.setFPContractMode(LangOptions::FPC_Fast);
else if (Val == "on")
@@ -2043,6 +1191,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.BlocksRuntimeOptional = Args.hasArg(OPT_fblocks_runtime_optional);
Opts.Modules = Args.hasArg(OPT_fmodules);
Opts.CharIsSigned = !Args.hasArg(OPT_fno_signed_char);
+ Opts.WChar = Opts.CPlusPlus && !Args.hasArg(OPT_fno_wchar);
Opts.ShortWChar = Args.hasArg(OPT_fshort_wchar);
Opts.ShortEnums = Args.hasArg(OPT_fshort_enums);
Opts.Freestanding = Args.hasArg(OPT_ffreestanding);
@@ -2064,7 +1213,8 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Args.getLastArgValue(OPT_fconstant_string_class);
Opts.ObjCDefaultSynthProperties =
Args.hasArg(OPT_fobjc_default_synthesize_properties);
- Opts.CatchUndefined = Args.hasArg(OPT_fcatch_undefined_behavior);
+ Opts.EncodeExtendedBlockSig =
+ Args.hasArg(OPT_fencode_extended_block_signature);
Opts.EmitAllDecls = Args.hasArg(OPT_femit_all_decls);
Opts.PackStruct = Args.getLastArgIntValue(OPT_fpack_struct_EQ, 0, Diags);
Opts.PICLevel = Args.getLastArgIntValue(OPT_pic_level, 0, Diags);
@@ -2085,8 +1235,6 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.DebuggerSupport = Args.hasArg(OPT_fdebugger_support);
Opts.DebuggerCastResultToId = Args.hasArg(OPT_fdebugger_cast_result_to_id);
Opts.DebuggerObjCLiteral = Args.hasArg(OPT_fdebugger_objc_literal);
- Opts.AddressSanitizer = Args.hasArg(OPT_faddress_sanitizer);
- Opts.ThreadSanitizer = Args.hasArg(OPT_fthread_sanitizer);
Opts.ApplePragmaPack = Args.hasArg(OPT_fapple_pragma_pack);
Opts.CurrentModule = Args.getLastArgValue(OPT_fmodule_name);
@@ -2109,6 +1257,11 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.FastMath = Args.hasArg(OPT_ffast_math);
Opts.FiniteMathOnly = Args.hasArg(OPT_ffinite_math_only);
+ Opts.EmitMicrosoftInlineAsm = Args.hasArg(OPT_fenable_experimental_ms_inline_asm);
+
+ Opts.RetainCommentsFromSystemHeaders =
+ Args.hasArg(OPT_fretain_comments_from_system_headers);
+
unsigned SSP = Args.getLastArgIntValue(OPT_stack_protector, 0, Diags);
switch (SSP) {
default:
@@ -2119,6 +1272,37 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
case 1: Opts.setStackProtector(LangOptions::SSPOn); break;
case 2: Opts.setStackProtector(LangOptions::SSPReq); break;
}
+
+ // Parse -fsanitize= arguments.
+ std::vector<std::string> Sanitizers = Args.getAllArgValues(OPT_fsanitize_EQ);
+ for (unsigned I = 0, N = Sanitizers.size(); I != N; ++I) {
+ // Since the Opts.Sanitize* values are bitfields, it's a little tricky to
+ // efficiently map string values to them. Perform the mapping indirectly:
+ // convert strings to enumerated values, then switch over the enum to set
+ // the right bitfield value.
+ enum Sanitizer {
+#define SANITIZER(NAME, ID) \
+ ID,
+#include "clang/Basic/Sanitizers.def"
+ Unknown
+ };
+ switch (llvm::StringSwitch<unsigned>(Sanitizers[I])
+#define SANITIZER(NAME, ID) \
+ .Case(NAME, ID)
+#include "clang/Basic/Sanitizers.def"
+ .Default(Unknown)) {
+#define SANITIZER(NAME, ID) \
+ case ID: \
+ Opts.Sanitize##ID = true; \
+ break;
+#include "clang/Basic/Sanitizers.def"
+
+ case Unknown:
+ Diags.Report(diag::err_drv_invalid_value)
+ << "-fsanitize=" << Sanitizers[I];
+ break;
+ }
+ }
}
static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
@@ -2128,7 +1312,7 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
Opts.ImplicitPCHInclude = Args.getLastArgValue(OPT_include_pch);
Opts.ImplicitPTHInclude = Args.getLastArgValue(OPT_include_pth);
if (const Arg *A = Args.getLastArg(OPT_token_cache))
- Opts.TokenCache = A->getValue(Args);
+ Opts.TokenCache = A->getValue();
else
Opts.TokenCache = Opts.ImplicitPTHInclude;
Opts.UsePredefines = !Args.hasArg(OPT_undef);
@@ -2139,11 +1323,11 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
for (arg_iterator it = Args.filtered_begin(OPT_error_on_deserialized_pch_decl),
ie = Args.filtered_end(); it != ie; ++it) {
const Arg *A = *it;
- Opts.DeserializedPCHDeclsToErrorOn.insert(A->getValue(Args));
+ Opts.DeserializedPCHDeclsToErrorOn.insert(A->getValue());
}
if (const Arg *A = Args.getLastArg(OPT_preamble_bytes_EQ)) {
- StringRef Value(A->getValue(Args));
+ StringRef Value(A->getValue());
size_t Comma = Value.find(',');
unsigned Bytes = 0;
unsigned EndOfLine = 0;
@@ -2162,9 +1346,9 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
for (arg_iterator it = Args.filtered_begin(OPT_D, OPT_U),
ie = Args.filtered_end(); it != ie; ++it) {
if ((*it)->getOption().matches(OPT_D))
- Opts.addMacroDef((*it)->getValue(Args));
+ Opts.addMacroDef((*it)->getValue());
else
- Opts.addMacroUndef((*it)->getValue(Args));
+ Opts.addMacroUndef((*it)->getValue());
}
Opts.MacroIncludes = Args.getAllArgValues(OPT_imacros);
@@ -2174,22 +1358,13 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
OPT_include_pth),
ie = Args.filtered_end(); it != ie; ++it) {
const Arg *A = *it;
- // PCH is handled specially, we need to extra the original include path.
- if (A->getOption().matches(OPT_include_pch)) {
- std::string OriginalFile =
- ASTReader::getOriginalSourceFile(A->getValue(Args), FileMgr, Diags);
- if (OriginalFile.empty())
- continue;
-
- Opts.Includes.push_back(OriginalFile);
- } else
- Opts.Includes.push_back(A->getValue(Args));
+ Opts.Includes.push_back(A->getValue());
}
for (arg_iterator it = Args.filtered_begin(OPT_chain_include),
ie = Args.filtered_end(); it != ie; ++it) {
const Arg *A = *it;
- Opts.ChainedIncludes.push_back(A->getValue(Args));
+ Opts.ChainedIncludes.push_back(A->getValue());
}
// Include 'altivec.h' if -faltivec option present
@@ -2200,7 +1375,7 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
ie = Args.filtered_end(); it != ie; ++it) {
const Arg *A = *it;
std::pair<StringRef,StringRef> Split =
- StringRef(A->getValue(Args)).split(';');
+ StringRef(A->getValue()).split(';');
if (Split.second.empty()) {
Diags.Report(diag::err_drv_invalid_remap_file) << A->getAsString(Args);
@@ -2211,7 +1386,7 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
}
if (Arg *A = Args.getLastArg(OPT_fobjc_arc_cxxlib_EQ)) {
- StringRef Name = A->getValue(Args);
+ StringRef Name = A->getValue();
unsigned Library = llvm::StringSwitch<unsigned>(Name)
.Case("libc++", ARCXX_libcxx)
.Case("libstdc++", ARCXX_libstdcxx)
@@ -2240,7 +1415,7 @@ static void ParseTargetArgs(TargetOptions &Opts, ArgList &Args) {
Opts.ABI = Args.getLastArgValue(OPT_target_abi);
Opts.CXXABI = Args.getLastArgValue(OPT_cxx_abi);
Opts.CPU = Args.getLastArgValue(OPT_target_cpu);
- Opts.Features = Args.getAllArgValues(OPT_target_feature);
+ Opts.FeaturesAsWritten = Args.getAllArgValues(OPT_target_feature);
Opts.LinkerVersion = Args.getLastArgValue(OPT_target_linker_version);
Opts.Triple = llvm::Triple::normalize(Args.getLastArgValue(OPT_triple));
@@ -2280,13 +1455,13 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
// Issue errors on arguments that are not valid for CC1.
for (ArgList::iterator I = Args->begin(), E = Args->end();
I != E; ++I) {
- if (!(*I)->getOption().isCC1Option()) {
+ if (!(*I)->getOption().hasFlag(options::CC1Option)) {
Diags.Report(diag::err_drv_unknown_argument) << (*I)->getAsString(*Args);
Success = false;
}
}
- Success = ParseAnalyzerArgs(Res.getAnalyzerOpts(), *Args, Diags) && Success;
+ Success = ParseAnalyzerArgs(*Res.getAnalyzerOpts(), *Args, Diags) && Success;
Success = ParseMigratorArgs(Res.getMigratorOpts(), *Args) && Success;
ParseDependencyOutputArgs(Res.getDependencyOutputOpts(), *Args);
Success = ParseDiagnosticArgs(Res.getDiagnosticOpts(), *Args, &Diags)
@@ -2368,53 +1543,49 @@ llvm::APInt ModuleSignature::getAsInteger() const {
}
std::string CompilerInvocation::getModuleHash() const {
- ModuleSignature Signature;
-
+ using llvm::hash_code;
+ using llvm::hash_value;
+ using llvm::hash_combine;
+
// Start the signature with the compiler version.
- // FIXME: The full version string can be quite long. Omit it from the
- // module hash for now to avoid failures where the path name becomes too
- // long. An MD5 or similar checksum would work well here.
- // Signature.add(getClangFullRepositoryVersion());
-
+ // FIXME: We'd rather use something more cryptographically sound than
+ // CityHash, but this will do for now.
+ hash_code code = hash_value(getClangFullRepositoryVersion());
+
// Extend the signature with the language options
#define LANGOPT(Name, Bits, Default, Description) \
- Signature.add(LangOpts->Name, Bits);
+ code = hash_combine(code, LangOpts->Name);
#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \
- Signature.add(static_cast<unsigned>(LangOpts->get##Name()), Bits);
+ code = hash_combine(code, static_cast<unsigned>(LangOpts->get##Name()));
#define BENIGN_LANGOPT(Name, Bits, Default, Description)
#define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description)
#include "clang/Basic/LangOptions.def"
- // Extend the signature with the target triple
- llvm::Triple T(TargetOpts.Triple);
- Signature.add((unsigned)T.getArch(), 5);
- Signature.add((unsigned)T.getVendor(), 4);
- Signature.add((unsigned)T.getOS(), 5);
- Signature.add((unsigned)T.getEnvironment(), 4);
+ // Extend the signature with the target options.
+ code = hash_combine(code, TargetOpts->Triple, TargetOpts->CPU,
+ TargetOpts->ABI, TargetOpts->CXXABI,
+ TargetOpts->LinkerVersion);
+ for (unsigned i = 0, n = TargetOpts->FeaturesAsWritten.size(); i != n; ++i)
+ code = hash_combine(code, TargetOpts->FeaturesAsWritten[i]);
// Extend the signature with preprocessor options.
- Signature.add(getPreprocessorOpts().UsePredefines, 1);
- Signature.add(getPreprocessorOpts().DetailedRecord, 1);
-
- // Hash the preprocessor defines.
- // FIXME: This is terrible. Use an MD5 sum of the preprocessor defines.
+ const PreprocessorOptions &ppOpts = getPreprocessorOpts();
+ code = hash_combine(code, ppOpts.UsePredefines, ppOpts.DetailedRecord);
+
std::vector<StringRef> MacroDefs;
for (std::vector<std::pair<std::string, bool/*isUndef*/> >::const_iterator
I = getPreprocessorOpts().Macros.begin(),
IEnd = getPreprocessorOpts().Macros.end();
I != IEnd; ++I) {
- if (!I->second)
- MacroDefs.push_back(I->first);
+ code = hash_combine(code, I->first, I->second);
}
- llvm::array_pod_sort(MacroDefs.begin(), MacroDefs.end());
-
- unsigned PPHashResult = 0;
- for (unsigned I = 0, N = MacroDefs.size(); I != N; ++I)
- PPHashResult = llvm::HashString(MacroDefs[I], PPHashResult);
- Signature.add(PPHashResult, 32);
-
- // We've generated the signature. Treat it as one large APInt that we'll
- // encode in base-36 and return.
- Signature.flush();
- return Signature.getAsInteger().toString(36, /*Signed=*/false);
+
+ // Extend the signature with the sysroot.
+ const HeaderSearchOptions &hsOpts = getHeaderSearchOpts();
+ code = hash_combine(code, hsOpts.Sysroot, hsOpts.UseBuiltinIncludes,
+ hsOpts.UseStandardSystemIncludes,
+ hsOpts.UseStandardCXXIncludes,
+ hsOpts.UseLibcxx);
+
+ return llvm::APInt(64, code).toString(36, /*Signed=*/false);
}
diff --git a/lib/Frontend/CreateInvocationFromCommandLine.cpp b/lib/Frontend/CreateInvocationFromCommandLine.cpp
index 0aca86e2c97f..d82cb6d05157 100644
--- a/lib/Frontend/CreateInvocationFromCommandLine.cpp
+++ b/lib/Frontend/CreateInvocationFromCommandLine.cpp
@@ -11,9 +11,9 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Frontend/Utils.h"
#include "clang/Frontend/CompilerInstance.h"
-#include "clang/Frontend/DiagnosticOptions.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
@@ -34,8 +34,8 @@ clang::createInvocationFromCommandLine(ArrayRef<const char *> ArgList,
if (!Diags.getPtr()) {
// No diagnostics engine was provided, so create our own diagnostics object
// with the default options.
- DiagnosticOptions DiagOpts;
- Diags = CompilerInstance::createDiagnostics(DiagOpts, ArgList.size(),
+ Diags = CompilerInstance::createDiagnostics(new DiagnosticOptions,
+ ArgList.size(),
ArgList.begin());
}
@@ -49,11 +49,6 @@ clang::createInvocationFromCommandLine(ArrayRef<const char *> ArgList,
// FIXME: We shouldn't have to pass in the path info.
driver::Driver TheDriver("clang", llvm::sys::getDefaultTargetTriple(),
"a.out", false, *Diags);
- // Force driver to use clang.
- // FIXME: This seems like a hack. Maybe the "Clang" tool subclass should be
- // available for using it to get the arguments, thus avoiding the overkill
- // of using the driver.
- TheDriver.setForcedClangUse();
// Don't check that inputs exist, they may have been remapped.
TheDriver.setCheckInputsExist(false);
diff --git a/lib/Frontend/DependencyFile.cpp b/lib/Frontend/DependencyFile.cpp
index 21f5daa9ee39..53ea8befbc09 100644
--- a/lib/Frontend/DependencyFile.cpp
+++ b/lib/Frontend/DependencyFile.cpp
@@ -59,10 +59,11 @@ public:
const Token &IncludeTok,
StringRef FileName,
bool IsAngled,
+ CharSourceRange FilenameRange,
const FileEntry *File,
- SourceLocation EndLoc,
StringRef SearchPath,
- StringRef RelativePath);
+ StringRef RelativePath,
+ const Module *Imported);
virtual void EndOfMainFile() {
OutputDependencyFile();
@@ -132,10 +133,11 @@ void DependencyFileCallback::InclusionDirective(SourceLocation HashLoc,
const Token &IncludeTok,
StringRef FileName,
bool IsAngled,
+ CharSourceRange FilenameRange,
const FileEntry *File,
- SourceLocation EndLoc,
StringRef SearchPath,
- StringRef RelativePath) {
+ StringRef RelativePath,
+ const Module *Imported) {
if (!File) {
if (AddMissingHeaderDeps)
AddFilename(FileName);
diff --git a/lib/Frontend/DependencyGraph.cpp b/lib/Frontend/DependencyGraph.cpp
index eebaf0c8fe48..28d9c5d320e2 100644
--- a/lib/Frontend/DependencyGraph.cpp
+++ b/lib/Frontend/DependencyGraph.cpp
@@ -51,10 +51,11 @@ public:
const Token &IncludeTok,
StringRef FileName,
bool IsAngled,
+ CharSourceRange FilenameRange,
const FileEntry *File,
- SourceLocation EndLoc,
StringRef SearchPath,
- StringRef RelativePath);
+ StringRef RelativePath,
+ const Module *Imported);
virtual void EndOfMainFile() {
OutputGraphFile();
@@ -72,10 +73,11 @@ void DependencyGraphCallback::InclusionDirective(SourceLocation HashLoc,
const Token &IncludeTok,
StringRef FileName,
bool IsAngled,
+ CharSourceRange FilenameRange,
const FileEntry *File,
- SourceLocation EndLoc,
StringRef SearchPath,
- StringRef RelativePath) {
+ StringRef RelativePath,
+ const Module *Imported) {
if (!File)
return;
diff --git a/lib/Frontend/DiagnosticRenderer.cpp b/lib/Frontend/DiagnosticRenderer.cpp
index f052f90fa953..359b82be6062 100644
--- a/lib/Frontend/DiagnosticRenderer.cpp
+++ b/lib/Frontend/DiagnosticRenderer.cpp
@@ -8,9 +8,9 @@
//===----------------------------------------------------------------------===//
#include "clang/Frontend/DiagnosticRenderer.h"
+#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
-#include "clang/Frontend/DiagnosticOptions.h"
#include "clang/Lex/Lexer.h"
#include "clang/Edit/EditedSource.h"
#include "clang/Edit/Commit.h"
@@ -18,6 +18,7 @@
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallString.h"
#include <algorithm>
using namespace clang;
@@ -60,8 +61,8 @@ static StringRef getImmediateMacroName(SourceLocation Loc,
}
DiagnosticRenderer::DiagnosticRenderer(const LangOptions &LangOpts,
- const DiagnosticOptions &DiagOpts)
-: LangOpts(LangOpts), DiagOpts(DiagOpts), LastLevel() {}
+ DiagnosticOptions *DiagOpts)
+ : LangOpts(LangOpts), DiagOpts(DiagOpts), LastLevel() {}
DiagnosticRenderer::~DiagnosticRenderer() {}
@@ -194,7 +195,7 @@ void DiagnosticRenderer::emitIncludeStack(SourceLocation Loc,
return;
LastIncludeLoc = Loc;
- if (!DiagOpts.ShowNoteIncludeStack && Level == DiagnosticsEngine::Note)
+ if (!DiagOpts->ShowNoteIncludeStack && Level == DiagnosticsEngine::Note)
return;
emitIncludeStackRecursively(Loc, SM);
@@ -218,6 +219,53 @@ void DiagnosticRenderer::emitIncludeStackRecursively(SourceLocation Loc,
emitIncludeLocation(Loc, PLoc, SM);
}
+// Helper function to fix up source ranges. It takes in an array of ranges,
+// and outputs an array of ranges where we want to draw the range highlighting
+// around the location specified by CaretLoc.
+//
+// To find locations which correspond to the caret, we crawl the macro caller
+// chain for the beginning and end of each range. If the caret location
+// is in a macro expansion, we search each chain for a location
+// in the same expansion as the caret; otherwise, we crawl to the top of
+// each chain. Two locations are part of the same macro expansion
+// iff the FileID is the same.
+static void mapDiagnosticRanges(
+ SourceLocation CaretLoc,
+ const SmallVectorImpl<CharSourceRange>& Ranges,
+ SmallVectorImpl<CharSourceRange>& SpellingRanges,
+ const SourceManager *SM) {
+ FileID CaretLocFileID = SM->getFileID(CaretLoc);
+
+ for (SmallVectorImpl<CharSourceRange>::const_iterator I = Ranges.begin(),
+ E = Ranges.end();
+ I != E; ++I) {
+ SourceLocation Begin = I->getBegin(), End = I->getEnd();
+ bool IsTokenRange = I->isTokenRange();
+
+ // Search the macro caller chain for the beginning of the range.
+ while (Begin.isMacroID() && SM->getFileID(Begin) != CaretLocFileID)
+ Begin = SM->getImmediateMacroCallerLoc(Begin);
+
+ // Search the macro caller chain for the beginning of the range.
+ while (End.isMacroID() && SM->getFileID(End) != CaretLocFileID) {
+ // The computation of the next End is an inlined version of
+ // getImmediateMacroCallerLoc, except it chooses the end of an
+ // expansion range.
+ if (SM->isMacroArgExpansion(End)) {
+ End = SM->getImmediateSpellingLoc(End);
+ } else {
+ End = SM->getImmediateExpansionRange(End).second;
+ }
+ }
+
+ // Return the spelling location of the beginning and end of the range.
+ Begin = SM->getSpellingLoc(Begin);
+ End = SM->getSpellingLoc(End);
+ SpellingRanges.push_back(CharSourceRange(SourceRange(Begin, End),
+ IsTokenRange));
+ }
+}
+
/// \brief Recursively emit notes for each macro expansion and caret
/// diagnostics where appropriate.
///
@@ -245,9 +293,13 @@ void DiagnosticRenderer::emitMacroExpansionsAndCarets(
// If this is a file source location, directly emit the source snippet and
// caret line. Also record the macro depth reached.
if (Loc.isFileID()) {
+ // Map the ranges.
+ SmallVector<CharSourceRange, 4> SpellingRanges;
+ mapDiagnosticRanges(Loc, Ranges, SpellingRanges, &SM);
+
assert(MacroDepth == 0 && "We shouldn't hit a leaf node twice!");
MacroDepth = OnMacroInst;
- emitCodeContext(Loc, Level, Ranges, Hints, SM);
+ emitCodeContext(Loc, Level, SpellingRanges, Hints, SM);
return;
}
// Otherwise recurse through each macro expansion layer.
@@ -257,8 +309,7 @@ void DiagnosticRenderer::emitMacroExpansionsAndCarets(
Loc = SM.skipToMacroArgExpansion(Loc);
SourceLocation OneLevelUp = SM.getImmediateMacroCallerLoc(Loc);
-
- // FIXME: Map ranges?
+
emitMacroExpansionsAndCarets(OneLevelUp, Level, Ranges, Hints, SM, MacroDepth,
OnMacroInst + 1);
@@ -269,28 +320,17 @@ void DiagnosticRenderer::emitMacroExpansionsAndCarets(
Loc = SM.getImmediateMacroCalleeLoc(Loc);
unsigned MacroSkipStart = 0, MacroSkipEnd = 0;
- if (MacroDepth > DiagOpts.MacroBacktraceLimit &&
- DiagOpts.MacroBacktraceLimit != 0) {
- MacroSkipStart = DiagOpts.MacroBacktraceLimit / 2 +
- DiagOpts.MacroBacktraceLimit % 2;
- MacroSkipEnd = MacroDepth - DiagOpts.MacroBacktraceLimit / 2;
+ if (MacroDepth > DiagOpts->MacroBacktraceLimit &&
+ DiagOpts->MacroBacktraceLimit != 0) {
+ MacroSkipStart = DiagOpts->MacroBacktraceLimit / 2 +
+ DiagOpts->MacroBacktraceLimit % 2;
+ MacroSkipEnd = MacroDepth - DiagOpts->MacroBacktraceLimit / 2;
}
// Whether to suppress printing this macro expansion.
bool Suppressed = (OnMacroInst >= MacroSkipStart &&
OnMacroInst < MacroSkipEnd);
- // Map the ranges.
- for (SmallVectorImpl<CharSourceRange>::iterator I = Ranges.begin(),
- E = Ranges.end();
- I != E; ++I) {
- SourceLocation Start = I->getBegin(), End = I->getEnd();
- if (Start.isMacroID())
- I->setBegin(SM.getImmediateMacroCalleeLoc(Start));
- if (End.isMacroID())
- I->setEnd(SM.getImmediateMacroCalleeLoc(End));
- }
-
if (Suppressed) {
// Tell the user that we've skipped contexts.
if (OnMacroInst == MacroSkipStart) {
@@ -303,14 +343,18 @@ void DiagnosticRenderer::emitMacroExpansionsAndCarets(
}
return;
}
-
+
+ // Map the ranges.
+ SmallVector<CharSourceRange, 4> SpellingRanges;
+ mapDiagnosticRanges(MacroLoc, Ranges, SpellingRanges, &SM);
+
SmallString<100> MessageStorage;
llvm::raw_svector_ostream Message(MessageStorage);
Message << "expanded from macro '"
<< getImmediateMacroName(MacroLoc, SM, LangOpts) << "'";
emitDiagnostic(SM.getSpellingLoc(Loc), DiagnosticsEngine::Note,
Message.str(),
- Ranges, ArrayRef<FixItHint>(), &SM);
+ SpellingRanges, ArrayRef<FixItHint>(), &SM);
}
DiagnosticNoteRenderer::~DiagnosticNoteRenderer() {}
diff --git a/lib/Frontend/FrontendAction.cpp b/lib/Frontend/FrontendAction.cpp
index a4321e720ed0..2e9a791c3039 100644
--- a/lib/Frontend/FrontendAction.cpp
+++ b/lib/Frontend/FrontendAction.cpp
@@ -23,10 +23,12 @@
#include "clang/Parse/ParseAST.h"
#include "clang/Serialization/ASTDeserializationListener.h"
#include "clang/Serialization/ASTReader.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/Timer.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/system_error.h"
+#include "llvm/Support/Timer.h"
using namespace clang;
namespace {
@@ -155,20 +157,22 @@ ASTConsumer* FrontendAction::CreateWrappedASTConsumer(CompilerInstance &CI,
return new MultiplexConsumer(Consumers);
}
+
bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
const FrontendInputFile &Input) {
assert(!Instance && "Already processing a source file!");
- assert(!Input.File.empty() && "Unexpected empty filename!");
+ assert(!Input.isEmpty() && "Unexpected empty filename!");
setCurrentInput(Input);
setCompilerInstance(&CI);
+ StringRef InputFile = Input.getFile();
bool HasBegunSourceFile = false;
if (!BeginInvocation(CI))
goto failure;
// AST files follow a very different path, since they share objects via the
// AST unit.
- if (Input.Kind == IK_AST) {
+ if (Input.getKind() == IK_AST) {
assert(!usesPreprocessorOnly() &&
"Attempt to pass AST file to preprocessor only action!");
assert(hasASTFileSupport() &&
@@ -176,7 +180,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
IntrusiveRefCntPtr<DiagnosticsEngine> Diags(&CI.getDiagnostics());
std::string Error;
- ASTUnit *AST = ASTUnit::LoadFromASTFile(Input.File, Diags,
+ ASTUnit *AST = ASTUnit::LoadFromASTFile(InputFile, Diags,
CI.getFileSystemOpts());
if (!AST)
goto failure;
@@ -191,11 +195,11 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
CI.setASTContext(&AST->getASTContext());
// Initialize the action.
- if (!BeginSourceFileAction(CI, Input.File))
+ if (!BeginSourceFileAction(CI, InputFile))
goto failure;
/// Create the AST consumer.
- CI.setASTConsumer(CreateWrappedASTConsumer(CI, Input.File));
+ CI.setASTConsumer(CreateWrappedASTConsumer(CI, InputFile));
if (!CI.hasASTConsumer())
goto failure;
@@ -209,7 +213,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
CI.createSourceManager(CI.getFileManager());
// IR files bypass the rest of initialization.
- if (Input.Kind == IK_LLVM_IR) {
+ if (Input.getKind() == IK_LLVM_IR) {
assert(hasIRSupport() &&
"This action does not have IR file support!");
@@ -218,12 +222,51 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
HasBegunSourceFile = true;
// Initialize the action.
- if (!BeginSourceFileAction(CI, Input.File))
+ if (!BeginSourceFileAction(CI, InputFile))
goto failure;
return true;
}
+ // If the implicit PCH include is actually a directory, rather than
+ // a single file, search for a suitable PCH file in that directory.
+ if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) {
+ FileManager &FileMgr = CI.getFileManager();
+ PreprocessorOptions &PPOpts = CI.getPreprocessorOpts();
+ StringRef PCHInclude = PPOpts.ImplicitPCHInclude;
+ if (const DirectoryEntry *PCHDir = FileMgr.getDirectory(PCHInclude)) {
+ llvm::error_code EC;
+ SmallString<128> DirNative;
+ llvm::sys::path::native(PCHDir->getName(), DirNative);
+ bool Found = false;
+ for (llvm::sys::fs::directory_iterator Dir(DirNative.str(), EC), DirEnd;
+ Dir != DirEnd && !EC; Dir.increment(EC)) {
+ // Check whether this is an acceptable AST file.
+ if (ASTReader::isAcceptableASTFile(Dir->path(), FileMgr,
+ CI.getLangOpts(),
+ CI.getTargetOpts(),
+ CI.getPreprocessorOpts())) {
+ for (unsigned I = 0, N = PPOpts.Includes.size(); I != N; ++I) {
+ if (PPOpts.Includes[I] == PPOpts.ImplicitPCHInclude) {
+ PPOpts.Includes[I] = Dir->path();
+ PPOpts.ImplicitPCHInclude = Dir->path();
+ Found = true;
+ break;
+ }
+ }
+
+ assert(Found && "Implicit PCH include not in includes list?");
+ break;
+ }
+ }
+
+ if (!Found) {
+ CI.getDiagnostics().Report(diag::err_fe_no_pch_in_dir) << PCHInclude;
+ return true;
+ }
+ }
+ }
+
// Set up the preprocessor.
CI.createPreprocessor();
@@ -233,7 +276,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
HasBegunSourceFile = true;
// Initialize the action.
- if (!BeginSourceFileAction(CI, Input.File))
+ if (!BeginSourceFileAction(CI, InputFile))
goto failure;
/// Create the AST context and consumer unless this is a preprocessor only
@@ -242,12 +285,14 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
CI.createASTContext();
OwningPtr<ASTConsumer> Consumer(
- CreateWrappedASTConsumer(CI, Input.File));
+ CreateWrappedASTConsumer(CI, InputFile));
if (!Consumer)
goto failure;
CI.getASTContext().setASTMutationListener(Consumer->GetASTMutationListener());
-
+ CI.getPreprocessor().setPPMutationListener(
+ Consumer->GetPPMutationListener());
+
if (!CI.getPreprocessorOpts().ChainedIncludes.empty()) {
// Convert headers to PCH and chain them.
OwningPtr<ExternalASTSource> source;
@@ -270,7 +315,6 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
CI.createPCHExternalASTSource(
CI.getPreprocessorOpts().ImplicitPCHInclude,
CI.getPreprocessorOpts().DisablePCHValidation,
- CI.getPreprocessorOpts().DisableStatCache,
CI.getPreprocessorOpts().AllowPCHWithCompilerErrors,
DeserialListener);
if (!CI.getASTContext().getExternalSource())
@@ -314,6 +358,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
if (HasBegunSourceFile)
CI.getDiagnosticClient().EndSourceFile();
+ CI.clearOutputFiles(/*EraseFiles=*/true);
setCurrentInput(FrontendInputFile());
setCompilerInstance(0);
return false;
@@ -325,10 +370,7 @@ bool FrontendAction::Execute() {
// Initialize the main file entry. This needs to be delayed until after PCH
// has loaded.
if (!isCurrentFileAST()) {
- if (!CI.InitializeSourceManager(getCurrentFile(),
- getCurrentInput().IsSystem
- ? SrcMgr::C_System
- : SrcMgr::C_User))
+ if (!CI.InitializeSourceManager(getCurrentInput()))
return false;
}
diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp
index 24960cf6a0c9..47063f78b5d9 100644
--- a/lib/Frontend/FrontendActions.cpp
+++ b/lib/Frontend/FrontendActions.cpp
@@ -131,8 +131,31 @@ ASTConsumer *GenerateModuleAction::CreateASTConsumer(CompilerInstance &CI,
Sysroot, OS);
}
+static SmallVectorImpl<char> &
+operator+=(SmallVectorImpl<char> &Includes, StringRef RHS) {
+ Includes.append(RHS.begin(), RHS.end());
+ return Includes;
+}
+
+static void addHeaderInclude(StringRef HeaderName,
+ SmallVectorImpl<char> &Includes,
+ const LangOptions &LangOpts) {
+ if (LangOpts.ObjC1)
+ Includes += "#import \"";
+ else
+ Includes += "#include \"";
+ Includes += HeaderName;
+ Includes += "\"\n";
+}
+
+static void addHeaderInclude(const FileEntry *Header,
+ SmallVectorImpl<char> &Includes,
+ const LangOptions &LangOpts) {
+ addHeaderInclude(Header->getName(), Includes, LangOpts);
+}
+
/// \brief Collect the set of header includes needed to construct the given
-/// module.
+/// module and update the TopHeaders file set of the module.
///
/// \param Module The module we're collecting includes from.
///
@@ -142,30 +165,23 @@ static void collectModuleHeaderIncludes(const LangOptions &LangOpts,
FileManager &FileMgr,
ModuleMap &ModMap,
clang::Module *Module,
- SmallString<256> &Includes) {
+ SmallVectorImpl<char> &Includes) {
// Don't collect any headers for unavailable modules.
if (!Module->isAvailable())
return;
// Add includes for each of these headers.
for (unsigned I = 0, N = Module->Headers.size(); I != N; ++I) {
- if (LangOpts.ObjC1)
- Includes += "#import \"";
- else
- Includes += "#include \"";
- Includes += Module->Headers[I]->getName();
- Includes += "\"\n";
+ const FileEntry *Header = Module->Headers[I];
+ Module->TopHeaders.insert(Header);
+ addHeaderInclude(Header, Includes, LangOpts);
}
if (const FileEntry *UmbrellaHeader = Module->getUmbrellaHeader()) {
+ Module->TopHeaders.insert(UmbrellaHeader);
if (Module->Parent) {
// Include the umbrella header for submodules.
- if (LangOpts.ObjC1)
- Includes += "#import \"";
- else
- Includes += "#include \"";
- Includes += UmbrellaHeader->getName();
- Includes += "\"\n";
+ addHeaderInclude(UmbrellaHeader, Includes, LangOpts);
}
} else if (const DirectoryEntry *UmbrellaDir = Module->getUmbrellaDir()) {
// Add all of the headers we find in this subdirectory.
@@ -184,17 +200,14 @@ static void collectModuleHeaderIncludes(const LangOptions &LangOpts,
// If this header is marked 'unavailable' in this module, don't include
// it.
- if (const FileEntry *Header = FileMgr.getFile(Dir->path()))
+ if (const FileEntry *Header = FileMgr.getFile(Dir->path())) {
if (ModMap.isHeaderInUnavailableModule(Header))
continue;
+ Module->TopHeaders.insert(Header);
+ }
// Include this header umbrella header for submodules.
- if (LangOpts.ObjC1)
- Includes += "#import \"";
- else
- Includes += "#include \"";
- Includes += Dir->path();
- Includes += "\"\n";
+ addHeaderInclude(Dir->path(), Includes, LangOpts);
}
}
@@ -250,77 +263,29 @@ bool GenerateModuleAction::BeginSourceFileAction(CompilerInstance &CI,
return false;
}
- // Do we have an umbrella header for this module?
- const FileEntry *UmbrellaHeader = Module->getUmbrellaHeader();
-
+ FileManager &FileMgr = CI.getFileManager();
+
// Collect the set of #includes we need to build the module.
SmallString<256> HeaderContents;
- collectModuleHeaderIncludes(CI.getLangOpts(), CI.getFileManager(),
+ if (const FileEntry *UmbrellaHeader = Module->getUmbrellaHeader())
+ addHeaderInclude(UmbrellaHeader, HeaderContents, CI.getLangOpts());
+ collectModuleHeaderIncludes(CI.getLangOpts(), FileMgr,
CI.getPreprocessor().getHeaderSearchInfo().getModuleMap(),
Module, HeaderContents);
- if (UmbrellaHeader && HeaderContents.empty()) {
- // Simple case: we have an umbrella header and there are no additional
- // includes, we can just parse the umbrella header directly.
- setCurrentInput(FrontendInputFile(UmbrellaHeader->getName(),
- getCurrentFileKind(),
- Module->IsSystem));
- return true;
- }
-
- FileManager &FileMgr = CI.getFileManager();
- SmallString<128> HeaderName;
- time_t ModTime;
- if (UmbrellaHeader) {
- // Read in the umbrella header.
- // FIXME: Go through the source manager; the umbrella header may have
- // been overridden.
- std::string ErrorStr;
- llvm::MemoryBuffer *UmbrellaContents
- = FileMgr.getBufferForFile(UmbrellaHeader, &ErrorStr);
- if (!UmbrellaContents) {
- CI.getDiagnostics().Report(diag::err_missing_umbrella_header)
- << UmbrellaHeader->getName() << ErrorStr;
- return false;
- }
-
- // Combine the contents of the umbrella header with the automatically-
- // generated includes.
- SmallString<256> OldContents = HeaderContents;
- HeaderContents = UmbrellaContents->getBuffer();
- HeaderContents += "\n\n";
- HeaderContents += "/* Module includes */\n";
- HeaderContents += OldContents;
-
- // Pretend that we're parsing the umbrella header.
- HeaderName = UmbrellaHeader->getName();
- ModTime = UmbrellaHeader->getModificationTime();
-
- delete UmbrellaContents;
- } else {
- // Pick an innocuous-sounding name for the umbrella header.
- HeaderName = Module->Name + ".h";
- if (FileMgr.getFile(HeaderName, /*OpenFile=*/false,
- /*CacheFailure=*/false)) {
- // Try again!
- HeaderName = Module->Name + "-module.h";
- if (FileMgr.getFile(HeaderName, /*OpenFile=*/false,
- /*CacheFailure=*/false)) {
- // Pick something ridiculous and go with it.
- HeaderName = Module->Name + "-module.hmod";
- }
- }
- ModTime = time(0);
- }
-
- // Remap the contents of the header name we're using to our synthesized
- // buffer.
- const FileEntry *HeaderFile = FileMgr.getVirtualFile(HeaderName,
+
+ StringRef InputName = Module::getModuleInputBufferName();
+
+ // We consistently construct a buffer as input to build the module.
+ // This means the main file for modules will always be a virtual one.
+ // FIXME: Maybe allow using a memory buffer as input directly instead of
+ // messing with virtual files.
+ const FileEntry *HeaderFile = FileMgr.getVirtualFile(InputName,
HeaderContents.size(),
- ModTime);
+ time(0));
llvm::MemoryBuffer *HeaderContentsBuf
= llvm::MemoryBuffer::getMemBufferCopy(HeaderContents);
CI.getSourceManager().overrideFileContents(HeaderFile, HeaderContentsBuf);
- setCurrentInput(FrontendInputFile(HeaderName, getCurrentFileKind(),
+ setCurrentInput(FrontendInputFile(InputName, getCurrentFileKind(),
Module->IsSystem));
return true;
}
diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp
index 8178f7a9362a..4fddd112df7e 100644
--- a/lib/Frontend/InitHeaderSearch.cpp
+++ b/lib/Frontend/InitHeaderSearch.cpp
@@ -14,7 +14,7 @@
#include "clang/Frontend/Utils.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/LangOptions.h"
-#include "clang/Frontend/HeaderSearchOptions.h"
+#include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Lex/HeaderSearch.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallPtrSet.h"
@@ -320,7 +320,9 @@ void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple,
P.appendComponent("../../../include"); // <sysroot>/include
AddPath(P.str(), System, true, false, false);
AddPath("/mingw/include", System, true, false, false);
+#if defined(_WIN32)
AddPath("c:/mingw/include", System, true, false, false);
+#endif
}
break;
@@ -396,12 +398,14 @@ AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple, const HeaderSearchOp
AddMinGW64CXXPaths(HSOpts.ResourceDir, "4.7.0");
// mingw.org C++ include paths
AddMinGWCPlusPlusIncludePaths("/mingw/lib/gcc", "mingw32", "4.5.2"); //MSYS
+#if defined(_WIN32)
AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.6.2");
AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.6.1");
AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.5.2");
AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.5.0");
AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.4.0");
AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.3.0");
+#endif
break;
case llvm::Triple::DragonFly:
AddPath("/usr/include/c++/4.1", CXXSystem, true, false, false);
diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp
index 1440da6e3755..4bbd033f1c2e 100644
--- a/lib/Frontend/InitPreprocessor.cpp
+++ b/lib/Frontend/InitPreprocessor.cpp
@@ -17,11 +17,12 @@
#include "clang/Basic/TargetInfo.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/FrontendOptions.h"
-#include "clang/Frontend/PreprocessorOptions.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Serialization/ASTReader.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -83,6 +84,19 @@ static void AddImplicitIncludePTH(MacroBuilder &Builder, Preprocessor &PP,
AddImplicitInclude(Builder, OriginalFile, PP.getFileManager());
}
+/// \brief Add an implicit \#include using the original file used to generate
+/// a PCH file.
+static void AddImplicitIncludePCH(MacroBuilder &Builder, Preprocessor &PP,
+ StringRef ImplicitIncludePCH) {
+ std::string OriginalFile =
+ ASTReader::getOriginalSourceFile(ImplicitIncludePCH, PP.getFileManager(),
+ PP.getDiagnostics());
+ if (OriginalFile.empty())
+ return;
+
+ AddImplicitInclude(Builder, OriginalFile, PP.getFileManager());
+}
+
/// PickFP - This is used to pick a value based on the FP semantics of the
/// specified FP model.
template <typename T>
@@ -102,51 +116,51 @@ static T PickFP(const llvm::fltSemantics *Sem, T IEEESingleVal,
}
static void DefineFloatMacros(MacroBuilder &Builder, StringRef Prefix,
- const llvm::fltSemantics *Sem) {
+ const llvm::fltSemantics *Sem, StringRef Ext) {
const char *DenormMin, *Epsilon, *Max, *Min;
- DenormMin = PickFP(Sem, "1.40129846e-45F", "4.9406564584124654e-324",
- "3.64519953188247460253e-4951L",
- "4.94065645841246544176568792868221e-324L",
- "6.47517511943802511092443895822764655e-4966L");
+ DenormMin = PickFP(Sem, "1.40129846e-45", "4.9406564584124654e-324",
+ "3.64519953188247460253e-4951",
+ "4.94065645841246544176568792868221e-324",
+ "6.47517511943802511092443895822764655e-4966");
int Digits = PickFP(Sem, 6, 15, 18, 31, 33);
- Epsilon = PickFP(Sem, "1.19209290e-7F", "2.2204460492503131e-16",
- "1.08420217248550443401e-19L",
- "4.94065645841246544176568792868221e-324L",
- "1.92592994438723585305597794258492732e-34L");
+ Epsilon = PickFP(Sem, "1.19209290e-7", "2.2204460492503131e-16",
+ "1.08420217248550443401e-19",
+ "4.94065645841246544176568792868221e-324",
+ "1.92592994438723585305597794258492732e-34");
int MantissaDigits = PickFP(Sem, 24, 53, 64, 106, 113);
int Min10Exp = PickFP(Sem, -37, -307, -4931, -291, -4931);
int Max10Exp = PickFP(Sem, 38, 308, 4932, 308, 4932);
int MinExp = PickFP(Sem, -125, -1021, -16381, -968, -16381);
int MaxExp = PickFP(Sem, 128, 1024, 16384, 1024, 16384);
- Min = PickFP(Sem, "1.17549435e-38F", "2.2250738585072014e-308",
- "3.36210314311209350626e-4932L",
- "2.00416836000897277799610805135016e-292L",
- "3.36210314311209350626267781732175260e-4932L");
- Max = PickFP(Sem, "3.40282347e+38F", "1.7976931348623157e+308",
- "1.18973149535723176502e+4932L",
- "1.79769313486231580793728971405301e+308L",
- "1.18973149535723176508575932662800702e+4932L");
+ Min = PickFP(Sem, "1.17549435e-38", "2.2250738585072014e-308",
+ "3.36210314311209350626e-4932",
+ "2.00416836000897277799610805135016e-292",
+ "3.36210314311209350626267781732175260e-4932");
+ Max = PickFP(Sem, "3.40282347e+38", "1.7976931348623157e+308",
+ "1.18973149535723176502e+4932",
+ "1.79769313486231580793728971405301e+308",
+ "1.18973149535723176508575932662800702e+4932");
SmallString<32> DefPrefix;
DefPrefix = "__";
DefPrefix += Prefix;
DefPrefix += "_";
- Builder.defineMacro(DefPrefix + "DENORM_MIN__", DenormMin);
+ Builder.defineMacro(DefPrefix + "DENORM_MIN__", Twine(DenormMin)+Ext);
Builder.defineMacro(DefPrefix + "HAS_DENORM__");
Builder.defineMacro(DefPrefix + "DIG__", Twine(Digits));
- Builder.defineMacro(DefPrefix + "EPSILON__", Twine(Epsilon));
+ Builder.defineMacro(DefPrefix + "EPSILON__", Twine(Epsilon)+Ext);
Builder.defineMacro(DefPrefix + "HAS_INFINITY__");
Builder.defineMacro(DefPrefix + "HAS_QUIET_NAN__");
Builder.defineMacro(DefPrefix + "MANT_DIG__", Twine(MantissaDigits));
Builder.defineMacro(DefPrefix + "MAX_10_EXP__", Twine(Max10Exp));
Builder.defineMacro(DefPrefix + "MAX_EXP__", Twine(MaxExp));
- Builder.defineMacro(DefPrefix + "MAX__", Twine(Max));
+ Builder.defineMacro(DefPrefix + "MAX__", Twine(Max)+Ext);
Builder.defineMacro(DefPrefix + "MIN_10_EXP__","("+Twine(Min10Exp)+")");
Builder.defineMacro(DefPrefix + "MIN_EXP__", "("+Twine(MinExp)+")");
- Builder.defineMacro(DefPrefix + "MIN__", Twine(Min));
+ Builder.defineMacro(DefPrefix + "MIN__", Twine(Min)+Ext);
}
@@ -247,7 +261,7 @@ static void AddObjCXXARCLibstdcxxDefines(const LangOptions &LangOpts,
<< "};\n"
<< "\n";
- if (LangOpts.ObjCRuntimeHasWeak) {
+ if (LangOpts.ObjCARCWeak) {
Out << "template<typename _Tp>\n"
<< "struct __is_scalar<__attribute__((objc_ownership(weak))) _Tp> {\n"
<< " enum { __value = 0 };\n"
@@ -288,6 +302,8 @@ static void InitializeStandardPredefinedMacros(const TargetInfo &TI,
else if (!LangOpts.GNUMode && LangOpts.Digraphs)
Builder.defineMacro("__STDC_VERSION__", "199409L");
} else {
+ // FIXME: LangOpts.CPlusPlus1y
+
// C++11 [cpp.predefined]p1:
// The name __cplusplus is defined to the value 201103L when compiling a
// C++ translation unit.
@@ -325,8 +341,8 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
Builder.defineMacro("__clang_patchlevel__", "0");
#endif
Builder.defineMacro("__clang_version__",
- "\"" CLANG_VERSION_STRING " ("
- + getClangFullRepositoryVersion() + ")\"");
+ "\"" CLANG_VERSION_STRING " "
+ + getClangFullRepositoryVersion() + "\"");
#undef TOSTR
#undef TOSTR2
if (!LangOpts.MicrosoftMode) {
@@ -420,19 +436,17 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
// Both __PRETTY_FUNCTION__ and __FUNCTION__ are GCC extensions, however
// VC++ appears to only like __FUNCTION__.
Builder.defineMacro("__PRETTY_FUNCTION__", "__FUNCTION__");
- // Work around some issues with Visual C++ headerws.
- if (LangOpts.CPlusPlus) {
- // Since we define wchar_t in C++ mode.
+ // Work around some issues with Visual C++ headers.
+ if (LangOpts.WChar) {
+ // wchar_t supported as a keyword.
Builder.defineMacro("_WCHAR_T_DEFINED");
Builder.defineMacro("_NATIVE_WCHAR_T_DEFINED");
+ }
+ if (LangOpts.CPlusPlus) {
// FIXME: Support Microsoft's __identifier extension in the lexer.
Builder.append("#define __identifier(x) x");
Builder.append("class type_info;");
}
-
- if (LangOpts.CPlusPlus0x) {
- Builder.defineMacro("_HAS_CHAR16_T_LANGUAGE_SUPPORT", "1");
- }
}
if (LangOpts.Optimize)
@@ -511,9 +525,9 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
DefineType("__CHAR16_TYPE__", TI.getChar16Type(), Builder);
DefineType("__CHAR32_TYPE__", TI.getChar32Type(), Builder);
- DefineFloatMacros(Builder, "FLT", &TI.getFloatFormat());
- DefineFloatMacros(Builder, "DBL", &TI.getDoubleFormat());
- DefineFloatMacros(Builder, "LDBL", &TI.getLongDoubleFormat());
+ DefineFloatMacros(Builder, "FLT", &TI.getFloatFormat(), "F");
+ DefineFloatMacros(Builder, "DBL", &TI.getDoubleFormat(), "");
+ DefineFloatMacros(Builder, "LDBL", &TI.getLongDoubleFormat(), "L");
// Define a __POINTER_WIDTH__ macro for stdint.h.
Builder.defineMacro("__POINTER_WIDTH__",
@@ -763,6 +777,8 @@ void clang::InitializePreprocessor(Preprocessor &PP,
const std::string &Path = InitOpts.Includes[i];
if (Path == InitOpts.ImplicitPTHInclude)
AddImplicitIncludePTH(Builder, PP, Path);
+ else if (Path == InitOpts.ImplicitPCHInclude)
+ AddImplicitIncludePCH(Builder, PP, Path);
else
AddImplicitInclude(Builder, Path, PP.getFileManager());
}
diff --git a/lib/Frontend/LogDiagnosticPrinter.cpp b/lib/Frontend/LogDiagnosticPrinter.cpp
index 3fee95749986..3a04f1859bda 100644
--- a/lib/Frontend/LogDiagnosticPrinter.cpp
+++ b/lib/Frontend/LogDiagnosticPrinter.cpp
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Frontend/LogDiagnosticPrinter.h"
+#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/SmallString.h"
@@ -16,9 +17,9 @@
using namespace clang;
LogDiagnosticPrinter::LogDiagnosticPrinter(raw_ostream &os,
- const DiagnosticOptions &diags,
+ DiagnosticOptions *diags,
bool _OwnsOutputStream)
- : OS(os), LangOpts(0), DiagOpts(&diags),
+ : OS(os), LangOpts(0), DiagOpts(diags),
OwnsOutputStream(_OwnsOutputStream) {
}
@@ -172,6 +173,6 @@ void LogDiagnosticPrinter::HandleDiagnostic(DiagnosticsEngine::Level Level,
DiagnosticConsumer *
LogDiagnosticPrinter::clone(DiagnosticsEngine &Diags) const {
- return new LogDiagnosticPrinter(OS, *DiagOpts, /*OwnsOutputStream=*/false);
+ return new LogDiagnosticPrinter(OS, &*DiagOpts, /*OwnsOutputStream=*/false);
}
diff --git a/lib/Frontend/PrintPreprocessedOutput.cpp b/lib/Frontend/PrintPreprocessedOutput.cpp
index 5311ed52cd29..30707dc0c008 100644
--- a/lib/Frontend/PrintPreprocessedOutput.cpp
+++ b/lib/Frontend/PrintPreprocessedOutput.cpp
@@ -570,8 +570,12 @@ static void DoPrintMacros(Preprocessor &PP, raw_ostream *OS) {
do PP.Lex(Tok);
while (Tok.isNot(tok::eof));
- SmallVector<id_macro_pair, 128>
- MacrosByID(PP.macro_begin(), PP.macro_end());
+ SmallVector<id_macro_pair, 128> MacrosByID;
+ 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));
+ }
llvm::array_pod_sort(MacrosByID.begin(), MacrosByID.end(), MacroIDCompare);
for (unsigned i = 0, e = MacrosByID.size(); i != e; ++i) {
diff --git a/lib/Frontend/SerializedDiagnosticPrinter.cpp b/lib/Frontend/SerializedDiagnosticPrinter.cpp
index a20f30d6be83..5f8fc1ecfc60 100644
--- a/lib/Frontend/SerializedDiagnosticPrinter.cpp
+++ b/lib/Frontend/SerializedDiagnosticPrinter.cpp
@@ -12,6 +12,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/DenseSet.h"
+#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/Diagnostic.h"
@@ -50,13 +51,10 @@ class SDiagsWriter;
class SDiagsRenderer : public DiagnosticNoteRenderer {
SDiagsWriter &Writer;
- RecordData &Record;
public:
- SDiagsRenderer(SDiagsWriter &Writer, RecordData &Record,
- const LangOptions &LangOpts,
- const DiagnosticOptions &DiagOpts)
- : DiagnosticNoteRenderer(LangOpts, DiagOpts),
- Writer(Writer), Record(Record){}
+ SDiagsRenderer(SDiagsWriter &Writer, const LangOptions &LangOpts,
+ DiagnosticOptions *DiagOpts)
+ : DiagnosticNoteRenderer(LangOpts, DiagOpts), Writer(Writer) {}
virtual ~SDiagsRenderer() {}
@@ -73,15 +71,16 @@ protected:
DiagnosticsEngine::Level Level,
ArrayRef<CharSourceRange> Ranges,
const SourceManager &SM) {}
-
- void emitNote(SourceLocation Loc, StringRef Message, const SourceManager *SM);
-
+
+ virtual void emitNote(SourceLocation Loc, StringRef Message,
+ const SourceManager *SM);
+
virtual void emitCodeContext(SourceLocation Loc,
DiagnosticsEngine::Level Level,
SmallVectorImpl<CharSourceRange>& Ranges,
ArrayRef<FixItHint> Hints,
const SourceManager &SM);
-
+
virtual void beginDiagnostic(DiagOrStoredDiag D,
DiagnosticsEngine::Level Level);
virtual void endDiagnostic(DiagOrStoredDiag D,
@@ -91,13 +90,12 @@ protected:
class SDiagsWriter : public DiagnosticConsumer {
friend class SDiagsRenderer;
public:
- explicit SDiagsWriter(llvm::raw_ostream *os, const DiagnosticOptions &diags)
- : LangOpts(0), DiagOpts(diags),
- Stream(Buffer), OS(os), inNonNoteDiagnostic(false)
- {
+ explicit SDiagsWriter(llvm::raw_ostream *os, DiagnosticOptions *diags)
+ : LangOpts(0), DiagOpts(diags), Stream(Buffer), OS(os),
+ EmittedAnyDiagBlocks(false) {
EmitPreamble();
}
-
+
~SDiagsWriter() {}
void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
@@ -124,7 +122,26 @@ private:
/// \brief Emit the META data block.
void EmitMetaBlock();
-
+
+ /// \brief Start a DIAG block.
+ void EnterDiagBlock();
+
+ /// \brief End a DIAG block.
+ void ExitDiagBlock();
+
+ /// \brief Emit a DIAG record.
+ void EmitDiagnosticMessage(SourceLocation Loc,
+ PresumedLoc PLoc,
+ DiagnosticsEngine::Level Level,
+ StringRef Message,
+ const SourceManager *SM,
+ DiagOrStoredDiag D);
+
+ /// \brief Emit FIXIT and SOURCE_RANGE records for a diagnostic.
+ void EmitCodeContext(SmallVectorImpl<CharSourceRange> &Ranges,
+ ArrayRef<FixItHint> Hints,
+ const SourceManager &SM);
+
/// \brief Emit a record for a CharSourceRange.
void EmitCharSourceRange(CharSourceRange R, const SourceManager &SM);
@@ -159,7 +176,7 @@ private:
enum { Version = 1 };
const LangOptions *LangOpts;
- const DiagnosticOptions &DiagOpts;
+ llvm::IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
/// \brief The byte buffer for the serialized content.
SmallString<1024> Buffer;
@@ -190,17 +207,18 @@ private:
/// \brief Map for uniquing strings.
DiagFlagsTy DiagFlags;
-
- /// \brief Flag indicating whether or not we are in the process of
- /// emitting a non-note diagnostic.
- bool inNonNoteDiagnostic;
+
+ /// \brief Whether we have already started emission of any DIAG blocks. Once
+ /// this becomes \c true, we never close a DIAG block until we know that we're
+ /// starting another one or we're done.
+ bool EmittedAnyDiagBlocks;
};
} // end anonymous namespace
namespace clang {
namespace serialized_diags {
DiagnosticConsumer *create(llvm::raw_ostream *OS,
- const DiagnosticOptions &diags) {
+ DiagnosticOptions *diags) {
return new SDiagsWriter(OS, diags);
}
} // end namespace serialized_diags
@@ -474,31 +492,69 @@ unsigned SDiagsWriter::getEmitDiagnosticFlag(DiagnosticsEngine::Level DiagLevel,
void SDiagsWriter::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
const Diagnostic &Info) {
+ // Enter the block for a non-note diagnostic immediately, rather than waiting
+ // for beginDiagnostic, in case associated notes are emitted before we get
+ // there.
if (DiagLevel != DiagnosticsEngine::Note) {
- if (inNonNoteDiagnostic) {
- // We have encountered a non-note diagnostic. Finish up the previous
- // diagnostic block before starting a new one.
- Stream.ExitBlock();
- }
- inNonNoteDiagnostic = true;
+ if (EmittedAnyDiagBlocks)
+ ExitDiagBlock();
+
+ EnterDiagBlock();
+ EmittedAnyDiagBlocks = true;
}
// Compute the diagnostic text.
- diagBuf.clear();
+ diagBuf.clear();
Info.FormatDiagnostic(diagBuf);
- const SourceManager *
- SM = Info.hasSourceManager() ? &Info.getSourceManager() : 0;
- SDiagsRenderer Renderer(*this, Record, *LangOpts, DiagOpts);
+ if (Info.getLocation().isInvalid()) {
+ // Special-case diagnostics with no location. We may not have entered a
+ // source file in this case, so we can't use the normal DiagnosticsRenderer
+ // machinery.
+ EmitDiagnosticMessage(SourceLocation(), PresumedLoc(), DiagLevel,
+ diagBuf, 0, &Info);
+ return;
+ }
+
+ assert(Info.hasSourceManager() && LangOpts &&
+ "Unexpected diagnostic with valid location outside of a source file");
+ SDiagsRenderer Renderer(*this, *LangOpts, &*DiagOpts);
Renderer.emitDiagnostic(Info.getLocation(), DiagLevel,
diagBuf.str(),
Info.getRanges(),
llvm::makeArrayRef(Info.getFixItHints(),
Info.getNumFixItHints()),
- SM,
+ &Info.getSourceManager(),
&Info);
}
+void SDiagsWriter::EmitDiagnosticMessage(SourceLocation Loc,
+ PresumedLoc PLoc,
+ DiagnosticsEngine::Level Level,
+ StringRef Message,
+ const SourceManager *SM,
+ DiagOrStoredDiag D) {
+ // Emit the RECORD_DIAG record.
+ Record.clear();
+ Record.push_back(RECORD_DIAG);
+ Record.push_back(Level);
+ AddLocToRecord(Loc, SM, PLoc, Record);
+
+ if (const Diagnostic *Info = D.dyn_cast<const Diagnostic*>()) {
+ // Emit the category string lazily and get the category ID.
+ unsigned DiagID = DiagnosticIDs::getCategoryNumberForDiag(Info->getID());
+ Record.push_back(getEmitCategory(DiagID));
+ // Emit the diagnostic flag string lazily and get the mapped ID.
+ Record.push_back(getEmitDiagnosticFlag(Level, Info->getID()));
+ } else {
+ Record.push_back(getEmitCategory());
+ Record.push_back(getEmitDiagnosticFlag(Level));
+ }
+
+ Record.push_back(Message.size());
+ Stream.EmitRecordWithBlob(Abbrevs.get(RECORD_DIAG), Record, Message);
+}
+
void
SDiagsRenderer::emitDiagnosticMessage(SourceLocation Loc,
PresumedLoc PLoc,
@@ -507,94 +563,80 @@ SDiagsRenderer::emitDiagnosticMessage(SourceLocation Loc,
ArrayRef<clang::CharSourceRange> Ranges,
const SourceManager *SM,
DiagOrStoredDiag D) {
- // Emit the RECORD_DIAG record.
- Writer.Record.clear();
- Writer.Record.push_back(RECORD_DIAG);
- Writer.Record.push_back(Level);
- Writer.AddLocToRecord(Loc, SM, PLoc, Record);
+ Writer.EmitDiagnosticMessage(Loc, PLoc, Level, Message, SM, D);
+}
- if (const Diagnostic *Info = D.dyn_cast<const Diagnostic*>()) {
- // Emit the category string lazily and get the category ID.
- unsigned DiagID = DiagnosticIDs::getCategoryNumberForDiag(Info->getID());
- Writer.Record.push_back(Writer.getEmitCategory(DiagID));
- // Emit the diagnostic flag string lazily and get the mapped ID.
- Writer.Record.push_back(Writer.getEmitDiagnosticFlag(Level, Info->getID()));
- }
- else {
- Writer.Record.push_back(Writer.getEmitCategory());
- Writer.Record.push_back(Writer.getEmitDiagnosticFlag(Level));
- }
+void SDiagsWriter::EnterDiagBlock() {
+ Stream.EnterSubblock(BLOCK_DIAG, 4);
+}
- Writer.Record.push_back(Message.size());
- Writer.Stream.EmitRecordWithBlob(Writer.Abbrevs.get(RECORD_DIAG),
- Writer.Record, Message);
+void SDiagsWriter::ExitDiagBlock() {
+ Stream.ExitBlock();
}
void SDiagsRenderer::beginDiagnostic(DiagOrStoredDiag D,
DiagnosticsEngine::Level Level) {
- Writer.Stream.EnterSubblock(BLOCK_DIAG, 4);
+ if (Level == DiagnosticsEngine::Note)
+ Writer.EnterDiagBlock();
}
void SDiagsRenderer::endDiagnostic(DiagOrStoredDiag D,
DiagnosticsEngine::Level Level) {
- if (D && Level != DiagnosticsEngine::Note)
- return;
- Writer.Stream.ExitBlock();
+ // Only end note diagnostics here, because we can't be sure when we've seen
+ // the last note associated with a non-note diagnostic.
+ if (Level == DiagnosticsEngine::Note)
+ Writer.ExitDiagBlock();
}
-void SDiagsRenderer::emitCodeContext(SourceLocation Loc,
- DiagnosticsEngine::Level Level,
- SmallVectorImpl<CharSourceRange> &Ranges,
- ArrayRef<FixItHint> Hints,
- const SourceManager &SM) {
+void SDiagsWriter::EmitCodeContext(SmallVectorImpl<CharSourceRange> &Ranges,
+ ArrayRef<FixItHint> Hints,
+ const SourceManager &SM) {
// Emit Source Ranges.
- for (ArrayRef<CharSourceRange>::iterator it=Ranges.begin(), ei=Ranges.end();
- it != ei; ++it) {
- if (it->isValid())
- Writer.EmitCharSourceRange(*it, SM);
- }
-
+ for (ArrayRef<CharSourceRange>::iterator I = Ranges.begin(), E = Ranges.end();
+ I != E; ++I)
+ if (I->isValid())
+ EmitCharSourceRange(*I, SM);
+
// Emit FixIts.
- for (ArrayRef<FixItHint>::iterator it = Hints.begin(), et = Hints.end();
- it != et; ++it) {
- const FixItHint &fix = *it;
- if (fix.isNull())
+ for (ArrayRef<FixItHint>::iterator I = Hints.begin(), E = Hints.end();
+ I != E; ++I) {
+ const FixItHint &Fix = *I;
+ if (Fix.isNull())
continue;
- Writer.Record.clear();
- Writer.Record.push_back(RECORD_FIXIT);
- Writer.AddCharSourceRangeToRecord(fix.RemoveRange, Record, SM);
- Writer.Record.push_back(fix.CodeToInsert.size());
- Writer.Stream.EmitRecordWithBlob(Writer.Abbrevs.get(RECORD_FIXIT), Record,
- fix.CodeToInsert);
+ Record.clear();
+ Record.push_back(RECORD_FIXIT);
+ AddCharSourceRangeToRecord(Fix.RemoveRange, Record, SM);
+ Record.push_back(Fix.CodeToInsert.size());
+ Stream.EmitRecordWithBlob(Abbrevs.get(RECORD_FIXIT), Record,
+ Fix.CodeToInsert);
}
}
+void SDiagsRenderer::emitCodeContext(SourceLocation Loc,
+ DiagnosticsEngine::Level Level,
+ SmallVectorImpl<CharSourceRange> &Ranges,
+ ArrayRef<FixItHint> Hints,
+ const SourceManager &SM) {
+ Writer.EmitCodeContext(Ranges, Hints, SM);
+}
+
void SDiagsRenderer::emitNote(SourceLocation Loc, StringRef Message,
const SourceManager *SM) {
- Writer.Stream.EnterSubblock(BLOCK_DIAG, 4);
- RecordData Record;
- Record.push_back(RECORD_DIAG);
- Record.push_back(DiagnosticsEngine::Note);
- Writer.AddLocToRecord(Loc, Record, SM);
- Record.push_back(Writer.getEmitCategory());
- Record.push_back(Writer.getEmitDiagnosticFlag(DiagnosticsEngine::Note));
- Record.push_back(Message.size());
- Writer.Stream.EmitRecordWithBlob(Writer.Abbrevs.get(RECORD_DIAG),
- Record, Message);
- Writer.Stream.ExitBlock();
+ Writer.EnterDiagBlock();
+ PresumedLoc PLoc = SM ? SM->getPresumedLoc(Loc) : PresumedLoc();
+ Writer.EmitDiagnosticMessage(Loc, PLoc, DiagnosticsEngine::Note,
+ Message, SM, DiagOrStoredDiag());
+ Writer.ExitDiagBlock();
}
void SDiagsWriter::finish() {
- if (inNonNoteDiagnostic) {
- // Finish off any diagnostics we were in the process of emitting.
- Stream.ExitBlock();
- inNonNoteDiagnostic = false;
- }
+ // Finish off any diagnostic we were in the process of emitting.
+ if (EmittedAnyDiagBlocks)
+ ExitDiagBlock();
// Write the generated bitstream to "Out".
OS->write((char *)&Buffer.front(), Buffer.size());
OS->flush();
-
+
OS.reset(0);
}
-
diff --git a/lib/Frontend/TextDiagnostic.cpp b/lib/Frontend/TextDiagnostic.cpp
index 9bb3e1dce8c7..35dabad60657 100644
--- a/lib/Frontend/TextDiagnostic.cpp
+++ b/lib/Frontend/TextDiagnostic.cpp
@@ -11,7 +11,7 @@
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/ConvertUTF.h"
-#include "clang/Frontend/DiagnosticOptions.h"
+#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Lex/Lexer.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
@@ -43,19 +43,22 @@ static const enum raw_ostream::Colors savedColor =
/// \brief Add highlights to differences in template strings.
static void applyTemplateHighlighting(raw_ostream &OS, StringRef Str,
bool &Normal, bool Bold) {
- for (unsigned i = 0, e = Str.size(); i < e; ++i)
- if (Str[i] != ToggleHighlight) {
- OS << Str[i];
- } else {
- if (Normal)
- OS.changeColor(templateColor, true);
- else {
- OS.resetColor();
- if (Bold)
- OS.changeColor(savedColor, true);
- }
- Normal = !Normal;
+ while (1) {
+ size_t Pos = Str.find(ToggleHighlight);
+ OS << Str.slice(0, Pos);
+ if (Pos == StringRef::npos)
+ break;
+
+ Str = Str.substr(Pos + 1);
+ if (Normal)
+ OS.changeColor(templateColor, true);
+ else {
+ OS.resetColor();
+ if (Bold)
+ OS.changeColor(savedColor, true);
}
+ Normal = !Normal;
+ }
}
/// \brief Number of spaces to indent when word-wrapping.
@@ -110,28 +113,15 @@ printableTextForNextCharacter(StringRef SourceLine, size_t *i,
return std::make_pair(expandedTab, true);
}
- // FIXME: this data is copied from the private implementation of ConvertUTF.h
- static const char trailingBytesForUTF8[256] = {
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
- 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
- };
-
unsigned char const *begin, *end;
begin = reinterpret_cast<unsigned char const *>(&*(SourceLine.begin() + *i));
- end = begin + SourceLine.size();
+ end = begin + (SourceLine.size() - *i);
if (isLegalUTF8Sequence(begin, end)) {
UTF32 c;
UTF32 *cptr = &c;
unsigned char const *original_begin = begin;
- char trailingBytes = trailingBytesForUTF8[(unsigned char)SourceLine[*i]];
- unsigned char const *cp_end = begin+trailingBytes+1;
+ unsigned char const *cp_end = begin+getNumBytesForUTF8(SourceLine[*i]);
ConversionResult res = ConvertUTF8toUTF32(&begin, cp_end, &cptr, cptr+1,
strictConversion);
@@ -274,14 +264,44 @@ struct SourceColumnMap {
}
int columns() const { return m_byteToColumn.back(); }
int bytes() const { return m_columnToByte.back(); }
+
+ /// \brief Map a byte to the column which it is at the start of, or return -1
+ /// if it is not at the start of a column (for a UTF-8 trailing byte).
int byteToColumn(int n) const {
assert(0<=n && n<static_cast<int>(m_byteToColumn.size()));
return m_byteToColumn[n];
}
+
+ /// \brief Map a byte to the first column which contains it.
+ int byteToContainingColumn(int N) const {
+ assert(0 <= N && N < static_cast<int>(m_byteToColumn.size()));
+ while (m_byteToColumn[N] == -1)
+ --N;
+ return m_byteToColumn[N];
+ }
+
+ /// \brief Map a column to the byte which starts the column, or return -1 if
+ /// the column the second or subsequent column of an expanded tab or similar
+ /// multi-column entity.
int columnToByte(int n) const {
assert(0<=n && n<static_cast<int>(m_columnToByte.size()));
return m_columnToByte[n];
}
+
+ /// \brief Map from a byte index to the next byte which starts a column.
+ int startOfNextColumn(int N) const {
+ assert(0 <= N && N < static_cast<int>(m_columnToByte.size() - 1));
+ while (byteToColumn(++N) == -1) {}
+ return N;
+ }
+
+ /// \brief Map from a byte index to the previous byte which starts a column.
+ int startOfPreviousColumn(int N) const {
+ assert(0 < N && N < static_cast<int>(m_columnToByte.size()));
+ while (byteToColumn(--N) == -1) {}
+ return N;
+ }
+
StringRef getSourceLine() const {
return m_SourceLine;
}
@@ -398,25 +418,24 @@ static void selectInterestingSourceRegion(std::string &SourceLine,
bool ExpandedRegion = false;
if (SourceStart>0) {
- unsigned NewStart = SourceStart-1;
+ unsigned NewStart = map.startOfPreviousColumn(SourceStart);
// Skip over any whitespace we see here; we're looking for
// another bit of interesting text.
+ // FIXME: Detect non-ASCII whitespace characters too.
while (NewStart &&
- (map.byteToColumn(NewStart)==-1 ||
- isspace(static_cast<unsigned char>(SourceLine[NewStart]))))
- --NewStart;
+ isspace(static_cast<unsigned char>(SourceLine[NewStart])))
+ NewStart = map.startOfPreviousColumn(NewStart);
// Skip over this bit of "interesting" text.
- while (NewStart &&
- (map.byteToColumn(NewStart)!=-1 &&
- !isspace(static_cast<unsigned char>(SourceLine[NewStart]))))
- --NewStart;
-
- // Move up to the non-whitespace character we just saw.
- if (NewStart)
- ++NewStart;
+ while (NewStart) {
+ unsigned Prev = map.startOfPreviousColumn(NewStart);
+ if (isspace(static_cast<unsigned char>(SourceLine[Prev])))
+ break;
+ NewStart = Prev;
+ }
+ assert(map.byteToColumn(NewStart) != -1);
unsigned NewColumns = map.byteToColumn(SourceEnd) -
map.byteToColumn(NewStart);
if (NewColumns <= TargetColumns) {
@@ -426,21 +445,21 @@ static void selectInterestingSourceRegion(std::string &SourceLine,
}
if (SourceEnd<SourceLine.size()) {
- unsigned NewEnd = SourceEnd+1;
+ unsigned NewEnd = map.startOfNextColumn(SourceEnd);
// Skip over any whitespace we see here; we're looking for
// another bit of interesting text.
- while (NewEnd<SourceLine.size() &&
- (map.byteToColumn(NewEnd)==-1 ||
- isspace(static_cast<unsigned char>(SourceLine[NewEnd]))))
- ++NewEnd;
+ // FIXME: Detect non-ASCII whitespace characters too.
+ while (NewEnd < SourceLine.size() &&
+ isspace(static_cast<unsigned char>(SourceLine[NewEnd])))
+ NewEnd = map.startOfNextColumn(NewEnd);
// Skip over this bit of "interesting" text.
- while (NewEnd<SourceLine.size() &&
- (map.byteToColumn(NewEnd)!=-1 &&
- !isspace(static_cast<unsigned char>(SourceLine[NewEnd]))))
- ++NewEnd;
+ while (NewEnd < SourceLine.size() &&
+ !isspace(static_cast<unsigned char>(SourceLine[NewEnd])))
+ NewEnd = map.startOfNextColumn(NewEnd);
+ assert(map.byteToColumn(NewEnd) != -1);
unsigned NewColumns = map.byteToColumn(NewEnd) -
map.byteToColumn(SourceStart);
if (NewColumns <= TargetColumns) {
@@ -475,7 +494,7 @@ static void selectInterestingSourceRegion(std::string &SourceLine,
// The line needs some trunctiona, and we'd prefer to keep the front
// if possible, so remove the back
- if (BackColumnsRemoved)
+ if (BackColumnsRemoved > strlen(back_ellipse))
SourceLine.replace(SourceEnd, std::string::npos, back_ellipse);
// If that's enough then we're done
@@ -483,7 +502,7 @@ static void selectInterestingSourceRegion(std::string &SourceLine,
return;
// Otherwise remove the front as well
- if (FrontColumnsRemoved) {
+ if (FrontColumnsRemoved > strlen(front_ellipse)) {
SourceLine.replace(0, SourceStart, front_ellipse);
CaretLine.replace(0, CaretStart, front_space);
if (!FixItInsertionLine.empty())
@@ -651,7 +670,7 @@ static bool printWordWrapped(raw_ostream &OS, StringRef Str,
TextDiagnostic::TextDiagnostic(raw_ostream &OS,
const LangOptions &LangOpts,
- const DiagnosticOptions &DiagOpts)
+ DiagnosticOptions *DiagOpts)
: DiagnosticRenderer(LangOpts, DiagOpts), OS(OS) {}
TextDiagnostic::~TextDiagnostic() {}
@@ -670,13 +689,13 @@ TextDiagnostic::emitDiagnosticMessage(SourceLocation Loc,
if (Loc.isValid())
emitDiagnosticLoc(Loc, PLoc, Level, Ranges, *SM);
- if (DiagOpts.ShowColors)
+ if (DiagOpts->ShowColors)
OS.resetColor();
- printDiagnosticLevel(OS, Level, DiagOpts.ShowColors);
+ printDiagnosticLevel(OS, Level, DiagOpts->ShowColors);
printDiagnosticMessage(OS, Level, Message,
OS.tell() - StartOfLocationInfo,
- DiagOpts.MessageLength, DiagOpts.ShowColors);
+ DiagOpts->MessageLength, DiagOpts->ShowColors);
}
/*static*/ void
@@ -770,36 +789,36 @@ void TextDiagnostic::emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
}
unsigned LineNo = PLoc.getLine();
- if (!DiagOpts.ShowLocation)
+ if (!DiagOpts->ShowLocation)
return;
- if (DiagOpts.ShowColors)
+ if (DiagOpts->ShowColors)
OS.changeColor(savedColor, true);
OS << PLoc.getFilename();
- switch (DiagOpts.Format) {
+ switch (DiagOpts->getFormat()) {
case DiagnosticOptions::Clang: OS << ':' << LineNo; break;
case DiagnosticOptions::Msvc: OS << '(' << LineNo; break;
case DiagnosticOptions::Vi: OS << " +" << LineNo; break;
}
- if (DiagOpts.ShowColumn)
+ if (DiagOpts->ShowColumn)
// Compute the column number.
if (unsigned ColNo = PLoc.getColumn()) {
- if (DiagOpts.Format == DiagnosticOptions::Msvc) {
+ if (DiagOpts->getFormat() == DiagnosticOptions::Msvc) {
OS << ',';
ColNo--;
} else
OS << ':';
OS << ColNo;
}
- switch (DiagOpts.Format) {
+ switch (DiagOpts->getFormat()) {
case DiagnosticOptions::Clang:
case DiagnosticOptions::Vi: OS << ':'; break;
case DiagnosticOptions::Msvc: OS << ") : "; break;
}
- if (DiagOpts.ShowSourceRanges && !Ranges.empty()) {
+ if (DiagOpts->ShowSourceRanges && !Ranges.empty()) {
FileID CaretFileID =
SM.getFileID(SM.getExpansionLoc(Loc));
bool PrintedRange = false;
@@ -858,7 +877,7 @@ void TextDiagnostic::emitBasicNote(StringRef Message) {
void TextDiagnostic::emitIncludeLocation(SourceLocation Loc,
PresumedLoc PLoc,
const SourceManager &SM) {
- if (DiagOpts.ShowLocation)
+ if (DiagOpts->ShowLocation)
OS << "In file included from " << PLoc.getFilename() << ':'
<< PLoc.getLine() << ":\n";
else
@@ -886,7 +905,7 @@ void TextDiagnostic::emitSnippetAndCaret(
// was part of a different warning or error diagnostic, or if the
// diagnostic has ranges. We don't want to emit the same caret
// multiple times if one loc has multiple diagnostics.
- if (!DiagOpts.ShowCarets)
+ if (!DiagOpts->ShowCarets)
return;
if (Loc == LastLoc && Ranges.empty() && Hints.empty() &&
(LastLevel != DiagnosticsEngine::Note || Level == LastLevel))
@@ -924,7 +943,7 @@ void TextDiagnostic::emitSnippetAndCaret(
// length as the line of source code.
std::string CaretLine(LineEnd-LineStart, ' ');
- const SourceColumnMap sourceColMap(SourceLine, DiagOpts.TabStop);
+ const SourceColumnMap sourceColMap(SourceLine, DiagOpts->TabStop);
// Highlight all of the characters covered by Ranges with ~ characters.
for (SmallVectorImpl<CharSourceRange>::iterator I = Ranges.begin(),
@@ -933,7 +952,7 @@ void TextDiagnostic::emitSnippetAndCaret(
highlightRange(*I, LineNo, FID, sourceColMap, CaretLine, SM);
// Next, insert the caret itself.
- ColNo = sourceColMap.byteToColumn(ColNo-1);
+ ColNo = sourceColMap.byteToContainingColumn(ColNo-1);
if (CaretLine.size()<ColNo+1)
CaretLine.resize(ColNo+1, ' ');
CaretLine[ColNo] = '^';
@@ -944,7 +963,7 @@ void TextDiagnostic::emitSnippetAndCaret(
// If the source line is too long for our terminal, select only the
// "interesting" source region within that line.
- unsigned Columns = DiagOpts.MessageLength;
+ unsigned Columns = DiagOpts->MessageLength;
if (Columns)
selectInterestingSourceRegion(SourceLine, CaretLine, FixItInsertionLine,
Columns, sourceColMap);
@@ -953,7 +972,7 @@ void TextDiagnostic::emitSnippetAndCaret(
// to produce easily machine parsable output. Add a space before the
// source line and the caret to make it trivial to tell the main diagnostic
// line from what the user is intended to see.
- if (DiagOpts.ShowSourceRanges) {
+ if (DiagOpts->ShowSourceRanges) {
SourceLine = ' ' + SourceLine;
CaretLine = ' ' + CaretLine;
}
@@ -965,20 +984,20 @@ void TextDiagnostic::emitSnippetAndCaret(
// Emit what we have computed.
emitSnippet(SourceLine);
- if (DiagOpts.ShowColors)
+ if (DiagOpts->ShowColors)
OS.changeColor(caretColor, true);
OS << CaretLine << '\n';
- if (DiagOpts.ShowColors)
+ if (DiagOpts->ShowColors)
OS.resetColor();
if (!FixItInsertionLine.empty()) {
- if (DiagOpts.ShowColors)
+ if (DiagOpts->ShowColors)
// Print fixit line in color
OS.changeColor(fixitColor, false);
- if (DiagOpts.ShowSourceRanges)
+ if (DiagOpts->ShowSourceRanges)
OS << ' ';
OS << FixItInsertionLine << '\n';
- if (DiagOpts.ShowColors)
+ if (DiagOpts->ShowColors)
OS.resetColor();
}
@@ -997,15 +1016,15 @@ void TextDiagnostic::emitSnippet(StringRef line) {
while (i<line.size()) {
std::pair<SmallString<16>,bool> res
- = printableTextForNextCharacter(line, &i, DiagOpts.TabStop);
+ = printableTextForNextCharacter(line, &i, DiagOpts->TabStop);
bool was_printable = res.second;
- if (DiagOpts.ShowColors && was_printable == print_reversed) {
+ if (DiagOpts->ShowColors && was_printable == print_reversed) {
if (print_reversed)
OS.reverseColor();
OS << to_print;
to_print.clear();
- if (DiagOpts.ShowColors)
+ if (DiagOpts->ShowColors)
OS.resetColor();
}
@@ -1013,10 +1032,10 @@ void TextDiagnostic::emitSnippet(StringRef line) {
to_print += res.first.str();
}
- if (print_reversed && DiagOpts.ShowColors)
+ if (print_reversed && DiagOpts->ShowColors)
OS.reverseColor();
OS << to_print;
- if (print_reversed && DiagOpts.ShowColors)
+ if (print_reversed && DiagOpts->ShowColors)
OS.resetColor();
OS << '\n';
@@ -1030,16 +1049,8 @@ void TextDiagnostic::highlightRange(const CharSourceRange &R,
const SourceManager &SM) {
if (!R.isValid()) return;
- SourceLocation Begin = SM.getExpansionLoc(R.getBegin());
- SourceLocation End = SM.getExpansionLoc(R.getEnd());
-
- // If the End location and the start location are the same and are a macro
- // location, then the range was something that came from a macro expansion
- // or _Pragma. If this is an object-like macro, the best we can do is to
- // highlight the range. If this is a function-like macro, we'd also like to
- // highlight the arguments.
- if (Begin == End && R.getEnd().isMacroID())
- End = SM.getExpansionRange(R.getEnd()).second;
+ SourceLocation Begin = R.getBegin();
+ SourceLocation End = R.getEnd();
unsigned StartLineNo = SM.getExpansionLineNumber(Begin);
if (StartLineNo > LineNo || SM.getFileID(Begin) != FID)
@@ -1080,7 +1091,7 @@ void TextDiagnostic::highlightRange(const CharSourceRange &R,
while (StartColNo < map.getSourceLine().size() &&
(map.getSourceLine()[StartColNo] == ' ' ||
map.getSourceLine()[StartColNo] == '\t'))
- ++StartColNo;
+ StartColNo = map.startOfNextColumn(StartColNo);
// Pick the last non-whitespace column.
if (EndColNo > map.getSourceLine().size())
@@ -1088,7 +1099,7 @@ void TextDiagnostic::highlightRange(const CharSourceRange &R,
while (EndColNo-1 &&
(map.getSourceLine()[EndColNo-1] == ' ' ||
map.getSourceLine()[EndColNo-1] == '\t'))
- --EndColNo;
+ EndColNo = map.startOfPreviousColumn(EndColNo);
// If the start/end passed each other, then we are trying to highlight a
// range that just exists in whitespace, which must be some sort of other
@@ -1100,8 +1111,8 @@ void TextDiagnostic::highlightRange(const CharSourceRange &R,
assert(EndColNo <= map.getSourceLine().size() && "Invalid range!");
// Fill the range with ~'s.
- StartColNo = map.byteToColumn(StartColNo);
- EndColNo = map.byteToColumn(EndColNo);
+ StartColNo = map.byteToContainingColumn(StartColNo);
+ EndColNo = map.byteToContainingColumn(EndColNo);
assert(StartColNo <= EndColNo && "Invalid range!");
if (CaretLine.size() < EndColNo)
@@ -1116,7 +1127,7 @@ std::string TextDiagnostic::buildFixItInsertionLine(
const SourceManager &SM) {
std::string FixItInsertionLine;
- if (Hints.empty() || !DiagOpts.ShowFixits)
+ if (Hints.empty() || !DiagOpts->ShowFixits)
return FixItInsertionLine;
unsigned PrevHintEndCol = 0;
@@ -1139,7 +1150,7 @@ std::string TextDiagnostic::buildFixItInsertionLine(
// The hint must start inside the source or right at the end
assert(HintByteOffset < static_cast<unsigned>(map.bytes())+1);
- unsigned HintCol = map.byteToColumn(HintByteOffset);
+ unsigned HintCol = map.byteToContainingColumn(HintByteOffset);
// If we inserted a long previous hint, push this one forwards, and add
// an extra space to show that this is not part of the previous
@@ -1176,14 +1187,14 @@ std::string TextDiagnostic::buildFixItInsertionLine(
}
}
- expandTabs(FixItInsertionLine, DiagOpts.TabStop);
+ expandTabs(FixItInsertionLine, DiagOpts->TabStop);
return FixItInsertionLine;
}
void TextDiagnostic::emitParseableFixits(ArrayRef<FixItHint> Hints,
const SourceManager &SM) {
- if (!DiagOpts.ShowParseableFixits)
+ if (!DiagOpts->ShowParseableFixits)
return;
// We follow FixItRewriter's example in not (yet) handling
diff --git a/lib/Frontend/TextDiagnosticPrinter.cpp b/lib/Frontend/TextDiagnosticPrinter.cpp
index 382e1567c7f4..aa7a61a60f9e 100644
--- a/lib/Frontend/TextDiagnosticPrinter.cpp
+++ b/lib/Frontend/TextDiagnosticPrinter.cpp
@@ -12,9 +12,9 @@
//===----------------------------------------------------------------------===//
#include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
-#include "clang/Frontend/DiagnosticOptions.h"
#include "clang/Frontend/TextDiagnostic.h"
#include "clang/Lex/Lexer.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -25,9 +25,9 @@
using namespace clang;
TextDiagnosticPrinter::TextDiagnosticPrinter(raw_ostream &os,
- const DiagnosticOptions &diags,
+ DiagnosticOptions *diags,
bool _OwnsOutputStream)
- : OS(os), DiagOpts(&diags),
+ : OS(os), DiagOpts(diags),
OwnsOutputStream(_OwnsOutputStream) {
}
@@ -39,7 +39,7 @@ TextDiagnosticPrinter::~TextDiagnosticPrinter() {
void TextDiagnosticPrinter::BeginSourceFile(const LangOptions &LO,
const Preprocessor *PP) {
// Build the TextDiagnostic utility.
- TextDiag.reset(new TextDiagnostic(OS, LO, *DiagOpts));
+ TextDiag.reset(new TextDiagnostic(OS, LO, &*DiagOpts));
}
void TextDiagnosticPrinter::EndSourceFile() {
@@ -158,5 +158,5 @@ void TextDiagnosticPrinter::HandleDiagnostic(DiagnosticsEngine::Level Level,
DiagnosticConsumer *
TextDiagnosticPrinter::clone(DiagnosticsEngine &Diags) const {
- return new TextDiagnosticPrinter(OS, *DiagOpts, /*OwnsOutputStream=*/false);
+ return new TextDiagnosticPrinter(OS, &*DiagOpts, /*OwnsOutputStream=*/false);
}
diff --git a/lib/Frontend/VerifyDiagnosticConsumer.cpp b/lib/Frontend/VerifyDiagnosticConsumer.cpp
index a9378a117d6b..1750946af497 100644
--- a/lib/Frontend/VerifyDiagnosticConsumer.cpp
+++ b/lib/Frontend/VerifyDiagnosticConsumer.cpp
@@ -31,14 +31,17 @@ VerifyDiagnosticConsumer::VerifyDiagnosticConsumer(DiagnosticsEngine &_Diags)
: Diags(_Diags),
PrimaryClient(Diags.getClient()), OwnsPrimaryClient(Diags.ownsClient()),
Buffer(new TextDiagnosticBuffer()), CurrentPreprocessor(0),
- ActiveSourceFiles(0)
+ LangOpts(0), SrcManager(0), ActiveSourceFiles(0), Status(HasNoDirectives)
{
Diags.takeClient();
+ if (Diags.hasSourceManager())
+ setSourceManager(Diags.getSourceManager());
}
VerifyDiagnosticConsumer::~VerifyDiagnosticConsumer() {
assert(!ActiveSourceFiles && "Incomplete parsing of source files!");
assert(!CurrentPreprocessor && "CurrentPreprocessor should be invalid!");
+ SrcManager = 0;
CheckDiagnostics();
Diags.takeClient();
if (OwnsPrimaryClient)
@@ -48,21 +51,20 @@ VerifyDiagnosticConsumer::~VerifyDiagnosticConsumer() {
#ifndef NDEBUG
namespace {
class VerifyFileTracker : public PPCallbacks {
- typedef VerifyDiagnosticConsumer::FilesParsedForDirectivesSet ListType;
- ListType &FilesList;
+ VerifyDiagnosticConsumer &Verify;
SourceManager &SM;
public:
- VerifyFileTracker(ListType &FilesList, SourceManager &SM)
- : FilesList(FilesList), SM(SM) { }
+ VerifyFileTracker(VerifyDiagnosticConsumer &Verify, SourceManager &SM)
+ : Verify(Verify), SM(SM) { }
/// \brief Hook into the preprocessor and update the list of parsed
/// files when the preprocessor indicates a new file is entered.
virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason,
SrcMgr::CharacteristicKind FileType,
FileID PrevFID) {
- if (const FileEntry *E = SM.getFileEntryForID(SM.getFileID(Loc)))
- FilesList.insert(E);
+ Verify.UpdateParsedFileStatus(SM, SM.getFileID(Loc),
+ VerifyDiagnosticConsumer::IsParsed);
}
};
} // End anonymous namespace.
@@ -76,10 +78,12 @@ void VerifyDiagnosticConsumer::BeginSourceFile(const LangOptions &LangOpts,
if (++ActiveSourceFiles == 1) {
if (PP) {
CurrentPreprocessor = PP;
+ this->LangOpts = &LangOpts;
+ setSourceManager(PP->getSourceManager());
const_cast<Preprocessor*>(PP)->addCommentHandler(this);
#ifndef NDEBUG
- VerifyFileTracker *V = new VerifyFileTracker(FilesParsedForDirectives,
- PP->getSourceManager());
+ // Debug build tracks parsed files.
+ VerifyFileTracker *V = new VerifyFileTracker(*this, *SrcManager);
const_cast<Preprocessor*>(PP)->addPPCallbacks(V);
#endif
}
@@ -101,18 +105,40 @@ void VerifyDiagnosticConsumer::EndSourceFile() {
// Check diagnostics once last file completed.
CheckDiagnostics();
CurrentPreprocessor = 0;
+ LangOpts = 0;
}
}
void VerifyDiagnosticConsumer::HandleDiagnostic(
DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info) {
+ if (Info.hasSourceManager())
+ setSourceManager(Info.getSourceManager());
+
#ifndef NDEBUG
- if (Info.hasSourceManager()) {
- FileID FID = Info.getSourceManager().getFileID(Info.getLocation());
- if (!FID.isInvalid())
- FilesWithDiagnostics.insert(FID);
+ // Debug build tracks unparsed files for possible
+ // unparsed expected-* directives.
+ if (SrcManager) {
+ SourceLocation Loc = Info.getLocation();
+ if (Loc.isValid()) {
+ ParsedStatus PS = IsUnparsed;
+
+ Loc = SrcManager->getExpansionLoc(Loc);
+ FileID FID = SrcManager->getFileID(Loc);
+
+ const FileEntry *FE = SrcManager->getFileEntryForID(FID);
+ if (FE && CurrentPreprocessor && SrcManager->isLoadedFileID(FID)) {
+ // If the file is a modules header file it shall not be parsed
+ // for expected-* directives.
+ HeaderSearch &HS = CurrentPreprocessor->getHeaderSearchInfo();
+ if (HS.findModuleForHeader(FE))
+ PS = IsUnparsedNoDirectives;
+ }
+
+ UpdateParsedFileStatus(*SrcManager, FID, PS);
+ }
}
#endif
+
// Send the diagnostic to the buffer, we will check it once we reach the end
// of the source file (or are destructed).
Buffer->HandleDiagnostic(DiagLevel, Info);
@@ -200,10 +226,22 @@ public:
// Return true if string literal is found.
// When true, P marks begin-position of S in content.
- bool Search(StringRef S) {
- P = std::search(C, End, S.begin(), S.end());
- PEnd = P + S.size();
- return P != End;
+ bool Search(StringRef S, bool EnsureStartOfWord = false) {
+ do {
+ P = std::search(C, End, S.begin(), S.end());
+ PEnd = P + S.size();
+ if (P == End)
+ break;
+ if (!EnsureStartOfWord
+ // Check if string literal starts a new word.
+ || P == Begin || isspace(P[-1])
+ // Or it could be preceeded by the start of a comment.
+ || (P > (Begin + 1) && (P[-1] == '/' || P[-1] == '*')
+ && P[-2] == '/'))
+ return true;
+ // Otherwise, skip and search again.
+ } while (Advance());
+ return false;
}
// Advance 1-past previous next/search.
@@ -240,12 +278,13 @@ private:
///
/// Returns true if any valid directives were found.
static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM,
- SourceLocation Pos, DiagnosticsEngine &Diags) {
+ SourceLocation Pos, DiagnosticsEngine &Diags,
+ VerifyDiagnosticConsumer::DirectiveStatus &Status) {
// A single comment may contain multiple directives.
bool FoundDirective = false;
for (ParseHelper PH(S); !PH.Done();) {
// Search for token: expected
- if (!PH.Search("expected"))
+ if (!PH.Search("expected", true))
break;
PH.Advance();
@@ -262,10 +301,24 @@ static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM,
DL = ED ? &ED->Warnings : NULL;
else if (PH.Next("note"))
DL = ED ? &ED->Notes : NULL;
- else
+ else if (PH.Next("no-diagnostics")) {
+ if (Status == VerifyDiagnosticConsumer::HasOtherExpectedDirectives)
+ Diags.Report(Pos, diag::err_verify_invalid_no_diags)
+ << /*IsExpectedNoDiagnostics=*/true;
+ else
+ Status = VerifyDiagnosticConsumer::HasExpectedNoDiagnostics;
+ continue;
+ } else
continue;
PH.Advance();
+ if (Status == VerifyDiagnosticConsumer::HasExpectedNoDiagnostics) {
+ Diags.Report(Pos, diag::err_verify_invalid_no_diags)
+ << /*IsExpectedNoDiagnostics=*/false;
+ continue;
+ }
+ Status = VerifyDiagnosticConsumer::HasOtherExpectedDirectives;
+
// If a directive has been found but we're not interested
// in storing the directive information, return now.
if (!DL)
@@ -412,7 +465,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());
+ ParseDirective(C, &ED, SM, CommentBegin, PP.getDiagnostics(), Status);
return false;
}
@@ -442,7 +495,7 @@ bool VerifyDiagnosticConsumer::HandleComment(Preprocessor &PP,
}
if (!C2.empty())
- ParseDirective(C2, &ED, SM, CommentBegin, PP.getDiagnostics());
+ ParseDirective(C2, &ED, SM, CommentBegin, PP.getDiagnostics(), Status);
return false;
}
@@ -452,34 +505,36 @@ bool VerifyDiagnosticConsumer::HandleComment(Preprocessor &PP,
/// Preprocessor, directives inside skipped #if blocks will still be found.
///
/// \return true if any directives were found.
-static bool findDirectives(const Preprocessor &PP, FileID FID) {
+static bool findDirectives(SourceManager &SM, FileID FID,
+ const LangOptions &LangOpts) {
// Create a raw lexer to pull all the comments out of FID.
if (FID.isInvalid())
return false;
- SourceManager& SM = PP.getSourceManager();
// Create a lexer to lex all the tokens of the main file in raw mode.
const llvm::MemoryBuffer *FromFile = SM.getBuffer(FID);
- Lexer RawLex(FID, FromFile, SM, PP.getLangOpts());
+ Lexer RawLex(FID, FromFile, SM, LangOpts);
// Return comments as tokens, this is how we find expected diagnostics.
RawLex.SetCommentRetentionState(true);
Token Tok;
Tok.setKind(tok::comment);
- bool Found = false;
+ VerifyDiagnosticConsumer::DirectiveStatus Status =
+ VerifyDiagnosticConsumer::HasNoDirectives;
while (Tok.isNot(tok::eof)) {
RawLex.Lex(Tok);
if (!Tok.is(tok::comment)) continue;
- std::string Comment = PP.getSpelling(Tok);
+ std::string Comment = RawLex.getSpelling(Tok, SM, LangOpts);
if (Comment.empty()) continue;
- // Find all expected errors/warnings/notes.
- Found |= ParseDirective(Comment, 0, SM, Tok.getLocation(),
- PP.getDiagnostics());
+ // Find first directive.
+ if (ParseDirective(Comment, 0, SM, Tok.getLocation(),
+ SM.getDiagnostics(), Status))
+ return true;
}
- return Found;
+ return false;
}
#endif // !NDEBUG
@@ -601,41 +656,95 @@ static unsigned CheckResults(DiagnosticsEngine &Diags, SourceManager &SourceMgr,
return NumProblems;
}
+void VerifyDiagnosticConsumer::UpdateParsedFileStatus(SourceManager &SM,
+ FileID FID,
+ ParsedStatus PS) {
+ // Check SourceManager hasn't changed.
+ setSourceManager(SM);
+
+#ifndef NDEBUG
+ if (FID.isInvalid())
+ return;
+
+ const FileEntry *FE = SM.getFileEntryForID(FID);
+
+ if (PS == IsParsed) {
+ // Move the FileID from the unparsed set to the parsed set.
+ UnparsedFiles.erase(FID);
+ ParsedFiles.insert(std::make_pair(FID, FE));
+ } else if (!ParsedFiles.count(FID) && !UnparsedFiles.count(FID)) {
+ // Add the FileID to the unparsed set if we haven't seen it before.
+
+ // Check for directives.
+ bool FoundDirectives;
+ if (PS == IsUnparsedNoDirectives)
+ FoundDirectives = false;
+ else
+ FoundDirectives = !LangOpts || findDirectives(SM, FID, *LangOpts);
+
+ // Add the FileID to the unparsed set.
+ UnparsedFiles.insert(std::make_pair(FID,
+ UnparsedFileStatus(FE, FoundDirectives)));
+ }
+#endif
+}
+
void VerifyDiagnosticConsumer::CheckDiagnostics() {
// Ensure any diagnostics go to the primary client.
bool OwnsCurClient = Diags.ownsClient();
DiagnosticConsumer *CurClient = Diags.takeClient();
Diags.setClient(PrimaryClient, false);
- // If we have a preprocessor, scan the source for expected diagnostic
- // markers. If not then any diagnostics are unexpected.
- if (CurrentPreprocessor) {
- SourceManager &SM = CurrentPreprocessor->getSourceManager();
-
#ifndef NDEBUG
- // In a debug build, scan through any files that may have been missed
- // during parsing and issue a fatal error if directives are contained
- // within these files. If a fatal error occurs, this suggests that
- // this file is being parsed separately from the main file.
- HeaderSearch &HS = CurrentPreprocessor->getHeaderSearchInfo();
- for (FilesWithDiagnosticsSet::iterator I = FilesWithDiagnostics.begin(),
- End = FilesWithDiagnostics.end();
- I != End; ++I) {
- const FileEntry *E = SM.getFileEntryForID(*I);
- // Don't check files already parsed or those handled as modules.
- if (E && (FilesParsedForDirectives.count(E)
- || HS.findModuleForHeader(E)))
+ // In a debug build, scan through any files that may have been missed
+ // during parsing and issue a fatal error if directives are contained
+ // within these files. If a fatal error occurs, this suggests that
+ // this file is being parsed separately from the main file, in which
+ // case consider moving the directives to the correct place, if this
+ // is applicable.
+ if (UnparsedFiles.size() > 0) {
+ // Generate a cache of parsed FileEntry pointers for alias lookups.
+ llvm::SmallPtrSet<const FileEntry *, 8> ParsedFileCache;
+ for (ParsedFilesMap::iterator I = ParsedFiles.begin(),
+ End = ParsedFiles.end(); I != End; ++I) {
+ if (const FileEntry *FE = I->second)
+ ParsedFileCache.insert(FE);
+ }
+
+ // Iterate through list of unparsed files.
+ for (UnparsedFilesMap::iterator I = UnparsedFiles.begin(),
+ End = UnparsedFiles.end(); I != End; ++I) {
+ const UnparsedFileStatus &Status = I->second;
+ const FileEntry *FE = Status.getFile();
+
+ // Skip files that have been parsed via an alias.
+ if (FE && ParsedFileCache.count(FE))
continue;
- if (findDirectives(*CurrentPreprocessor, *I))
+ // Report a fatal error if this file contained directives.
+ if (Status.foundDirectives()) {
llvm::report_fatal_error(Twine("-verify directives found after rather"
" than during normal parsing of ",
- StringRef(E ? E->getName() : "(unknown)")));
+ StringRef(FE ? FE->getName() : "(unknown)")));
+ }
+ }
+
+ // UnparsedFiles has been processed now, so clear it.
+ UnparsedFiles.clear();
+ }
+#endif // !NDEBUG
+
+ if (SrcManager) {
+ // Produce an error if no expected-* directives could be found in the
+ // source file(s) processed.
+ if (Status == HasNoDirectives) {
+ Diags.Report(diag::err_verify_no_directives).setForceEmit();
+ ++NumErrors;
+ Status = HasNoDirectivesReported;
}
-#endif
// Check that the expected diagnostics occurred.
- NumErrors += CheckResults(Diags, SM, *Buffer, ED);
+ NumErrors += CheckResults(Diags, *SrcManager, *Buffer, ED);
} else {
NumErrors += (PrintUnexpected(Diags, 0, Buffer->err_begin(),
Buffer->err_end(), "error") +
diff --git a/lib/Frontend/Warnings.cpp b/lib/Frontend/Warnings.cpp
index b7d4a3b92538..f789b7f3053f 100644
--- a/lib/Frontend/Warnings.cpp
+++ b/lib/Frontend/Warnings.cpp
@@ -24,7 +24,7 @@
#include "clang/Basic/Diagnostic.h"
#include "clang/Sema/SemaDiagnostic.h"
#include "clang/Lex/LexDiagnostic.h"
-#include "clang/Frontend/DiagnosticOptions.h"
+#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include <cstring>
#include <utility>
@@ -51,8 +51,7 @@ void clang::ProcessWarningOptions(DiagnosticsEngine &Diags,
const DiagnosticOptions &Opts) {
Diags.setSuppressSystemWarnings(true); // Default to -Wno-system-headers
Diags.setIgnoreAllWarnings(Opts.IgnoreWarnings);
- Diags.setShowOverloads(
- static_cast<DiagnosticsEngine::OverloadsShown>(Opts.ShowOverloads));
+ Diags.setShowOverloads(Opts.getShowOverloads());
Diags.setElideType(Opts.ElideType);
Diags.setPrintTemplateTree(Opts.ShowTemplateTree);