summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp306
1 files changed, 205 insertions, 101 deletions
diff --git a/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp b/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp
index 42a6772..5576854 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp
+++ b/contrib/llvm/tools/clang/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())
OpenPOWER on IntegriCloud