diff options
Diffstat (limited to 'lib/Frontend')
26 files changed, 1914 insertions, 13147 deletions
diff --git a/lib/Frontend/ASTConsumers.cpp b/lib/Frontend/ASTConsumers.cpp index 87b01d4..eb7f270 100644 --- a/lib/Frontend/ASTConsumers.cpp +++ b/lib/Frontend/ASTConsumers.cpp @@ -37,7 +37,7 @@ namespace { public: ASTPrinter(llvm::raw_ostream* o = NULL, bool Dump = false) - : Out(o? *o : llvm::errs()), Dump(Dump) { } + : Out(o? *o : llvm::outs()), Dump(Dump) { } virtual void HandleTranslationUnit(ASTContext &Context) { PrintingPolicy Policy = Context.PrintingPolicy; diff --git a/lib/Frontend/ASTMerge.cpp b/lib/Frontend/ASTMerge.cpp index e916e20..b46212f 100644 --- a/lib/Frontend/ASTMerge.cpp +++ b/lib/Frontend/ASTMerge.cpp @@ -40,10 +40,16 @@ void ASTMergeAction::ExecuteAction() { &CI.getASTContext()); llvm::IntrusiveRefCntPtr<Diagnostic> Diags(&CI.getDiagnostics()); for (unsigned I = 0, N = ASTFiles.size(); I != N; ++I) { - ASTUnit *Unit = ASTUnit::LoadFromPCHFile(ASTFiles[I], Diags, false); + ASTUnit *Unit = ASTUnit::LoadFromASTFile(ASTFiles[I], Diags, false); if (!Unit) continue; + // Reset the argument -> string function so that it has the AST + // context we want, since the Sema object created by + // LoadFromASTFile will override it. + CI.getDiagnostics().SetArgToStringFn(&FormatASTNodeDiagnosticArgument, + &CI.getASTContext()); + ASTImporter Importer(CI.getDiagnostics(), CI.getASTContext(), CI.getFileManager(), diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp index 88f0037..c76488b 100644 --- a/lib/Frontend/ASTUnit.cpp +++ b/lib/Frontend/ASTUnit.cpp @@ -12,10 +12,10 @@ //===----------------------------------------------------------------------===// #include "clang/Frontend/ASTUnit.h" -#include "clang/Frontend/PCHReader.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/DeclVisitor.h" +#include "clang/AST/TypeOrdering.h" #include "clang/AST/StmtVisitor.h" #include "clang/Driver/Compilation.h" #include "clang/Driver/Driver.h" @@ -25,30 +25,294 @@ #include "clang/Frontend/FrontendActions.h" #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Frontend/FrontendOptions.h" +#include "clang/Serialization/ASTReader.h" +#include "clang/Serialization/ASTWriter.h" #include "clang/Lex/HeaderSearch.h" #include "clang/Lex/Preprocessor.h" #include "clang/Basic/TargetOptions.h" #include "clang/Basic/TargetInfo.h" #include "clang/Basic/Diagnostic.h" +#include "llvm/ADT/StringSet.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/System/Host.h" #include "llvm/System/Path.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Timer.h" +#include <cstdlib> +#include <cstdio> +#include <sys/stat.h> using namespace clang; +/// \brief After failing to build a precompiled preamble (due to +/// errors in the source that occurs in the preamble), the number of +/// reparses during which we'll skip even trying to precompile the +/// preamble. +const unsigned DefaultPreambleRebuildInterval = 5; + ASTUnit::ASTUnit(bool _MainFileIsAST) - : MainFileIsAST(_MainFileIsAST), ConcurrencyCheckValue(CheckUnlocked) { } + : CaptureDiagnostics(false), MainFileIsAST(_MainFileIsAST), + CompleteTranslationUnit(true), ConcurrencyCheckValue(CheckUnlocked), + PreambleRebuildCounter(0), SavedMainFileBuffer(0), PreambleBuffer(0), + ShouldCacheCodeCompletionResults(false), + NumTopLevelDeclsAtLastCompletionCache(0), + CacheCodeCompletionCoolDown(0), + UnsafeToFree(false) { +} ASTUnit::~ASTUnit() { ConcurrencyCheckValue = CheckLocked; + CleanTemporaryFiles(); + if (!PreambleFile.empty()) + llvm::sys::Path(PreambleFile).eraseFromDisk(); + + // Free the buffers associated with remapped files. We are required to + // perform this operation here because we explicitly request that the + // compiler instance *not* free these buffers for each invocation of the + // parser. + if (Invocation.get()) { + PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts(); + for (PreprocessorOptions::remapped_file_buffer_iterator + FB = PPOpts.remapped_file_buffer_begin(), + FBEnd = PPOpts.remapped_file_buffer_end(); + FB != FBEnd; + ++FB) + delete FB->second; + } + + delete SavedMainFileBuffer; + delete PreambleBuffer; + + ClearCachedCompletionResults(); + + for (unsigned I = 0, N = Timers.size(); I != N; ++I) + delete Timers[I]; +} + +void ASTUnit::CleanTemporaryFiles() { for (unsigned I = 0, N = TemporaryFiles.size(); I != N; ++I) TemporaryFiles[I].eraseFromDisk(); + TemporaryFiles.clear(); +} + +/// \brief Determine the set of code-completion contexts in which this +/// declaration should be shown. +static unsigned getDeclShowContexts(NamedDecl *ND, + const LangOptions &LangOpts, + bool &IsNestedNameSpecifier) { + IsNestedNameSpecifier = false; + + if (isa<UsingShadowDecl>(ND)) + ND = dyn_cast<NamedDecl>(ND->getUnderlyingDecl()); + if (!ND) + return 0; + + unsigned Contexts = 0; + if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND) || + isa<ClassTemplateDecl>(ND) || isa<TemplateTemplateParmDecl>(ND)) { + // Types can appear in these contexts. + if (LangOpts.CPlusPlus || !isa<TagDecl>(ND)) + Contexts |= (1 << (CodeCompletionContext::CCC_TopLevel - 1)) + | (1 << (CodeCompletionContext::CCC_ObjCIvarList - 1)) + | (1 << (CodeCompletionContext::CCC_ClassStructUnion - 1)) + | (1 << (CodeCompletionContext::CCC_Statement - 1)) + | (1 << (CodeCompletionContext::CCC_Type - 1)); + + // In C++, types can appear in expressions contexts (for functional casts). + if (LangOpts.CPlusPlus) + Contexts |= (1 << (CodeCompletionContext::CCC_Expression - 1)); + + // In Objective-C, message sends can send interfaces. In Objective-C++, + // all types are available due to functional casts. + if (LangOpts.CPlusPlus || isa<ObjCInterfaceDecl>(ND)) + Contexts |= (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1)); + + // Deal with tag names. + if (isa<EnumDecl>(ND)) { + Contexts |= (1 << (CodeCompletionContext::CCC_EnumTag - 1)); + + // Part of the nested-name-specifier in C++0x. + if (LangOpts.CPlusPlus0x) + IsNestedNameSpecifier = true; + } else if (RecordDecl *Record = dyn_cast<RecordDecl>(ND)) { + if (Record->isUnion()) + Contexts |= (1 << (CodeCompletionContext::CCC_UnionTag - 1)); + else + Contexts |= (1 << (CodeCompletionContext::CCC_ClassOrStructTag - 1)); + + if (LangOpts.CPlusPlus) + IsNestedNameSpecifier = true; + } else if (isa<ClassTemplateDecl>(ND) || isa<TemplateTemplateParmDecl>(ND)) + IsNestedNameSpecifier = true; + } else if (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND)) { + // Values can appear in these contexts. + Contexts = (1 << (CodeCompletionContext::CCC_Statement - 1)) + | (1 << (CodeCompletionContext::CCC_Expression - 1)) + | (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1)); + } else if (isa<ObjCProtocolDecl>(ND)) { + Contexts = (1 << (CodeCompletionContext::CCC_ObjCProtocolName - 1)); + } else if (isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) { + Contexts = (1 << (CodeCompletionContext::CCC_Namespace - 1)); + + // Part of the nested-name-specifier. + IsNestedNameSpecifier = true; + } + + return Contexts; +} + +void ASTUnit::CacheCodeCompletionResults() { + if (!TheSema) + return; + + llvm::Timer *CachingTimer = 0; + if (TimerGroup.get()) { + CachingTimer = new llvm::Timer("Cache global code completions", + *TimerGroup); + CachingTimer->startTimer(); + Timers.push_back(CachingTimer); + } + + // Clear out the previous results. + ClearCachedCompletionResults(); + + // Gather the set of global code completions. + typedef CodeCompletionResult Result; + llvm::SmallVector<Result, 8> Results; + TheSema->GatherGlobalCodeCompletions(Results); + + // Translate global code completions into cached completions. + llvm::DenseMap<CanQualType, unsigned> CompletionTypes; + + for (unsigned I = 0, N = Results.size(); I != N; ++I) { + switch (Results[I].Kind) { + case Result::RK_Declaration: { + bool IsNestedNameSpecifier = false; + CachedCodeCompletionResult CachedResult; + CachedResult.Completion = Results[I].CreateCodeCompletionString(*TheSema); + CachedResult.ShowInContexts = getDeclShowContexts(Results[I].Declaration, + Ctx->getLangOptions(), + IsNestedNameSpecifier); + CachedResult.Priority = Results[I].Priority; + CachedResult.Kind = Results[I].CursorKind; + CachedResult.Availability = Results[I].Availability; + + // Keep track of the type of this completion in an ASTContext-agnostic + // way. + QualType UsageType = getDeclUsageType(*Ctx, Results[I].Declaration); + if (UsageType.isNull()) { + CachedResult.TypeClass = STC_Void; + CachedResult.Type = 0; + } else { + CanQualType CanUsageType + = Ctx->getCanonicalType(UsageType.getUnqualifiedType()); + CachedResult.TypeClass = getSimplifiedTypeClass(CanUsageType); + + // Determine whether we have already seen this type. If so, we save + // ourselves the work of formatting the type string by using the + // temporary, CanQualType-based hash table to find the associated value. + unsigned &TypeValue = CompletionTypes[CanUsageType]; + if (TypeValue == 0) { + TypeValue = CompletionTypes.size(); + CachedCompletionTypes[QualType(CanUsageType).getAsString()] + = TypeValue; + } + + CachedResult.Type = TypeValue; + } + + CachedCompletionResults.push_back(CachedResult); + + /// Handle nested-name-specifiers in C++. + if (TheSema->Context.getLangOptions().CPlusPlus && + IsNestedNameSpecifier && !Results[I].StartsNestedNameSpecifier) { + // The contexts in which a nested-name-specifier can appear in C++. + unsigned NNSContexts + = (1 << (CodeCompletionContext::CCC_TopLevel - 1)) + | (1 << (CodeCompletionContext::CCC_ObjCIvarList - 1)) + | (1 << (CodeCompletionContext::CCC_ClassStructUnion - 1)) + | (1 << (CodeCompletionContext::CCC_Statement - 1)) + | (1 << (CodeCompletionContext::CCC_Expression - 1)) + | (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1)) + | (1 << (CodeCompletionContext::CCC_EnumTag - 1)) + | (1 << (CodeCompletionContext::CCC_UnionTag - 1)) + | (1 << (CodeCompletionContext::CCC_ClassOrStructTag - 1)) + | (1 << (CodeCompletionContext::CCC_Type - 1)) + | (1 << (CodeCompletionContext::CCC_PotentiallyQualifiedName - 1)); + + if (isa<NamespaceDecl>(Results[I].Declaration) || + isa<NamespaceAliasDecl>(Results[I].Declaration)) + NNSContexts |= (1 << (CodeCompletionContext::CCC_Namespace - 1)); + + if (unsigned RemainingContexts + = NNSContexts & ~CachedResult.ShowInContexts) { + // If there any contexts where this completion can be a + // nested-name-specifier but isn't already an option, create a + // nested-name-specifier completion. + Results[I].StartsNestedNameSpecifier = true; + CachedResult.Completion = Results[I].CreateCodeCompletionString(*TheSema); + CachedResult.ShowInContexts = RemainingContexts; + CachedResult.Priority = CCP_NestedNameSpecifier; + CachedResult.TypeClass = STC_Void; + CachedResult.Type = 0; + CachedCompletionResults.push_back(CachedResult); + } + } + break; + } + + case Result::RK_Keyword: + case Result::RK_Pattern: + // Ignore keywords and patterns; we don't care, since they are so + // easily regenerated. + break; + + case Result::RK_Macro: { + CachedCodeCompletionResult CachedResult; + CachedResult.Completion = Results[I].CreateCodeCompletionString(*TheSema); + CachedResult.ShowInContexts + = (1 << (CodeCompletionContext::CCC_TopLevel - 1)) + | (1 << (CodeCompletionContext::CCC_ObjCInterface - 1)) + | (1 << (CodeCompletionContext::CCC_ObjCImplementation - 1)) + | (1 << (CodeCompletionContext::CCC_ObjCIvarList - 1)) + | (1 << (CodeCompletionContext::CCC_ClassStructUnion - 1)) + | (1 << (CodeCompletionContext::CCC_Statement - 1)) + | (1 << (CodeCompletionContext::CCC_Expression - 1)) + | (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1)) + | (1 << (CodeCompletionContext::CCC_MacroNameUse - 1)) + | (1 << (CodeCompletionContext::CCC_PreprocessorExpression - 1)); + + CachedResult.Priority = Results[I].Priority; + CachedResult.Kind = Results[I].CursorKind; + CachedResult.Availability = Results[I].Availability; + CachedResult.TypeClass = STC_Void; + CachedResult.Type = 0; + CachedCompletionResults.push_back(CachedResult); + break; + } + } + Results[I].Destroy(); + } + + if (CachingTimer) + CachingTimer->stopTimer(); + + // Make a note of the state when we performed this caching. + NumTopLevelDeclsAtLastCompletionCache = top_level_size(); + CacheCodeCompletionCoolDown = 15; +} + +void ASTUnit::ClearCachedCompletionResults() { + for (unsigned I = 0, N = CachedCompletionResults.size(); I != N; ++I) + delete CachedCompletionResults[I].Completion; + CachedCompletionResults.clear(); + CachedCompletionTypes.clear(); } namespace { -/// \brief Gathers information from PCHReader that will be used to initialize +/// \brief Gathers information from ASTReader that will be used to initialize /// a Preprocessor. -class PCHInfoCollector : public PCHReaderListener { +class ASTInfoCollector : public ASTReaderListener { LangOptions &LangOpt; HeaderSearch &HSI; std::string &TargetTriple; @@ -58,7 +322,7 @@ class PCHInfoCollector : public PCHReaderListener { unsigned NumHeaderInfos; public: - PCHInfoCollector(LangOptions &LangOpt, HeaderSearch &HSI, + ASTInfoCollector(LangOptions &LangOpt, HeaderSearch &HSI, std::string &TargetTriple, std::string &Predefines, unsigned &Counter) : LangOpt(LangOpt), HSI(HSI), TargetTriple(TargetTriple), @@ -115,14 +379,19 @@ class CaptureDroppedDiagnostics { public: CaptureDroppedDiagnostics(bool RequestCapture, Diagnostic &Diags, llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiags) - : Diags(Diags), Client(StoredDiags), PreviousClient(Diags.getClient()) + : Diags(Diags), Client(StoredDiags), PreviousClient(0) { - if (RequestCapture || Diags.getClient() == 0) + if (RequestCapture || Diags.getClient() == 0) { + PreviousClient = Diags.takeClient(); Diags.setClient(&Client); + } } ~CaptureDroppedDiagnostics() { - Diags.setClient(PreviousClient); + if (Diags.getClient() == &Client) { + Diags.takeClient(); + Diags.setClient(PreviousClient); + } } }; @@ -137,12 +406,12 @@ const std::string &ASTUnit::getOriginalSourceFileName() { return OriginalSourceFile; } -const std::string &ASTUnit::getPCHFileName() { - assert(isMainFileAST() && "Not an ASTUnit from a PCH file!"); - return static_cast<PCHReader *>(Ctx->getExternalSource())->getFileName(); +const std::string &ASTUnit::getASTFileName() { + assert(isMainFileAST() && "Not an ASTUnit from an AST file!"); + return static_cast<ASTReader *>(Ctx->getExternalSource())->getFileName(); } -ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename, +ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename, llvm::IntrusiveRefCntPtr<Diagnostic> Diags, bool OnlyLocalDecls, RemappedFile *RemappedFiles, @@ -156,13 +425,14 @@ ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename, DiagnosticOptions DiagOpts; Diags = CompilerInstance::createDiagnostics(DiagOpts, 0, 0); } - + + AST->CaptureDiagnostics = CaptureDiagnostics; AST->OnlyLocalDecls = OnlyLocalDecls; AST->Diagnostics = Diags; AST->FileMgr.reset(new FileManager); AST->SourceMgr.reset(new SourceManager(AST->getDiagnostics())); AST->HeaderInfo.reset(new HeaderSearch(AST->getFileManager())); - + // If requested, capture diagnostics in the ASTUnit. CaptureDroppedDiagnostics Capture(CaptureDiagnostics, AST->getDiagnostics(), AST->StoredDiagnostics); @@ -194,34 +464,33 @@ ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename, std::string Predefines; unsigned Counter; - llvm::OwningPtr<PCHReader> Reader; - llvm::OwningPtr<ExternalASTSource> Source; + llvm::OwningPtr<ASTReader> Reader; - Reader.reset(new PCHReader(AST->getSourceManager(), AST->getFileManager(), + Reader.reset(new ASTReader(AST->getSourceManager(), AST->getFileManager(), AST->getDiagnostics())); - Reader->setListener(new PCHInfoCollector(LangInfo, HeaderInfo, TargetTriple, + Reader->setListener(new ASTInfoCollector(LangInfo, HeaderInfo, TargetTriple, Predefines, Counter)); - switch (Reader->ReadPCH(Filename)) { - case PCHReader::Success: + switch (Reader->ReadAST(Filename)) { + case ASTReader::Success: break; - case PCHReader::Failure: - case PCHReader::IgnorePCH: + case ASTReader::Failure: + case ASTReader::IgnorePCH: AST->getDiagnostics().Report(diag::err_fe_unable_to_load_pch); return NULL; } AST->OriginalSourceFile = Reader->getOriginalSourceFile(); - // PCH loaded successfully. Now create the preprocessor. + // AST file loaded successfully. Now create the preprocessor. // Get information about the target being compiled for. // - // FIXME: This is broken, we should store the TargetOptions in the PCH. + // FIXME: This is broken, we should store the TargetOptions in the AST file. TargetOptions TargetOpts; TargetOpts.ABI = ""; - TargetOpts.CXXABI = "itanium"; + TargetOpts.CXXABI = ""; TargetOpts.CPU = ""; TargetOpts.Features.clear(); TargetOpts.Triple = TargetTriple; @@ -244,18 +513,26 @@ ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename, PP.getIdentifierTable(), PP.getSelectorTable(), PP.getBuiltinInfo(), - /* FreeMemory = */ false, /* size_reserve = */0)); ASTContext &Context = *AST->Ctx.get(); Reader->InitializeContext(Context); - // Attach the PCH reader to the AST context as an external AST + // Attach the AST reader to the AST context as an external AST // source, so that declarations will be deserialized from the - // PCH file as needed. - Source.reset(Reader.take()); + // AST file as needed. + ASTReader *ReaderPtr = Reader.get(); + llvm::OwningPtr<ExternalASTSource> Source(Reader.take()); Context.setExternalSource(Source); + // Create an AST consumer, even though it isn't used. + AST->Consumer.reset(new ASTConsumer); + + // Create a semantic analysis object and tell the AST reader about it. + AST->TheSema.reset(new Sema(PP, Context, *AST->Consumer)); + AST->TheSema->Initialize(); + ReaderPtr->InitializeSema(*AST->TheSema); + return AST.take(); } @@ -276,9 +553,12 @@ public: // fundamental problem in the parser right now. if (isa<ObjCMethodDecl>(D)) continue; - Unit.getTopLevelDecls().push_back(D); + Unit.addTopLevelDecl(D); } } + + // We're not interested in "interesting" decls. + void HandleInterestingDecl(DeclGroupRef) {} }; class TopLevelDeclTrackerAction : public ASTFrontendAction { @@ -294,37 +574,108 @@ public: TopLevelDeclTrackerAction(ASTUnit &_Unit) : Unit(_Unit) {} virtual bool hasCodeCompletionSupport() const { return false; } + virtual bool usesCompleteTranslationUnit() { + return Unit.isCompleteTranslationUnit(); + } }; -} +class PrecompilePreambleConsumer : public PCHGenerator { + ASTUnit &Unit; + std::vector<Decl *> TopLevelDecls; -ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI, - llvm::IntrusiveRefCntPtr<Diagnostic> Diags, - bool OnlyLocalDecls, - bool CaptureDiagnostics) { - // Create the compiler instance to use for building the AST. - CompilerInstance Clang; - llvm::OwningPtr<ASTUnit> AST; - llvm::OwningPtr<TopLevelDeclTrackerAction> Act; +public: + PrecompilePreambleConsumer(ASTUnit &Unit, + const Preprocessor &PP, bool Chaining, + const char *isysroot, llvm::raw_ostream *Out) + : PCHGenerator(PP, Chaining, isysroot, Out), Unit(Unit) { } - if (!Diags.getPtr()) { - // No diagnostics engine was provided, so create our own diagnostics object - // with the default options. - DiagnosticOptions DiagOpts; - Diags = CompilerInstance::createDiagnostics(DiagOpts, 0, 0); + virtual void HandleTopLevelDecl(DeclGroupRef D) { + for (DeclGroupRef::iterator it = D.begin(), ie = D.end(); it != ie; ++it) { + Decl *D = *it; + // FIXME: Currently ObjC method declarations are incorrectly being + // reported as top-level declarations, even though their DeclContext + // is the containing ObjC @interface/@implementation. This is a + // fundamental problem in the parser right now. + if (isa<ObjCMethodDecl>(D)) + continue; + TopLevelDecls.push_back(D); + } } - - Clang.setInvocation(CI); - Clang.setDiagnostics(Diags.getPtr()); - Clang.setDiagnosticClient(Diags->getClient()); + virtual void HandleTranslationUnit(ASTContext &Ctx) { + PCHGenerator::HandleTranslationUnit(Ctx); + if (!Unit.getDiagnostics().hasErrorOccurred()) { + // Translate the top-level declarations we captured during + // parsing into declaration IDs in the precompiled + // preamble. This will allow us to deserialize those top-level + // declarations when requested. + for (unsigned I = 0, N = TopLevelDecls.size(); I != N; ++I) + Unit.addTopLevelDeclFromPreamble( + getWriter().getDeclID(TopLevelDecls[I])); + } + } +}; + +class PrecompilePreambleAction : public ASTFrontendAction { + ASTUnit &Unit; + +public: + explicit PrecompilePreambleAction(ASTUnit &Unit) : Unit(Unit) {} + + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile) { + std::string Sysroot; + llvm::raw_ostream *OS = 0; + bool Chaining; + if (GeneratePCHAction::ComputeASTConsumerArguments(CI, InFile, Sysroot, + OS, Chaining)) + return 0; + + const char *isysroot = CI.getFrontendOpts().RelocatablePCH ? + Sysroot.c_str() : 0; + return new PrecompilePreambleConsumer(Unit, CI.getPreprocessor(), Chaining, + isysroot, OS); + } + + virtual bool hasCodeCompletionSupport() const { return false; } + virtual bool hasASTFileSupport() const { return false; } + virtual bool usesCompleteTranslationUnit() { return false; } +}; + +} +/// Parse the source file into a translation unit using the given compiler +/// invocation, replacing the current translation unit. +/// +/// \returns True if a failure occurred that causes the ASTUnit not to +/// contain any translation-unit information, false otherwise. +bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) { + delete SavedMainFileBuffer; + SavedMainFileBuffer = 0; + + if (!Invocation.get()) { + delete OverrideMainBuffer; + return true; + } + + // Create the compiler instance to use for building the AST. + CompilerInstance Clang; + Clang.setInvocation(Invocation.take()); + OriginalSourceFile = Clang.getFrontendOpts().Inputs[0].second; + + // Set up diagnostics, capturing any diagnostics that would + // otherwise be dropped. + Clang.setDiagnostics(&getDiagnostics()); + CaptureDroppedDiagnostics Capture(CaptureDiagnostics, + getDiagnostics(), + StoredDiagnostics); + // Create the target instance. Clang.setTarget(TargetInfo::CreateTargetInfo(Clang.getDiagnostics(), Clang.getTargetOpts())); if (!Clang.hasTarget()) { - Clang.takeDiagnosticClient(); - return 0; + delete OverrideMainBuffer; + return true; } // Inform the target of the language options. @@ -332,7 +683,7 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI, // FIXME: We shouldn't need to do this, the target should be immutable once // created. This complexity should be lifted elsewhere. Clang.getTarget().setForcedLangOptions(Clang.getLangOpts()); - + assert(Clang.getFrontendOpts().Inputs.size() == 1 && "Invocation must have exactly one source file!"); assert(Clang.getFrontendOpts().Inputs[0].first != IK_AST && @@ -340,53 +691,649 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI, assert(Clang.getFrontendOpts().Inputs[0].first != IK_LLVM_IR && "IR inputs not support here!"); - // Create the AST unit. - AST.reset(new ASTUnit(false)); - AST->Diagnostics = Diags; - AST->FileMgr.reset(new FileManager); - AST->SourceMgr.reset(new SourceManager(AST->getDiagnostics())); - AST->OnlyLocalDecls = OnlyLocalDecls; - AST->OriginalSourceFile = Clang.getFrontendOpts().Inputs[0].second; - - // Capture any diagnostics that would otherwise be dropped. - CaptureDroppedDiagnostics Capture(CaptureDiagnostics, - Clang.getDiagnostics(), - AST->StoredDiagnostics); + // Configure the various subsystems. + // FIXME: Should we retain the previous file manager? + FileMgr.reset(new FileManager); + SourceMgr.reset(new SourceManager(getDiagnostics())); + TheSema.reset(); + Ctx.reset(); + PP.reset(); + + // Clear out old caches and data. + TopLevelDecls.clear(); + CleanTemporaryFiles(); + PreprocessedEntitiesByFile.clear(); + + if (!OverrideMainBuffer) { + StoredDiagnostics.clear(); + TopLevelDeclsInPreamble.clear(); + } // Create a file manager object to provide access to and cache the filesystem. - Clang.setFileManager(&AST->getFileManager()); - + Clang.setFileManager(&getFileManager()); + // Create the source manager. - Clang.setSourceManager(&AST->getSourceManager()); - - Act.reset(new TopLevelDeclTrackerAction(*AST)); + Clang.setSourceManager(&getSourceManager()); + + // If the main file has been overridden due to the use of a preamble, + // make that override happen and introduce the preamble. + PreprocessorOptions &PreprocessorOpts = Clang.getPreprocessorOpts(); + std::string PriorImplicitPCHInclude; + if (OverrideMainBuffer) { + PreprocessorOpts.addRemappedFile(OriginalSourceFile, OverrideMainBuffer); + PreprocessorOpts.PrecompiledPreambleBytes.first = Preamble.size(); + PreprocessorOpts.PrecompiledPreambleBytes.second + = PreambleEndsAtStartOfLine; + PriorImplicitPCHInclude = PreprocessorOpts.ImplicitPCHInclude; + PreprocessorOpts.ImplicitPCHInclude = PreambleFile; + PreprocessorOpts.DisablePCHValidation = true; + + // Keep track of the override buffer; + SavedMainFileBuffer = OverrideMainBuffer; + + // The stored diagnostic has the old source manager in it; update + // the locations to refer into the new source manager. Since we've + // been careful to make sure that the source manager's state + // before and after are identical, so that we can reuse the source + // location itself. + for (unsigned I = 0, N = StoredDiagnostics.size(); I != N; ++I) { + FullSourceLoc Loc(StoredDiagnostics[I].getLocation(), + getSourceManager()); + StoredDiagnostics[I].setLocation(Loc); + } + } else { + PreprocessorOpts.PrecompiledPreambleBytes.first = 0; + PreprocessorOpts.PrecompiledPreambleBytes.second = false; + } + + llvm::OwningPtr<TopLevelDeclTrackerAction> Act; + Act.reset(new TopLevelDeclTrackerAction(*this)); if (!Act->BeginSourceFile(Clang, Clang.getFrontendOpts().Inputs[0].second, Clang.getFrontendOpts().Inputs[0].first)) goto error; - + Act->Execute(); - + // Steal the created target, context, and preprocessor, and take back the // source and file managers. - AST->Ctx.reset(Clang.takeASTContext()); - AST->PP.reset(Clang.takePreprocessor()); + TheSema.reset(Clang.takeSema()); + Consumer.reset(Clang.takeASTConsumer()); + Ctx.reset(Clang.takeASTContext()); + PP.reset(Clang.takePreprocessor()); Clang.takeSourceManager(); Clang.takeFileManager(); - AST->Target.reset(Clang.takeTarget()); - + Target.reset(Clang.takeTarget()); + Act->EndSourceFile(); - Clang.takeDiagnosticClient(); - Clang.takeInvocation(); - - AST->Invocation.reset(Clang.takeInvocation()); - return AST.take(); + // Remove the overridden buffer we used for the preamble. + if (OverrideMainBuffer) { + PreprocessorOpts.eraseRemappedFile( + PreprocessorOpts.remapped_file_buffer_end() - 1); + PreprocessorOpts.ImplicitPCHInclude = PriorImplicitPCHInclude; + } + Invocation.reset(Clang.takeInvocation()); + + // If we were asked to cache code-completion results and don't have any + // results yet, do so now. + if (ShouldCacheCodeCompletionResults && CachedCompletionResults.empty()) + CacheCodeCompletionResults(); + + return false; + error: + // Remove the overridden buffer we used for the preamble. + if (OverrideMainBuffer) { + PreprocessorOpts.eraseRemappedFile( + PreprocessorOpts.remapped_file_buffer_end() - 1); + PreprocessorOpts.DisablePCHValidation = true; + PreprocessorOpts.ImplicitPCHInclude = PriorImplicitPCHInclude; + delete OverrideMainBuffer; + } + Clang.takeSourceManager(); Clang.takeFileManager(); - Clang.takeDiagnosticClient(); - return 0; + Invocation.reset(Clang.takeInvocation()); + return true; +} + +/// \brief Simple function to retrieve a path for a preamble precompiled header. +static std::string GetPreamblePCHPath() { + // FIXME: This is lame; sys::Path should provide this function (in particular, + // it should know how to find the temporary files dir). + // FIXME: This is really lame. I copied this code from the Driver! + std::string Error; + const char *TmpDir = ::getenv("TMPDIR"); + if (!TmpDir) + TmpDir = ::getenv("TEMP"); + if (!TmpDir) + TmpDir = ::getenv("TMP"); + if (!TmpDir) + TmpDir = "/tmp"; + llvm::sys::Path P(TmpDir); + P.appendComponent("preamble"); + P.appendSuffix("pch"); + if (P.createTemporaryFileOnDisk()) + return std::string(); + + return P.str(); +} + +/// \brief Compute the preamble for the main file, providing the source buffer +/// that corresponds to the main file along with a pair (bytes, start-of-line) +/// that describes the preamble. +std::pair<llvm::MemoryBuffer *, std::pair<unsigned, bool> > +ASTUnit::ComputePreamble(CompilerInvocation &Invocation, + unsigned MaxLines, bool &CreatedBuffer) { + FrontendOptions &FrontendOpts = Invocation.getFrontendOpts(); + PreprocessorOptions &PreprocessorOpts + = Invocation.getPreprocessorOpts(); + CreatedBuffer = false; + + // Try to determine if the main file has been remapped, either from the + // 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].second); + 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 + M = PreprocessorOpts.remapped_file_begin(), + E = PreprocessorOpts.remapped_file_end(); + M != E; + ++M) { + llvm::sys::PathWithStatus MPath(M->first); + if (const llvm::sys::FileStatus *MStatus = MPath.getFileStatus()) { + if (MainFileStatus->uniqueID == MStatus->uniqueID) { + // We found a remapping. Try to load the resulting, remapped source. + if (CreatedBuffer) { + delete Buffer; + CreatedBuffer = false; + } + + Buffer = llvm::MemoryBuffer::getFile(M->second); + if (!Buffer) + return std::make_pair((llvm::MemoryBuffer*)0, + std::make_pair(0, true)); + CreatedBuffer = true; + + // Remove this remapping. We've captured the buffer already. + M = PreprocessorOpts.eraseRemappedFile(M); + E = PreprocessorOpts.remapped_file_end(); + if (M == E) + break; + } + } + } + + // Check whether there is a file-buffer remapping. It supercedes the + // file-file remapping. + for (PreprocessorOptions::remapped_file_buffer_iterator + M = PreprocessorOpts.remapped_file_buffer_begin(), + E = PreprocessorOpts.remapped_file_buffer_end(); + M != E; + ++M) { + llvm::sys::PathWithStatus MPath(M->first); + if (const llvm::sys::FileStatus *MStatus = MPath.getFileStatus()) { + if (MainFileStatus->uniqueID == MStatus->uniqueID) { + // We found a remapping. + if (CreatedBuffer) { + delete Buffer; + CreatedBuffer = false; + } + + Buffer = const_cast<llvm::MemoryBuffer *>(M->second); + + // Remove this remapping. We've captured the buffer already. + M = PreprocessorOpts.eraseRemappedFile(M); + E = PreprocessorOpts.remapped_file_buffer_end(); + if (M == E) + break; + } + } + } + } + + // If the main source file was not remapped, load it now. + if (!Buffer) { + Buffer = llvm::MemoryBuffer::getFile(FrontendOpts.Inputs[0].second); + if (!Buffer) + return std::make_pair((llvm::MemoryBuffer*)0, std::make_pair(0, true)); + + CreatedBuffer = true; + } + + return std::make_pair(Buffer, Lexer::ComputePreamble(Buffer, MaxLines)); +} + +static llvm::MemoryBuffer *CreatePaddedMainFileBuffer(llvm::MemoryBuffer *Old, + bool DeleteOld, + unsigned NewSize, + llvm::StringRef NewName) { + llvm::MemoryBuffer *Result + = llvm::MemoryBuffer::getNewUninitMemBuffer(NewSize, NewName); + memcpy(const_cast<char*>(Result->getBufferStart()), + Old->getBufferStart(), Old->getBufferSize()); + memset(const_cast<char*>(Result->getBufferStart()) + Old->getBufferSize(), + ' ', NewSize - Old->getBufferSize() - 1); + const_cast<char*>(Result->getBufferEnd())[-1] = '\n'; + + if (DeleteOld) + delete Old; + + return Result; +} + +/// \brief Attempt to build or re-use a precompiled preamble when (re-)parsing +/// the source file. +/// +/// This routine will compute the preamble of the main source file. If a +/// non-trivial preamble is found, it will precompile that preamble into a +/// precompiled header so that the precompiled preamble can be used to reduce +/// reparsing time. If a precompiled preamble has already been constructed, +/// this routine will determine if it is still valid and, if so, avoid +/// rebuilding the precompiled preamble. +/// +/// \param AllowRebuild When true (the default), this routine is +/// allowed to rebuild the precompiled preamble if it is found to be +/// out-of-date. +/// +/// \param MaxLines When non-zero, the maximum number of lines that +/// can occur within the preamble. +/// +/// \returns If the precompiled preamble can be used, returns a newly-allocated +/// buffer that should be used in place of the main file when doing so. +/// Otherwise, returns a NULL pointer. +llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble( + CompilerInvocation PreambleInvocation, + bool AllowRebuild, + unsigned MaxLines) { + FrontendOptions &FrontendOpts = PreambleInvocation.getFrontendOpts(); + PreprocessorOptions &PreprocessorOpts + = PreambleInvocation.getPreprocessorOpts(); + + bool CreatedPreambleBuffer = false; + std::pair<llvm::MemoryBuffer *, std::pair<unsigned, bool> > NewPreamble + = ComputePreamble(PreambleInvocation, MaxLines, CreatedPreambleBuffer); + + if (!NewPreamble.second.first) { + // We couldn't find a preamble in the main source. Clear out the current + // preamble, if we have one. It's obviously no good any more. + Preamble.clear(); + if (!PreambleFile.empty()) { + llvm::sys::Path(PreambleFile).eraseFromDisk(); + PreambleFile.clear(); + } + if (CreatedPreambleBuffer) + delete NewPreamble.first; + + // The next time we actually see a preamble, precompile it. + PreambleRebuildCounter = 1; + return 0; + } + + if (!Preamble.empty()) { + // We've previously computed a preamble. Check whether we have the same + // preamble now that we did before, and that there's enough space in + // the main-file buffer within the precompiled preamble to fit the + // new main file. + if (Preamble.size() == NewPreamble.second.first && + PreambleEndsAtStartOfLine == NewPreamble.second.second && + NewPreamble.first->getBufferSize() < PreambleReservedSize-2 && + memcmp(&Preamble[0], NewPreamble.first->getBufferStart(), + NewPreamble.second.first) == 0) { + // The preamble has not changed. We may be able to re-use the precompiled + // preamble. + + // Check that none of the files used by the preamble have changed. + bool AnyFileChanged = false; + + // First, make a record of those files that have been overridden via + // remapping or unsaved_files. + llvm::StringMap<std::pair<off_t, time_t> > OverriddenFiles; + for (PreprocessorOptions::remapped_file_iterator + R = PreprocessorOpts.remapped_file_begin(), + REnd = PreprocessorOpts.remapped_file_end(); + !AnyFileChanged && R != REnd; + ++R) { + struct stat StatBuf; + if (stat(R->second.c_str(), &StatBuf)) { + // If we can't stat the file we're remapping to, assume that something + // horrible happened. + AnyFileChanged = true; + break; + } + + OverriddenFiles[R->first] = std::make_pair(StatBuf.st_size, + StatBuf.st_mtime); + } + for (PreprocessorOptions::remapped_file_buffer_iterator + R = PreprocessorOpts.remapped_file_buffer_begin(), + REnd = PreprocessorOpts.remapped_file_buffer_end(); + !AnyFileChanged && R != REnd; + ++R) { + // FIXME: Should we actually compare the contents of file->buffer + // remappings? + OverriddenFiles[R->first] = std::make_pair(R->second->getBufferSize(), + 0); + } + + // Check whether anything has changed. + for (llvm::StringMap<std::pair<off_t, time_t> >::iterator + F = FilesInPreamble.begin(), FEnd = FilesInPreamble.end(); + !AnyFileChanged && F != FEnd; + ++F) { + llvm::StringMap<std::pair<off_t, time_t> >::iterator Overridden + = OverriddenFiles.find(F->first()); + if (Overridden != OverriddenFiles.end()) { + // This file was remapped; check whether the newly-mapped file + // matches up with the previous mapping. + if (Overridden->second != F->second) + AnyFileChanged = true; + continue; + } + + // The file was not remapped; check whether it has changed on disk. + struct stat StatBuf; + if (stat(F->first(), &StatBuf)) { + // If we can't stat the file, assume that something horrible happened. + AnyFileChanged = true; + } else if (StatBuf.st_size != F->second.first || + StatBuf.st_mtime != F->second.second) + AnyFileChanged = true; + } + + if (!AnyFileChanged) { + // Okay! We can re-use the precompiled preamble. + + // Set the state of the diagnostic object to mimic its state + // after parsing the preamble. + getDiagnostics().Reset(); + getDiagnostics().setNumWarnings(NumWarningsInPreamble); + if (StoredDiagnostics.size() > NumStoredDiagnosticsInPreamble) + StoredDiagnostics.erase( + StoredDiagnostics.begin() + NumStoredDiagnosticsInPreamble, + StoredDiagnostics.end()); + + // Create a version of the main file buffer that is padded to + // buffer size we reserved when creating the preamble. + return CreatePaddedMainFileBuffer(NewPreamble.first, + CreatedPreambleBuffer, + PreambleReservedSize, + FrontendOpts.Inputs[0].second); + } + } + + // If we aren't allowed to rebuild the precompiled preamble, just + // return now. + if (!AllowRebuild) + return 0; + + // We can't reuse the previously-computed preamble. Build a new one. + Preamble.clear(); + llvm::sys::Path(PreambleFile).eraseFromDisk(); + PreambleRebuildCounter = 1; + } else if (!AllowRebuild) { + // We aren't allowed to rebuild the precompiled preamble; just + // return now. + return 0; + } + + // If the preamble rebuild counter > 1, it's because we previously + // failed to build a preamble and we're not yet ready to try + // again. Decrement the counter and return a failure. + if (PreambleRebuildCounter > 1) { + --PreambleRebuildCounter; + return 0; + } + + // We did not previously compute a preamble, or it can't be reused anyway. + llvm::Timer *PreambleTimer = 0; + if (TimerGroup.get()) { + PreambleTimer = new llvm::Timer("Precompiling preamble", *TimerGroup); + PreambleTimer->startTimer(); + Timers.push_back(PreambleTimer); + } + + // Create a new buffer that stores the preamble. The buffer also contains + // extra space for the original contents of the file (which will be present + // when we actually parse the file) along with more room in case the file + // grows. + PreambleReservedSize = NewPreamble.first->getBufferSize(); + if (PreambleReservedSize < 4096) + PreambleReservedSize = 8191; + else + PreambleReservedSize *= 2; + + // Save the preamble text for later; we'll need to compare against it for + // subsequent reparses. + Preamble.assign(NewPreamble.first->getBufferStart(), + NewPreamble.first->getBufferStart() + + NewPreamble.second.first); + PreambleEndsAtStartOfLine = NewPreamble.second.second; + + delete PreambleBuffer; + PreambleBuffer + = llvm::MemoryBuffer::getNewUninitMemBuffer(PreambleReservedSize, + FrontendOpts.Inputs[0].second); + memcpy(const_cast<char*>(PreambleBuffer->getBufferStart()), + NewPreamble.first->getBufferStart(), Preamble.size()); + memset(const_cast<char*>(PreambleBuffer->getBufferStart()) + Preamble.size(), + ' ', PreambleReservedSize - Preamble.size() - 1); + const_cast<char*>(PreambleBuffer->getBufferEnd())[-1] = '\n'; + + // Remap the main source file to the preamble buffer. + llvm::sys::PathWithStatus MainFilePath(FrontendOpts.Inputs[0].second); + PreprocessorOpts.addRemappedFile(MainFilePath.str(), PreambleBuffer); + + // Tell the compiler invocation to generate a temporary precompiled header. + FrontendOpts.ProgramAction = frontend::GeneratePCH; + // FIXME: Set ChainedPCH unconditionally, once it is ready. + if (::getenv("LIBCLANG_CHAINING")) + FrontendOpts.ChainedPCH = true; + // FIXME: Generate the precompiled header into memory? + FrontendOpts.OutputFile = GetPreamblePCHPath(); + + // Create the compiler instance to use for building the precompiled preamble. + CompilerInstance Clang; + Clang.setInvocation(&PreambleInvocation); + OriginalSourceFile = Clang.getFrontendOpts().Inputs[0].second; + + // Set up diagnostics, capturing all of the diagnostics produced. + Clang.setDiagnostics(&getDiagnostics()); + CaptureDroppedDiagnostics Capture(CaptureDiagnostics, + getDiagnostics(), + StoredDiagnostics); + + // Create the target instance. + Clang.setTarget(TargetInfo::CreateTargetInfo(Clang.getDiagnostics(), + Clang.getTargetOpts())); + if (!Clang.hasTarget()) { + llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk(); + Preamble.clear(); + if (CreatedPreambleBuffer) + delete NewPreamble.first; + if (PreambleTimer) + PreambleTimer->stopTimer(); + PreambleRebuildCounter = DefaultPreambleRebuildInterval; + PreprocessorOpts.eraseRemappedFile( + PreprocessorOpts.remapped_file_buffer_end() - 1); + return 0; + } + + // 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. + Clang.getTarget().setForcedLangOptions(Clang.getLangOpts()); + + assert(Clang.getFrontendOpts().Inputs.size() == 1 && + "Invocation must have exactly one source file!"); + assert(Clang.getFrontendOpts().Inputs[0].first != IK_AST && + "FIXME: AST inputs not yet supported here!"); + assert(Clang.getFrontendOpts().Inputs[0].first != IK_LLVM_IR && + "IR inputs not support here!"); + + // Clear out old caches and data. + StoredDiagnostics.clear(); + TopLevelDecls.clear(); + TopLevelDeclsInPreamble.clear(); + + // Create a file manager object to provide access to and cache the filesystem. + Clang.setFileManager(new FileManager); + + // Create the source manager. + Clang.setSourceManager(new SourceManager(getDiagnostics())); + + llvm::OwningPtr<PrecompilePreambleAction> Act; + Act.reset(new PrecompilePreambleAction(*this)); + if (!Act->BeginSourceFile(Clang, Clang.getFrontendOpts().Inputs[0].second, + Clang.getFrontendOpts().Inputs[0].first)) { + Clang.takeInvocation(); + llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk(); + Preamble.clear(); + if (CreatedPreambleBuffer) + delete NewPreamble.first; + if (PreambleTimer) + PreambleTimer->stopTimer(); + PreambleRebuildCounter = DefaultPreambleRebuildInterval; + PreprocessorOpts.eraseRemappedFile( + PreprocessorOpts.remapped_file_buffer_end() - 1); + return 0; + } + + Act->Execute(); + Act->EndSourceFile(); + Clang.takeInvocation(); + + if (Diagnostics->hasErrorOccurred()) { + // There were errors parsing the preamble, so no precompiled header was + // generated. Forget that we even tried. + // FIXME: Should we leave a note for ourselves to try again? + llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk(); + Preamble.clear(); + if (CreatedPreambleBuffer) + delete NewPreamble.first; + if (PreambleTimer) + PreambleTimer->stopTimer(); + TopLevelDeclsInPreamble.clear(); + PreambleRebuildCounter = DefaultPreambleRebuildInterval; + PreprocessorOpts.eraseRemappedFile( + PreprocessorOpts.remapped_file_buffer_end() - 1); + return 0; + } + + // Keep track of the preamble we precompiled. + PreambleFile = FrontendOpts.OutputFile; + NumStoredDiagnosticsInPreamble = StoredDiagnostics.size(); + NumWarningsInPreamble = getDiagnostics().getNumWarnings(); + + // Keep track of all of the files that the source manager knows about, + // so we can verify whether they have changed or not. + FilesInPreamble.clear(); + SourceManager &SourceMgr = Clang.getSourceManager(); + const llvm::MemoryBuffer *MainFileBuffer + = SourceMgr.getBuffer(SourceMgr.getMainFileID()); + for (SourceManager::fileinfo_iterator F = SourceMgr.fileinfo_begin(), + FEnd = SourceMgr.fileinfo_end(); + F != FEnd; + ++F) { + const FileEntry *File = F->second->Entry; + if (!File || F->second->getRawBuffer() == MainFileBuffer) + continue; + + FilesInPreamble[File->getName()] + = std::make_pair(F->second->getSize(), File->getModificationTime()); + } + + if (PreambleTimer) + PreambleTimer->stopTimer(); + + PreambleRebuildCounter = 1; + PreprocessorOpts.eraseRemappedFile( + PreprocessorOpts.remapped_file_buffer_end() - 1); + return CreatePaddedMainFileBuffer(NewPreamble.first, + CreatedPreambleBuffer, + PreambleReservedSize, + FrontendOpts.Inputs[0].second); +} + +void ASTUnit::RealizeTopLevelDeclsFromPreamble() { + std::vector<Decl *> Resolved; + Resolved.reserve(TopLevelDeclsInPreamble.size()); + ExternalASTSource &Source = *getASTContext().getExternalSource(); + for (unsigned I = 0, N = TopLevelDeclsInPreamble.size(); I != N; ++I) { + // Resolve the declaration ID to an actual declaration, possibly + // deserializing the declaration in the process. + Decl *D = Source.GetExternalDecl(TopLevelDeclsInPreamble[I]); + if (D) + Resolved.push_back(D); + } + TopLevelDeclsInPreamble.clear(); + TopLevelDecls.insert(TopLevelDecls.begin(), Resolved.begin(), Resolved.end()); +} + +unsigned ASTUnit::getMaxPCHLevel() const { + if (!getOnlyLocalDecls()) + return Decl::MaxPCHLevel; + + unsigned Result = 0; + if (isMainFileAST() || SavedMainFileBuffer) + ++Result; + return Result; +} + +ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI, + llvm::IntrusiveRefCntPtr<Diagnostic> Diags, + bool OnlyLocalDecls, + bool CaptureDiagnostics, + bool PrecompilePreamble, + bool CompleteTranslationUnit, + bool CacheCodeCompletionResults) { + if (!Diags.getPtr()) { + // No diagnostics engine was provided, so create our own diagnostics object + // with the default options. + DiagnosticOptions DiagOpts; + Diags = CompilerInstance::createDiagnostics(DiagOpts, 0, 0); + } + + // Create the AST unit. + llvm::OwningPtr<ASTUnit> AST; + AST.reset(new ASTUnit(false)); + AST->Diagnostics = Diags; + AST->CaptureDiagnostics = CaptureDiagnostics; + AST->OnlyLocalDecls = OnlyLocalDecls; + AST->CompleteTranslationUnit = CompleteTranslationUnit; + AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults; + AST->Invocation.reset(CI); + CI->getPreprocessorOpts().RetainRemappedFileBuffers = true; + + if (getenv("LIBCLANG_TIMING")) + AST->TimerGroup.reset( + new llvm::TimerGroup(CI->getFrontendOpts().Inputs[0].second)); + + + llvm::MemoryBuffer *OverrideMainBuffer = 0; + // FIXME: When C++ PCH is ready, allow use of it for a precompiled preamble. + if (PrecompilePreamble && !CI->getLangOpts().CPlusPlus) { + AST->PreambleRebuildCounter = 1; + OverrideMainBuffer + = AST->getMainBufferWithPrecompiledPreamble(*AST->Invocation); + } + + llvm::Timer *ParsingTimer = 0; + if (AST->TimerGroup.get()) { + ParsingTimer = new llvm::Timer("Initial parse", *AST->TimerGroup); + ParsingTimer->startTimer(); + AST->Timers.push_back(ParsingTimer); + } + + bool Failed = AST->Parse(OverrideMainBuffer); + if (ParsingTimer) + ParsingTimer->stopTimer(); + + return Failed? 0 : AST.take(); } ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin, @@ -396,12 +1343,18 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin, bool OnlyLocalDecls, RemappedFile *RemappedFiles, unsigned NumRemappedFiles, - bool CaptureDiagnostics) { + bool CaptureDiagnostics, + bool PrecompilePreamble, + bool CompleteTranslationUnit, + bool CacheCodeCompletionResults) { + bool CreatedDiagnosticsObject = false; + if (!Diags.getPtr()) { // No diagnostics engine was provided, so create our own diagnostics object // with the default options. DiagnosticOptions DiagOpts; Diags = CompilerInstance::createDiagnostics(DiagOpts, 0, 0); + CreatedDiagnosticsObject = true; } llvm::SmallVector<const char *, 16> Args; @@ -413,7 +1366,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin, Args.push_back("-fsyntax-only"); // FIXME: We shouldn't have to pass in the path info. - driver::Driver TheDriver("clang", "/", llvm::sys::getHostTriple(), + driver::Driver TheDriver("clang", llvm::sys::getHostTriple(), "a.out", false, false, *Diags); // Don't check that inputs exist, they have been remapped. @@ -444,7 +1397,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin, CompilerInvocation::CreateFromArgs(*CI, const_cast<const char **>(CCArgs.data()), const_cast<const char **>(CCArgs.data()) + - CCArgs.size(), + CCArgs.size(), *Diags); // Override any files that need remapping @@ -455,7 +1408,468 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin, // Override the resources path. CI->getHeaderSearchOpts().ResourceDir = ResourceFilesPath; - CI->getFrontendOpts().DisableFree = true; + CI->getFrontendOpts().DisableFree = false; return LoadFromCompilerInvocation(CI.take(), Diags, OnlyLocalDecls, - CaptureDiagnostics); + CaptureDiagnostics, PrecompilePreamble, + CompleteTranslationUnit, + CacheCodeCompletionResults); +} + +bool ASTUnit::Reparse(RemappedFile *RemappedFiles, unsigned NumRemappedFiles) { + if (!Invocation.get()) + return true; + + llvm::Timer *ReparsingTimer = 0; + if (TimerGroup.get()) { + ReparsingTimer = new llvm::Timer("Reparse", *TimerGroup); + ReparsingTimer->startTimer(); + Timers.push_back(ReparsingTimer); + } + + // Remap files. + PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts(); + for (PreprocessorOptions::remapped_file_buffer_iterator + R = PPOpts.remapped_file_buffer_begin(), + REnd = PPOpts.remapped_file_buffer_end(); + R != REnd; + ++R) { + delete R->second; + } + Invocation->getPreprocessorOpts().clearRemappedFiles(); + for (unsigned I = 0; I != NumRemappedFiles; ++I) + Invocation->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first, + RemappedFiles[I].second); + + // If we have a preamble file lying around, or if we might try to + // build a precompiled preamble, do so now. + llvm::MemoryBuffer *OverrideMainBuffer = 0; + if (!PreambleFile.empty() || PreambleRebuildCounter > 0) + OverrideMainBuffer = getMainBufferWithPrecompiledPreamble(*Invocation); + + // Clear out the diagnostics state. + if (!OverrideMainBuffer) + getDiagnostics().Reset(); + + // Parse the sources + bool Result = Parse(OverrideMainBuffer); + if (ReparsingTimer) + ReparsingTimer->stopTimer(); + + if (ShouldCacheCodeCompletionResults) { + if (CacheCodeCompletionCoolDown > 0) + --CacheCodeCompletionCoolDown; + else if (top_level_size() != NumTopLevelDeclsAtLastCompletionCache) + CacheCodeCompletionResults(); + } + + return Result; +} + +//----------------------------------------------------------------------------// +// Code completion +//----------------------------------------------------------------------------// + +namespace { + /// \brief Code completion consumer that combines the cached code-completion + /// results from an ASTUnit with the code-completion results provided to it, + /// then passes the result on to + class AugmentedCodeCompleteConsumer : public CodeCompleteConsumer { + unsigned NormalContexts; + ASTUnit &AST; + CodeCompleteConsumer &Next; + + public: + AugmentedCodeCompleteConsumer(ASTUnit &AST, CodeCompleteConsumer &Next, + bool IncludeMacros, bool IncludeCodePatterns, + bool IncludeGlobals) + : CodeCompleteConsumer(IncludeMacros, IncludeCodePatterns, IncludeGlobals, + Next.isOutputBinary()), AST(AST), Next(Next) + { + // Compute the set of contexts in which we will look when we don't have + // any information about the specific context. + NormalContexts + = (1 << (CodeCompletionContext::CCC_TopLevel - 1)) + | (1 << (CodeCompletionContext::CCC_ObjCInterface - 1)) + | (1 << (CodeCompletionContext::CCC_ObjCImplementation - 1)) + | (1 << (CodeCompletionContext::CCC_ObjCIvarList - 1)) + | (1 << (CodeCompletionContext::CCC_Statement - 1)) + | (1 << (CodeCompletionContext::CCC_Expression - 1)) + | (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1)) + | (1 << (CodeCompletionContext::CCC_MemberAccess - 1)) + | (1 << (CodeCompletionContext::CCC_ObjCProtocolName - 1)); + + if (AST.getASTContext().getLangOptions().CPlusPlus) + NormalContexts |= (1 << (CodeCompletionContext::CCC_EnumTag - 1)) + | (1 << (CodeCompletionContext::CCC_UnionTag - 1)) + | (1 << (CodeCompletionContext::CCC_ClassOrStructTag - 1)); + } + + virtual void ProcessCodeCompleteResults(Sema &S, + CodeCompletionContext Context, + CodeCompletionResult *Results, + unsigned NumResults); + + virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg, + OverloadCandidate *Candidates, + unsigned NumCandidates) { + Next.ProcessOverloadCandidates(S, CurrentArg, Candidates, NumCandidates); + } + }; +} + +/// \brief Helper function that computes which global names are hidden by the +/// local code-completion results. +void CalculateHiddenNames(const CodeCompletionContext &Context, + CodeCompletionResult *Results, + unsigned NumResults, + ASTContext &Ctx, + llvm::StringSet<> &HiddenNames) { + bool OnlyTagNames = false; + switch (Context.getKind()) { + case CodeCompletionContext::CCC_Other: + case CodeCompletionContext::CCC_TopLevel: + case CodeCompletionContext::CCC_ObjCInterface: + case CodeCompletionContext::CCC_ObjCImplementation: + case CodeCompletionContext::CCC_ObjCIvarList: + case CodeCompletionContext::CCC_ClassStructUnion: + case CodeCompletionContext::CCC_Statement: + case CodeCompletionContext::CCC_Expression: + case CodeCompletionContext::CCC_ObjCMessageReceiver: + case CodeCompletionContext::CCC_MemberAccess: + case CodeCompletionContext::CCC_Namespace: + case CodeCompletionContext::CCC_Type: + case CodeCompletionContext::CCC_Name: + case CodeCompletionContext::CCC_PotentiallyQualifiedName: + break; + + case CodeCompletionContext::CCC_EnumTag: + case CodeCompletionContext::CCC_UnionTag: + case CodeCompletionContext::CCC_ClassOrStructTag: + OnlyTagNames = true; + break; + + case CodeCompletionContext::CCC_ObjCProtocolName: + case CodeCompletionContext::CCC_MacroName: + case CodeCompletionContext::CCC_MacroNameUse: + case CodeCompletionContext::CCC_PreprocessorExpression: + case CodeCompletionContext::CCC_PreprocessorDirective: + case CodeCompletionContext::CCC_NaturalLanguage: + case CodeCompletionContext::CCC_SelectorName: + case CodeCompletionContext::CCC_TypeQualifiers: + // We're looking for nothing, or we're looking for names that cannot + // be hidden. + return; + } + + typedef CodeCompletionResult Result; + for (unsigned I = 0; I != NumResults; ++I) { + if (Results[I].Kind != Result::RK_Declaration) + continue; + + unsigned IDNS + = Results[I].Declaration->getUnderlyingDecl()->getIdentifierNamespace(); + + bool Hiding = false; + if (OnlyTagNames) + Hiding = (IDNS & Decl::IDNS_Tag); + else { + unsigned HiddenIDNS = (Decl::IDNS_Type | Decl::IDNS_Member | + Decl::IDNS_Namespace | Decl::IDNS_Ordinary | + Decl::IDNS_NonMemberOperator); + if (Ctx.getLangOptions().CPlusPlus) + HiddenIDNS |= Decl::IDNS_Tag; + Hiding = (IDNS & HiddenIDNS); + } + + if (!Hiding) + continue; + + DeclarationName Name = Results[I].Declaration->getDeclName(); + if (IdentifierInfo *Identifier = Name.getAsIdentifierInfo()) + HiddenNames.insert(Identifier->getName()); + else + HiddenNames.insert(Name.getAsString()); + } +} + + +void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S, + CodeCompletionContext Context, + CodeCompletionResult *Results, + unsigned NumResults) { + // Merge the results we were given with the results we cached. + bool AddedResult = false; + unsigned InContexts + = (Context.getKind() == CodeCompletionContext::CCC_Other? NormalContexts + : (1 << (Context.getKind() - 1))); + + // Contains the set of names that are hidden by "local" completion results. + llvm::StringSet<> HiddenNames; + llvm::SmallVector<CodeCompletionString *, 4> StringsToDestroy; + typedef CodeCompletionResult Result; + llvm::SmallVector<Result, 8> AllResults; + for (ASTUnit::cached_completion_iterator + C = AST.cached_completion_begin(), + CEnd = AST.cached_completion_end(); + C != CEnd; ++C) { + // If the context we are in matches any of the contexts we are + // interested in, we'll add this result. + if ((C->ShowInContexts & InContexts) == 0) + continue; + + // If we haven't added any results previously, do so now. + if (!AddedResult) { + CalculateHiddenNames(Context, Results, NumResults, S.Context, + HiddenNames); + AllResults.insert(AllResults.end(), Results, Results + NumResults); + AddedResult = true; + } + + // Determine whether this global completion result is hidden by a local + // completion result. If so, skip it. + if (C->Kind != CXCursor_MacroDefinition && + HiddenNames.count(C->Completion->getTypedText())) + continue; + + // 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) { + Priority = getMacroUsagePriority(C->Completion->getTypedText(), + Context.getPreferredType()->isAnyPointerType()); + } else if (C->Type) { + CanQualType Expected + = S.Context.getCanonicalType( + Context.getPreferredType().getUnqualifiedType()); + SimplifiedTypeClass ExpectedSTC = getSimplifiedTypeClass(Expected); + if (ExpectedSTC == C->TypeClass) { + // We know this type is similar; check for an exact match. + llvm::StringMap<unsigned> &CachedCompletionTypes + = AST.getCachedCompletionTypes(); + llvm::StringMap<unsigned>::iterator Pos + = CachedCompletionTypes.find(QualType(Expected).getAsString()); + if (Pos != CachedCompletionTypes.end() && Pos->second == C->Type) + Priority /= CCF_ExactTypeMatch; + else + Priority /= CCF_SimilarTypeMatch; + } + } + } + + // Adjust the completion string, if required. + if (C->Kind == CXCursor_MacroDefinition && + Context.getKind() == CodeCompletionContext::CCC_MacroNameUse) { + // Create a new code-completion string that just contains the + // macro name, without its arguments. + Completion = new CodeCompletionString; + Completion->AddTypedTextChunk(C->Completion->getTypedText()); + StringsToDestroy.push_back(Completion); + CursorKind = CXCursor_NotImplemented; + Priority = CCP_CodePattern; + } + + AllResults.push_back(Result(Completion, Priority, CursorKind, + C->Availability)); + } + + // If we did not add any cached completion results, just forward the + // results we were given to the next consumer. + if (!AddedResult) { + Next.ProcessCodeCompleteResults(S, Context, Results, NumResults); + return; + } + + Next.ProcessCodeCompleteResults(S, Context, AllResults.data(), + AllResults.size()); + + for (unsigned I = 0, N = StringsToDestroy.size(); I != N; ++I) + delete StringsToDestroy[I]; +} + + + +void ASTUnit::CodeComplete(llvm::StringRef File, unsigned Line, unsigned Column, + RemappedFile *RemappedFiles, + unsigned NumRemappedFiles, + bool IncludeMacros, + bool IncludeCodePatterns, + CodeCompleteConsumer &Consumer, + Diagnostic &Diag, LangOptions &LangOpts, + SourceManager &SourceMgr, FileManager &FileMgr, + llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiagnostics, + llvm::SmallVectorImpl<const llvm::MemoryBuffer *> &OwnedBuffers) { + if (!Invocation.get()) + return; + + llvm::Timer *CompletionTimer = 0; + if (TimerGroup.get()) { + llvm::SmallString<128> TimerName; + llvm::raw_svector_ostream TimerNameOut(TimerName); + TimerNameOut << "Code completion @ " << File << ":" << Line << ":" + << Column; + CompletionTimer = new llvm::Timer(TimerNameOut.str(), *TimerGroup); + CompletionTimer->startTimer(); + Timers.push_back(CompletionTimer); + } + + CompilerInvocation CCInvocation(*Invocation); + FrontendOptions &FrontendOpts = CCInvocation.getFrontendOpts(); + PreprocessorOptions &PreprocessorOpts = CCInvocation.getPreprocessorOpts(); + + FrontendOpts.ShowMacrosInCodeCompletion + = IncludeMacros && CachedCompletionResults.empty(); + FrontendOpts.ShowCodePatternsInCodeCompletion = IncludeCodePatterns; + FrontendOpts.ShowGlobalSymbolsInCodeCompletion + = CachedCompletionResults.empty(); + FrontendOpts.CodeCompletionAt.FileName = File; + FrontendOpts.CodeCompletionAt.Line = Line; + FrontendOpts.CodeCompletionAt.Column = Column; + + // Turn on spell-checking when performing code completion. It leads + // to better results. + unsigned SpellChecking = CCInvocation.getLangOpts().SpellChecking; + CCInvocation.getLangOpts().SpellChecking = 1; + + // Set the language options appropriately. + LangOpts = CCInvocation.getLangOpts(); + + CompilerInstance Clang; + Clang.setInvocation(&CCInvocation); + OriginalSourceFile = Clang.getFrontendOpts().Inputs[0].second; + + // Set up diagnostics, capturing any diagnostics produced. + Clang.setDiagnostics(&Diag); + CaptureDroppedDiagnostics Capture(true, + Clang.getDiagnostics(), + StoredDiagnostics); + + // Create the target instance. + Clang.setTarget(TargetInfo::CreateTargetInfo(Clang.getDiagnostics(), + Clang.getTargetOpts())); + if (!Clang.hasTarget()) { + Clang.takeInvocation(); + CCInvocation.getLangOpts().SpellChecking = SpellChecking; + 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. + Clang.getTarget().setForcedLangOptions(Clang.getLangOpts()); + + assert(Clang.getFrontendOpts().Inputs.size() == 1 && + "Invocation must have exactly one source file!"); + assert(Clang.getFrontendOpts().Inputs[0].first != IK_AST && + "FIXME: AST inputs not yet supported here!"); + assert(Clang.getFrontendOpts().Inputs[0].first != IK_LLVM_IR && + "IR inputs not support here!"); + + + // Use the source and file managers that we were given. + Clang.setFileManager(&FileMgr); + Clang.setSourceManager(&SourceMgr); + + // Remap files. + PreprocessorOpts.clearRemappedFiles(); + PreprocessorOpts.RetainRemappedFileBuffers = true; + for (unsigned I = 0; I != NumRemappedFiles; ++I) { + PreprocessorOpts.addRemappedFile(RemappedFiles[I].first, + RemappedFiles[I].second); + OwnedBuffers.push_back(RemappedFiles[I].second); + } + + // Use the code completion consumer we were given, but adding any cached + // code-completion results. + AugmentedCodeCompleteConsumer + AugmentedConsumer(*this, Consumer, FrontendOpts.ShowMacrosInCodeCompletion, + FrontendOpts.ShowCodePatternsInCodeCompletion, + FrontendOpts.ShowGlobalSymbolsInCodeCompletion); + Clang.setCodeCompletionConsumer(&AugmentedConsumer); + + // 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 + // preamble. + llvm::MemoryBuffer *OverrideMainBuffer = 0; + if (!PreambleFile.empty()) { + using llvm::sys::FileStatus; + llvm::sys::PathWithStatus CompleteFilePath(File); + llvm::sys::PathWithStatus MainPath(OriginalSourceFile); + if (const FileStatus *CompleteFileStatus = CompleteFilePath.getFileStatus()) + if (const FileStatus *MainStatus = MainPath.getFileStatus()) + if (CompleteFileStatus->getUniqueID() == MainStatus->getUniqueID()) + OverrideMainBuffer + = getMainBufferWithPrecompiledPreamble(CCInvocation, false, + Line - 1); + } + + // If the main file has been overridden due to the use of a preamble, + // make that override happen and introduce the preamble. + if (OverrideMainBuffer) { + PreprocessorOpts.addRemappedFile(OriginalSourceFile, OverrideMainBuffer); + PreprocessorOpts.PrecompiledPreambleBytes.first = Preamble.size(); + PreprocessorOpts.PrecompiledPreambleBytes.second + = PreambleEndsAtStartOfLine; + PreprocessorOpts.ImplicitPCHInclude = PreambleFile; + PreprocessorOpts.DisablePCHValidation = true; + + // The stored diagnostics have the old source manager. Copy them + // to our output set of stored diagnostics, updating the source + // manager to the one we were given. + for (unsigned I = 0, N = this->StoredDiagnostics.size(); I != N; ++I) { + StoredDiagnostics.push_back(this->StoredDiagnostics[I]); + FullSourceLoc Loc(StoredDiagnostics[I].getLocation(), SourceMgr); + StoredDiagnostics[I].setLocation(Loc); + } + + OwnedBuffers.push_back(OverrideMainBuffer); + } else { + PreprocessorOpts.PrecompiledPreambleBytes.first = 0; + PreprocessorOpts.PrecompiledPreambleBytes.second = false; + } + + llvm::OwningPtr<SyntaxOnlyAction> Act; + Act.reset(new SyntaxOnlyAction); + if (Act->BeginSourceFile(Clang, Clang.getFrontendOpts().Inputs[0].second, + Clang.getFrontendOpts().Inputs[0].first)) { + Act->Execute(); + Act->EndSourceFile(); + } + + if (CompletionTimer) + CompletionTimer->stopTimer(); + + // Steal back our resources. + Clang.takeFileManager(); + Clang.takeSourceManager(); + Clang.takeInvocation(); + Clang.takeCodeCompletionConsumer(); + CCInvocation.getLangOpts().SpellChecking = SpellChecking; +} + +bool ASTUnit::Save(llvm::StringRef File) { + if (getDiagnostics().hasErrorOccurred()) + 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? + std::string ErrorInfo; + llvm::raw_fd_ostream Out(File.str().c_str(), ErrorInfo, + llvm::raw_fd_ostream::F_Binary); + if (!ErrorInfo.empty() || Out.has_error()) + return true; + + std::vector<unsigned char> Buffer; + llvm::BitstreamWriter Stream(Buffer); + ASTWriter Writer(Stream); + Writer.WriteAST(getSema(), 0, 0); + + // Write the generated bitstream to "Out". + if (!Buffer.empty()) + Out.write((char *)&Buffer.front(), Buffer.size()); + Out.close(); + return Out.has_error(); } diff --git a/lib/Frontend/CMakeLists.txt b/lib/Frontend/CMakeLists.txt index 8757e2c..5a31495 100644 --- a/lib/Frontend/CMakeLists.txt +++ b/lib/Frontend/CMakeLists.txt @@ -15,17 +15,9 @@ add_clang_library(clangFrontend FrontendAction.cpp FrontendActions.cpp FrontendOptions.cpp - GeneratePCH.cpp InitHeaderSearch.cpp InitPreprocessor.cpp LangStandards.cpp - PCHReader.cpp - PCHReaderDecl.cpp - PCHReaderStmt.cpp - PCHWriter.cpp - PCHWriterDecl.cpp - PCHWriterStmt.cpp - PrintParserCallbacks.cpp PrintPreprocessedOutput.cpp StmtXML.cpp TextDiagnosticBuffer.cpp diff --git a/lib/Frontend/CacheTokens.cpp b/lib/Frontend/CacheTokens.cpp index a5fcebe..53f7362 100644 --- a/lib/Frontend/CacheTokens.cpp +++ b/lib/Frontend/CacheTokens.cpp @@ -311,14 +311,19 @@ PTHEntry PTHWriter::LexTokens(Lexer& L) { // the next token. assert(!ParsingPreprocessorDirective); Offset HashOff = (Offset) Out.tell(); - EmitToken(Tok); // Get the next token. - L.LexFromRawLexer(Tok); + Token NextTok; + L.LexFromRawLexer(NextTok); - // If we see the start of line, then we had a null directive "#". - if (Tok.isAtStartOfLine()) + // If we see the start of line, then we had a null directive "#". In + // this case, discard both tokens. + if (NextTok.isAtStartOfLine()) goto NextToken; + + // The token is the start of a directive. Emit it. + EmitToken(Tok); + Tok = NextTok; // Did we see 'include'/'import'/'include_next'? if (Tok.isNot(tok::identifier)) { diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index 5037c83..ce0b072 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/lib/Frontend/CompilerInstance.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "clang/Frontend/CompilerInstance.h" +#include "clang/Sema/Sema.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/Basic/Diagnostic.h" @@ -20,11 +21,11 @@ #include "clang/Lex/PTHManager.h" #include "clang/Frontend/ChainedDiagnosticClient.h" #include "clang/Frontend/FrontendAction.h" -#include "clang/Frontend/PCHReader.h" #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Frontend/TextDiagnosticPrinter.h" #include "clang/Frontend/VerifyDiagnosticsClient.h" #include "clang/Frontend/Utils.h" +#include "clang/Serialization/ASTReader.h" #include "clang/Sema/CodeCompleteConsumer.h" #include "llvm/LLVMContext.h" #include "llvm/Support/MemoryBuffer.h" @@ -37,7 +38,7 @@ using namespace clang; CompilerInstance::CompilerInstance() - : Invocation(new CompilerInvocation()), Reader(0) { + : Invocation(new CompilerInvocation()) { } CompilerInstance::~CompilerInstance() { @@ -55,10 +56,6 @@ void CompilerInstance::setDiagnostics(Diagnostic *Value) { Diagnostics = Value; } -void CompilerInstance::setDiagnosticClient(DiagnosticClient *Value) { - DiagClient.reset(Value); -} - void CompilerInstance::setTarget(TargetInfo *Value) { Target.reset(Value); } @@ -79,6 +76,10 @@ void CompilerInstance::setASTContext(ASTContext *Value) { Context.reset(Value); } +void CompilerInstance::setSema(Sema *S) { + TheSema.reset(S); +} + void CompilerInstance::setASTConsumer(ASTConsumer *Value) { Consumer.reset(Value); } @@ -126,14 +127,11 @@ static void SetUpBuildDumpLog(const DiagnosticOptions &DiagOpts, // Chain in a diagnostic client which will log the diagnostics. DiagnosticClient *Logger = new TextDiagnosticPrinter(*OS.take(), DiagOpts, /*OwnsOutputStream=*/true); - Diags.setClient(new ChainedDiagnosticClient(Diags.getClient(), Logger)); + Diags.setClient(new ChainedDiagnosticClient(Diags.takeClient(), Logger)); } void CompilerInstance::createDiagnostics(int Argc, char **Argv) { Diagnostics = createDiagnostics(getDiagnosticOpts(), Argc, Argv); - - if (Diagnostics) - DiagClient.reset(Diagnostics->getClient()); } llvm::IntrusiveRefCntPtr<Diagnostic> @@ -150,22 +148,20 @@ CompilerInstance::createDiagnostics(const DiagnosticOptions &Opts, // bit of a problem. So, just create a text diagnostic printer // to complain about this problem, and pretend that the user // didn't try to use binary output. - DiagClient.reset(new TextDiagnosticPrinter(llvm::errs(), Opts)); - Diags->setClient(DiagClient.take()); + Diags->setClient(new TextDiagnosticPrinter(llvm::errs(), Opts)); Diags->Report(diag::err_fe_stderr_binary); return Diags; } else { - DiagClient.reset(new BinaryDiagnosticSerializer(llvm::errs())); + Diags->setClient(new BinaryDiagnosticSerializer(llvm::errs())); } } else { - DiagClient.reset(new TextDiagnosticPrinter(llvm::errs(), Opts)); + Diags->setClient(new TextDiagnosticPrinter(llvm::errs(), Opts)); } // Chain in -verify checker, if requested. if (Opts.VerifyDiagnostics) - DiagClient.reset(new VerifyDiagnosticsClient(*Diags, DiagClient.take())); + Diags->setClient(new VerifyDiagnosticsClient(*Diags, Diags->takeClient())); - Diags->setClient(DiagClient.take()); if (!Opts.DumpBuildInformation.empty()) SetUpBuildDumpLog(Opts, Argc, Argv, *Diags); @@ -245,42 +241,48 @@ void CompilerInstance::createASTContext() { Context.reset(new ASTContext(getLangOpts(), PP.getSourceManager(), getTarget(), PP.getIdentifierTable(), PP.getSelectorTable(), PP.getBuiltinInfo(), - /*FreeMemory=*/ !getFrontendOpts().DisableFree, /*size_reserve=*/ 0)); } // ExternalASTSource -void CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path) { +void CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path, + bool DisablePCHValidation, + void *DeserializationListener){ llvm::OwningPtr<ExternalASTSource> Source; Source.reset(createPCHExternalASTSource(Path, getHeaderSearchOpts().Sysroot, - getPreprocessor(), getASTContext())); - // Remember the PCHReader, but in a non-owning way. - Reader = static_cast<PCHReader*>(Source.get()); + DisablePCHValidation, + getPreprocessor(), getASTContext(), + DeserializationListener)); getASTContext().setExternalSource(Source); } ExternalASTSource * CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path, const std::string &Sysroot, + bool DisablePCHValidation, Preprocessor &PP, - ASTContext &Context) { - llvm::OwningPtr<PCHReader> Reader; - Reader.reset(new PCHReader(PP, &Context, - Sysroot.empty() ? 0 : Sysroot.c_str())); - - switch (Reader->ReadPCH(Path)) { - case PCHReader::Success: + ASTContext &Context, + void *DeserializationListener) { + llvm::OwningPtr<ASTReader> Reader; + Reader.reset(new ASTReader(PP, &Context, + Sysroot.empty() ? 0 : Sysroot.c_str(), + DisablePCHValidation)); + + Reader->setDeserializationListener( + static_cast<ASTDeserializationListener *>(DeserializationListener)); + switch (Reader->ReadAST(Path)) { + case ASTReader::Success: // Set the predefines buffer as suggested by the PCH reader. Typically, the // predefines buffer will be empty. PP.setPredefines(Reader->getSuggestedPredefines()); return Reader.take(); - case PCHReader::Failure: + case ASTReader::Failure: // Unrecoverable failure: don't even try to process the input file. break; - case PCHReader::IgnorePCH: + case ASTReader::IgnorePCH: // No suitable PCH file could be found. Return an error. break; } @@ -290,17 +292,42 @@ CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path, // Code Completion +static bool EnableCodeCompletion(Preprocessor &PP, + const std::string &Filename, + unsigned Line, + unsigned Column) { + // Tell the source manager to chop off the given file at a specific + // line and column. + const FileEntry *Entry = PP.getFileManager().getFile(Filename); + if (!Entry) { + PP.getDiagnostics().Report(diag::err_fe_invalid_code_complete_file) + << Filename; + return true; + } + + // Truncate the named file at the given line/column. + PP.SetCodeCompletionPoint(Entry, Line, Column); + return false; +} + void CompilerInstance::createCodeCompletionConsumer() { const ParsedSourceLocation &Loc = getFrontendOpts().CodeCompletionAt; - CompletionConsumer.reset( - createCodeCompletionConsumer(getPreprocessor(), - Loc.FileName, Loc.Line, Loc.Column, - getFrontendOpts().DebugCodeCompletionPrinter, - getFrontendOpts().ShowMacrosInCodeCompletion, + if (!CompletionConsumer) { + CompletionConsumer.reset( + createCodeCompletionConsumer(getPreprocessor(), + Loc.FileName, Loc.Line, Loc.Column, + getFrontendOpts().DebugCodeCompletionPrinter, + getFrontendOpts().ShowMacrosInCodeCompletion, getFrontendOpts().ShowCodePatternsInCodeCompletion, - llvm::outs())); - if (!CompletionConsumer) + getFrontendOpts().ShowGlobalSymbolsInCodeCompletion, + llvm::outs())); + if (!CompletionConsumer) + return; + } else if (EnableCodeCompletion(getPreprocessor(), Loc.FileName, + Loc.Line, Loc.Column)) { + CompletionConsumer.reset(); return; + } if (CompletionConsumer->isOutputBinary() && llvm::sys::Program::ChangeStdoutToBinary()) { @@ -321,24 +348,24 @@ CompilerInstance::createCodeCompletionConsumer(Preprocessor &PP, bool UseDebugPrinter, bool ShowMacros, bool ShowCodePatterns, + bool ShowGlobals, llvm::raw_ostream &OS) { - // Tell the source manager to chop off the given file at a specific - // line and column. - const FileEntry *Entry = PP.getFileManager().getFile(Filename); - if (!Entry) { - PP.getDiagnostics().Report(diag::err_fe_invalid_code_complete_file) - << Filename; + if (EnableCodeCompletion(PP, Filename, Line, Column)) return 0; - } - - // Truncate the named file at the given line/column. - PP.SetCodeCompletionPoint(Entry, Line, Column); // Set up the creation routine for code-completion. if (UseDebugPrinter) - return new PrintingCodeCompleteConsumer(ShowMacros, ShowCodePatterns, OS); + return new PrintingCodeCompleteConsumer(ShowMacros, ShowCodePatterns, + ShowGlobals, OS); else - return new CIndexCodeCompleteConsumer(ShowMacros, ShowCodePatterns, OS); + return new CIndexCodeCompleteConsumer(ShowMacros, ShowCodePatterns, + ShowGlobals, OS); +} + +void CompilerInstance::createSema(bool CompleteTranslationUnit, + CodeCompleteConsumer *CompletionConsumer) { + TheSema.reset(new Sema(getPreprocessor(), getASTContext(), getASTConsumer(), + CompleteTranslationUnit, CompletionConsumer)); } // Output Files @@ -437,7 +464,7 @@ bool CompilerInstance::InitializeSourceManager(llvm::StringRef InputFile, // Figure out where to get and map in the main file. if (InputFile != "-") { const FileEntry *File = FileMgr.getFile(InputFile); - if (File) SourceMgr.createMainFileID(File, SourceLocation()); + if (File) SourceMgr.createMainFileID(File); if (SourceMgr.getMainFileID().isInvalid()) { Diags.Report(diag::err_fe_error_reading) << InputFile; return false; diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 418d25b..8c64483 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -18,11 +18,12 @@ #include "clang/Driver/Option.h" #include "clang/Frontend/CompilerInvocation.h" #include "clang/Frontend/LangStandard.h" -#include "clang/Frontend/PCHReader.h" +#include "clang/Serialization/ASTReader.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/Triple.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/System/Host.h" #include "llvm/System/Path.h" @@ -112,8 +113,8 @@ static void AnalyzerOptsToArgs(const AnalyzerOptions &Opts, Res.push_back("-analyzer-experimental-checks"); if (Opts.EnableExperimentalInternalChecks) Res.push_back("-analyzer-experimental-internal-checks"); - if (Opts.EnableIdempotentOperationChecker) - Res.push_back("-analyzer-idempotent-operation"); + if (Opts.IdempotentOps) + Res.push_back("-analyzer-check-idempotent-operations"); } static void CodeGenOptsToArgs(const CodeGenOptions &Opts, @@ -148,9 +149,12 @@ static void CodeGenOptsToArgs(const CodeGenOptions &Opts, // SimplifyLibCalls is only derived. // TimePasses is only derived. // UnitAtATime is unused. - // UnrollLoops is only derived. // 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) @@ -241,6 +245,8 @@ static void DiagnosticOptsToArgs(const DiagnosticOptions &Opts, 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) @@ -316,6 +322,7 @@ static const char *getActionName(frontend::ActionKind Kind) { case frontend::ASTPrintXML: return "-ast-print-xml"; case frontend::ASTView: return "-ast-view"; case frontend::BoostCon: return "-boostcon"; + case frontend::CreateModule: return "-create-module"; case frontend::DumpRawTokens: return "-dump-raw-tokens"; case frontend::DumpTokens: return "-dump-tokens"; case frontend::EmitAssembly: return "-S"; @@ -329,10 +336,9 @@ static const char *getActionName(frontend::ActionKind Kind) { case frontend::GeneratePCH: return "-emit-pch"; case frontend::GeneratePTH: return "-emit-pth"; case frontend::InitOnly: return "-init-only"; - case frontend::ParseNoop: return "-parse-noop"; - case frontend::ParsePrintCallbacks: return "-parse-print-callbacks"; 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"; @@ -361,12 +367,16 @@ static void FrontendOptsToArgs(const FrontendOptions &Opts, Res.push_back("-code-completion-macros"); if (Opts.ShowCodePatternsInCodeCompletion) Res.push_back("-code-completion-patterns"); + if (!Opts.ShowGlobalSymbolsInCodeCompletion) + Res.push_back("-no-code-completion-globals"); 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"); bool NeedLang = false; for (unsigned i = 0, e = Opts.Inputs.size(); i != e; ++i) @@ -416,6 +426,10 @@ static void FrontendOptsToArgs(const FrontendOptions &Opts, Res.push_back("-ast-merge"); Res.push_back(Opts.ASTMergeFiles[i]); } + for (unsigned i = 0, e = Opts.Modules.size(); i != e; ++i) { + Res.push_back("-import-module"); + Res.push_back(Opts.Modules[i]); + } for (unsigned i = 0, e = Opts.LLVMArgs.size(); i != e; ++i) { Res.push_back("-mllvm"); Res.push_back(Opts.LLVMArgs[i]); @@ -512,6 +526,8 @@ static void LangOptsToArgs(const LangOptions &Opts, Res.push_back("-fgnu-keywords"); if (Opts.Microsoft) Res.push_back("-fms-extensions"); + if (Opts.Borland) + Res.push_back("-fborland-extensions"); if (Opts.ObjCNonFragileABI) Res.push_back("-fobjc-nonfragile-abi"); if (Opts.ObjCNonFragileABI2) @@ -676,6 +692,8 @@ static void PreprocessorOutputOptsToArgs(const PreprocessorOutputOptions &Opts, else if (!Opts.ShowCPP && Opts.ShowMacros) Res.push_back("-dM"); + if (Opts.ShowHeaderIncludes) + Res.push_back("-H"); if (!Opts.ShowLineMarkers) Res.push_back("-P"); if (Opts.ShowComments) @@ -696,8 +714,14 @@ static void TargetOptsToArgs(const TargetOptions &Opts, Res.push_back("-target-abi"); Res.push_back(Opts.ABI); } - Res.push_back("-cxx-abi"); - Res.push_back(Opts.CXXABI); + if (!Opts.LinkerVersion.empty()) { + Res.push_back("-target-linker-version"); + Res.push_back(Opts.LinkerVersion); + } + if (!Opts.CXXABI.empty()) { + Res.push_back("-cxx-abi"); + Res.push_back(Opts.CXXABI); + } for (unsigned i = 0, e = Opts.Features.size(); i != e; ++i) { Res.push_back("-target-feature"); Res.push_back(Opts.Features[i]); @@ -789,15 +813,15 @@ static void ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args, Opts.PurgeDead = !Args.hasArg(OPT_analyzer_no_purge_dead); Opts.EagerlyAssume = Args.hasArg(OPT_analyzer_eagerly_assume); Opts.AnalyzeSpecificFunction = Args.getLastArgValue(OPT_analyze_function); + Opts.UnoptimizedCFG = Args.hasArg(OPT_analysis_UnoptimizedCFG); Opts.EnableExperimentalChecks = Args.hasArg(OPT_analyzer_experimental_checks); Opts.EnableExperimentalInternalChecks = Args.hasArg(OPT_analyzer_experimental_internal_checks); - Opts.EnableIdempotentOperationChecker = - Args.hasArg(OPT_analyzer_idempotent_operation); 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, 3, Diags); Opts.InlineCall = Args.hasArg(OPT_analyzer_inline_call); + Opts.IdempotentOps = Args.hasArg(OPT_analysis_WarnIdempotentOps); } static void ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, @@ -829,7 +853,8 @@ static void ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, Opts.OptimizeSize = Args.hasArg(OPT_Os); Opts.SimplifyLibCalls = !(Args.hasArg(OPT_fno_builtin) || Args.hasArg(OPT_ffreestanding)); - Opts.UnrollLoops = (Opts.OptimizationLevel > 1 && !Opts.OptimizeSize); + Opts.UnrollLoops = Args.hasArg(OPT_funroll_loops) || + (Opts.OptimizationLevel > 1 && !Opts.OptimizeSize); Opts.AsmVerbose = Args.hasArg(OPT_masm_verbose); Opts.CXAAtExit = !Args.hasArg(OPT_fno_use_cxa_atexit); @@ -838,6 +863,7 @@ static void ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, Opts.DebugPass = Args.getLastArgValue(OPT_mdebug_pass); Opts.DisableFPElim = Args.hasArg(OPT_mdisable_fp_elim); Opts.FloatABI = Args.getLastArgValue(OPT_mfloat_abi); + Opts.HiddenWeakVTables = Args.hasArg(OPT_fhidden_weak_vtables); Opts.LimitFloatPrecision = Args.getLastArgValue(OPT_mlimit_float_precision); Opts.NoZeroInitializedInBSS = Args.hasArg(OPT_mno_zero_initialized_in_bss); Opts.RelaxAll = Args.hasArg(OPT_mrelax_all); @@ -916,6 +942,7 @@ static void ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args, << ShowCategory; Opts.ShowSourceRanges = Args.hasArg(OPT_fdiagnostics_print_source_range_info); + Opts.ShowParseableFixits = Args.hasArg(OPT_fdiagnostics_parseable_fixits); Opts.VerifyDiagnostics = Args.hasArg(OPT_verify); Opts.BinaryOutput = Args.hasArg(OPT_fdiagnostics_binary); Opts.ErrorLimit = Args.getLastArgIntValue(OPT_ferror_limit, 0, Diags); @@ -985,14 +1012,12 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Opts.ProgramAction = frontend::GeneratePTH; break; case OPT_init_only: Opts.ProgramAction = frontend::InitOnly; break; - case OPT_parse_noop: - Opts.ProgramAction = frontend::ParseNoop; break; - case OPT_parse_print_callbacks: - Opts.ProgramAction = frontend::ParsePrintCallbacks; break; case OPT_fsyntax_only: Opts.ProgramAction = frontend::ParseSyntaxOnly; break; case OPT_print_decl_contexts: Opts.ProgramAction = frontend::PrintDeclContext; break; + case OPT_print_preamble: + Opts.ProgramAction = frontend::PrintPreamble; break; case OPT_E: Opts.ProgramAction = frontend::PrintPreprocessedInput; break; case OPT_rewrite_macros: @@ -1005,6 +1030,8 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Opts.ProgramAction = frontend::RunAnalysis; break; case OPT_Eonly: Opts.ProgramAction = frontend::RunPreprocessorOnly; break; + case OPT_create_module: + Opts.ProgramAction = frontend::CreateModule; break; } } @@ -1039,12 +1066,16 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Opts.ShowMacrosInCodeCompletion = Args.hasArg(OPT_code_completion_macros); Opts.ShowCodePatternsInCodeCompletion = Args.hasArg(OPT_code_completion_patterns); + Opts.ShowGlobalSymbolsInCodeCompletion + = !Args.hasArg(OPT_no_code_completion_globals); Opts.ShowStats = Args.hasArg(OPT_print_stats); Opts.ShowTimers = Args.hasArg(OPT_ftime_report); Opts.ShowVersion = Args.hasArg(OPT_version); Opts.ViewClassInheritance = Args.getLastArgValue(OPT_cxx_inheritance_view); Opts.ASTMergeFiles = Args.getAllArgValues(OPT_ast_merge); Opts.LLVMArgs = Args.getAllArgValues(OPT_mllvm); + Opts.FixWhatYouCan = Args.hasArg(OPT_fix_what_you_can); + Opts.Modules = Args.getAllArgValues(OPT_import_module); InputKind DashX = IK_None; if (const Arg *A = Args.getLastArg(OPT_x)) { @@ -1123,7 +1154,7 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) { for (arg_iterator it = Args.filtered_begin(OPT_I, OPT_F), ie = Args.filtered_end(); it != ie; ++it) Opts.AddPath((*it)->getValue(Args), frontend::Angled, true, - /*IsFramework=*/ (*it)->getOption().matches(OPT_F)); + /*IsFramework=*/ (*it)->getOption().matches(OPT_F), true); // Add -iprefix/-iwith-prefix/-iwithprefixbefore options. llvm::StringRef Prefix = ""; // FIXME: This isn't the correct default prefix. @@ -1135,21 +1166,22 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) { Prefix = A->getValue(Args); else if (A->getOption().matches(OPT_iwithprefix)) Opts.AddPath(Prefix.str() + A->getValue(Args), - frontend::System, false, false); + frontend::System, false, false, true); else Opts.AddPath(Prefix.str() + A->getValue(Args), - frontend::Angled, false, false); + frontend::Angled, false, false, true); } 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); + Opts.AddPath((*it)->getValue(Args), frontend::After, true, false, true); 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); - for (arg_iterator it = Args.filtered_begin(OPT_isystem), + Opts.AddPath((*it)->getValue(Args), frontend::Quoted, true, false, true); + 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(Args), frontend::System, true, false, + (*it)->getOption().matches(OPT_iwithsysroot)); // FIXME: Need options for the various environment variables! } @@ -1287,6 +1319,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, !Opts.AsmPreprocessor); Opts.PascalStrings = Args.hasArg(OPT_fpascal_strings); Opts.Microsoft = Args.hasArg(OPT_fms_extensions); + Opts.Borland = Args.hasArg(OPT_fborland_extensions); Opts.WritableStrings = Args.hasArg(OPT_fwritable_strings); Opts.ConstStrings = Args.hasArg(OPT_Wwrite_strings); if (Args.hasArg(OPT_fno_lax_vector_conversions)) @@ -1360,6 +1393,24 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args, Opts.TokenCache = Opts.ImplicitPTHInclude; Opts.UsePredefines = !Args.hasArg(OPT_undef); Opts.DetailedRecord = Args.hasArg(OPT_detailed_preprocessing_record); + Opts.DisablePCHValidation = Args.hasArg(OPT_fno_validate_pch); + + if (const Arg *A = Args.getLastArg(OPT_preamble_bytes_EQ)) { + llvm::StringRef Value(A->getValue(Args)); + size_t Comma = Value.find(','); + unsigned Bytes = 0; + unsigned EndOfLine = 0; + + if (Comma == llvm::StringRef::npos || + Value.substr(0, Comma).getAsInteger(10, Bytes) || + Value.substr(Comma + 1).getAsInteger(10, EndOfLine)) + Diags.Report(diag::err_drv_preamble_format); + else { + Opts.PrecompiledPreambleBytes.first = Bytes; + Opts.PrecompiledPreambleBytes.second = (EndOfLine != 0); + } + } + // Add macros from the command line. for (arg_iterator it = Args.filtered_begin(OPT_D, OPT_U), ie = Args.filtered_end(); it != ie; ++it) { @@ -1379,7 +1430,7 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args, // PCH is handled specially, we need to extra the original include path. if (A->getOption().matches(OPT_include_pch)) { std::string OriginalFile = - PCHReader::getOriginalSourceFile(A->getValue(Args), Diags); + ASTReader::getOriginalSourceFile(A->getValue(Args), Diags); if (OriginalFile.empty()) continue; @@ -1411,10 +1462,11 @@ static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts, ArgList &Args) { using namespace cc1options; Opts.ShowCPP = !Args.hasArg(OPT_dM); - Opts.ShowMacros = Args.hasArg(OPT_dM) || Args.hasArg(OPT_dD); - Opts.ShowLineMarkers = !Args.hasArg(OPT_P); Opts.ShowComments = Args.hasArg(OPT_C); + Opts.ShowHeaderIncludes = Args.hasArg(OPT_H); + Opts.ShowLineMarkers = !Args.hasArg(OPT_P); Opts.ShowMacroComments = Args.hasArg(OPT_CC); + Opts.ShowMacros = Args.hasArg(OPT_dM) || Args.hasArg(OPT_dD); } static void ParseTargetArgs(TargetOptions &Opts, ArgList &Args) { @@ -1422,16 +1474,13 @@ 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.Triple = Args.getLastArgValue(OPT_triple); Opts.Features = Args.getAllArgValues(OPT_target_feature); + Opts.LinkerVersion = Args.getLastArgValue(OPT_target_linker_version); + Opts.Triple = llvm::Triple::normalize(Args.getLastArgValue(OPT_triple)); // Use the host triple if unspecified. if (Opts.Triple.empty()) Opts.Triple = llvm::sys::getHostTriple(); - - // Use the Itanium C++ ABI if unspecified. - if (Opts.CXXABI.empty()) - Opts.CXXABI = "itanium"; } // diff --git a/lib/Frontend/DependencyFile.cpp b/lib/Frontend/DependencyFile.cpp index 14aee35..cdff807 100644 --- a/lib/Frontend/DependencyFile.cpp +++ b/lib/Frontend/DependencyFile.cpp @@ -53,7 +53,6 @@ public: virtual void EndOfMainFile() { OutputDependencyFile(); - OS->flush(); delete OS; OS = 0; } diff --git a/lib/Frontend/DiagChecker.cpp b/lib/Frontend/DiagChecker.cpp index a50cc99..66d7ed7 100644 --- a/lib/Frontend/DiagChecker.cpp +++ b/lib/Frontend/DiagChecker.cpp @@ -13,7 +13,7 @@ #include "clang/Frontend/Utils.h" #include "clang/Frontend/TextDiagnosticBuffer.h" -#include "clang/Sema/ParseAST.h" +#include "clang/Parse/ParseAST.h" #include "clang/AST/ASTConsumer.h" #include "clang/Basic/SourceManager.h" #include "clang/Lex/Preprocessor.h" diff --git a/lib/Frontend/FrontendAction.cpp b/lib/Frontend/FrontendAction.cpp index dbbf69c..b244c5c 100644 --- a/lib/Frontend/FrontendAction.cpp +++ b/lib/Frontend/FrontendAction.cpp @@ -8,13 +8,14 @@ //===----------------------------------------------------------------------===// #include "clang/Frontend/FrontendAction.h" +#include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/Lex/HeaderSearch.h" #include "clang/Lex/Preprocessor.h" #include "clang/Frontend/ASTUnit.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendDiagnostic.h" -#include "clang/Sema/ParseAST.h" +#include "clang/Parse/ParseAST.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Timer.h" #include "llvm/Support/ErrorHandling.h" @@ -50,7 +51,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, llvm::IntrusiveRefCntPtr<Diagnostic> Diags(&CI.getDiagnostics()); std::string Error; - ASTUnit *AST = ASTUnit::LoadFromPCHFile(Filename, Diags); + ASTUnit *AST = ASTUnit::LoadFromASTFile(Filename, Diags); if (!AST) goto failure; @@ -112,18 +113,21 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, if (!usesPreprocessorOnly()) { CI.createASTContext(); - /// Use PCH? If so, we want the PCHReader active before the consumer - /// is created, because the consumer might be interested in the reader - /// (e.g. the PCH writer for chaining). + llvm::OwningPtr<ASTConsumer> Consumer(CreateASTConsumer(CI, Filename)); + + /// Use PCH? if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) { assert(hasPCHSupport() && "This action does not have PCH support!"); CI.createPCHExternalASTSource( - CI.getPreprocessorOpts().ImplicitPCHInclude); + CI.getPreprocessorOpts().ImplicitPCHInclude, + CI.getPreprocessorOpts().DisablePCHValidation, + CI.getInvocation().getFrontendOpts().ChainedPCH? + Consumer->GetASTDeserializationListener() : 0); if (!CI.getASTContext().getExternalSource()) goto failure; } - CI.setASTConsumer(CreateASTConsumer(CI, Filename)); + CI.setASTConsumer(Consumer.take()); if (!CI.hasASTConsumer()) goto failure; } @@ -192,12 +196,16 @@ void FrontendAction::EndSourceFile() { // FIXME: There is more per-file stuff we could just drop here? if (CI.getFrontendOpts().DisableFree) { CI.takeASTConsumer(); - if (!isCurrentFileAST()) + if (!isCurrentFileAST()) { + CI.takeSema(); CI.takeASTContext(); + } } else { - CI.setASTConsumer(0); - if (!isCurrentFileAST()) + if (!isCurrentFileAST()) { + CI.setSema(0); CI.setASTContext(0); + } + CI.setASTConsumer(0); } // Inform the preprocessor we are done. @@ -221,6 +229,7 @@ void FrontendAction::EndSourceFile() { CI.getDiagnosticClient().EndSourceFile(); if (isCurrentFileAST()) { + CI.takeSema(); CI.takeASTContext(); CI.takePreprocessor(); CI.takeSourceManager(); @@ -249,9 +258,10 @@ void ASTFrontendAction::ExecuteAction() { if (CI.hasCodeCompletionConsumer()) CompletionConsumer = &CI.getCodeCompletionConsumer(); - ParseAST(CI.getPreprocessor(), &CI.getASTConsumer(), CI.getASTContext(), - CI.getFrontendOpts().ShowStats, - usesCompleteTranslationUnit(), CompletionConsumer); + if (!CI.hasSema()) + CI.createSema(usesCompleteTranslationUnit(), CompletionConsumer); + + ParseAST(CI.getSema(), CI.getFrontendOpts().ShowStats); } ASTConsumer * diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp index 3a53dee..5bc6506 100644 --- a/lib/Frontend/FrontendActions.cpp +++ b/lib/Frontend/FrontendActions.cpp @@ -18,7 +18,9 @@ #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Frontend/Utils.h" +#include "clang/Serialization/ASTWriter.h" #include "llvm/ADT/OwningPtr.h" +#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" using namespace clang; @@ -69,22 +71,35 @@ ASTConsumer *DeclContextPrintAction::CreateASTConsumer(CompilerInstance &CI, ASTConsumer *GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI, llvm::StringRef InFile) { - const std::string &Sysroot = CI.getHeaderSearchOpts().Sysroot; - if (CI.getFrontendOpts().RelocatablePCH && - Sysroot.empty()) { - CI.getDiagnostics().Report(diag::err_relocatable_without_without_isysroot); + std::string Sysroot; + llvm::raw_ostream *OS = 0; + bool Chaining; + if (ComputeASTConsumerArguments(CI, InFile, Sysroot, OS, Chaining)) return 0; + + const char *isysroot = CI.getFrontendOpts().RelocatablePCH ? + Sysroot.c_str() : 0; + return new PCHGenerator(CI.getPreprocessor(), Chaining, isysroot, OS); +} + +bool GeneratePCHAction::ComputeASTConsumerArguments(CompilerInstance &CI, + llvm::StringRef InFile, + std::string &Sysroot, + llvm::raw_ostream *&OS, + bool &Chaining) { + Sysroot = CI.getHeaderSearchOpts().Sysroot; + if (CI.getFrontendOpts().RelocatablePCH && Sysroot.empty()) { + CI.getDiagnostics().Report(diag::err_relocatable_without_isysroot); + return true; } - llvm::raw_ostream *OS = CI.createDefaultOutputFile(true, InFile); + OS = CI.createDefaultOutputFile(true, InFile); if (!OS) - return 0; + return true; - PCHReader *Chain = CI.getInvocation().getFrontendOpts().ChainedPCH ? - CI.getPCHReader() : 0; - const char *isysroot = CI.getFrontendOpts().RelocatablePCH ? - Sysroot.c_str() : 0; - return CreatePCHGenerator(CI.getPreprocessor(), OS, Chain, isysroot); + Chaining = CI.getInvocation().getFrontendOpts().ChainedPCH && + !CI.getPreprocessorOpts().ImplicitPCHInclude.empty(); + return false; } ASTConsumer *InheritanceViewAction::CreateASTConsumer(CompilerInstance &CI, @@ -146,15 +161,6 @@ void GeneratePTHAction::ExecuteAction() { CacheTokens(CI.getPreprocessor(), OS); } -void ParseOnlyAction::ExecuteAction() { - Preprocessor &PP = getCompilerInstance().getPreprocessor(); - llvm::OwningPtr<Action> PA(new MinimalAction(PP)); - - Parser P(PP, *PA); - PP.EnterMainSourceFile(); - P.ParseTranslationUnit(); -} - void PreprocessOnlyAction::ExecuteAction() { Preprocessor &PP = getCompilerInstance().getPreprocessor(); @@ -169,19 +175,6 @@ void PreprocessOnlyAction::ExecuteAction() { } while (Tok.isNot(tok::eof)); } -void PrintParseAction::ExecuteAction() { - CompilerInstance &CI = getCompilerInstance(); - Preprocessor &PP = getCompilerInstance().getPreprocessor(); - llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, getCurrentFile()); - if (!OS) return; - - llvm::OwningPtr<Action> PA(CreatePrintParserActionsAction(PP, OS)); - - Parser P(PP, *PA); - PP.EnterMainSourceFile(); - P.ParseTranslationUnit(); -} - void PrintPreprocessedAction::ExecuteAction() { CompilerInstance &CI = getCompilerInstance(); // Output file needs to be set to 'Binary', to avoid converting Unix style @@ -192,3 +185,32 @@ void PrintPreprocessedAction::ExecuteAction() { DoPrintPreprocessedInput(CI.getPreprocessor(), OS, CI.getPreprocessorOutputOpts()); } + +void PrintPreambleAction::ExecuteAction() { + switch (getCurrentFileKind()) { + case IK_C: + case IK_CXX: + case IK_ObjC: + case IK_ObjCXX: + case IK_OpenCL: + break; + + case IK_None: + case IK_Asm: + case IK_PreprocessedC: + case IK_PreprocessedCXX: + case IK_PreprocessedObjC: + case IK_PreprocessedObjCXX: + case IK_AST: + case IK_LLVM_IR: + // We can't do anything with these. + return; + } + + llvm::MemoryBuffer *Buffer = llvm::MemoryBuffer::getFile(getCurrentFile()); + if (Buffer) { + unsigned Preamble = Lexer::ComputePreamble(Buffer).first; + llvm::outs().write(Buffer->getBufferStart(), Preamble); + delete Buffer; + } +} diff --git a/lib/Frontend/GeneratePCH.cpp b/lib/Frontend/GeneratePCH.cpp deleted file mode 100644 index 2f3df94..0000000 --- a/lib/Frontend/GeneratePCH.cpp +++ /dev/null @@ -1,83 +0,0 @@ -//===--- GeneratePCH.cpp - AST Consumer for PCH Generation ------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the CreatePCHGenerate function, which creates an -// ASTConsume that generates a PCH file. -// -//===----------------------------------------------------------------------===// - -#include "clang/Frontend/ASTConsumers.h" -#include "clang/Frontend/PCHWriter.h" -#include "clang/Sema/SemaConsumer.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/ASTConsumer.h" -#include "clang/Lex/Preprocessor.h" -#include "clang/Basic/FileManager.h" -#include "llvm/Bitcode/BitstreamWriter.h" -#include "llvm/Support/raw_ostream.h" -#include <string> - -using namespace clang; - -namespace { - class PCHGenerator : public SemaConsumer { - const Preprocessor &PP; - const char *isysroot; - llvm::raw_ostream *Out; - Sema *SemaPtr; - MemorizeStatCalls *StatCalls; // owned by the FileManager - std::vector<unsigned char> Buffer; - llvm::BitstreamWriter Stream; - PCHWriter Writer; - - public: - PCHGenerator(const Preprocessor &PP, PCHReader *Chain, - const char *isysroot, llvm::raw_ostream *Out); - virtual void InitializeSema(Sema &S) { SemaPtr = &S; } - virtual void HandleTranslationUnit(ASTContext &Ctx); - }; -} - -PCHGenerator::PCHGenerator(const Preprocessor &PP, - PCHReader *Chain, - const char *isysroot, - llvm::raw_ostream *OS) - : PP(PP), isysroot(isysroot), Out(OS), SemaPtr(0), StatCalls(0), - Stream(Buffer), Writer(Stream, Chain) { - - // Install a stat() listener to keep track of all of the stat() - // calls. - StatCalls = new MemorizeStatCalls; - PP.getFileManager().addStatCache(StatCalls, /*AtBeginning=*/true); -} - -void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) { - if (PP.getDiagnostics().hasErrorOccurred()) - return; - - // Emit the PCH file - assert(SemaPtr && "No Sema?"); - Writer.WritePCH(*SemaPtr, StatCalls, isysroot); - - // Write the generated bitstream to "Out". - Out->write((char *)&Buffer.front(), Buffer.size()); - - // Make sure it hits disk now. - Out->flush(); - - // Free up some memory, in case the process is kept alive. - Buffer.clear(); -} - -ASTConsumer *clang::CreatePCHGenerator(const Preprocessor &PP, - llvm::raw_ostream *OS, - PCHReader *Chain, - const char *isysroot) { - return new PCHGenerator(PP, Chain, isysroot, OS); -} diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp index d640d42..df91713 100644 --- a/lib/Frontend/InitHeaderSearch.cpp +++ b/lib/Frontend/InitHeaderSearch.cpp @@ -1,4 +1,4 @@ -//===--- InitHeaderSearch.cpp - Initialize header search paths ----------*-===// +//===--- InitHeaderSearch.cpp - Initialize header search paths ------------===// // // The LLVM Compiler Infrastructure // @@ -195,6 +195,8 @@ void InitHeaderSearch::AddMinGWCPlusPlusIncludePaths(llvm::StringRef Base, System, true, false, false); AddPath(Base + "/" + Arch + "/" + Version + "/include/c++", System, true, false, false); + AddPath(Base + "/" + Arch + "/" + Version + "/include/c++/" + Arch, + System, true, false, false); AddPath(Base + "/" + Arch + "/" + Version + "/include/c++/backward", System, true, false, false); } @@ -323,9 +325,19 @@ static bool getSystemRegistryString(const char*, const char*, char*, size_t) { // Get Visual Studio installation directory. static bool getVisualStudioDir(std::string &path) { + // First check the environment variables that vsvars32.bat sets. + const char* vcinstalldir = getenv("VCINSTALLDIR"); + if(vcinstalldir) { + char *p = const_cast<char *>(strstr(vcinstalldir, "\\VC")); + if (p) + *p = '\0'; + path = vcinstalldir; + return(true); + } + char vsIDEInstallDir[256]; char vsExpressIDEInstallDir[256]; - // Try the Windows registry first. + // Then try the windows registry. bool hasVCDir = getSystemRegistryString( "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION", "InstallDir", vsIDEInstallDir, sizeof(vsIDEInstallDir) - 1); @@ -440,7 +452,7 @@ void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple, if (getVisualStudioDir(VSDir)) { AddPath(VSDir + "\\VC\\include", System, false, false, false); if (getWindowsSDKDir(WindowsSDKDir)) - AddPath(WindowsSDKDir, System, false, false, false); + AddPath(WindowsSDKDir + "\\include", System, false, false, false); else AddPath(VSDir + "\\VC\\PlatformSDK\\Include", System, false, false, false); @@ -510,7 +522,7 @@ void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple, AddPath("/boot/develop/headers/glibc", System, true, false, false); AddPath("/boot/develop/headers/posix", System, true, false, false); AddPath("/boot/develop/headers", System, true, false, false); - break; + break; case llvm::Triple::MinGW64: case llvm::Triple::MinGW32: AddPath("c:/mingw/include", System, true, false, false); @@ -549,12 +561,16 @@ AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple) { System, true, false, false); break; case llvm::Triple::MinGW64: + // Try gcc 4.5.0 + AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw64", "4.5.0"); // Try gcc 4.4.0 AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw64", "4.4.0"); // Try gcc 4.3.0 AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw64", "4.3.0"); // Fall through. case llvm::Triple::MinGW32: + // Try gcc 4.5.0 + AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.5.0"); // Try gcc 4.4.0 AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.4.0"); // Try gcc 4.3.0 @@ -716,6 +732,11 @@ AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple) { AddGnuCPlusPlusIncludePaths( "/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.3/include/g++-v4", "x86_64-pc-linux-gnu", "32", "", triple); + + // Gentoo amd64 llvm-gcc trunk + AddGnuCPlusPlusIncludePaths( + "/usr/lib/llvm-gcc-4.2-9999/include/c++/4.2.1", + "x86_64-pc-linux-gnu", "", "", triple); break; case llvm::Triple::FreeBSD: @@ -723,6 +744,17 @@ AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple) { // FreeBSD 7.3 AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2", "", "", "", triple); break; + case llvm::Triple::NetBSD: + AddGnuCPlusPlusIncludePaths("/usr/include/g++", "", "", "", triple); + break; + case llvm::Triple::OpenBSD: { + std::string t = triple.getTriple(); + if (t.substr(0, 6) == "x86_64") + t.replace(0, 6, "amd64"); + AddGnuCPlusPlusIncludePaths("/usr/include/g++", + t, "", "", triple); + break; + } case llvm::Triple::Minix: AddGnuCPlusPlusIncludePaths("/usr/gnu/include/c++/4.4.3", "", "", "", triple); @@ -889,7 +921,7 @@ void clang::ApplyHeaderSearchOptions(HeaderSearch &HS, for (unsigned i = 0, e = HSOpts.UserEntries.size(); i != e; ++i) { const HeaderSearchOptions::Entry &E = HSOpts.UserEntries[i]; Init.AddPath(E.Path, E.Group, false, E.IsUserSupplied, E.IsFramework, - false); + !E.IsSysRootRelative); } // Add entries from CPATH and friends. diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp index 889b6e5..0d07192 100644 --- a/lib/Frontend/InitPreprocessor.cpp +++ b/lib/Frontend/InitPreprocessor.cpp @@ -169,10 +169,11 @@ static void DefineTypeSize(llvm::StringRef MacroName, unsigned TypeWidth, llvm::StringRef ValSuffix, bool isSigned, MacroBuilder& Builder) { long long MaxVal; - if (isSigned) - MaxVal = (1LL << (TypeWidth - 1)) - 1; - else - MaxVal = ~0LL >> (64-TypeWidth); + if (isSigned) { + assert(TypeWidth != 1); + MaxVal = ~0ULL >> (65-TypeWidth); + } else + MaxVal = ~0ULL >> (64-TypeWidth); Builder.defineMacro(MacroName, llvm::Twine(MaxVal) + ValSuffix); } @@ -318,7 +319,7 @@ static void InitializePredefinedMacros(const TargetInfo &TI, Builder.defineMacro("__cplusplus"); else // C++ [cpp.predefined]p1: - // The name_ _cplusplusis defined to the value199711Lwhen compiling a + // The name_ _cplusplusis defined to the value 199711L when compiling a // C++ translation unit. Builder.defineMacro("__cplusplus", "199711L"); Builder.defineMacro("__private_extern__", "extern"); @@ -339,9 +340,7 @@ static void InitializePredefinedMacros(const TargetInfo &TI, // Since we define wchar_t in C++ mode. Builder.defineMacro("_WCHAR_T_DEFINED"); Builder.defineMacro("_NATIVE_WCHAR_T_DEFINED"); - // FIXME: This should be temporary until we have a __pragma - // solution, to avoid some errors flagged in VC++ headers. - Builder.defineMacro("_CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES", "0"); + Builder.append("class type_info;"); } } @@ -477,7 +476,7 @@ static void InitializeFileRemapping(Diagnostic &Diags, FileManager &FileMgr, const PreprocessorOptions &InitOpts) { // Remap files in the source manager (with buffers). - for (PreprocessorOptions::remapped_file_buffer_iterator + for (PreprocessorOptions::const_remapped_file_buffer_iterator Remap = InitOpts.remapped_file_buffer_begin(), RemapEnd = InitOpts.remapped_file_buffer_end(); Remap != RemapEnd; @@ -489,19 +488,21 @@ static void InitializeFileRemapping(Diagnostic &Diags, if (!FromFile) { Diags.Report(diag::err_fe_remap_missing_from_file) << Remap->first; - delete Remap->second; + if (!InitOpts.RetainRemappedFileBuffers) + delete Remap->second; continue; } // Override the contents of the "from" file with the contents of // the "to" file. - SourceMgr.overrideFileContents(FromFile, Remap->second); + SourceMgr.overrideFileContents(FromFile, Remap->second, + InitOpts.RetainRemappedFileBuffers); } // Remap files in the source manager (with other files). - for (PreprocessorOptions::remapped_file_iterator - Remap = InitOpts.remapped_file_begin(), - RemapEnd = InitOpts.remapped_file_end(); + for (PreprocessorOptions::const_remapped_file_iterator + Remap = InitOpts.remapped_file_begin(), + RemapEnd = InitOpts.remapped_file_end(); Remap != RemapEnd; ++Remap) { // Find the file that we're mapping to. @@ -596,6 +597,10 @@ void clang::InitializePreprocessor(Preprocessor &PP, if (!PP.getLangOptions().AsmPreprocessor) Builder.append("# 1 \"<built-in>\" 2"); + // Instruct the preprocessor to skip the preamble. + PP.setSkipMainFilePreamble(InitOpts.PrecompiledPreambleBytes.first, + InitOpts.PrecompiledPreambleBytes.second); + // Copy PredefinedBuffer into the Preprocessor. PP.setPredefines(Predefines.str()); diff --git a/lib/Frontend/Makefile b/lib/Frontend/Makefile index 3eb4bc9..3c13ad6 100644 --- a/lib/Frontend/Makefile +++ b/lib/Frontend/Makefile @@ -9,7 +9,6 @@ CLANG_LEVEL := ../.. LIBRARYNAME := clangFrontend -BUILD_ARCHIVE = 1 include $(CLANG_LEVEL)/Makefile diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp deleted file mode 100644 index 00aee49..0000000 --- a/lib/Frontend/PCHReader.cpp +++ /dev/null @@ -1,3469 +0,0 @@ -//===--- PCHReader.cpp - Precompiled Headers Reader -------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the PCHReader class, which reads a precompiled header. -// -//===----------------------------------------------------------------------===// - -#include "clang/Frontend/PCHReader.h" -#include "clang/Frontend/FrontendDiagnostic.h" -#include "clang/Frontend/PCHDeserializationListener.h" -#include "clang/Frontend/Utils.h" -#include "../Sema/Sema.h" // FIXME: move Sema headers elsewhere -#include "clang/AST/ASTConsumer.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/Expr.h" -#include "clang/AST/Type.h" -#include "clang/AST/TypeLocVisitor.h" -#include "clang/Lex/MacroInfo.h" -#include "clang/Lex/PreprocessingRecord.h" -#include "clang/Lex/Preprocessor.h" -#include "clang/Lex/HeaderSearch.h" -#include "clang/Basic/OnDiskHashTable.h" -#include "clang/Basic/SourceManager.h" -#include "clang/Basic/SourceManagerInternals.h" -#include "clang/Basic/FileManager.h" -#include "clang/Basic/TargetInfo.h" -#include "clang/Basic/Version.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/Bitcode/BitstreamReader.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/System/Path.h" -#include <algorithm> -#include <iterator> -#include <cstdio> -#include <sys/stat.h> -using namespace clang; - -//===----------------------------------------------------------------------===// -// PCH reader validator implementation -//===----------------------------------------------------------------------===// - -PCHReaderListener::~PCHReaderListener() {} - -bool -PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts) { - const LangOptions &PPLangOpts = PP.getLangOptions(); -#define PARSE_LANGOPT_BENIGN(Option) -#define PARSE_LANGOPT_IMPORTANT(Option, DiagID) \ - if (PPLangOpts.Option != LangOpts.Option) { \ - Reader.Diag(DiagID) << LangOpts.Option << PPLangOpts.Option; \ - return true; \ - } - - PARSE_LANGOPT_BENIGN(Trigraphs); - PARSE_LANGOPT_BENIGN(BCPLComment); - PARSE_LANGOPT_BENIGN(DollarIdents); - PARSE_LANGOPT_BENIGN(AsmPreprocessor); - PARSE_LANGOPT_IMPORTANT(GNUMode, diag::warn_pch_gnu_extensions); - PARSE_LANGOPT_IMPORTANT(GNUKeywords, diag::warn_pch_gnu_keywords); - PARSE_LANGOPT_BENIGN(ImplicitInt); - PARSE_LANGOPT_BENIGN(Digraphs); - PARSE_LANGOPT_BENIGN(HexFloats); - PARSE_LANGOPT_IMPORTANT(C99, diag::warn_pch_c99); - PARSE_LANGOPT_IMPORTANT(Microsoft, diag::warn_pch_microsoft_extensions); - PARSE_LANGOPT_IMPORTANT(CPlusPlus, diag::warn_pch_cplusplus); - PARSE_LANGOPT_IMPORTANT(CPlusPlus0x, diag::warn_pch_cplusplus0x); - PARSE_LANGOPT_BENIGN(CXXOperatorName); - PARSE_LANGOPT_IMPORTANT(ObjC1, diag::warn_pch_objective_c); - PARSE_LANGOPT_IMPORTANT(ObjC2, diag::warn_pch_objective_c2); - PARSE_LANGOPT_IMPORTANT(ObjCNonFragileABI, diag::warn_pch_nonfragile_abi); - PARSE_LANGOPT_IMPORTANT(ObjCNonFragileABI2, diag::warn_pch_nonfragile_abi2); - PARSE_LANGOPT_IMPORTANT(NoConstantCFStrings, - diag::warn_pch_no_constant_cfstrings); - PARSE_LANGOPT_BENIGN(PascalStrings); - PARSE_LANGOPT_BENIGN(WritableStrings); - PARSE_LANGOPT_IMPORTANT(LaxVectorConversions, - diag::warn_pch_lax_vector_conversions); - PARSE_LANGOPT_IMPORTANT(AltiVec, diag::warn_pch_altivec); - PARSE_LANGOPT_IMPORTANT(Exceptions, diag::warn_pch_exceptions); - PARSE_LANGOPT_IMPORTANT(SjLjExceptions, diag::warn_pch_sjlj_exceptions); - PARSE_LANGOPT_IMPORTANT(NeXTRuntime, diag::warn_pch_objc_runtime); - PARSE_LANGOPT_IMPORTANT(Freestanding, diag::warn_pch_freestanding); - PARSE_LANGOPT_IMPORTANT(NoBuiltin, diag::warn_pch_builtins); - PARSE_LANGOPT_IMPORTANT(ThreadsafeStatics, - diag::warn_pch_thread_safe_statics); - PARSE_LANGOPT_IMPORTANT(POSIXThreads, diag::warn_pch_posix_threads); - PARSE_LANGOPT_IMPORTANT(Blocks, diag::warn_pch_blocks); - PARSE_LANGOPT_BENIGN(EmitAllDecls); - PARSE_LANGOPT_IMPORTANT(MathErrno, diag::warn_pch_math_errno); - PARSE_LANGOPT_BENIGN(getSignedOverflowBehavior()); - PARSE_LANGOPT_IMPORTANT(HeinousExtensions, - diag::warn_pch_heinous_extensions); - // FIXME: Most of the options below are benign if the macro wasn't - // used. Unfortunately, this means that a PCH compiled without - // optimization can't be used with optimization turned on, even - // though the only thing that changes is whether __OPTIMIZE__ was - // defined... but if __OPTIMIZE__ never showed up in the header, it - // doesn't matter. We could consider making this some special kind - // of check. - PARSE_LANGOPT_IMPORTANT(Optimize, diag::warn_pch_optimize); - PARSE_LANGOPT_IMPORTANT(OptimizeSize, diag::warn_pch_optimize_size); - PARSE_LANGOPT_IMPORTANT(Static, diag::warn_pch_static); - PARSE_LANGOPT_IMPORTANT(PICLevel, diag::warn_pch_pic_level); - PARSE_LANGOPT_IMPORTANT(GNUInline, diag::warn_pch_gnu_inline); - PARSE_LANGOPT_IMPORTANT(NoInline, diag::warn_pch_no_inline); - PARSE_LANGOPT_IMPORTANT(AccessControl, diag::warn_pch_access_control); - PARSE_LANGOPT_IMPORTANT(CharIsSigned, diag::warn_pch_char_signed); - PARSE_LANGOPT_IMPORTANT(ShortWChar, diag::warn_pch_short_wchar); - if ((PPLangOpts.getGCMode() != 0) != (LangOpts.getGCMode() != 0)) { - Reader.Diag(diag::warn_pch_gc_mode) - << LangOpts.getGCMode() << PPLangOpts.getGCMode(); - return true; - } - PARSE_LANGOPT_BENIGN(getVisibilityMode()); - PARSE_LANGOPT_IMPORTANT(getStackProtectorMode(), - diag::warn_pch_stack_protector); - PARSE_LANGOPT_BENIGN(InstantiationDepth); - PARSE_LANGOPT_IMPORTANT(OpenCL, diag::warn_pch_opencl); - PARSE_LANGOPT_BENIGN(CatchUndefined); - PARSE_LANGOPT_IMPORTANT(ElideConstructors, diag::warn_pch_elide_constructors); - PARSE_LANGOPT_BENIGN(SpellChecking); -#undef PARSE_LANGOPT_IMPORTANT -#undef PARSE_LANGOPT_BENIGN - - return false; -} - -bool PCHValidator::ReadTargetTriple(llvm::StringRef Triple) { - if (Triple == PP.getTargetInfo().getTriple().str()) - return false; - - Reader.Diag(diag::warn_pch_target_triple) - << Triple << PP.getTargetInfo().getTriple().str(); - return true; -} - -struct EmptyStringRef { - bool operator ()(llvm::StringRef r) const { return r.empty(); } -}; -struct EmptyBlock { - bool operator ()(const PCHPredefinesBlock &r) const { return r.Data.empty(); } -}; - -static bool EqualConcatenations(llvm::SmallVector<llvm::StringRef, 2> L, - PCHPredefinesBlocks R) { - // First, sum up the lengths. - unsigned LL = 0, RL = 0; - for (unsigned I = 0, N = L.size(); I != N; ++I) { - LL += L[I].size(); - } - for (unsigned I = 0, N = R.size(); I != N; ++I) { - RL += R[I].Data.size(); - } - if (LL != RL) - return false; - if (LL == 0 && RL == 0) - return true; - - // Kick out empty parts, they confuse the algorithm below. - L.erase(std::remove_if(L.begin(), L.end(), EmptyStringRef()), L.end()); - R.erase(std::remove_if(R.begin(), R.end(), EmptyBlock()), R.end()); - - // Do it the hard way. At this point, both vectors must be non-empty. - llvm::StringRef LR = L[0], RR = R[0].Data; - unsigned LI = 0, RI = 0, LN = L.size(), RN = R.size(); - for (;;) { - // Compare the current pieces. - if (LR.size() == RR.size()) { - // If they're the same length, it's pretty easy. - if (LR != RR) - return false; - // Both pieces are done, advance. - ++LI; - ++RI; - // If either string is done, they're both done, since they're the same - // length. - if (LI == LN) { - assert(RI == RN && "Strings not the same length after all?"); - return true; - } - LR = L[LI]; - RR = R[RI].Data; - } else if (LR.size() < RR.size()) { - // Right piece is longer. - if (!RR.startswith(LR)) - return false; - ++LI; - assert(LI != LN && "Strings not the same length after all?"); - RR = RR.substr(LR.size()); - LR = L[LI]; - } else { - // Left piece is longer. - if (!LR.startswith(RR)) - return false; - ++RI; - assert(RI != RN && "Strings not the same length after all?"); - LR = LR.substr(RR.size()); - RR = R[RI].Data; - } - } -} - -static std::pair<FileID, llvm::StringRef::size_type> -FindMacro(const PCHPredefinesBlocks &Buffers, llvm::StringRef MacroDef) { - std::pair<FileID, llvm::StringRef::size_type> Res; - for (unsigned I = 0, N = Buffers.size(); I != N; ++I) { - Res.second = Buffers[I].Data.find(MacroDef); - if (Res.second != llvm::StringRef::npos) { - Res.first = Buffers[I].BufferID; - break; - } - } - return Res; -} - -bool PCHValidator::ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers, - llvm::StringRef OriginalFileName, - std::string &SuggestedPredefines) { - // We are in the context of an implicit include, so the predefines buffer will - // have a #include entry for the PCH file itself (as normalized by the - // preprocessor initialization). Find it and skip over it in the checking - // below. - llvm::SmallString<256> PCHInclude; - PCHInclude += "#include \""; - PCHInclude += NormalizeDashIncludePath(OriginalFileName); - PCHInclude += "\"\n"; - std::pair<llvm::StringRef,llvm::StringRef> Split = - llvm::StringRef(PP.getPredefines()).split(PCHInclude.str()); - llvm::StringRef Left = Split.first, Right = Split.second; - if (Left == PP.getPredefines()) { - Error("Missing PCH include entry!"); - return true; - } - - // If the concatenation of all the PCH buffers is equal to the adjusted - // command line, we're done. - // We build a SmallVector of the command line here, because we'll eventually - // need to support an arbitrary amount of pieces anyway (when we have chained - // PCH reading). - llvm::SmallVector<llvm::StringRef, 2> CommandLine; - CommandLine.push_back(Left); - CommandLine.push_back(Right); - if (EqualConcatenations(CommandLine, Buffers)) - return false; - - SourceManager &SourceMgr = PP.getSourceManager(); - - // The predefines buffers are different. Determine what the differences are, - // and whether they require us to reject the PCH file. - llvm::SmallVector<llvm::StringRef, 8> PCHLines; - for (unsigned I = 0, N = Buffers.size(); I != N; ++I) - Buffers[I].Data.split(PCHLines, "\n", /*MaxSplit=*/-1, /*KeepEmpty=*/false); - - llvm::SmallVector<llvm::StringRef, 8> CmdLineLines; - Left.split(CmdLineLines, "\n", /*MaxSplit=*/-1, /*KeepEmpty=*/false); - Right.split(CmdLineLines, "\n", /*MaxSplit=*/-1, /*KeepEmpty=*/false); - - // Sort both sets of predefined buffer lines, since we allow some extra - // definitions and they may appear at any point in the output. - std::sort(CmdLineLines.begin(), CmdLineLines.end()); - std::sort(PCHLines.begin(), PCHLines.end()); - - // Determine which predefines that were used to build the PCH file are missing - // from the command line. - std::vector<llvm::StringRef> MissingPredefines; - std::set_difference(PCHLines.begin(), PCHLines.end(), - CmdLineLines.begin(), CmdLineLines.end(), - std::back_inserter(MissingPredefines)); - - bool MissingDefines = false; - bool ConflictingDefines = false; - for (unsigned I = 0, N = MissingPredefines.size(); I != N; ++I) { - llvm::StringRef Missing = MissingPredefines[I]; - if (!Missing.startswith("#define ")) { - Reader.Diag(diag::warn_pch_compiler_options_mismatch); - return true; - } - - // This is a macro definition. Determine the name of the macro we're - // defining. - std::string::size_type StartOfMacroName = strlen("#define "); - std::string::size_type EndOfMacroName - = Missing.find_first_of("( \n\r", StartOfMacroName); - assert(EndOfMacroName != std::string::npos && - "Couldn't find the end of the macro name"); - llvm::StringRef MacroName = Missing.slice(StartOfMacroName, EndOfMacroName); - - // Determine whether this macro was given a different definition on the - // command line. - std::string MacroDefStart = "#define " + MacroName.str(); - std::string::size_type MacroDefLen = MacroDefStart.size(); - llvm::SmallVector<llvm::StringRef, 8>::iterator ConflictPos - = std::lower_bound(CmdLineLines.begin(), CmdLineLines.end(), - MacroDefStart); - for (; ConflictPos != CmdLineLines.end(); ++ConflictPos) { - if (!ConflictPos->startswith(MacroDefStart)) { - // Different macro; we're done. - ConflictPos = CmdLineLines.end(); - break; - } - - assert(ConflictPos->size() > MacroDefLen && - "Invalid #define in predefines buffer?"); - if ((*ConflictPos)[MacroDefLen] != ' ' && - (*ConflictPos)[MacroDefLen] != '(') - continue; // Longer macro name; keep trying. - - // We found a conflicting macro definition. - break; - } - - if (ConflictPos != CmdLineLines.end()) { - Reader.Diag(diag::warn_cmdline_conflicting_macro_def) - << MacroName; - - // Show the definition of this macro within the PCH file. - std::pair<FileID, llvm::StringRef::size_type> MacroLoc = - FindMacro(Buffers, Missing); - assert(MacroLoc.second!=llvm::StringRef::npos && "Unable to find macro!"); - SourceLocation PCHMissingLoc = - SourceMgr.getLocForStartOfFile(MacroLoc.first) - .getFileLocWithOffset(MacroLoc.second); - Reader.Diag(PCHMissingLoc, diag::note_pch_macro_defined_as) << MacroName; - - ConflictingDefines = true; - continue; - } - - // If the macro doesn't conflict, then we'll just pick up the macro - // definition from the PCH file. Warn the user that they made a mistake. - if (ConflictingDefines) - continue; // Don't complain if there are already conflicting defs - - if (!MissingDefines) { - Reader.Diag(diag::warn_cmdline_missing_macro_defs); - MissingDefines = true; - } - - // Show the definition of this macro within the PCH file. - std::pair<FileID, llvm::StringRef::size_type> MacroLoc = - FindMacro(Buffers, Missing); - assert(MacroLoc.second!=llvm::StringRef::npos && "Unable to find macro!"); - SourceLocation PCHMissingLoc = - SourceMgr.getLocForStartOfFile(MacroLoc.first) - .getFileLocWithOffset(MacroLoc.second); - Reader.Diag(PCHMissingLoc, diag::note_using_macro_def_from_pch); - } - - if (ConflictingDefines) - return true; - - // Determine what predefines were introduced based on command-line - // parameters that were not present when building the PCH - // file. Extra #defines are okay, so long as the identifiers being - // defined were not used within the precompiled header. - std::vector<llvm::StringRef> ExtraPredefines; - std::set_difference(CmdLineLines.begin(), CmdLineLines.end(), - PCHLines.begin(), PCHLines.end(), - std::back_inserter(ExtraPredefines)); - for (unsigned I = 0, N = ExtraPredefines.size(); I != N; ++I) { - llvm::StringRef &Extra = ExtraPredefines[I]; - if (!Extra.startswith("#define ")) { - Reader.Diag(diag::warn_pch_compiler_options_mismatch); - return true; - } - - // This is an extra macro definition. Determine the name of the - // macro we're defining. - std::string::size_type StartOfMacroName = strlen("#define "); - std::string::size_type EndOfMacroName - = Extra.find_first_of("( \n\r", StartOfMacroName); - assert(EndOfMacroName != std::string::npos && - "Couldn't find the end of the macro name"); - llvm::StringRef MacroName = Extra.slice(StartOfMacroName, EndOfMacroName); - - // Check whether this name was used somewhere in the PCH file. If - // so, defining it as a macro could change behavior, so we reject - // the PCH file. - if (IdentifierInfo *II = Reader.get(MacroName)) { - Reader.Diag(diag::warn_macro_name_used_in_pch) << II; - return true; - } - - // Add this definition to the suggested predefines buffer. - SuggestedPredefines += Extra; - SuggestedPredefines += '\n'; - } - - // If we get here, it's because the predefines buffer had compatible - // contents. Accept the PCH file. - return false; -} - -void PCHValidator::ReadHeaderFileInfo(const HeaderFileInfo &HFI, - unsigned ID) { - PP.getHeaderSearchInfo().setHeaderFileInfoForUID(HFI, ID); - ++NumHeaderInfos; -} - -void PCHValidator::ReadCounter(unsigned Value) { - PP.setCounterValue(Value); -} - -//===----------------------------------------------------------------------===// -// PCH reader implementation -//===----------------------------------------------------------------------===// - -PCHReader::PCHReader(Preprocessor &PP, ASTContext *Context, - const char *isysroot) - : Listener(new PCHValidator(PP, *this)), DeserializationListener(0), - SourceMgr(PP.getSourceManager()), FileMgr(PP.getFileManager()), - Diags(PP.getDiagnostics()), SemaObj(0), PP(&PP), Context(Context), - StatCache(0), Consumer(0), IdentifierTableData(0), IdentifierLookupTable(0), - IdentifierOffsets(0), - MethodPoolLookupTable(0), MethodPoolLookupTableData(0), - TotalSelectorsInMethodPool(0), SelectorOffsets(0), - TotalNumSelectors(0), MacroDefinitionOffsets(0), - NumPreallocatedPreprocessingEntities(0), - isysroot(isysroot), NumStatHits(0), NumStatMisses(0), - NumSLocEntriesRead(0), NumStatementsRead(0), - NumMacrosRead(0), NumMethodPoolSelectorsRead(0), NumMethodPoolMisses(0), - NumLexicalDeclContextsRead(0), NumVisibleDeclContextsRead(0), - CurrentlyLoadingTypeOrDecl(0) { - RelocatablePCH = false; -} - -PCHReader::PCHReader(SourceManager &SourceMgr, FileManager &FileMgr, - Diagnostic &Diags, const char *isysroot) - : DeserializationListener(0), SourceMgr(SourceMgr), FileMgr(FileMgr), - Diags(Diags), SemaObj(0), PP(0), Context(0), StatCache(0), Consumer(0), - IdentifierTableData(0), IdentifierLookupTable(0), - IdentifierOffsets(0), - MethodPoolLookupTable(0), MethodPoolLookupTableData(0), - TotalSelectorsInMethodPool(0), SelectorOffsets(0), - TotalNumSelectors(0), MacroDefinitionOffsets(0), - NumPreallocatedPreprocessingEntities(0), - isysroot(isysroot), NumStatHits(0), NumStatMisses(0), - NumSLocEntriesRead(0), NumStatementsRead(0), - NumMacrosRead(0), NumMethodPoolSelectorsRead(0), NumMethodPoolMisses(0), - NumLexicalDeclContextsRead(0), NumVisibleDeclContextsRead(0), - CurrentlyLoadingTypeOrDecl(0) { - RelocatablePCH = false; -} - -PCHReader::~PCHReader() {} - - -namespace { -class PCHMethodPoolLookupTrait { - PCHReader &Reader; - -public: - typedef std::pair<ObjCMethodList, ObjCMethodList> data_type; - - typedef Selector external_key_type; - typedef external_key_type internal_key_type; - - explicit PCHMethodPoolLookupTrait(PCHReader &Reader) : Reader(Reader) { } - - static bool EqualKey(const internal_key_type& a, - const internal_key_type& b) { - return a == b; - } - - static unsigned ComputeHash(Selector Sel) { - unsigned N = Sel.getNumArgs(); - if (N == 0) - ++N; - unsigned R = 5381; - for (unsigned I = 0; I != N; ++I) - if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(I)) - R = llvm::HashString(II->getName(), R); - return R; - } - - // This hopefully will just get inlined and removed by the optimizer. - static const internal_key_type& - GetInternalKey(const external_key_type& x) { return x; } - - static std::pair<unsigned, unsigned> - ReadKeyDataLength(const unsigned char*& d) { - using namespace clang::io; - unsigned KeyLen = ReadUnalignedLE16(d); - unsigned DataLen = ReadUnalignedLE16(d); - return std::make_pair(KeyLen, DataLen); - } - - internal_key_type ReadKey(const unsigned char* d, unsigned) { - using namespace clang::io; - SelectorTable &SelTable = Reader.getContext()->Selectors; - unsigned N = ReadUnalignedLE16(d); - IdentifierInfo *FirstII - = Reader.DecodeIdentifierInfo(ReadUnalignedLE32(d)); - if (N == 0) - return SelTable.getNullarySelector(FirstII); - else if (N == 1) - return SelTable.getUnarySelector(FirstII); - - llvm::SmallVector<IdentifierInfo *, 16> Args; - Args.push_back(FirstII); - for (unsigned I = 1; I != N; ++I) - Args.push_back(Reader.DecodeIdentifierInfo(ReadUnalignedLE32(d))); - - return SelTable.getSelector(N, Args.data()); - } - - data_type ReadData(Selector, const unsigned char* d, unsigned DataLen) { - using namespace clang::io; - unsigned NumInstanceMethods = ReadUnalignedLE16(d); - unsigned NumFactoryMethods = ReadUnalignedLE16(d); - - data_type Result; - - // Load instance methods - ObjCMethodList *Prev = 0; - for (unsigned I = 0; I != NumInstanceMethods; ++I) { - ObjCMethodDecl *Method - = cast<ObjCMethodDecl>(Reader.GetDecl(ReadUnalignedLE32(d))); - if (!Result.first.Method) { - // This is the first method, which is the easy case. - Result.first.Method = Method; - Prev = &Result.first; - continue; - } - - ObjCMethodList *Mem = - Reader.getSema()->BumpAlloc.Allocate<ObjCMethodList>(); - Prev->Next = new (Mem) ObjCMethodList(Method, 0); - Prev = Prev->Next; - } - - // Load factory methods - Prev = 0; - for (unsigned I = 0; I != NumFactoryMethods; ++I) { - ObjCMethodDecl *Method - = cast<ObjCMethodDecl>(Reader.GetDecl(ReadUnalignedLE32(d))); - if (!Result.second.Method) { - // This is the first method, which is the easy case. - Result.second.Method = Method; - Prev = &Result.second; - continue; - } - - ObjCMethodList *Mem = - Reader.getSema()->BumpAlloc.Allocate<ObjCMethodList>(); - Prev->Next = new (Mem) ObjCMethodList(Method, 0); - Prev = Prev->Next; - } - - return Result; - } -}; - -} // end anonymous namespace - -/// \brief The on-disk hash table used for the global method pool. -typedef OnDiskChainedHashTable<PCHMethodPoolLookupTrait> - PCHMethodPoolLookupTable; - -namespace { -class PCHIdentifierLookupTrait { - PCHReader &Reader; - - // If we know the IdentifierInfo in advance, it is here and we will - // not build a new one. Used when deserializing information about an - // identifier that was constructed before the PCH file was read. - IdentifierInfo *KnownII; - -public: - typedef IdentifierInfo * data_type; - - typedef const std::pair<const char*, unsigned> external_key_type; - - typedef external_key_type internal_key_type; - - explicit PCHIdentifierLookupTrait(PCHReader &Reader, IdentifierInfo *II = 0) - : Reader(Reader), KnownII(II) { } - - static bool EqualKey(const internal_key_type& a, - const internal_key_type& b) { - return (a.second == b.second) ? memcmp(a.first, b.first, a.second) == 0 - : false; - } - - static unsigned ComputeHash(const internal_key_type& a) { - return llvm::HashString(llvm::StringRef(a.first, a.second)); - } - - // This hopefully will just get inlined and removed by the optimizer. - static const internal_key_type& - GetInternalKey(const external_key_type& x) { return x; } - - static std::pair<unsigned, unsigned> - ReadKeyDataLength(const unsigned char*& d) { - using namespace clang::io; - unsigned DataLen = ReadUnalignedLE16(d); - unsigned KeyLen = ReadUnalignedLE16(d); - return std::make_pair(KeyLen, DataLen); - } - - static std::pair<const char*, unsigned> - ReadKey(const unsigned char* d, unsigned n) { - assert(n >= 2 && d[n-1] == '\0'); - return std::make_pair((const char*) d, n-1); - } - - IdentifierInfo *ReadData(const internal_key_type& k, - const unsigned char* d, - unsigned DataLen) { - using namespace clang::io; - pch::IdentID ID = ReadUnalignedLE32(d); - bool IsInteresting = ID & 0x01; - - // Wipe out the "is interesting" bit. - ID = ID >> 1; - - if (!IsInteresting) { - // For unintersting identifiers, just build the IdentifierInfo - // and associate it with the persistent ID. - IdentifierInfo *II = KnownII; - if (!II) - II = &Reader.getIdentifierTable().CreateIdentifierInfo( - k.first, k.first + k.second); - Reader.SetIdentifierInfo(ID, II); - return II; - } - - unsigned Bits = ReadUnalignedLE16(d); - bool CPlusPlusOperatorKeyword = Bits & 0x01; - Bits >>= 1; - bool Poisoned = Bits & 0x01; - Bits >>= 1; - bool ExtensionToken = Bits & 0x01; - Bits >>= 1; - bool hasMacroDefinition = Bits & 0x01; - Bits >>= 1; - unsigned ObjCOrBuiltinID = Bits & 0x3FF; - Bits >>= 10; - - assert(Bits == 0 && "Extra bits in the identifier?"); - DataLen -= 6; - - // Build the IdentifierInfo itself and link the identifier ID with - // the new IdentifierInfo. - IdentifierInfo *II = KnownII; - if (!II) - II = &Reader.getIdentifierTable().CreateIdentifierInfo( - k.first, k.first + k.second); - Reader.SetIdentifierInfo(ID, II); - - // Set or check the various bits in the IdentifierInfo structure. - // FIXME: Load token IDs lazily, too? - II->setObjCOrBuiltinID(ObjCOrBuiltinID); - assert(II->isExtensionToken() == ExtensionToken && - "Incorrect extension token flag"); - (void)ExtensionToken; - II->setIsPoisoned(Poisoned); - assert(II->isCPlusPlusOperatorKeyword() == CPlusPlusOperatorKeyword && - "Incorrect C++ operator keyword flag"); - (void)CPlusPlusOperatorKeyword; - - // If this identifier is a macro, deserialize the macro - // definition. - if (hasMacroDefinition) { - uint32_t Offset = ReadUnalignedLE32(d); - Reader.ReadMacroRecord(Offset); - DataLen -= 4; - } - - // Read all of the declarations visible at global scope with this - // name. - if (Reader.getContext() == 0) return II; - if (DataLen > 0) { - llvm::SmallVector<uint32_t, 4> DeclIDs; - for (; DataLen > 0; DataLen -= 4) - DeclIDs.push_back(ReadUnalignedLE32(d)); - Reader.SetGloballyVisibleDecls(II, DeclIDs); - } - - return II; - } -}; - -} // end anonymous namespace - -/// \brief The on-disk hash table used to contain information about -/// all of the identifiers in the program. -typedef OnDiskChainedHashTable<PCHIdentifierLookupTrait> - PCHIdentifierLookupTable; - -void PCHReader::Error(const char *Msg) { - Diag(diag::err_fe_pch_malformed) << Msg; -} - -/// \brief Check the contents of the concatenation of all predefines buffers in -/// the PCH chain against the contents of the predefines buffer of the current -/// compiler invocation. -/// -/// The contents should be the same. If not, then some command-line option -/// changed the preprocessor state and we must probably reject the PCH file. -/// -/// \returns true if there was a mismatch (in which case the PCH file -/// should be ignored), or false otherwise. -bool PCHReader::CheckPredefinesBuffers() { - if (Listener) - return Listener->ReadPredefinesBuffer(PCHPredefinesBuffers, - ActualOriginalFileName, - SuggestedPredefines); - return false; -} - -//===----------------------------------------------------------------------===// -// Source Manager Deserialization -//===----------------------------------------------------------------------===// - -/// \brief Read the line table in the source manager block. -/// \returns true if ther was an error. -bool PCHReader::ParseLineTable(llvm::SmallVectorImpl<uint64_t> &Record) { - unsigned Idx = 0; - LineTableInfo &LineTable = SourceMgr.getLineTable(); - - // Parse the file names - std::map<int, int> FileIDs; - for (int I = 0, N = Record[Idx++]; I != N; ++I) { - // Extract the file name - unsigned FilenameLen = Record[Idx++]; - std::string Filename(&Record[Idx], &Record[Idx] + FilenameLen); - Idx += FilenameLen; - MaybeAddSystemRootToFilename(Filename); - FileIDs[I] = LineTable.getLineTableFilenameID(Filename.c_str(), - Filename.size()); - } - - // Parse the line entries - std::vector<LineEntry> Entries; - while (Idx < Record.size()) { - int FID = Record[Idx++]; - - // Extract the line entries - unsigned NumEntries = Record[Idx++]; - assert(NumEntries && "Numentries is 00000"); - Entries.clear(); - Entries.reserve(NumEntries); - for (unsigned I = 0; I != NumEntries; ++I) { - unsigned FileOffset = Record[Idx++]; - unsigned LineNo = Record[Idx++]; - int FilenameID = FileIDs[Record[Idx++]]; - SrcMgr::CharacteristicKind FileKind - = (SrcMgr::CharacteristicKind)Record[Idx++]; - unsigned IncludeOffset = Record[Idx++]; - Entries.push_back(LineEntry::get(FileOffset, LineNo, FilenameID, - FileKind, IncludeOffset)); - } - LineTable.AddEntry(FID, Entries); - } - - return false; -} - -namespace { - -class PCHStatData { -public: - const bool hasStat; - const ino_t ino; - const dev_t dev; - const mode_t mode; - const time_t mtime; - const off_t size; - - PCHStatData(ino_t i, dev_t d, mode_t mo, time_t m, off_t s) - : hasStat(true), ino(i), dev(d), mode(mo), mtime(m), size(s) {} - - PCHStatData() - : hasStat(false), ino(0), dev(0), mode(0), mtime(0), size(0) {} -}; - -class PCHStatLookupTrait { - public: - typedef const char *external_key_type; - typedef const char *internal_key_type; - - typedef PCHStatData data_type; - - static unsigned ComputeHash(const char *path) { - return llvm::HashString(path); - } - - static internal_key_type GetInternalKey(const char *path) { return path; } - - static bool EqualKey(internal_key_type a, internal_key_type b) { - return strcmp(a, b) == 0; - } - - static std::pair<unsigned, unsigned> - ReadKeyDataLength(const unsigned char*& d) { - unsigned KeyLen = (unsigned) clang::io::ReadUnalignedLE16(d); - unsigned DataLen = (unsigned) *d++; - return std::make_pair(KeyLen + 1, DataLen); - } - - static internal_key_type ReadKey(const unsigned char *d, unsigned) { - return (const char *)d; - } - - static data_type ReadData(const internal_key_type, const unsigned char *d, - unsigned /*DataLen*/) { - using namespace clang::io; - - if (*d++ == 1) - return data_type(); - - ino_t ino = (ino_t) ReadUnalignedLE32(d); - dev_t dev = (dev_t) ReadUnalignedLE32(d); - mode_t mode = (mode_t) ReadUnalignedLE16(d); - time_t mtime = (time_t) ReadUnalignedLE64(d); - off_t size = (off_t) ReadUnalignedLE64(d); - return data_type(ino, dev, mode, mtime, size); - } -}; - -/// \brief stat() cache for precompiled headers. -/// -/// This cache is very similar to the stat cache used by pretokenized -/// headers. -class PCHStatCache : public StatSysCallCache { - typedef OnDiskChainedHashTable<PCHStatLookupTrait> CacheTy; - CacheTy *Cache; - - unsigned &NumStatHits, &NumStatMisses; -public: - PCHStatCache(const unsigned char *Buckets, - const unsigned char *Base, - unsigned &NumStatHits, - unsigned &NumStatMisses) - : Cache(0), NumStatHits(NumStatHits), NumStatMisses(NumStatMisses) { - Cache = CacheTy::Create(Buckets, Base); - } - - ~PCHStatCache() { delete Cache; } - - int stat(const char *path, struct stat *buf) { - // Do the lookup for the file's data in the PCH file. - CacheTy::iterator I = Cache->find(path); - - // If we don't get a hit in the PCH file just forward to 'stat'. - if (I == Cache->end()) { - ++NumStatMisses; - return StatSysCallCache::stat(path, buf); - } - - ++NumStatHits; - PCHStatData Data = *I; - - if (!Data.hasStat) - return 1; - - buf->st_ino = Data.ino; - buf->st_dev = Data.dev; - buf->st_mtime = Data.mtime; - buf->st_mode = Data.mode; - buf->st_size = Data.size; - return 0; - } -}; -} // end anonymous namespace - - -/// \brief Read the source manager block -PCHReader::PCHReadResult PCHReader::ReadSourceManagerBlock() { - using namespace SrcMgr; - - // Set the source-location entry cursor to the current position in - // the stream. This cursor will be used to read the contents of the - // source manager block initially, and then lazily read - // source-location entries as needed. - SLocEntryCursor = Stream; - - // The stream itself is going to skip over the source manager block. - if (Stream.SkipBlock()) { - Error("malformed block record in PCH file"); - return Failure; - } - - // Enter the source manager block. - if (SLocEntryCursor.EnterSubBlock(pch::SOURCE_MANAGER_BLOCK_ID)) { - Error("malformed source manager block record in PCH file"); - return Failure; - } - - RecordData Record; - while (true) { - unsigned Code = SLocEntryCursor.ReadCode(); - if (Code == llvm::bitc::END_BLOCK) { - if (SLocEntryCursor.ReadBlockEnd()) { - Error("error at end of Source Manager block in PCH file"); - return Failure; - } - return Success; - } - - if (Code == llvm::bitc::ENTER_SUBBLOCK) { - // No known subblocks, always skip them. - SLocEntryCursor.ReadSubBlockID(); - if (SLocEntryCursor.SkipBlock()) { - Error("malformed block record in PCH file"); - return Failure; - } - continue; - } - - if (Code == llvm::bitc::DEFINE_ABBREV) { - SLocEntryCursor.ReadAbbrevRecord(); - continue; - } - - // Read a record. - const char *BlobStart; - unsigned BlobLen; - Record.clear(); - switch (SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) { - default: // Default behavior: ignore. - break; - - case pch::SM_LINE_TABLE: - if (ParseLineTable(Record)) - return Failure; - break; - - case pch::SM_SLOC_FILE_ENTRY: - case pch::SM_SLOC_BUFFER_ENTRY: - case pch::SM_SLOC_INSTANTIATION_ENTRY: - // Once we hit one of the source location entries, we're done. - return Success; - } - } -} - -/// \brief Read in the source location entry with the given ID. -PCHReader::PCHReadResult PCHReader::ReadSLocEntryRecord(unsigned ID) { - if (ID == 0) - return Success; - - if (ID > TotalNumSLocEntries) { - Error("source location entry ID out-of-range for PCH file"); - return Failure; - } - - ++NumSLocEntriesRead; - SLocEntryCursor.JumpToBit(SLocOffsets[ID - 1]); - unsigned Code = SLocEntryCursor.ReadCode(); - if (Code == llvm::bitc::END_BLOCK || - Code == llvm::bitc::ENTER_SUBBLOCK || - Code == llvm::bitc::DEFINE_ABBREV) { - Error("incorrectly-formatted source location entry in PCH file"); - return Failure; - } - - RecordData Record; - const char *BlobStart; - unsigned BlobLen; - switch (SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) { - default: - Error("incorrectly-formatted source location entry in PCH file"); - return Failure; - - case pch::SM_SLOC_FILE_ENTRY: { - std::string Filename(BlobStart, BlobStart + BlobLen); - MaybeAddSystemRootToFilename(Filename); - const FileEntry *File = FileMgr.getFile(Filename); - if (File == 0) { - std::string ErrorStr = "could not find file '"; - ErrorStr += Filename; - ErrorStr += "' referenced by PCH file"; - Error(ErrorStr.c_str()); - return Failure; - } - - if (Record.size() < 10) { - Error("source location entry is incorrect"); - return Failure; - } - - if ((off_t)Record[4] != File->getSize() -#if !defined(LLVM_ON_WIN32) - // In our regression testing, the Windows file system seems to - // have inconsistent modification times that sometimes - // erroneously trigger this error-handling path. - || (time_t)Record[5] != File->getModificationTime() -#endif - ) { - Diag(diag::err_fe_pch_file_modified) - << Filename; - return Failure; - } - - FileID FID = SourceMgr.createFileID(File, - SourceLocation::getFromRawEncoding(Record[1]), - (SrcMgr::CharacteristicKind)Record[2], - ID, Record[0]); - if (Record[3]) - const_cast<SrcMgr::FileInfo&>(SourceMgr.getSLocEntry(FID).getFile()) - .setHasLineDirectives(); - - // Reconstruct header-search information for this file. - HeaderFileInfo HFI; - HFI.isImport = Record[6]; - HFI.DirInfo = Record[7]; - HFI.NumIncludes = Record[8]; - HFI.ControllingMacroID = Record[9]; - if (Listener) - Listener->ReadHeaderFileInfo(HFI, File->getUID()); - break; - } - - case pch::SM_SLOC_BUFFER_ENTRY: { - const char *Name = BlobStart; - unsigned Offset = Record[0]; - unsigned Code = SLocEntryCursor.ReadCode(); - Record.clear(); - unsigned RecCode - = SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen); - - if (RecCode != pch::SM_SLOC_BUFFER_BLOB) { - Error("PCH record has invalid code"); - return Failure; - } - - llvm::MemoryBuffer *Buffer - = llvm::MemoryBuffer::getMemBuffer(llvm::StringRef(BlobStart, BlobLen - 1), - Name); - FileID BufferID = SourceMgr.createFileIDForMemBuffer(Buffer, ID, Offset); - - if (strcmp(Name, "<built-in>") == 0) { - PCHPredefinesBlock Block = { - BufferID, - llvm::StringRef(BlobStart, BlobLen - 1) - }; - PCHPredefinesBuffers.push_back(Block); - } - - break; - } - - case pch::SM_SLOC_INSTANTIATION_ENTRY: { - SourceLocation SpellingLoc - = SourceLocation::getFromRawEncoding(Record[1]); - SourceMgr.createInstantiationLoc(SpellingLoc, - SourceLocation::getFromRawEncoding(Record[2]), - SourceLocation::getFromRawEncoding(Record[3]), - Record[4], - ID, - Record[0]); - break; - } - } - - return Success; -} - -/// ReadBlockAbbrevs - Enter a subblock of the specified BlockID with the -/// specified cursor. Read the abbreviations that are at the top of the block -/// and then leave the cursor pointing into the block. -bool PCHReader::ReadBlockAbbrevs(llvm::BitstreamCursor &Cursor, - unsigned BlockID) { - if (Cursor.EnterSubBlock(BlockID)) { - Error("malformed block record in PCH file"); - return Failure; - } - - while (true) { - unsigned Code = Cursor.ReadCode(); - - // We expect all abbrevs to be at the start of the block. - if (Code != llvm::bitc::DEFINE_ABBREV) - return false; - Cursor.ReadAbbrevRecord(); - } -} - -void PCHReader::ReadMacroRecord(uint64_t Offset) { - assert(PP && "Forgot to set Preprocessor ?"); - - // Keep track of where we are in the stream, then jump back there - // after reading this macro. - SavedStreamPosition SavedPosition(Stream); - - Stream.JumpToBit(Offset); - RecordData Record; - llvm::SmallVector<IdentifierInfo*, 16> MacroArgs; - MacroInfo *Macro = 0; - - while (true) { - unsigned Code = Stream.ReadCode(); - switch (Code) { - case llvm::bitc::END_BLOCK: - return; - - case llvm::bitc::ENTER_SUBBLOCK: - // No known subblocks, always skip them. - Stream.ReadSubBlockID(); - if (Stream.SkipBlock()) { - Error("malformed block record in PCH file"); - return; - } - continue; - - case llvm::bitc::DEFINE_ABBREV: - Stream.ReadAbbrevRecord(); - continue; - default: break; - } - - // Read a record. - Record.clear(); - pch::PreprocessorRecordTypes RecType = - (pch::PreprocessorRecordTypes)Stream.ReadRecord(Code, Record); - switch (RecType) { - case pch::PP_MACRO_OBJECT_LIKE: - case pch::PP_MACRO_FUNCTION_LIKE: { - // If we already have a macro, that means that we've hit the end - // of the definition of the macro we were looking for. We're - // done. - if (Macro) - return; - - IdentifierInfo *II = DecodeIdentifierInfo(Record[0]); - if (II == 0) { - Error("macro must have a name in PCH file"); - return; - } - SourceLocation Loc = SourceLocation::getFromRawEncoding(Record[1]); - bool isUsed = Record[2]; - - MacroInfo *MI = PP->AllocateMacroInfo(Loc); - MI->setIsUsed(isUsed); - - unsigned NextIndex = 3; - if (RecType == pch::PP_MACRO_FUNCTION_LIKE) { - // Decode function-like macro info. - bool isC99VarArgs = Record[3]; - bool isGNUVarArgs = Record[4]; - MacroArgs.clear(); - unsigned NumArgs = Record[5]; - NextIndex = 6 + NumArgs; - for (unsigned i = 0; i != NumArgs; ++i) - MacroArgs.push_back(DecodeIdentifierInfo(Record[6+i])); - - // Install function-like macro info. - MI->setIsFunctionLike(); - if (isC99VarArgs) MI->setIsC99Varargs(); - if (isGNUVarArgs) MI->setIsGNUVarargs(); - MI->setArgumentList(MacroArgs.data(), MacroArgs.size(), - PP->getPreprocessorAllocator()); - } - - // Finally, install the macro. - PP->setMacroInfo(II, MI); - - // Remember that we saw this macro last so that we add the tokens that - // form its body to it. - Macro = MI; - - if (NextIndex + 1 == Record.size() && PP->getPreprocessingRecord()) { - // We have a macro definition. Load it now. - PP->getPreprocessingRecord()->RegisterMacroDefinition(Macro, - getMacroDefinition(Record[NextIndex])); - } - - ++NumMacrosRead; - break; - } - - case pch::PP_TOKEN: { - // If we see a TOKEN before a PP_MACRO_*, then the file is - // erroneous, just pretend we didn't see this. - if (Macro == 0) break; - - Token Tok; - Tok.startToken(); - Tok.setLocation(SourceLocation::getFromRawEncoding(Record[0])); - Tok.setLength(Record[1]); - if (IdentifierInfo *II = DecodeIdentifierInfo(Record[2])) - Tok.setIdentifierInfo(II); - Tok.setKind((tok::TokenKind)Record[3]); - Tok.setFlag((Token::TokenFlags)Record[4]); - Macro->AddTokenToBody(Tok); - break; - } - - case pch::PP_MACRO_INSTANTIATION: { - // If we already have a macro, that means that we've hit the end - // of the definition of the macro we were looking for. We're - // done. - if (Macro) - return; - - if (!PP->getPreprocessingRecord()) { - Error("missing preprocessing record in PCH file"); - return; - } - - PreprocessingRecord &PPRec = *PP->getPreprocessingRecord(); - if (PPRec.getPreprocessedEntity(Record[0])) - return; - - MacroInstantiation *MI - = new (PPRec) MacroInstantiation(DecodeIdentifierInfo(Record[3]), - SourceRange( - SourceLocation::getFromRawEncoding(Record[1]), - SourceLocation::getFromRawEncoding(Record[2])), - getMacroDefinition(Record[4])); - PPRec.SetPreallocatedEntity(Record[0], MI); - return; - } - - case pch::PP_MACRO_DEFINITION: { - // If we already have a macro, that means that we've hit the end - // of the definition of the macro we were looking for. We're - // done. - if (Macro) - return; - - if (!PP->getPreprocessingRecord()) { - Error("missing preprocessing record in PCH file"); - return; - } - - PreprocessingRecord &PPRec = *PP->getPreprocessingRecord(); - if (PPRec.getPreprocessedEntity(Record[0])) - return; - - if (Record[1] >= MacroDefinitionsLoaded.size()) { - Error("out-of-bounds macro definition record"); - return; - } - - MacroDefinition *MD - = new (PPRec) MacroDefinition(DecodeIdentifierInfo(Record[4]), - SourceLocation::getFromRawEncoding(Record[5]), - SourceRange( - SourceLocation::getFromRawEncoding(Record[2]), - SourceLocation::getFromRawEncoding(Record[3]))); - PPRec.SetPreallocatedEntity(Record[0], MD); - MacroDefinitionsLoaded[Record[1]] = MD; - return; - } - } - } -} - -void PCHReader::ReadDefinedMacros() { - // If there was no preprocessor block, do nothing. - if (!MacroCursor.getBitStreamReader()) - return; - - llvm::BitstreamCursor Cursor = MacroCursor; - if (Cursor.EnterSubBlock(pch::PREPROCESSOR_BLOCK_ID)) { - Error("malformed preprocessor block record in PCH file"); - return; - } - - RecordData Record; - while (true) { - unsigned Code = Cursor.ReadCode(); - if (Code == llvm::bitc::END_BLOCK) { - if (Cursor.ReadBlockEnd()) - Error("error at end of preprocessor block in PCH file"); - return; - } - - if (Code == llvm::bitc::ENTER_SUBBLOCK) { - // No known subblocks, always skip them. - Cursor.ReadSubBlockID(); - if (Cursor.SkipBlock()) { - Error("malformed block record in PCH file"); - return; - } - continue; - } - - if (Code == llvm::bitc::DEFINE_ABBREV) { - Cursor.ReadAbbrevRecord(); - continue; - } - - // Read a record. - const char *BlobStart; - unsigned BlobLen; - Record.clear(); - switch (Cursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) { - default: // Default behavior: ignore. - break; - - case pch::PP_MACRO_OBJECT_LIKE: - case pch::PP_MACRO_FUNCTION_LIKE: - DecodeIdentifierInfo(Record[0]); - break; - - case pch::PP_TOKEN: - // Ignore tokens. - break; - - case pch::PP_MACRO_INSTANTIATION: - case pch::PP_MACRO_DEFINITION: - // Read the macro record. - ReadMacroRecord(Cursor.GetCurrentBitNo()); - break; - } - } -} - -MacroDefinition *PCHReader::getMacroDefinition(pch::IdentID ID) { - if (ID == 0 || ID >= MacroDefinitionsLoaded.size()) - return 0; - - if (!MacroDefinitionsLoaded[ID]) - ReadMacroRecord(MacroDefinitionOffsets[ID]); - - return MacroDefinitionsLoaded[ID]; -} - -/// \brief If we are loading a relocatable PCH file, and the filename is -/// not an absolute path, add the system root to the beginning of the file -/// name. -void PCHReader::MaybeAddSystemRootToFilename(std::string &Filename) { - // If this is not a relocatable PCH file, there's nothing to do. - if (!RelocatablePCH) - return; - - if (Filename.empty() || llvm::sys::Path(Filename).isAbsolute()) - return; - - if (isysroot == 0) { - // If no system root was given, default to '/' - Filename.insert(Filename.begin(), '/'); - return; - } - - unsigned Length = strlen(isysroot); - if (isysroot[Length - 1] != '/') - Filename.insert(Filename.begin(), '/'); - - Filename.insert(Filename.begin(), isysroot, isysroot + Length); -} - -PCHReader::PCHReadResult -PCHReader::ReadPCHBlock() { - if (Stream.EnterSubBlock(pch::PCH_BLOCK_ID)) { - Error("malformed block record in PCH file"); - return Failure; - } - - // Read all of the records and blocks for the PCH file. - RecordData Record; - while (!Stream.AtEndOfStream()) { - unsigned Code = Stream.ReadCode(); - if (Code == llvm::bitc::END_BLOCK) { - if (Stream.ReadBlockEnd()) { - Error("error at end of module block in PCH file"); - return Failure; - } - - return Success; - } - - if (Code == llvm::bitc::ENTER_SUBBLOCK) { - switch (Stream.ReadSubBlockID()) { - case pch::DECLTYPES_BLOCK_ID: - // We lazily load the decls block, but we want to set up the - // DeclsCursor cursor to point into it. Clone our current bitcode - // cursor to it, enter the block and read the abbrevs in that block. - // With the main cursor, we just skip over it. - DeclsCursor = Stream; - if (Stream.SkipBlock() || // Skip with the main cursor. - // Read the abbrevs. - ReadBlockAbbrevs(DeclsCursor, pch::DECLTYPES_BLOCK_ID)) { - Error("malformed block record in PCH file"); - return Failure; - } - break; - - case pch::PREPROCESSOR_BLOCK_ID: - MacroCursor = Stream; - if (PP) - PP->setExternalSource(this); - - if (Stream.SkipBlock()) { - Error("malformed block record in PCH file"); - return Failure; - } - break; - - case pch::SOURCE_MANAGER_BLOCK_ID: - switch (ReadSourceManagerBlock()) { - case Success: - break; - - case Failure: - Error("malformed source manager block in PCH file"); - return Failure; - - case IgnorePCH: - return IgnorePCH; - } - break; - } - continue; - } - - if (Code == llvm::bitc::DEFINE_ABBREV) { - Stream.ReadAbbrevRecord(); - continue; - } - - // Read and process a record. - Record.clear(); - const char *BlobStart = 0; - unsigned BlobLen = 0; - switch ((pch::PCHRecordTypes)Stream.ReadRecord(Code, Record, - &BlobStart, &BlobLen)) { - default: // Default behavior: ignore. - break; - - case pch::TYPE_OFFSET: - if (!TypesLoaded.empty()) { - Error("duplicate TYPE_OFFSET record in PCH file"); - return Failure; - } - TypeOffsets = (const uint32_t *)BlobStart; - TypesLoaded.resize(Record[0]); - break; - - case pch::DECL_OFFSET: - if (!DeclsLoaded.empty()) { - Error("duplicate DECL_OFFSET record in PCH file"); - return Failure; - } - DeclOffsets = (const uint32_t *)BlobStart; - DeclsLoaded.resize(Record[0]); - break; - - case pch::LANGUAGE_OPTIONS: - if (ParseLanguageOptions(Record)) - return IgnorePCH; - break; - - case pch::METADATA: { - if (Record[0] != pch::VERSION_MAJOR) { - Diag(Record[0] < pch::VERSION_MAJOR? diag::warn_pch_version_too_old - : diag::warn_pch_version_too_new); - return IgnorePCH; - } - - RelocatablePCH = Record[4]; - if (Listener) { - std::string TargetTriple(BlobStart, BlobLen); - if (Listener->ReadTargetTriple(TargetTriple)) - return IgnorePCH; - } - break; - } - - case pch::IDENTIFIER_TABLE: - IdentifierTableData = BlobStart; - if (Record[0]) { - IdentifierLookupTable - = PCHIdentifierLookupTable::Create( - (const unsigned char *)IdentifierTableData + Record[0], - (const unsigned char *)IdentifierTableData, - PCHIdentifierLookupTrait(*this)); - if (PP) - PP->getIdentifierTable().setExternalIdentifierLookup(this); - } - break; - - case pch::IDENTIFIER_OFFSET: - if (!IdentifiersLoaded.empty()) { - Error("duplicate IDENTIFIER_OFFSET record in PCH file"); - return Failure; - } - IdentifierOffsets = (const uint32_t *)BlobStart; - IdentifiersLoaded.resize(Record[0]); - if (PP) - PP->getHeaderSearchInfo().SetExternalLookup(this); - break; - - case pch::EXTERNAL_DEFINITIONS: - if (!ExternalDefinitions.empty()) { - Error("duplicate EXTERNAL_DEFINITIONS record in PCH file"); - return Failure; - } - ExternalDefinitions.swap(Record); - break; - - case pch::SPECIAL_TYPES: - SpecialTypes.swap(Record); - break; - - case pch::STATISTICS: - TotalNumStatements = Record[0]; - TotalNumMacros = Record[1]; - TotalLexicalDeclContexts = Record[2]; - TotalVisibleDeclContexts = Record[3]; - break; - - case pch::TENTATIVE_DEFINITIONS: - if (!TentativeDefinitions.empty()) { - Error("duplicate TENTATIVE_DEFINITIONS record in PCH file"); - return Failure; - } - TentativeDefinitions.swap(Record); - break; - - case pch::UNUSED_STATIC_FUNCS: - if (!UnusedStaticFuncs.empty()) { - Error("duplicate UNUSED_STATIC_FUNCS record in PCH file"); - return Failure; - } - UnusedStaticFuncs.swap(Record); - break; - - case pch::LOCALLY_SCOPED_EXTERNAL_DECLS: - if (!LocallyScopedExternalDecls.empty()) { - Error("duplicate LOCALLY_SCOPED_EXTERNAL_DECLS record in PCH file"); - return Failure; - } - LocallyScopedExternalDecls.swap(Record); - break; - - case pch::SELECTOR_OFFSETS: - SelectorOffsets = (const uint32_t *)BlobStart; - TotalNumSelectors = Record[0]; - SelectorsLoaded.resize(TotalNumSelectors); - break; - - case pch::METHOD_POOL: - MethodPoolLookupTableData = (const unsigned char *)BlobStart; - if (Record[0]) - MethodPoolLookupTable - = PCHMethodPoolLookupTable::Create( - MethodPoolLookupTableData + Record[0], - MethodPoolLookupTableData, - PCHMethodPoolLookupTrait(*this)); - TotalSelectorsInMethodPool = Record[1]; - break; - - case pch::PP_COUNTER_VALUE: - if (!Record.empty() && Listener) - Listener->ReadCounter(Record[0]); - break; - - case pch::SOURCE_LOCATION_OFFSETS: - SLocOffsets = (const uint32_t *)BlobStart; - TotalNumSLocEntries = Record[0]; - SourceMgr.PreallocateSLocEntries(this, TotalNumSLocEntries, Record[1]); - break; - - case pch::SOURCE_LOCATION_PRELOADS: - for (unsigned I = 0, N = Record.size(); I != N; ++I) { - PCHReadResult Result = ReadSLocEntryRecord(Record[I]); - if (Result != Success) - return Result; - } - break; - - case pch::STAT_CACHE: { - PCHStatCache *MyStatCache = - new PCHStatCache((const unsigned char *)BlobStart + Record[0], - (const unsigned char *)BlobStart, - NumStatHits, NumStatMisses); - FileMgr.addStatCache(MyStatCache); - StatCache = MyStatCache; - break; - } - - case pch::EXT_VECTOR_DECLS: - if (!ExtVectorDecls.empty()) { - Error("duplicate EXT_VECTOR_DECLS record in PCH file"); - return Failure; - } - ExtVectorDecls.swap(Record); - break; - - case pch::VTABLE_USES: - if (!VTableUses.empty()) { - Error("duplicate VTABLE_USES record in PCH file"); - return Failure; - } - VTableUses.swap(Record); - break; - - case pch::DYNAMIC_CLASSES: - if (!DynamicClasses.empty()) { - Error("duplicate DYNAMIC_CLASSES record in PCH file"); - return Failure; - } - DynamicClasses.swap(Record); - break; - - case pch::ORIGINAL_FILE_NAME: - ActualOriginalFileName.assign(BlobStart, BlobLen); - OriginalFileName = ActualOriginalFileName; - MaybeAddSystemRootToFilename(OriginalFileName); - break; - - case pch::VERSION_CONTROL_BRANCH_REVISION: { - const std::string &CurBranch = getClangFullRepositoryVersion(); - llvm::StringRef PCHBranch(BlobStart, BlobLen); - if (llvm::StringRef(CurBranch) != PCHBranch) { - Diag(diag::warn_pch_different_branch) << PCHBranch << CurBranch; - return IgnorePCH; - } - break; - } - - case pch::MACRO_DEFINITION_OFFSETS: - MacroDefinitionOffsets = (const uint32_t *)BlobStart; - if (PP) { - if (!PP->getPreprocessingRecord()) - PP->createPreprocessingRecord(); - PP->getPreprocessingRecord()->SetExternalSource(*this, Record[0]); - } else { - NumPreallocatedPreprocessingEntities = Record[0]; - } - - MacroDefinitionsLoaded.resize(Record[1]); - break; - } - } - Error("premature end of bitstream in PCH file"); - return Failure; -} - -PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) { - // Set the PCH file name. - this->FileName = FileName; - - // Open the PCH file. - // - // FIXME: This shouldn't be here, we should just take a raw_ostream. - std::string ErrStr; - Buffer.reset(llvm::MemoryBuffer::getFileOrSTDIN(FileName, &ErrStr)); - if (!Buffer) { - Error(ErrStr.c_str()); - return IgnorePCH; - } - - // Initialize the stream - StreamFile.init((const unsigned char *)Buffer->getBufferStart(), - (const unsigned char *)Buffer->getBufferEnd()); - Stream.init(StreamFile); - - // Sniff for the signature. - if (Stream.Read(8) != 'C' || - Stream.Read(8) != 'P' || - Stream.Read(8) != 'C' || - Stream.Read(8) != 'H') { - Diag(diag::err_not_a_pch_file) << FileName; - return Failure; - } - - while (!Stream.AtEndOfStream()) { - unsigned Code = Stream.ReadCode(); - - if (Code != llvm::bitc::ENTER_SUBBLOCK) { - Error("invalid record at top-level of PCH file"); - return Failure; - } - - unsigned BlockID = Stream.ReadSubBlockID(); - - // We only know the PCH subblock ID. - switch (BlockID) { - case llvm::bitc::BLOCKINFO_BLOCK_ID: - if (Stream.ReadBlockInfoBlock()) { - Error("malformed BlockInfoBlock in PCH file"); - return Failure; - } - break; - case pch::PCH_BLOCK_ID: - switch (ReadPCHBlock()) { - case Success: - break; - - case Failure: - return Failure; - - case IgnorePCH: - // FIXME: We could consider reading through to the end of this - // PCH block, skipping subblocks, to see if there are other - // PCH blocks elsewhere. - - // Clear out any preallocated source location entries, so that - // the source manager does not try to resolve them later. - SourceMgr.ClearPreallocatedSLocEntries(); - - // Remove the stat cache. - if (StatCache) - FileMgr.removeStatCache((PCHStatCache*)StatCache); - - return IgnorePCH; - } - break; - default: - if (Stream.SkipBlock()) { - Error("malformed block record in PCH file"); - return Failure; - } - break; - } - } - - // Check the predefines buffer. - if (CheckPredefinesBuffers()) - return IgnorePCH; - - if (PP) { - // Initialization of keywords and pragmas occurs before the - // PCH file is read, so there may be some identifiers that were - // loaded into the IdentifierTable before we intercepted the - // creation of identifiers. Iterate through the list of known - // identifiers and determine whether we have to establish - // preprocessor definitions or top-level identifier declaration - // chains for those identifiers. - // - // We copy the IdentifierInfo pointers to a small vector first, - // since de-serializing declarations or macro definitions can add - // new entries into the identifier table, invalidating the - // iterators. - llvm::SmallVector<IdentifierInfo *, 128> Identifiers; - for (IdentifierTable::iterator Id = PP->getIdentifierTable().begin(), - IdEnd = PP->getIdentifierTable().end(); - Id != IdEnd; ++Id) - Identifiers.push_back(Id->second); - PCHIdentifierLookupTable *IdTable - = (PCHIdentifierLookupTable *)IdentifierLookupTable; - for (unsigned I = 0, N = Identifiers.size(); I != N; ++I) { - IdentifierInfo *II = Identifiers[I]; - // Look in the on-disk hash table for an entry for - PCHIdentifierLookupTrait Info(*this, II); - std::pair<const char*, unsigned> Key(II->getNameStart(), II->getLength()); - PCHIdentifierLookupTable::iterator Pos = IdTable->find(Key, &Info); - if (Pos == IdTable->end()) - continue; - - // Dereferencing the iterator has the effect of populating the - // IdentifierInfo node with the various declarations it needs. - (void)*Pos; - } - } - - if (Context) - InitializeContext(*Context); - - return Success; -} - -void PCHReader::setPreprocessor(Preprocessor &pp) { - PP = &pp; - - if (NumPreallocatedPreprocessingEntities) { - if (!PP->getPreprocessingRecord()) - PP->createPreprocessingRecord(); - PP->getPreprocessingRecord()->SetExternalSource(*this, - NumPreallocatedPreprocessingEntities); - NumPreallocatedPreprocessingEntities = 0; - } -} - -void PCHReader::InitializeContext(ASTContext &Ctx) { - Context = &Ctx; - assert(Context && "Passed null context!"); - - assert(PP && "Forgot to set Preprocessor ?"); - PP->getIdentifierTable().setExternalIdentifierLookup(this); - PP->getHeaderSearchInfo().SetExternalLookup(this); - PP->setExternalSource(this); - - // Load the translation unit declaration - GetTranslationUnitDecl(); - - // Load the special types. - Context->setBuiltinVaListType( - GetType(SpecialTypes[pch::SPECIAL_TYPE_BUILTIN_VA_LIST])); - if (unsigned Id = SpecialTypes[pch::SPECIAL_TYPE_OBJC_ID]) - Context->setObjCIdType(GetType(Id)); - if (unsigned Sel = SpecialTypes[pch::SPECIAL_TYPE_OBJC_SELECTOR]) - Context->setObjCSelType(GetType(Sel)); - if (unsigned Proto = SpecialTypes[pch::SPECIAL_TYPE_OBJC_PROTOCOL]) - Context->setObjCProtoType(GetType(Proto)); - if (unsigned Class = SpecialTypes[pch::SPECIAL_TYPE_OBJC_CLASS]) - Context->setObjCClassType(GetType(Class)); - - if (unsigned String = SpecialTypes[pch::SPECIAL_TYPE_CF_CONSTANT_STRING]) - Context->setCFConstantStringType(GetType(String)); - if (unsigned FastEnum - = SpecialTypes[pch::SPECIAL_TYPE_OBJC_FAST_ENUMERATION_STATE]) - Context->setObjCFastEnumerationStateType(GetType(FastEnum)); - if (unsigned File = SpecialTypes[pch::SPECIAL_TYPE_FILE]) { - QualType FileType = GetType(File); - if (FileType.isNull()) { - Error("FILE type is NULL"); - return; - } - if (const TypedefType *Typedef = FileType->getAs<TypedefType>()) - Context->setFILEDecl(Typedef->getDecl()); - else { - const TagType *Tag = FileType->getAs<TagType>(); - if (!Tag) { - Error("Invalid FILE type in PCH file"); - return; - } - Context->setFILEDecl(Tag->getDecl()); - } - } - if (unsigned Jmp_buf = SpecialTypes[pch::SPECIAL_TYPE_jmp_buf]) { - QualType Jmp_bufType = GetType(Jmp_buf); - if (Jmp_bufType.isNull()) { - Error("jmp_bug type is NULL"); - return; - } - if (const TypedefType *Typedef = Jmp_bufType->getAs<TypedefType>()) - Context->setjmp_bufDecl(Typedef->getDecl()); - else { - const TagType *Tag = Jmp_bufType->getAs<TagType>(); - if (!Tag) { - Error("Invalid jmp_bug type in PCH file"); - return; - } - Context->setjmp_bufDecl(Tag->getDecl()); - } - } - if (unsigned Sigjmp_buf = SpecialTypes[pch::SPECIAL_TYPE_sigjmp_buf]) { - QualType Sigjmp_bufType = GetType(Sigjmp_buf); - if (Sigjmp_bufType.isNull()) { - Error("sigjmp_buf type is NULL"); - return; - } - if (const TypedefType *Typedef = Sigjmp_bufType->getAs<TypedefType>()) - Context->setsigjmp_bufDecl(Typedef->getDecl()); - else { - const TagType *Tag = Sigjmp_bufType->getAs<TagType>(); - assert(Tag && "Invalid sigjmp_buf type in PCH file"); - Context->setsigjmp_bufDecl(Tag->getDecl()); - } - } - if (unsigned ObjCIdRedef - = SpecialTypes[pch::SPECIAL_TYPE_OBJC_ID_REDEFINITION]) - Context->ObjCIdRedefinitionType = GetType(ObjCIdRedef); - if (unsigned ObjCClassRedef - = SpecialTypes[pch::SPECIAL_TYPE_OBJC_CLASS_REDEFINITION]) - Context->ObjCClassRedefinitionType = GetType(ObjCClassRedef); - if (unsigned String = SpecialTypes[pch::SPECIAL_TYPE_BLOCK_DESCRIPTOR]) - Context->setBlockDescriptorType(GetType(String)); - if (unsigned String - = SpecialTypes[pch::SPECIAL_TYPE_BLOCK_EXTENDED_DESCRIPTOR]) - Context->setBlockDescriptorExtendedType(GetType(String)); - if (unsigned ObjCSelRedef - = SpecialTypes[pch::SPECIAL_TYPE_OBJC_SEL_REDEFINITION]) - Context->ObjCSelRedefinitionType = GetType(ObjCSelRedef); - if (unsigned String = SpecialTypes[pch::SPECIAL_TYPE_NS_CONSTANT_STRING]) - Context->setNSConstantStringType(GetType(String)); - - if (SpecialTypes[pch::SPECIAL_TYPE_INT128_INSTALLED]) - Context->setInt128Installed(); -} - -/// \brief Retrieve the name of the original source file name -/// directly from the PCH file, without actually loading the PCH -/// file. -std::string PCHReader::getOriginalSourceFile(const std::string &PCHFileName, - Diagnostic &Diags) { - // Open the PCH file. - std::string ErrStr; - llvm::OwningPtr<llvm::MemoryBuffer> Buffer; - Buffer.reset(llvm::MemoryBuffer::getFile(PCHFileName.c_str(), &ErrStr)); - if (!Buffer) { - Diags.Report(diag::err_fe_unable_to_read_pch_file) << ErrStr; - return std::string(); - } - - // Initialize the stream - llvm::BitstreamReader StreamFile; - llvm::BitstreamCursor Stream; - StreamFile.init((const unsigned char *)Buffer->getBufferStart(), - (const unsigned char *)Buffer->getBufferEnd()); - Stream.init(StreamFile); - - // Sniff for the signature. - if (Stream.Read(8) != 'C' || - Stream.Read(8) != 'P' || - Stream.Read(8) != 'C' || - Stream.Read(8) != 'H') { - Diags.Report(diag::err_fe_not_a_pch_file) << PCHFileName; - return std::string(); - } - - RecordData Record; - while (!Stream.AtEndOfStream()) { - unsigned Code = Stream.ReadCode(); - - if (Code == llvm::bitc::ENTER_SUBBLOCK) { - unsigned BlockID = Stream.ReadSubBlockID(); - - // We only know the PCH subblock ID. - switch (BlockID) { - case pch::PCH_BLOCK_ID: - if (Stream.EnterSubBlock(pch::PCH_BLOCK_ID)) { - Diags.Report(diag::err_fe_pch_malformed_block) << PCHFileName; - return std::string(); - } - break; - - default: - if (Stream.SkipBlock()) { - Diags.Report(diag::err_fe_pch_malformed_block) << PCHFileName; - return std::string(); - } - break; - } - continue; - } - - if (Code == llvm::bitc::END_BLOCK) { - if (Stream.ReadBlockEnd()) { - Diags.Report(diag::err_fe_pch_error_at_end_block) << PCHFileName; - return std::string(); - } - continue; - } - - if (Code == llvm::bitc::DEFINE_ABBREV) { - Stream.ReadAbbrevRecord(); - continue; - } - - Record.clear(); - const char *BlobStart = 0; - unsigned BlobLen = 0; - if (Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen) - == pch::ORIGINAL_FILE_NAME) - return std::string(BlobStart, BlobLen); - } - - return std::string(); -} - -/// \brief Parse the record that corresponds to a LangOptions data -/// structure. -/// -/// This routine compares the language options used to generate the -/// PCH file against the language options set for the current -/// compilation. For each option, we classify differences between the -/// two compiler states as either "benign" or "important". Benign -/// differences don't matter, and we accept them without complaint -/// (and without modifying the language options). Differences between -/// the states for important options cause the PCH file to be -/// unusable, so we emit a warning and return true to indicate that -/// there was an error. -/// -/// \returns true if the PCH file is unacceptable, false otherwise. -bool PCHReader::ParseLanguageOptions( - const llvm::SmallVectorImpl<uint64_t> &Record) { - if (Listener) { - LangOptions LangOpts; - - #define PARSE_LANGOPT(Option) \ - LangOpts.Option = Record[Idx]; \ - ++Idx - - unsigned Idx = 0; - PARSE_LANGOPT(Trigraphs); - PARSE_LANGOPT(BCPLComment); - PARSE_LANGOPT(DollarIdents); - PARSE_LANGOPT(AsmPreprocessor); - PARSE_LANGOPT(GNUMode); - PARSE_LANGOPT(GNUKeywords); - PARSE_LANGOPT(ImplicitInt); - PARSE_LANGOPT(Digraphs); - PARSE_LANGOPT(HexFloats); - PARSE_LANGOPT(C99); - PARSE_LANGOPT(Microsoft); - PARSE_LANGOPT(CPlusPlus); - PARSE_LANGOPT(CPlusPlus0x); - PARSE_LANGOPT(CXXOperatorNames); - PARSE_LANGOPT(ObjC1); - PARSE_LANGOPT(ObjC2); - PARSE_LANGOPT(ObjCNonFragileABI); - PARSE_LANGOPT(ObjCNonFragileABI2); - PARSE_LANGOPT(NoConstantCFStrings); - PARSE_LANGOPT(PascalStrings); - PARSE_LANGOPT(WritableStrings); - PARSE_LANGOPT(LaxVectorConversions); - PARSE_LANGOPT(AltiVec); - PARSE_LANGOPT(Exceptions); - PARSE_LANGOPT(SjLjExceptions); - PARSE_LANGOPT(NeXTRuntime); - PARSE_LANGOPT(Freestanding); - PARSE_LANGOPT(NoBuiltin); - PARSE_LANGOPT(ThreadsafeStatics); - PARSE_LANGOPT(POSIXThreads); - PARSE_LANGOPT(Blocks); - PARSE_LANGOPT(EmitAllDecls); - PARSE_LANGOPT(MathErrno); - LangOpts.setSignedOverflowBehavior((LangOptions::SignedOverflowBehaviorTy) - Record[Idx++]); - PARSE_LANGOPT(HeinousExtensions); - PARSE_LANGOPT(Optimize); - PARSE_LANGOPT(OptimizeSize); - PARSE_LANGOPT(Static); - PARSE_LANGOPT(PICLevel); - PARSE_LANGOPT(GNUInline); - PARSE_LANGOPT(NoInline); - PARSE_LANGOPT(AccessControl); - PARSE_LANGOPT(CharIsSigned); - PARSE_LANGOPT(ShortWChar); - LangOpts.setGCMode((LangOptions::GCMode)Record[Idx++]); - LangOpts.setVisibilityMode((LangOptions::VisibilityMode)Record[Idx++]); - LangOpts.setStackProtectorMode((LangOptions::StackProtectorMode) - Record[Idx++]); - PARSE_LANGOPT(InstantiationDepth); - PARSE_LANGOPT(OpenCL); - PARSE_LANGOPT(CatchUndefined); - // FIXME: Missing ElideConstructors?! - #undef PARSE_LANGOPT - - return Listener->ReadLanguageOptions(LangOpts); - } - - return false; -} - -void PCHReader::ReadPreprocessedEntities() { - ReadDefinedMacros(); -} - -/// \brief Read and return the type at the given offset. -/// -/// This routine actually reads the record corresponding to the type -/// at the given offset in the bitstream. It is a helper routine for -/// GetType, which deals with reading type IDs. -QualType PCHReader::ReadTypeRecord(uint64_t Offset) { - // Keep track of where we are in the stream, then jump back there - // after reading this type. - SavedStreamPosition SavedPosition(DeclsCursor); - - ReadingKindTracker ReadingKind(Read_Type, *this); - - // Note that we are loading a type record. - LoadingTypeOrDecl Loading(*this); - - DeclsCursor.JumpToBit(Offset); - RecordData Record; - unsigned Code = DeclsCursor.ReadCode(); - switch ((pch::TypeCode)DeclsCursor.ReadRecord(Code, Record)) { - case pch::TYPE_EXT_QUAL: { - if (Record.size() != 2) { - Error("Incorrect encoding of extended qualifier type"); - return QualType(); - } - QualType Base = GetType(Record[0]); - Qualifiers Quals = Qualifiers::fromOpaqueValue(Record[1]); - return Context->getQualifiedType(Base, Quals); - } - - case pch::TYPE_COMPLEX: { - if (Record.size() != 1) { - Error("Incorrect encoding of complex type"); - return QualType(); - } - QualType ElemType = GetType(Record[0]); - return Context->getComplexType(ElemType); - } - - case pch::TYPE_POINTER: { - if (Record.size() != 1) { - Error("Incorrect encoding of pointer type"); - return QualType(); - } - QualType PointeeType = GetType(Record[0]); - return Context->getPointerType(PointeeType); - } - - case pch::TYPE_BLOCK_POINTER: { - if (Record.size() != 1) { - Error("Incorrect encoding of block pointer type"); - return QualType(); - } - QualType PointeeType = GetType(Record[0]); - return Context->getBlockPointerType(PointeeType); - } - - case pch::TYPE_LVALUE_REFERENCE: { - if (Record.size() != 1) { - Error("Incorrect encoding of lvalue reference type"); - return QualType(); - } - QualType PointeeType = GetType(Record[0]); - return Context->getLValueReferenceType(PointeeType); - } - - case pch::TYPE_RVALUE_REFERENCE: { - if (Record.size() != 1) { - Error("Incorrect encoding of rvalue reference type"); - return QualType(); - } - QualType PointeeType = GetType(Record[0]); - return Context->getRValueReferenceType(PointeeType); - } - - case pch::TYPE_MEMBER_POINTER: { - if (Record.size() != 2) { - Error("Incorrect encoding of member pointer type"); - return QualType(); - } - QualType PointeeType = GetType(Record[0]); - QualType ClassType = GetType(Record[1]); - return Context->getMemberPointerType(PointeeType, ClassType.getTypePtr()); - } - - case pch::TYPE_CONSTANT_ARRAY: { - QualType ElementType = GetType(Record[0]); - ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1]; - unsigned IndexTypeQuals = Record[2]; - unsigned Idx = 3; - llvm::APInt Size = ReadAPInt(Record, Idx); - return Context->getConstantArrayType(ElementType, Size, - ASM, IndexTypeQuals); - } - - case pch::TYPE_INCOMPLETE_ARRAY: { - QualType ElementType = GetType(Record[0]); - ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1]; - unsigned IndexTypeQuals = Record[2]; - return Context->getIncompleteArrayType(ElementType, ASM, IndexTypeQuals); - } - - case pch::TYPE_VARIABLE_ARRAY: { - QualType ElementType = GetType(Record[0]); - ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1]; - unsigned IndexTypeQuals = Record[2]; - SourceLocation LBLoc = SourceLocation::getFromRawEncoding(Record[3]); - SourceLocation RBLoc = SourceLocation::getFromRawEncoding(Record[4]); - return Context->getVariableArrayType(ElementType, ReadExpr(), - ASM, IndexTypeQuals, - SourceRange(LBLoc, RBLoc)); - } - - case pch::TYPE_VECTOR: { - if (Record.size() != 3) { - Error("incorrect encoding of vector type in PCH file"); - return QualType(); - } - - QualType ElementType = GetType(Record[0]); - unsigned NumElements = Record[1]; - unsigned AltiVecSpec = Record[2]; - return Context->getVectorType(ElementType, NumElements, - (VectorType::AltiVecSpecific)AltiVecSpec); - } - - case pch::TYPE_EXT_VECTOR: { - if (Record.size() != 3) { - Error("incorrect encoding of extended vector type in PCH file"); - return QualType(); - } - - QualType ElementType = GetType(Record[0]); - unsigned NumElements = Record[1]; - return Context->getExtVectorType(ElementType, NumElements); - } - - case pch::TYPE_FUNCTION_NO_PROTO: { - if (Record.size() != 4) { - Error("incorrect encoding of no-proto function type"); - return QualType(); - } - QualType ResultType = GetType(Record[0]); - FunctionType::ExtInfo Info(Record[1], Record[2], (CallingConv)Record[3]); - return Context->getFunctionNoProtoType(ResultType, Info); - } - - case pch::TYPE_FUNCTION_PROTO: { - QualType ResultType = GetType(Record[0]); - bool NoReturn = Record[1]; - unsigned RegParm = Record[2]; - CallingConv CallConv = (CallingConv)Record[3]; - unsigned Idx = 4; - unsigned NumParams = Record[Idx++]; - llvm::SmallVector<QualType, 16> ParamTypes; - for (unsigned I = 0; I != NumParams; ++I) - ParamTypes.push_back(GetType(Record[Idx++])); - bool isVariadic = Record[Idx++]; - unsigned Quals = Record[Idx++]; - bool hasExceptionSpec = Record[Idx++]; - bool hasAnyExceptionSpec = Record[Idx++]; - unsigned NumExceptions = Record[Idx++]; - llvm::SmallVector<QualType, 2> Exceptions; - for (unsigned I = 0; I != NumExceptions; ++I) - Exceptions.push_back(GetType(Record[Idx++])); - return Context->getFunctionType(ResultType, ParamTypes.data(), NumParams, - isVariadic, Quals, hasExceptionSpec, - hasAnyExceptionSpec, NumExceptions, - Exceptions.data(), - FunctionType::ExtInfo(NoReturn, RegParm, - CallConv)); - } - - case pch::TYPE_UNRESOLVED_USING: - return Context->getTypeDeclType( - cast<UnresolvedUsingTypenameDecl>(GetDecl(Record[0]))); - - case pch::TYPE_TYPEDEF: { - if (Record.size() != 2) { - Error("incorrect encoding of typedef type"); - return QualType(); - } - TypedefDecl *Decl = cast<TypedefDecl>(GetDecl(Record[0])); - QualType Canonical = GetType(Record[1]); - return Context->getTypedefType(Decl, Canonical); - } - - case pch::TYPE_TYPEOF_EXPR: - return Context->getTypeOfExprType(ReadExpr()); - - case pch::TYPE_TYPEOF: { - if (Record.size() != 1) { - Error("incorrect encoding of typeof(type) in PCH file"); - return QualType(); - } - QualType UnderlyingType = GetType(Record[0]); - return Context->getTypeOfType(UnderlyingType); - } - - case pch::TYPE_DECLTYPE: - return Context->getDecltypeType(ReadExpr()); - - case pch::TYPE_RECORD: { - if (Record.size() != 2) { - Error("incorrect encoding of record type"); - return QualType(); - } - bool IsDependent = Record[0]; - QualType T = Context->getRecordType(cast<RecordDecl>(GetDecl(Record[1]))); - T->Dependent = IsDependent; - return T; - } - - case pch::TYPE_ENUM: { - if (Record.size() != 2) { - Error("incorrect encoding of enum type"); - return QualType(); - } - bool IsDependent = Record[0]; - QualType T = Context->getEnumType(cast<EnumDecl>(GetDecl(Record[1]))); - T->Dependent = IsDependent; - return T; - } - - case pch::TYPE_ELABORATED: { - unsigned Idx = 0; - ElaboratedTypeKeyword Keyword = (ElaboratedTypeKeyword)Record[Idx++]; - NestedNameSpecifier *NNS = ReadNestedNameSpecifier(Record, Idx); - QualType NamedType = GetType(Record[Idx++]); - return Context->getElaboratedType(Keyword, NNS, NamedType); - } - - case pch::TYPE_OBJC_INTERFACE: { - unsigned Idx = 0; - ObjCInterfaceDecl *ItfD = cast<ObjCInterfaceDecl>(GetDecl(Record[Idx++])); - return Context->getObjCInterfaceType(ItfD); - } - - case pch::TYPE_OBJC_OBJECT: { - unsigned Idx = 0; - QualType Base = GetType(Record[Idx++]); - unsigned NumProtos = Record[Idx++]; - llvm::SmallVector<ObjCProtocolDecl*, 4> Protos; - for (unsigned I = 0; I != NumProtos; ++I) - Protos.push_back(cast<ObjCProtocolDecl>(GetDecl(Record[Idx++]))); - return Context->getObjCObjectType(Base, Protos.data(), NumProtos); - } - - case pch::TYPE_OBJC_OBJECT_POINTER: { - unsigned Idx = 0; - QualType Pointee = GetType(Record[Idx++]); - return Context->getObjCObjectPointerType(Pointee); - } - - case pch::TYPE_SUBST_TEMPLATE_TYPE_PARM: { - unsigned Idx = 0; - QualType Parm = GetType(Record[Idx++]); - QualType Replacement = GetType(Record[Idx++]); - return - Context->getSubstTemplateTypeParmType(cast<TemplateTypeParmType>(Parm), - Replacement); - } - - case pch::TYPE_INJECTED_CLASS_NAME: { - CXXRecordDecl *D = cast<CXXRecordDecl>(GetDecl(Record[0])); - QualType TST = GetType(Record[1]); // probably derivable - // FIXME: ASTContext::getInjectedClassNameType is not currently suitable - // for PCH reading, too much interdependencies. - return - QualType(new (*Context, TypeAlignment) InjectedClassNameType(D, TST), 0); - } - - case pch::TYPE_TEMPLATE_TYPE_PARM: { - unsigned Idx = 0; - unsigned Depth = Record[Idx++]; - unsigned Index = Record[Idx++]; - bool Pack = Record[Idx++]; - IdentifierInfo *Name = GetIdentifierInfo(Record, Idx); - return Context->getTemplateTypeParmType(Depth, Index, Pack, Name); - } - - case pch::TYPE_DEPENDENT_NAME: { - unsigned Idx = 0; - ElaboratedTypeKeyword Keyword = (ElaboratedTypeKeyword)Record[Idx++]; - NestedNameSpecifier *NNS = ReadNestedNameSpecifier(Record, Idx); - const IdentifierInfo *Name = this->GetIdentifierInfo(Record, Idx); - QualType Canon = GetType(Record[Idx++]); - return Context->getDependentNameType(Keyword, NNS, Name, Canon); - } - - case pch::TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION: { - unsigned Idx = 0; - ElaboratedTypeKeyword Keyword = (ElaboratedTypeKeyword)Record[Idx++]; - NestedNameSpecifier *NNS = ReadNestedNameSpecifier(Record, Idx); - const IdentifierInfo *Name = this->GetIdentifierInfo(Record, Idx); - unsigned NumArgs = Record[Idx++]; - llvm::SmallVector<TemplateArgument, 8> Args; - Args.reserve(NumArgs); - while (NumArgs--) - Args.push_back(ReadTemplateArgument(Record, Idx)); - return Context->getDependentTemplateSpecializationType(Keyword, NNS, Name, - Args.size(), Args.data()); - } - - case pch::TYPE_DEPENDENT_SIZED_ARRAY: { - unsigned Idx = 0; - - // ArrayType - QualType ElementType = GetType(Record[Idx++]); - ArrayType::ArraySizeModifier ASM - = (ArrayType::ArraySizeModifier)Record[Idx++]; - unsigned IndexTypeQuals = Record[Idx++]; - - // DependentSizedArrayType - Expr *NumElts = ReadExpr(); - SourceRange Brackets = ReadSourceRange(Record, Idx); - - return Context->getDependentSizedArrayType(ElementType, NumElts, ASM, - IndexTypeQuals, Brackets); - } - - case pch::TYPE_TEMPLATE_SPECIALIZATION: { - unsigned Idx = 0; - bool IsDependent = Record[Idx++]; - TemplateName Name = ReadTemplateName(Record, Idx); - llvm::SmallVector<TemplateArgument, 8> Args; - ReadTemplateArgumentList(Args, Record, Idx); - QualType Canon = GetType(Record[Idx++]); - QualType T; - if (Canon.isNull()) - T = Context->getCanonicalTemplateSpecializationType(Name, Args.data(), - Args.size()); - else - T = Context->getTemplateSpecializationType(Name, Args.data(), - Args.size(), Canon); - T->Dependent = IsDependent; - return T; - } - } - // Suppress a GCC warning - return QualType(); -} - -namespace { - -class TypeLocReader : public TypeLocVisitor<TypeLocReader> { - PCHReader &Reader; - const PCHReader::RecordData &Record; - unsigned &Idx; - -public: - TypeLocReader(PCHReader &Reader, const PCHReader::RecordData &Record, - unsigned &Idx) - : Reader(Reader), Record(Record), Idx(Idx) { } - - // We want compile-time assurance that we've enumerated all of - // these, so unfortunately we have to declare them first, then - // define them out-of-line. -#define ABSTRACT_TYPELOC(CLASS, PARENT) -#define TYPELOC(CLASS, PARENT) \ - void Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc); -#include "clang/AST/TypeLocNodes.def" - - void VisitFunctionTypeLoc(FunctionTypeLoc); - void VisitArrayTypeLoc(ArrayTypeLoc); -}; - -} - -void TypeLocReader::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) { - // nothing to do -} -void TypeLocReader::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) { - TL.setBuiltinLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - if (TL.needsExtraLocalData()) { - TL.setWrittenTypeSpec(static_cast<DeclSpec::TST>(Record[Idx++])); - TL.setWrittenSignSpec(static_cast<DeclSpec::TSS>(Record[Idx++])); - TL.setWrittenWidthSpec(static_cast<DeclSpec::TSW>(Record[Idx++])); - TL.setModeAttr(Record[Idx++]); - } -} -void TypeLocReader::VisitComplexTypeLoc(ComplexTypeLoc TL) { - TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitPointerTypeLoc(PointerTypeLoc TL) { - TL.setStarLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) { - TL.setCaretLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) { - TL.setAmpLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) { - TL.setAmpAmpLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) { - TL.setStarLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitArrayTypeLoc(ArrayTypeLoc TL) { - TL.setLBracketLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - TL.setRBracketLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - if (Record[Idx++]) - TL.setSizeExpr(Reader.ReadExpr()); - else - TL.setSizeExpr(0); -} -void TypeLocReader::VisitConstantArrayTypeLoc(ConstantArrayTypeLoc TL) { - VisitArrayTypeLoc(TL); -} -void TypeLocReader::VisitIncompleteArrayTypeLoc(IncompleteArrayTypeLoc TL) { - VisitArrayTypeLoc(TL); -} -void TypeLocReader::VisitVariableArrayTypeLoc(VariableArrayTypeLoc TL) { - VisitArrayTypeLoc(TL); -} -void TypeLocReader::VisitDependentSizedArrayTypeLoc( - DependentSizedArrayTypeLoc TL) { - VisitArrayTypeLoc(TL); -} -void TypeLocReader::VisitDependentSizedExtVectorTypeLoc( - DependentSizedExtVectorTypeLoc TL) { - TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitVectorTypeLoc(VectorTypeLoc TL) { - TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) { - TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitFunctionTypeLoc(FunctionTypeLoc TL) { - TL.setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - TL.setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) { - TL.setArg(i, cast_or_null<ParmVarDecl>(Reader.GetDecl(Record[Idx++]))); - } -} -void TypeLocReader::VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc TL) { - VisitFunctionTypeLoc(TL); -} -void TypeLocReader::VisitFunctionNoProtoTypeLoc(FunctionNoProtoTypeLoc TL) { - VisitFunctionTypeLoc(TL); -} -void TypeLocReader::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) { - TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitTypedefTypeLoc(TypedefTypeLoc TL) { - TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) { - TL.setTypeofLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - TL.setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - TL.setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) { - TL.setTypeofLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - TL.setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - TL.setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - TL.setUnderlyingTInfo(Reader.GetTypeSourceInfo(Record, Idx)); -} -void TypeLocReader::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) { - TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitRecordTypeLoc(RecordTypeLoc TL) { - TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitEnumTypeLoc(EnumTypeLoc TL) { - TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) { - TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitSubstTemplateTypeParmTypeLoc( - SubstTemplateTypeParmTypeLoc TL) { - TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitTemplateSpecializationTypeLoc( - TemplateSpecializationTypeLoc TL) { - TL.setTemplateNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - TL.setLAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - TL.setRAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) - TL.setArgLocInfo(i, - Reader.GetTemplateArgumentLocInfo(TL.getTypePtr()->getArg(i).getKind(), - Record, Idx)); -} -void TypeLocReader::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) { - TL.setKeywordLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - TL.setQualifierRange(Reader.ReadSourceRange(Record, Idx)); -} -void TypeLocReader::VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) { - TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) { - TL.setKeywordLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - TL.setQualifierRange(Reader.ReadSourceRange(Record, Idx)); - TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitDependentTemplateSpecializationTypeLoc( - DependentTemplateSpecializationTypeLoc TL) { - TL.setKeywordLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - TL.setQualifierRange(Reader.ReadSourceRange(Record, Idx)); - TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - TL.setLAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - TL.setRAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) - TL.setArgLocInfo(I, - Reader.GetTemplateArgumentLocInfo(TL.getTypePtr()->getArg(I).getKind(), - Record, Idx)); -} -void TypeLocReader::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) { - TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) { - TL.setHasBaseTypeAsWritten(Record[Idx++]); - TL.setLAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - TL.setRAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i) - TL.setProtocolLoc(i, SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) { - TL.setStarLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -TypeSourceInfo *PCHReader::GetTypeSourceInfo(const RecordData &Record, - unsigned &Idx) { - QualType InfoTy = GetType(Record[Idx++]); - if (InfoTy.isNull()) - return 0; - - TypeSourceInfo *TInfo = getContext()->CreateTypeSourceInfo(InfoTy); - TypeLocReader TLR(*this, Record, Idx); - for (TypeLoc TL = TInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc()) - TLR.Visit(TL); - return TInfo; -} - -QualType PCHReader::GetType(pch::TypeID ID) { - unsigned FastQuals = ID & Qualifiers::FastMask; - unsigned Index = ID >> Qualifiers::FastWidth; - - if (Index < pch::NUM_PREDEF_TYPE_IDS) { - QualType T; - switch ((pch::PredefinedTypeIDs)Index) { - case pch::PREDEF_TYPE_NULL_ID: return QualType(); - case pch::PREDEF_TYPE_VOID_ID: T = Context->VoidTy; break; - case pch::PREDEF_TYPE_BOOL_ID: T = Context->BoolTy; break; - - case pch::PREDEF_TYPE_CHAR_U_ID: - case pch::PREDEF_TYPE_CHAR_S_ID: - // FIXME: Check that the signedness of CharTy is correct! - T = Context->CharTy; - break; - - case pch::PREDEF_TYPE_UCHAR_ID: T = Context->UnsignedCharTy; break; - case pch::PREDEF_TYPE_USHORT_ID: T = Context->UnsignedShortTy; break; - case pch::PREDEF_TYPE_UINT_ID: T = Context->UnsignedIntTy; break; - case pch::PREDEF_TYPE_ULONG_ID: T = Context->UnsignedLongTy; break; - case pch::PREDEF_TYPE_ULONGLONG_ID: T = Context->UnsignedLongLongTy; break; - case pch::PREDEF_TYPE_UINT128_ID: T = Context->UnsignedInt128Ty; break; - case pch::PREDEF_TYPE_SCHAR_ID: T = Context->SignedCharTy; break; - case pch::PREDEF_TYPE_WCHAR_ID: T = Context->WCharTy; break; - case pch::PREDEF_TYPE_SHORT_ID: T = Context->ShortTy; break; - case pch::PREDEF_TYPE_INT_ID: T = Context->IntTy; break; - case pch::PREDEF_TYPE_LONG_ID: T = Context->LongTy; break; - case pch::PREDEF_TYPE_LONGLONG_ID: T = Context->LongLongTy; break; - case pch::PREDEF_TYPE_INT128_ID: T = Context->Int128Ty; break; - case pch::PREDEF_TYPE_FLOAT_ID: T = Context->FloatTy; break; - case pch::PREDEF_TYPE_DOUBLE_ID: T = Context->DoubleTy; break; - case pch::PREDEF_TYPE_LONGDOUBLE_ID: T = Context->LongDoubleTy; break; - case pch::PREDEF_TYPE_OVERLOAD_ID: T = Context->OverloadTy; break; - case pch::PREDEF_TYPE_DEPENDENT_ID: T = Context->DependentTy; break; - case pch::PREDEF_TYPE_NULLPTR_ID: T = Context->NullPtrTy; break; - case pch::PREDEF_TYPE_CHAR16_ID: T = Context->Char16Ty; break; - case pch::PREDEF_TYPE_CHAR32_ID: T = Context->Char32Ty; break; - case pch::PREDEF_TYPE_OBJC_ID: T = Context->ObjCBuiltinIdTy; break; - case pch::PREDEF_TYPE_OBJC_CLASS: T = Context->ObjCBuiltinClassTy; break; - case pch::PREDEF_TYPE_OBJC_SEL: T = Context->ObjCBuiltinSelTy; break; - } - - assert(!T.isNull() && "Unknown predefined type"); - return T.withFastQualifiers(FastQuals); - } - - Index -= pch::NUM_PREDEF_TYPE_IDS; - //assert(Index < TypesLoaded.size() && "Type index out-of-range"); - if (TypesLoaded[Index].isNull()) { - TypesLoaded[Index] = ReadTypeRecord(TypeOffsets[Index]); - TypesLoaded[Index]->setFromPCH(); - if (DeserializationListener) - DeserializationListener->TypeRead(ID, TypesLoaded[Index]); - } - - return TypesLoaded[Index].withFastQualifiers(FastQuals); -} - -TemplateArgumentLocInfo -PCHReader::GetTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind, - const RecordData &Record, - unsigned &Index) { - switch (Kind) { - case TemplateArgument::Expression: - return ReadExpr(); - case TemplateArgument::Type: - return GetTypeSourceInfo(Record, Index); - case TemplateArgument::Template: { - SourceRange QualifierRange = ReadSourceRange(Record, Index); - SourceLocation TemplateNameLoc = ReadSourceLocation(Record, Index); - return TemplateArgumentLocInfo(QualifierRange, TemplateNameLoc); - } - case TemplateArgument::Null: - case TemplateArgument::Integral: - case TemplateArgument::Declaration: - case TemplateArgument::Pack: - return TemplateArgumentLocInfo(); - } - llvm_unreachable("unexpected template argument loc"); - return TemplateArgumentLocInfo(); -} - -TemplateArgumentLoc -PCHReader::ReadTemplateArgumentLoc(const RecordData &Record, unsigned &Index) { - TemplateArgument Arg = ReadTemplateArgument(Record, Index); - - if (Arg.getKind() == TemplateArgument::Expression) { - if (Record[Index++]) // bool InfoHasSameExpr. - return TemplateArgumentLoc(Arg, TemplateArgumentLocInfo(Arg.getAsExpr())); - } - return TemplateArgumentLoc(Arg, GetTemplateArgumentLocInfo(Arg.getKind(), - Record, Index)); -} - -Decl *PCHReader::GetExternalDecl(uint32_t ID) { - return GetDecl(ID); -} - -TranslationUnitDecl *PCHReader::GetTranslationUnitDecl() { - if (!DeclsLoaded[0]) { - ReadDeclRecord(DeclOffsets[0], 0); - if (DeserializationListener) - DeserializationListener->DeclRead(0, DeclsLoaded[0]); - } - - return cast<TranslationUnitDecl>(DeclsLoaded[0]); -} - -Decl *PCHReader::GetDecl(pch::DeclID ID) { - if (ID == 0) - return 0; - - if (ID > DeclsLoaded.size()) { - Error("declaration ID out-of-range for PCH file"); - return 0; - } - - unsigned Index = ID - 1; - if (!DeclsLoaded[Index]) { - ReadDeclRecord(DeclOffsets[Index], Index); - if (DeserializationListener) - DeserializationListener->DeclRead(ID, DeclsLoaded[Index]); - } - - return DeclsLoaded[Index]; -} - -/// \brief Resolve the offset of a statement into a statement. -/// -/// This operation will read a new statement from the external -/// source each time it is called, and is meant to be used via a -/// LazyOffsetPtr (which is used by Decls for the body of functions, etc). -Stmt *PCHReader::GetExternalDeclStmt(uint64_t Offset) { - // Since we know tha this statement is part of a decl, make sure to use the - // decl cursor to read it. - DeclsCursor.JumpToBit(Offset); - return ReadStmtFromStream(DeclsCursor); -} - -bool PCHReader::FindExternalLexicalDecls(const DeclContext *DC, - llvm::SmallVectorImpl<Decl*> &Decls) { - assert(DC->hasExternalLexicalStorage() && - "DeclContext has no lexical decls in storage"); - - uint64_t Offset = DeclContextOffsets[DC].first; - if (Offset == 0) { - Error("DeclContext has no lexical decls in storage"); - return true; - } - - // Keep track of where we are in the stream, then jump back there - // after reading this context. - SavedStreamPosition SavedPosition(DeclsCursor); - - // Load the record containing all of the declarations lexically in - // this context. - DeclsCursor.JumpToBit(Offset); - RecordData Record; - unsigned Code = DeclsCursor.ReadCode(); - unsigned RecCode = DeclsCursor.ReadRecord(Code, Record); - if (RecCode != pch::DECL_CONTEXT_LEXICAL) { - Error("Expected lexical block"); - return true; - } - - // Load all of the declaration IDs - for (RecordData::iterator I = Record.begin(), E = Record.end(); I != E; ++I) - Decls.push_back(GetDecl(*I)); - ++NumLexicalDeclContextsRead; - return false; -} - -DeclContext::lookup_result -PCHReader::FindExternalVisibleDeclsByName(const DeclContext *DC, - DeclarationName Name) { - assert(DC->hasExternalVisibleStorage() && - "DeclContext has no visible decls in storage"); - uint64_t Offset = DeclContextOffsets[DC].second; - if (Offset == 0) { - Error("DeclContext has no visible decls in storage"); - return DeclContext::lookup_result(DeclContext::lookup_iterator(), - DeclContext::lookup_iterator()); - } - - // Keep track of where we are in the stream, then jump back there - // after reading this context. - SavedStreamPosition SavedPosition(DeclsCursor); - - // Load the record containing all of the declarations visible in - // this context. - DeclsCursor.JumpToBit(Offset); - RecordData Record; - unsigned Code = DeclsCursor.ReadCode(); - unsigned RecCode = DeclsCursor.ReadRecord(Code, Record); - if (RecCode != pch::DECL_CONTEXT_VISIBLE) { - Error("Expected visible block"); - return DeclContext::lookup_result(DeclContext::lookup_iterator(), - DeclContext::lookup_iterator()); - } - - llvm::SmallVector<VisibleDeclaration, 64> Decls; - if (Record.empty()) { - SetExternalVisibleDecls(DC, Decls); - return DeclContext::lookup_result(DeclContext::lookup_iterator(), - DeclContext::lookup_iterator()); - } - - unsigned Idx = 0; - while (Idx < Record.size()) { - Decls.push_back(VisibleDeclaration()); - Decls.back().Name = ReadDeclarationName(Record, Idx); - - unsigned Size = Record[Idx++]; - llvm::SmallVector<unsigned, 4> &LoadedDecls = Decls.back().Declarations; - LoadedDecls.reserve(Size); - for (unsigned I = 0; I < Size; ++I) - LoadedDecls.push_back(Record[Idx++]); - } - - ++NumVisibleDeclContextsRead; - - SetExternalVisibleDecls(DC, Decls); - return const_cast<DeclContext*>(DC)->lookup(Name); -} - -void PCHReader::PassInterestingDeclsToConsumer() { - assert(Consumer); - while (!InterestingDecls.empty()) { - DeclGroupRef DG(InterestingDecls.front()); - InterestingDecls.pop_front(); - Consumer->HandleTopLevelDecl(DG); - } -} - -void PCHReader::StartTranslationUnit(ASTConsumer *Consumer) { - this->Consumer = Consumer; - - if (!Consumer) - return; - - for (unsigned I = 0, N = ExternalDefinitions.size(); I != N; ++I) { - // Force deserialization of this decl, which will cause it to be queued for - // passing to the consumer. - GetDecl(ExternalDefinitions[I]); - } - - PassInterestingDeclsToConsumer(); -} - -void PCHReader::PrintStats() { - std::fprintf(stderr, "*** PCH Statistics:\n"); - - unsigned NumTypesLoaded - = TypesLoaded.size() - std::count(TypesLoaded.begin(), TypesLoaded.end(), - QualType()); - unsigned NumDeclsLoaded - = DeclsLoaded.size() - std::count(DeclsLoaded.begin(), DeclsLoaded.end(), - (Decl *)0); - unsigned NumIdentifiersLoaded - = IdentifiersLoaded.size() - std::count(IdentifiersLoaded.begin(), - IdentifiersLoaded.end(), - (IdentifierInfo *)0); - unsigned NumSelectorsLoaded - = SelectorsLoaded.size() - std::count(SelectorsLoaded.begin(), - SelectorsLoaded.end(), - Selector()); - - std::fprintf(stderr, " %u stat cache hits\n", NumStatHits); - std::fprintf(stderr, " %u stat cache misses\n", NumStatMisses); - if (TotalNumSLocEntries) - std::fprintf(stderr, " %u/%u source location entries read (%f%%)\n", - NumSLocEntriesRead, TotalNumSLocEntries, - ((float)NumSLocEntriesRead/TotalNumSLocEntries * 100)); - if (!TypesLoaded.empty()) - std::fprintf(stderr, " %u/%u types read (%f%%)\n", - NumTypesLoaded, (unsigned)TypesLoaded.size(), - ((float)NumTypesLoaded/TypesLoaded.size() * 100)); - if (!DeclsLoaded.empty()) - std::fprintf(stderr, " %u/%u declarations read (%f%%)\n", - NumDeclsLoaded, (unsigned)DeclsLoaded.size(), - ((float)NumDeclsLoaded/DeclsLoaded.size() * 100)); - if (!IdentifiersLoaded.empty()) - std::fprintf(stderr, " %u/%u identifiers read (%f%%)\n", - NumIdentifiersLoaded, (unsigned)IdentifiersLoaded.size(), - ((float)NumIdentifiersLoaded/IdentifiersLoaded.size() * 100)); - if (TotalNumSelectors) - std::fprintf(stderr, " %u/%u selectors read (%f%%)\n", - NumSelectorsLoaded, TotalNumSelectors, - ((float)NumSelectorsLoaded/TotalNumSelectors * 100)); - if (TotalNumStatements) - std::fprintf(stderr, " %u/%u statements read (%f%%)\n", - NumStatementsRead, TotalNumStatements, - ((float)NumStatementsRead/TotalNumStatements * 100)); - if (TotalNumMacros) - std::fprintf(stderr, " %u/%u macros read (%f%%)\n", - NumMacrosRead, TotalNumMacros, - ((float)NumMacrosRead/TotalNumMacros * 100)); - if (TotalLexicalDeclContexts) - std::fprintf(stderr, " %u/%u lexical declcontexts read (%f%%)\n", - NumLexicalDeclContextsRead, TotalLexicalDeclContexts, - ((float)NumLexicalDeclContextsRead/TotalLexicalDeclContexts - * 100)); - if (TotalVisibleDeclContexts) - std::fprintf(stderr, " %u/%u visible declcontexts read (%f%%)\n", - NumVisibleDeclContextsRead, TotalVisibleDeclContexts, - ((float)NumVisibleDeclContextsRead/TotalVisibleDeclContexts - * 100)); - if (TotalSelectorsInMethodPool) { - std::fprintf(stderr, " %u/%u method pool entries read (%f%%)\n", - NumMethodPoolSelectorsRead, TotalSelectorsInMethodPool, - ((float)NumMethodPoolSelectorsRead/TotalSelectorsInMethodPool - * 100)); - std::fprintf(stderr, " %u method pool misses\n", NumMethodPoolMisses); - } - std::fprintf(stderr, "\n"); -} - -void PCHReader::InitializeSema(Sema &S) { - SemaObj = &S; - S.ExternalSource = this; - - // Makes sure any declarations that were deserialized "too early" - // still get added to the identifier's declaration chains. - for (unsigned I = 0, N = PreloadedDecls.size(); I != N; ++I) { - SemaObj->TUScope->AddDecl(Action::DeclPtrTy::make(PreloadedDecls[I])); - SemaObj->IdResolver.AddDecl(PreloadedDecls[I]); - } - PreloadedDecls.clear(); - - // If there were any tentative definitions, deserialize them and add - // them to Sema's list of tentative definitions. - for (unsigned I = 0, N = TentativeDefinitions.size(); I != N; ++I) { - VarDecl *Var = cast<VarDecl>(GetDecl(TentativeDefinitions[I])); - SemaObj->TentativeDefinitions.push_back(Var); - } - - // If there were any unused static functions, deserialize them and add to - // Sema's list of unused static functions. - for (unsigned I = 0, N = UnusedStaticFuncs.size(); I != N; ++I) { - FunctionDecl *FD = cast<FunctionDecl>(GetDecl(UnusedStaticFuncs[I])); - SemaObj->UnusedStaticFuncs.push_back(FD); - } - - // If there were any locally-scoped external declarations, - // deserialize them and add them to Sema's table of locally-scoped - // external declarations. - for (unsigned I = 0, N = LocallyScopedExternalDecls.size(); I != N; ++I) { - NamedDecl *D = cast<NamedDecl>(GetDecl(LocallyScopedExternalDecls[I])); - SemaObj->LocallyScopedExternalDecls[D->getDeclName()] = D; - } - - // If there were any ext_vector type declarations, deserialize them - // and add them to Sema's vector of such declarations. - for (unsigned I = 0, N = ExtVectorDecls.size(); I != N; ++I) - SemaObj->ExtVectorDecls.push_back( - cast<TypedefDecl>(GetDecl(ExtVectorDecls[I]))); - - // FIXME: Do VTable uses and dynamic classes deserialize too much ? - // Can we cut them down before writing them ? - - // If there were any VTable uses, deserialize the information and add it - // to Sema's vector and map of VTable uses. - unsigned Idx = 0; - for (unsigned I = 0, N = VTableUses[Idx++]; I != N; ++I) { - CXXRecordDecl *Class = cast<CXXRecordDecl>(GetDecl(VTableUses[Idx++])); - SourceLocation Loc = ReadSourceLocation(VTableUses, Idx); - bool DefinitionRequired = VTableUses[Idx++]; - SemaObj->VTableUses.push_back(std::make_pair(Class, Loc)); - SemaObj->VTablesUsed[Class] = DefinitionRequired; - } - - // If there were any dynamic classes declarations, deserialize them - // and add them to Sema's vector of such declarations. - for (unsigned I = 0, N = DynamicClasses.size(); I != N; ++I) - SemaObj->DynamicClasses.push_back( - cast<CXXRecordDecl>(GetDecl(DynamicClasses[I]))); -} - -IdentifierInfo* PCHReader::get(const char *NameStart, const char *NameEnd) { - // Try to find this name within our on-disk hash table - PCHIdentifierLookupTable *IdTable - = (PCHIdentifierLookupTable *)IdentifierLookupTable; - std::pair<const char*, unsigned> Key(NameStart, NameEnd - NameStart); - PCHIdentifierLookupTable::iterator Pos = IdTable->find(Key); - if (Pos == IdTable->end()) - return 0; - - // Dereferencing the iterator has the effect of building the - // IdentifierInfo node and populating it with the various - // declarations it needs. - return *Pos; -} - -std::pair<ObjCMethodList, ObjCMethodList> -PCHReader::ReadMethodPool(Selector Sel) { - if (!MethodPoolLookupTable) - return std::pair<ObjCMethodList, ObjCMethodList>(); - - // Try to find this selector within our on-disk hash table. - PCHMethodPoolLookupTable *PoolTable - = (PCHMethodPoolLookupTable*)MethodPoolLookupTable; - PCHMethodPoolLookupTable::iterator Pos = PoolTable->find(Sel); - if (Pos == PoolTable->end()) { - ++NumMethodPoolMisses; - return std::pair<ObjCMethodList, ObjCMethodList>();; - } - - ++NumMethodPoolSelectorsRead; - return *Pos; -} - -void PCHReader::SetIdentifierInfo(unsigned ID, IdentifierInfo *II) { - assert(ID && "Non-zero identifier ID required"); - assert(ID <= IdentifiersLoaded.size() && "identifier ID out of range"); - IdentifiersLoaded[ID - 1] = II; -} - -/// \brief Set the globally-visible declarations associated with the given -/// identifier. -/// -/// If the PCH reader is currently in a state where the given declaration IDs -/// cannot safely be resolved, they are queued until it is safe to resolve -/// them. -/// -/// \param II an IdentifierInfo that refers to one or more globally-visible -/// declarations. -/// -/// \param DeclIDs the set of declaration IDs with the name @p II that are -/// visible at global scope. -/// -/// \param Nonrecursive should be true to indicate that the caller knows that -/// this call is non-recursive, and therefore the globally-visible declarations -/// will not be placed onto the pending queue. -void -PCHReader::SetGloballyVisibleDecls(IdentifierInfo *II, - const llvm::SmallVectorImpl<uint32_t> &DeclIDs, - bool Nonrecursive) { - if (CurrentlyLoadingTypeOrDecl && !Nonrecursive) { - PendingIdentifierInfos.push_back(PendingIdentifierInfo()); - PendingIdentifierInfo &PII = PendingIdentifierInfos.back(); - PII.II = II; - for (unsigned I = 0, N = DeclIDs.size(); I != N; ++I) - PII.DeclIDs.push_back(DeclIDs[I]); - return; - } - - for (unsigned I = 0, N = DeclIDs.size(); I != N; ++I) { - NamedDecl *D = cast<NamedDecl>(GetDecl(DeclIDs[I])); - if (SemaObj) { - // Introduce this declaration into the translation-unit scope - // and add it to the declaration chain for this identifier, so - // that (unqualified) name lookup will find it. - SemaObj->TUScope->AddDecl(Action::DeclPtrTy::make(D)); - SemaObj->IdResolver.AddDeclToIdentifierChain(II, D); - } else { - // Queue this declaration so that it will be added to the - // translation unit scope and identifier's declaration chain - // once a Sema object is known. - PreloadedDecls.push_back(D); - } - } -} - -IdentifierInfo *PCHReader::DecodeIdentifierInfo(unsigned ID) { - if (ID == 0) - return 0; - - if (!IdentifierTableData || IdentifiersLoaded.empty()) { - Error("no identifier table in PCH file"); - return 0; - } - - assert(PP && "Forgot to set Preprocessor ?"); - if (!IdentifiersLoaded[ID - 1]) { - uint32_t Offset = IdentifierOffsets[ID - 1]; - const char *Str = IdentifierTableData + Offset; - - // All of the strings in the PCH file are preceded by a 16-bit - // length. Extract that 16-bit length to avoid having to execute - // strlen(). - // NOTE: 'StrLenPtr' is an 'unsigned char*' so that we load bytes as - // unsigned integers. This is important to avoid integer overflow when - // we cast them to 'unsigned'. - const unsigned char *StrLenPtr = (const unsigned char*) Str - 2; - unsigned StrLen = (((unsigned) StrLenPtr[0]) - | (((unsigned) StrLenPtr[1]) << 8)) - 1; - IdentifiersLoaded[ID - 1] - = &PP->getIdentifierTable().get(Str, StrLen); - } - - return IdentifiersLoaded[ID - 1]; -} - -void PCHReader::ReadSLocEntry(unsigned ID) { - ReadSLocEntryRecord(ID); -} - -Selector PCHReader::DecodeSelector(unsigned ID) { - if (ID == 0) - return Selector(); - - if (!MethodPoolLookupTableData) - return Selector(); - - if (ID > TotalNumSelectors) { - Error("selector ID out of range in PCH file"); - return Selector(); - } - - unsigned Index = ID - 1; - if (SelectorsLoaded[Index].getAsOpaquePtr() == 0) { - // Load this selector from the selector table. - // FIXME: endianness portability issues with SelectorOffsets table - PCHMethodPoolLookupTrait Trait(*this); - SelectorsLoaded[Index] - = Trait.ReadKey(MethodPoolLookupTableData + SelectorOffsets[Index], 0); - } - - return SelectorsLoaded[Index]; -} - -Selector PCHReader::GetExternalSelector(uint32_t ID) { - return DecodeSelector(ID); -} - -uint32_t PCHReader::GetNumExternalSelectors() { - return TotalNumSelectors + 1; -} - -DeclarationName -PCHReader::ReadDeclarationName(const RecordData &Record, unsigned &Idx) { - DeclarationName::NameKind Kind = (DeclarationName::NameKind)Record[Idx++]; - switch (Kind) { - case DeclarationName::Identifier: - return DeclarationName(GetIdentifierInfo(Record, Idx)); - - case DeclarationName::ObjCZeroArgSelector: - case DeclarationName::ObjCOneArgSelector: - case DeclarationName::ObjCMultiArgSelector: - return DeclarationName(GetSelector(Record, Idx)); - - case DeclarationName::CXXConstructorName: - return Context->DeclarationNames.getCXXConstructorName( - Context->getCanonicalType(GetType(Record[Idx++]))); - - case DeclarationName::CXXDestructorName: - return Context->DeclarationNames.getCXXDestructorName( - Context->getCanonicalType(GetType(Record[Idx++]))); - - case DeclarationName::CXXConversionFunctionName: - return Context->DeclarationNames.getCXXConversionFunctionName( - Context->getCanonicalType(GetType(Record[Idx++]))); - - case DeclarationName::CXXOperatorName: - return Context->DeclarationNames.getCXXOperatorName( - (OverloadedOperatorKind)Record[Idx++]); - - case DeclarationName::CXXLiteralOperatorName: - return Context->DeclarationNames.getCXXLiteralOperatorName( - GetIdentifierInfo(Record, Idx)); - - case DeclarationName::CXXUsingDirective: - return DeclarationName::getUsingDirectiveName(); - } - - // Required to silence GCC warning - return DeclarationName(); -} - -TemplateName -PCHReader::ReadTemplateName(const RecordData &Record, unsigned &Idx) { - TemplateName::NameKind Kind = (TemplateName::NameKind)Record[Idx++]; - switch (Kind) { - case TemplateName::Template: - return TemplateName(cast_or_null<TemplateDecl>(GetDecl(Record[Idx++]))); - - case TemplateName::OverloadedTemplate: { - unsigned size = Record[Idx++]; - UnresolvedSet<8> Decls; - while (size--) - Decls.addDecl(cast<NamedDecl>(GetDecl(Record[Idx++]))); - - return Context->getOverloadedTemplateName(Decls.begin(), Decls.end()); - } - - case TemplateName::QualifiedTemplate: { - NestedNameSpecifier *NNS = ReadNestedNameSpecifier(Record, Idx); - bool hasTemplKeyword = Record[Idx++]; - TemplateDecl *Template = cast<TemplateDecl>(GetDecl(Record[Idx++])); - return Context->getQualifiedTemplateName(NNS, hasTemplKeyword, Template); - } - - case TemplateName::DependentTemplate: { - NestedNameSpecifier *NNS = ReadNestedNameSpecifier(Record, Idx); - if (Record[Idx++]) // isIdentifier - return Context->getDependentTemplateName(NNS, - GetIdentifierInfo(Record, Idx)); - return Context->getDependentTemplateName(NNS, - (OverloadedOperatorKind)Record[Idx++]); - } - } - - assert(0 && "Unhandled template name kind!"); - return TemplateName(); -} - -TemplateArgument -PCHReader::ReadTemplateArgument(const RecordData &Record, unsigned &Idx) { - switch ((TemplateArgument::ArgKind)Record[Idx++]) { - case TemplateArgument::Null: - return TemplateArgument(); - case TemplateArgument::Type: - return TemplateArgument(GetType(Record[Idx++])); - case TemplateArgument::Declaration: - return TemplateArgument(GetDecl(Record[Idx++])); - case TemplateArgument::Integral: { - llvm::APSInt Value = ReadAPSInt(Record, Idx); - QualType T = GetType(Record[Idx++]); - return TemplateArgument(Value, T); - } - case TemplateArgument::Template: - return TemplateArgument(ReadTemplateName(Record, Idx)); - case TemplateArgument::Expression: - return TemplateArgument(ReadExpr()); - case TemplateArgument::Pack: { - unsigned NumArgs = Record[Idx++]; - llvm::SmallVector<TemplateArgument, 8> Args; - Args.reserve(NumArgs); - while (NumArgs--) - Args.push_back(ReadTemplateArgument(Record, Idx)); - TemplateArgument TemplArg; - TemplArg.setArgumentPack(Args.data(), Args.size(), /*CopyArgs=*/true); - return TemplArg; - } - } - - assert(0 && "Unhandled template argument kind!"); - return TemplateArgument(); -} - -TemplateParameterList * -PCHReader::ReadTemplateParameterList(const RecordData &Record, unsigned &Idx) { - SourceLocation TemplateLoc = ReadSourceLocation(Record, Idx); - SourceLocation LAngleLoc = ReadSourceLocation(Record, Idx); - SourceLocation RAngleLoc = ReadSourceLocation(Record, Idx); - - unsigned NumParams = Record[Idx++]; - llvm::SmallVector<NamedDecl *, 16> Params; - Params.reserve(NumParams); - while (NumParams--) - Params.push_back(cast<NamedDecl>(GetDecl(Record[Idx++]))); - - TemplateParameterList* TemplateParams = - TemplateParameterList::Create(*Context, TemplateLoc, LAngleLoc, - Params.data(), Params.size(), RAngleLoc); - return TemplateParams; -} - -void -PCHReader:: -ReadTemplateArgumentList(llvm::SmallVector<TemplateArgument, 8> &TemplArgs, - const RecordData &Record, unsigned &Idx) { - unsigned NumTemplateArgs = Record[Idx++]; - TemplArgs.reserve(NumTemplateArgs); - while (NumTemplateArgs--) - TemplArgs.push_back(ReadTemplateArgument(Record, Idx)); -} - -/// \brief Read a UnresolvedSet structure. -void PCHReader::ReadUnresolvedSet(UnresolvedSetImpl &Set, - const RecordData &Record, unsigned &Idx) { - unsigned NumDecls = Record[Idx++]; - while (NumDecls--) { - NamedDecl *D = cast<NamedDecl>(GetDecl(Record[Idx++])); - AccessSpecifier AS = (AccessSpecifier)Record[Idx++]; - Set.addDecl(D, AS); - } -} - -CXXBaseSpecifier -PCHReader::ReadCXXBaseSpecifier(const RecordData &Record, unsigned &Idx) { - bool isVirtual = static_cast<bool>(Record[Idx++]); - bool isBaseOfClass = static_cast<bool>(Record[Idx++]); - AccessSpecifier AS = static_cast<AccessSpecifier>(Record[Idx++]); - QualType T = GetType(Record[Idx++]); - SourceRange Range = ReadSourceRange(Record, Idx); - return CXXBaseSpecifier(Range, isVirtual, isBaseOfClass, AS, T); -} - -NestedNameSpecifier * -PCHReader::ReadNestedNameSpecifier(const RecordData &Record, unsigned &Idx) { - unsigned N = Record[Idx++]; - NestedNameSpecifier *NNS = 0, *Prev = 0; - for (unsigned I = 0; I != N; ++I) { - NestedNameSpecifier::SpecifierKind Kind - = (NestedNameSpecifier::SpecifierKind)Record[Idx++]; - switch (Kind) { - case NestedNameSpecifier::Identifier: { - IdentifierInfo *II = GetIdentifierInfo(Record, Idx); - NNS = NestedNameSpecifier::Create(*Context, Prev, II); - break; - } - - case NestedNameSpecifier::Namespace: { - NamespaceDecl *NS = cast<NamespaceDecl>(GetDecl(Record[Idx++])); - NNS = NestedNameSpecifier::Create(*Context, Prev, NS); - break; - } - - case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::TypeSpecWithTemplate: { - Type *T = GetType(Record[Idx++]).getTypePtr(); - bool Template = Record[Idx++]; - NNS = NestedNameSpecifier::Create(*Context, Prev, Template, T); - break; - } - - case NestedNameSpecifier::Global: { - NNS = NestedNameSpecifier::GlobalSpecifier(*Context); - // No associated value, and there can't be a prefix. - break; - } - } - Prev = NNS; - } - return NNS; -} - -SourceRange -PCHReader::ReadSourceRange(const RecordData &Record, unsigned &Idx) { - SourceLocation beg = SourceLocation::getFromRawEncoding(Record[Idx++]); - SourceLocation end = SourceLocation::getFromRawEncoding(Record[Idx++]); - return SourceRange(beg, end); -} - -/// \brief Read an integral value -llvm::APInt PCHReader::ReadAPInt(const RecordData &Record, unsigned &Idx) { - unsigned BitWidth = Record[Idx++]; - unsigned NumWords = llvm::APInt::getNumWords(BitWidth); - llvm::APInt Result(BitWidth, NumWords, &Record[Idx]); - Idx += NumWords; - return Result; -} - -/// \brief Read a signed integral value -llvm::APSInt PCHReader::ReadAPSInt(const RecordData &Record, unsigned &Idx) { - bool isUnsigned = Record[Idx++]; - return llvm::APSInt(ReadAPInt(Record, Idx), isUnsigned); -} - -/// \brief Read a floating-point value -llvm::APFloat PCHReader::ReadAPFloat(const RecordData &Record, unsigned &Idx) { - return llvm::APFloat(ReadAPInt(Record, Idx)); -} - -// \brief Read a string -std::string PCHReader::ReadString(const RecordData &Record, unsigned &Idx) { - unsigned Len = Record[Idx++]; - std::string Result(Record.data() + Idx, Record.data() + Idx + Len); - Idx += Len; - return Result; -} - -CXXTemporary *PCHReader::ReadCXXTemporary(const RecordData &Record, - unsigned &Idx) { - CXXDestructorDecl *Decl = cast<CXXDestructorDecl>(GetDecl(Record[Idx++])); - return CXXTemporary::Create(*Context, Decl); -} - -DiagnosticBuilder PCHReader::Diag(unsigned DiagID) { - return Diag(SourceLocation(), DiagID); -} - -DiagnosticBuilder PCHReader::Diag(SourceLocation Loc, unsigned DiagID) { - return Diags.Report(FullSourceLoc(Loc, SourceMgr), DiagID); -} - -/// \brief Retrieve the identifier table associated with the -/// preprocessor. -IdentifierTable &PCHReader::getIdentifierTable() { - assert(PP && "Forgot to set Preprocessor ?"); - return PP->getIdentifierTable(); -} - -/// \brief Record that the given ID maps to the given switch-case -/// statement. -void PCHReader::RecordSwitchCaseID(SwitchCase *SC, unsigned ID) { - assert(SwitchCaseStmts[ID] == 0 && "Already have a SwitchCase with this ID"); - SwitchCaseStmts[ID] = SC; -} - -/// \brief Retrieve the switch-case statement with the given ID. -SwitchCase *PCHReader::getSwitchCaseWithID(unsigned ID) { - assert(SwitchCaseStmts[ID] != 0 && "No SwitchCase with this ID"); - return SwitchCaseStmts[ID]; -} - -/// \brief Record that the given label statement has been -/// deserialized and has the given ID. -void PCHReader::RecordLabelStmt(LabelStmt *S, unsigned ID) { - assert(LabelStmts.find(ID) == LabelStmts.end() && - "Deserialized label twice"); - LabelStmts[ID] = S; - - // If we've already seen any goto statements that point to this - // label, resolve them now. - typedef std::multimap<unsigned, GotoStmt *>::iterator GotoIter; - std::pair<GotoIter, GotoIter> Gotos = UnresolvedGotoStmts.equal_range(ID); - for (GotoIter Goto = Gotos.first; Goto != Gotos.second; ++Goto) - Goto->second->setLabel(S); - UnresolvedGotoStmts.erase(Gotos.first, Gotos.second); - - // If we've already seen any address-label statements that point to - // this label, resolve them now. - typedef std::multimap<unsigned, AddrLabelExpr *>::iterator AddrLabelIter; - std::pair<AddrLabelIter, AddrLabelIter> AddrLabels - = UnresolvedAddrLabelExprs.equal_range(ID); - for (AddrLabelIter AddrLabel = AddrLabels.first; - AddrLabel != AddrLabels.second; ++AddrLabel) - AddrLabel->second->setLabel(S); - UnresolvedAddrLabelExprs.erase(AddrLabels.first, AddrLabels.second); -} - -/// \brief Set the label of the given statement to the label -/// identified by ID. -/// -/// Depending on the order in which the label and other statements -/// referencing that label occur, this operation may complete -/// immediately (updating the statement) or it may queue the -/// statement to be back-patched later. -void PCHReader::SetLabelOf(GotoStmt *S, unsigned ID) { - std::map<unsigned, LabelStmt *>::iterator Label = LabelStmts.find(ID); - if (Label != LabelStmts.end()) { - // We've already seen this label, so set the label of the goto and - // we're done. - S->setLabel(Label->second); - } else { - // We haven't seen this label yet, so add this goto to the set of - // unresolved goto statements. - UnresolvedGotoStmts.insert(std::make_pair(ID, S)); - } -} - -/// \brief Set the label of the given expression to the label -/// identified by ID. -/// -/// Depending on the order in which the label and other statements -/// referencing that label occur, this operation may complete -/// immediately (updating the statement) or it may queue the -/// statement to be back-patched later. -void PCHReader::SetLabelOf(AddrLabelExpr *S, unsigned ID) { - std::map<unsigned, LabelStmt *>::iterator Label = LabelStmts.find(ID); - if (Label != LabelStmts.end()) { - // We've already seen this label, so set the label of the - // label-address expression and we're done. - S->setLabel(Label->second); - } else { - // We haven't seen this label yet, so add this label-address - // expression to the set of unresolved label-address expressions. - UnresolvedAddrLabelExprs.insert(std::make_pair(ID, S)); - } -} - - -PCHReader::LoadingTypeOrDecl::LoadingTypeOrDecl(PCHReader &Reader) - : Reader(Reader), Parent(Reader.CurrentlyLoadingTypeOrDecl) { - Reader.CurrentlyLoadingTypeOrDecl = this; -} - -PCHReader::LoadingTypeOrDecl::~LoadingTypeOrDecl() { - if (!Parent) { - // If any identifiers with corresponding top-level declarations have - // been loaded, load those declarations now. - while (!Reader.PendingIdentifierInfos.empty()) { - Reader.SetGloballyVisibleDecls(Reader.PendingIdentifierInfos.front().II, - Reader.PendingIdentifierInfos.front().DeclIDs, - true); - Reader.PendingIdentifierInfos.pop_front(); - } - - // We are not in recursive loading, so it's safe to pass the "interesting" - // decls to the consumer. - if (Reader.Consumer) - Reader.PassInterestingDeclsToConsumer(); - } - - Reader.CurrentlyLoadingTypeOrDecl = Parent; -} diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Frontend/PCHReaderDecl.cpp deleted file mode 100644 index 742f0e4..0000000 --- a/lib/Frontend/PCHReaderDecl.cpp +++ /dev/null @@ -1,1484 +0,0 @@ -//===--- PCHReaderDecl.cpp - Decl Deserialization ---------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the PCHReader::ReadDeclRecord method, which is the -// entrypoint for loading a decl. -// -//===----------------------------------------------------------------------===// - -#include "clang/Frontend/PCHReader.h" -#include "clang/AST/ASTConsumer.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/DeclVisitor.h" -#include "clang/AST/DeclGroup.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclTemplate.h" -#include "clang/AST/Expr.h" -using namespace clang; - - -//===----------------------------------------------------------------------===// -// Declaration deserialization -//===----------------------------------------------------------------------===// - -namespace clang { - class PCHDeclReader : public DeclVisitor<PCHDeclReader, void> { - PCHReader &Reader; - const PCHReader::RecordData &Record; - unsigned &Idx; - pch::TypeID TypeIDForTypeDecl; - - public: - PCHDeclReader(PCHReader &Reader, const PCHReader::RecordData &Record, - unsigned &Idx) - : Reader(Reader), Record(Record), Idx(Idx), TypeIDForTypeDecl(0) { } - - void Visit(Decl *D); - - void VisitDecl(Decl *D); - void VisitTranslationUnitDecl(TranslationUnitDecl *TU); - void VisitNamedDecl(NamedDecl *ND); - void VisitNamespaceDecl(NamespaceDecl *D); - void VisitUsingDirectiveDecl(UsingDirectiveDecl *D); - void VisitNamespaceAliasDecl(NamespaceAliasDecl *D); - void VisitTypeDecl(TypeDecl *TD); - void VisitTypedefDecl(TypedefDecl *TD); - void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D); - void VisitTagDecl(TagDecl *TD); - void VisitEnumDecl(EnumDecl *ED); - void VisitRecordDecl(RecordDecl *RD); - void VisitCXXRecordDecl(CXXRecordDecl *D); - void VisitClassTemplateSpecializationDecl( - ClassTemplateSpecializationDecl *D); - void VisitClassTemplatePartialSpecializationDecl( - ClassTemplatePartialSpecializationDecl *D); - void VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D); - void VisitValueDecl(ValueDecl *VD); - void VisitEnumConstantDecl(EnumConstantDecl *ECD); - void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D); - void VisitDeclaratorDecl(DeclaratorDecl *DD); - void VisitFunctionDecl(FunctionDecl *FD); - void VisitCXXMethodDecl(CXXMethodDecl *D); - void VisitCXXConstructorDecl(CXXConstructorDecl *D); - void VisitCXXDestructorDecl(CXXDestructorDecl *D); - void VisitCXXConversionDecl(CXXConversionDecl *D); - void VisitFieldDecl(FieldDecl *FD); - void VisitVarDecl(VarDecl *VD); - void VisitImplicitParamDecl(ImplicitParamDecl *PD); - void VisitParmVarDecl(ParmVarDecl *PD); - void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D); - void VisitTemplateDecl(TemplateDecl *D); - void VisitClassTemplateDecl(ClassTemplateDecl *D); - void VisitFunctionTemplateDecl(FunctionTemplateDecl *D); - void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D); - void VisitUsingDecl(UsingDecl *D); - void VisitUsingShadowDecl(UsingShadowDecl *D); - void VisitLinkageSpecDecl(LinkageSpecDecl *D); - void VisitFileScopeAsmDecl(FileScopeAsmDecl *AD); - void VisitAccessSpecDecl(AccessSpecDecl *D); - void VisitFriendDecl(FriendDecl *D); - void VisitFriendTemplateDecl(FriendTemplateDecl *D); - void VisitStaticAssertDecl(StaticAssertDecl *D); - void VisitBlockDecl(BlockDecl *BD); - - std::pair<uint64_t, uint64_t> VisitDeclContext(DeclContext *DC); - - // FIXME: Reorder according to DeclNodes.td? - void VisitObjCMethodDecl(ObjCMethodDecl *D); - void VisitObjCContainerDecl(ObjCContainerDecl *D); - void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D); - void VisitObjCIvarDecl(ObjCIvarDecl *D); - void VisitObjCProtocolDecl(ObjCProtocolDecl *D); - void VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *D); - void VisitObjCClassDecl(ObjCClassDecl *D); - void VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D); - void VisitObjCCategoryDecl(ObjCCategoryDecl *D); - void VisitObjCImplDecl(ObjCImplDecl *D); - void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D); - void VisitObjCImplementationDecl(ObjCImplementationDecl *D); - void VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D); - void VisitObjCPropertyDecl(ObjCPropertyDecl *D); - void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D); - }; -} - -void PCHDeclReader::Visit(Decl *D) { - DeclVisitor<PCHDeclReader, void>::Visit(D); - - if (TypeDecl *TD = dyn_cast<TypeDecl>(D)) { - // if we have a fully initialized TypeDecl, we can safely read its type now. - TD->setTypeForDecl(Reader.GetType(TypeIDForTypeDecl).getTypePtr()); - } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { - // FunctionDecl's body was written last after all other Stmts/Exprs. - if (Record[Idx++]) - FD->setLazyBody(Reader.getDeclsCursor().GetCurrentBitNo()); - } -} - -void PCHDeclReader::VisitDecl(Decl *D) { - D->setDeclContext(cast_or_null<DeclContext>(Reader.GetDecl(Record[Idx++]))); - D->setLexicalDeclContext( - cast_or_null<DeclContext>(Reader.GetDecl(Record[Idx++]))); - D->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++])); - D->setInvalidDecl(Record[Idx++]); - if (Record[Idx++]) - D->initAttrs(Reader.ReadAttributes()); - D->setImplicit(Record[Idx++]); - D->setUsed(Record[Idx++]); - D->setAccess((AccessSpecifier)Record[Idx++]); - D->setPCHLevel(Record[Idx++] + 1); -} - -void PCHDeclReader::VisitTranslationUnitDecl(TranslationUnitDecl *TU) { - VisitDecl(TU); - TU->setAnonymousNamespace( - cast_or_null<NamespaceDecl>(Reader.GetDecl(Record[Idx++]))); -} - -void PCHDeclReader::VisitNamedDecl(NamedDecl *ND) { - VisitDecl(ND); - ND->setDeclName(Reader.ReadDeclarationName(Record, Idx)); -} - -void PCHDeclReader::VisitTypeDecl(TypeDecl *TD) { - VisitNamedDecl(TD); - // Delay type reading until after we have fully initialized the decl. - TypeIDForTypeDecl = Record[Idx++]; -} - -void PCHDeclReader::VisitTypedefDecl(TypedefDecl *TD) { - VisitTypeDecl(TD); - TD->setTypeSourceInfo(Reader.GetTypeSourceInfo(Record, Idx)); -} - -void PCHDeclReader::VisitTagDecl(TagDecl *TD) { - VisitTypeDecl(TD); - TD->IdentifierNamespace = Record[Idx++]; - TD->setPreviousDeclaration( - cast_or_null<TagDecl>(Reader.GetDecl(Record[Idx++]))); - TD->setTagKind((TagDecl::TagKind)Record[Idx++]); - TD->setDefinition(Record[Idx++]); - TD->setEmbeddedInDeclarator(Record[Idx++]); - TD->setRBraceLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - TD->setTagKeywordLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - // FIXME: maybe read optional qualifier and its range. - TD->setTypedefForAnonDecl( - cast_or_null<TypedefDecl>(Reader.GetDecl(Record[Idx++]))); -} - -void PCHDeclReader::VisitEnumDecl(EnumDecl *ED) { - VisitTagDecl(ED); - ED->setIntegerType(Reader.GetType(Record[Idx++])); - ED->setPromotionType(Reader.GetType(Record[Idx++])); - ED->setNumPositiveBits(Record[Idx++]); - ED->setNumNegativeBits(Record[Idx++]); - ED->setInstantiationOfMemberEnum( - cast_or_null<EnumDecl>(Reader.GetDecl(Record[Idx++]))); -} - -void PCHDeclReader::VisitRecordDecl(RecordDecl *RD) { - VisitTagDecl(RD); - RD->setHasFlexibleArrayMember(Record[Idx++]); - RD->setAnonymousStructOrUnion(Record[Idx++]); - RD->setHasObjectMember(Record[Idx++]); -} - -void PCHDeclReader::VisitValueDecl(ValueDecl *VD) { - VisitNamedDecl(VD); - VD->setType(Reader.GetType(Record[Idx++])); -} - -void PCHDeclReader::VisitEnumConstantDecl(EnumConstantDecl *ECD) { - VisitValueDecl(ECD); - if (Record[Idx++]) - ECD->setInitExpr(Reader.ReadExpr()); - ECD->setInitVal(Reader.ReadAPSInt(Record, Idx)); -} - -void PCHDeclReader::VisitDeclaratorDecl(DeclaratorDecl *DD) { - VisitValueDecl(DD); - TypeSourceInfo *TInfo = Reader.GetTypeSourceInfo(Record, Idx); - if (TInfo) - DD->setTypeSourceInfo(TInfo); - // FIXME: read optional qualifier and its range. -} - -void PCHDeclReader::VisitFunctionDecl(FunctionDecl *FD) { - VisitDeclaratorDecl(FD); - - FD->IdentifierNamespace = Record[Idx++]; - switch ((FunctionDecl::TemplatedKind)Record[Idx++]) { - default: assert(false && "Unhandled TemplatedKind!"); - break; - case FunctionDecl::TK_NonTemplate: - break; - case FunctionDecl::TK_FunctionTemplate: - FD->setDescribedFunctionTemplate( - cast<FunctionTemplateDecl>(Reader.GetDecl(Record[Idx++]))); - break; - case FunctionDecl::TK_MemberSpecialization: { - FunctionDecl *InstFD = cast<FunctionDecl>(Reader.GetDecl(Record[Idx++])); - TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++]; - SourceLocation POI = Reader.ReadSourceLocation(Record, Idx); - FD->setInstantiationOfMemberFunction(InstFD, TSK); - FD->getMemberSpecializationInfo()->setPointOfInstantiation(POI); - break; - } - case FunctionDecl::TK_FunctionTemplateSpecialization: { - FunctionTemplateDecl *Template - = cast<FunctionTemplateDecl>(Reader.GetDecl(Record[Idx++])); - TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++]; - - // Template arguments. - llvm::SmallVector<TemplateArgument, 8> TemplArgs; - Reader.ReadTemplateArgumentList(TemplArgs, Record, Idx); - - // Template args as written. - llvm::SmallVector<TemplateArgumentLoc, 8> TemplArgLocs; - SourceLocation LAngleLoc, RAngleLoc; - if (Record[Idx++]) { // TemplateArgumentsAsWritten != 0 - unsigned NumTemplateArgLocs = Record[Idx++]; - TemplArgLocs.reserve(NumTemplateArgLocs); - for (unsigned i=0; i != NumTemplateArgLocs; ++i) - TemplArgLocs.push_back(Reader.ReadTemplateArgumentLoc(Record, Idx)); - - LAngleLoc = Reader.ReadSourceLocation(Record, Idx); - RAngleLoc = Reader.ReadSourceLocation(Record, Idx); - } - - SourceLocation POI = Reader.ReadSourceLocation(Record, Idx); - - FD->setFunctionTemplateSpecialization(Template, TemplArgs.size(), - TemplArgs.data(), TSK, - TemplArgLocs.size(), - TemplArgLocs.data(), - LAngleLoc, RAngleLoc, POI); - break; - } - case FunctionDecl::TK_DependentFunctionTemplateSpecialization: { - // Templates. - UnresolvedSet<8> TemplDecls; - unsigned NumTemplates = Record[Idx++]; - while (NumTemplates--) - TemplDecls.addDecl(cast<NamedDecl>(Reader.GetDecl(Record[Idx++]))); - - // Templates args. - TemplateArgumentListInfo TemplArgs; - unsigned NumArgs = Record[Idx++]; - while (NumArgs--) - TemplArgs.addArgument(Reader.ReadTemplateArgumentLoc(Record, Idx)); - TemplArgs.setLAngleLoc(Reader.ReadSourceLocation(Record, Idx)); - TemplArgs.setRAngleLoc(Reader.ReadSourceLocation(Record, Idx)); - - FD->setDependentTemplateSpecialization(*Reader.getContext(), - TemplDecls, TemplArgs); - break; - } - } - - // FunctionDecl's body is handled last at PCHReaderDecl::Visit, - // after everything else is read. - - // Avoid side effects and invariant checking of FunctionDecl's - // setPreviousDeclaration. - FD->redeclarable_base::setPreviousDeclaration( - cast_or_null<FunctionDecl>(Reader.GetDecl(Record[Idx++]))); - FD->setStorageClass((FunctionDecl::StorageClass)Record[Idx++]); - FD->setStorageClassAsWritten((FunctionDecl::StorageClass)Record[Idx++]); - FD->setInlineSpecified(Record[Idx++]); - FD->setVirtualAsWritten(Record[Idx++]); - FD->setPure(Record[Idx++]); - FD->setHasInheritedPrototype(Record[Idx++]); - FD->setHasWrittenPrototype(Record[Idx++]); - FD->setDeleted(Record[Idx++]); - FD->setTrivial(Record[Idx++]); - FD->setCopyAssignment(Record[Idx++]); - FD->setHasImplicitReturnZero(Record[Idx++]); - FD->setLocEnd(SourceLocation::getFromRawEncoding(Record[Idx++])); - - // Read in the parameters. - unsigned NumParams = Record[Idx++]; - llvm::SmallVector<ParmVarDecl *, 16> Params; - Params.reserve(NumParams); - for (unsigned I = 0; I != NumParams; ++I) - Params.push_back(cast<ParmVarDecl>(Reader.GetDecl(Record[Idx++]))); - FD->setParams(Params.data(), NumParams); -} - -void PCHDeclReader::VisitObjCMethodDecl(ObjCMethodDecl *MD) { - VisitNamedDecl(MD); - if (Record[Idx++]) { - // In practice, this won't be executed (since method definitions - // don't occur in header files). - MD->setBody(Reader.ReadStmt()); - MD->setSelfDecl(cast<ImplicitParamDecl>(Reader.GetDecl(Record[Idx++]))); - MD->setCmdDecl(cast<ImplicitParamDecl>(Reader.GetDecl(Record[Idx++]))); - } - MD->setInstanceMethod(Record[Idx++]); - MD->setVariadic(Record[Idx++]); - MD->setSynthesized(Record[Idx++]); - MD->setDeclImplementation((ObjCMethodDecl::ImplementationControl)Record[Idx++]); - MD->setObjCDeclQualifier((Decl::ObjCDeclQualifier)Record[Idx++]); - MD->setNumSelectorArgs(unsigned(Record[Idx++])); - MD->setResultType(Reader.GetType(Record[Idx++])); - MD->setResultTypeSourceInfo(Reader.GetTypeSourceInfo(Record, Idx)); - MD->setEndLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - unsigned NumParams = Record[Idx++]; - llvm::SmallVector<ParmVarDecl *, 16> Params; - Params.reserve(NumParams); - for (unsigned I = 0; I != NumParams; ++I) - Params.push_back(cast<ParmVarDecl>(Reader.GetDecl(Record[Idx++]))); - MD->setMethodParams(*Reader.getContext(), Params.data(), NumParams, - NumParams); -} - -void PCHDeclReader::VisitObjCContainerDecl(ObjCContainerDecl *CD) { - VisitNamedDecl(CD); - SourceLocation A = SourceLocation::getFromRawEncoding(Record[Idx++]); - SourceLocation B = SourceLocation::getFromRawEncoding(Record[Idx++]); - CD->setAtEndRange(SourceRange(A, B)); -} - -void PCHDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) { - VisitObjCContainerDecl(ID); - ID->setTypeForDecl(Reader.GetType(Record[Idx++]).getTypePtr()); - ID->setSuperClass(cast_or_null<ObjCInterfaceDecl> - (Reader.GetDecl(Record[Idx++]))); - unsigned NumProtocols = Record[Idx++]; - llvm::SmallVector<ObjCProtocolDecl *, 16> Protocols; - Protocols.reserve(NumProtocols); - for (unsigned I = 0; I != NumProtocols; ++I) - Protocols.push_back(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++]))); - llvm::SmallVector<SourceLocation, 16> ProtoLocs; - ProtoLocs.reserve(NumProtocols); - for (unsigned I = 0; I != NumProtocols; ++I) - ProtoLocs.push_back(SourceLocation::getFromRawEncoding(Record[Idx++])); - ID->setProtocolList(Protocols.data(), NumProtocols, ProtoLocs.data(), - *Reader.getContext()); - unsigned NumIvars = Record[Idx++]; - llvm::SmallVector<ObjCIvarDecl *, 16> IVars; - IVars.reserve(NumIvars); - for (unsigned I = 0; I != NumIvars; ++I) - IVars.push_back(cast<ObjCIvarDecl>(Reader.GetDecl(Record[Idx++]))); - ID->setCategoryList( - cast_or_null<ObjCCategoryDecl>(Reader.GetDecl(Record[Idx++]))); - ID->setForwardDecl(Record[Idx++]); - ID->setImplicitInterfaceDecl(Record[Idx++]); - ID->setClassLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - ID->setSuperClassLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - ID->setLocEnd(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHDeclReader::VisitObjCIvarDecl(ObjCIvarDecl *IVD) { - VisitFieldDecl(IVD); - IVD->setAccessControl((ObjCIvarDecl::AccessControl)Record[Idx++]); -} - -void PCHDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) { - VisitObjCContainerDecl(PD); - PD->setForwardDecl(Record[Idx++]); - PD->setLocEnd(SourceLocation::getFromRawEncoding(Record[Idx++])); - unsigned NumProtoRefs = Record[Idx++]; - llvm::SmallVector<ObjCProtocolDecl *, 16> ProtoRefs; - ProtoRefs.reserve(NumProtoRefs); - for (unsigned I = 0; I != NumProtoRefs; ++I) - ProtoRefs.push_back(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++]))); - llvm::SmallVector<SourceLocation, 16> ProtoLocs; - ProtoLocs.reserve(NumProtoRefs); - for (unsigned I = 0; I != NumProtoRefs; ++I) - ProtoLocs.push_back(SourceLocation::getFromRawEncoding(Record[Idx++])); - PD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(), - *Reader.getContext()); -} - -void PCHDeclReader::VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *FD) { - VisitFieldDecl(FD); -} - -void PCHDeclReader::VisitObjCClassDecl(ObjCClassDecl *CD) { - VisitDecl(CD); - unsigned NumClassRefs = Record[Idx++]; - llvm::SmallVector<ObjCInterfaceDecl *, 16> ClassRefs; - ClassRefs.reserve(NumClassRefs); - for (unsigned I = 0; I != NumClassRefs; ++I) - ClassRefs.push_back(cast<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++]))); - llvm::SmallVector<SourceLocation, 16> SLocs; - SLocs.reserve(NumClassRefs); - for (unsigned I = 0; I != NumClassRefs; ++I) - SLocs.push_back(SourceLocation::getFromRawEncoding(Record[Idx++])); - CD->setClassList(*Reader.getContext(), ClassRefs.data(), SLocs.data(), - NumClassRefs); -} - -void PCHDeclReader::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *FPD) { - VisitDecl(FPD); - unsigned NumProtoRefs = Record[Idx++]; - llvm::SmallVector<ObjCProtocolDecl *, 16> ProtoRefs; - ProtoRefs.reserve(NumProtoRefs); - for (unsigned I = 0; I != NumProtoRefs; ++I) - ProtoRefs.push_back(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++]))); - llvm::SmallVector<SourceLocation, 16> ProtoLocs; - ProtoLocs.reserve(NumProtoRefs); - for (unsigned I = 0; I != NumProtoRefs; ++I) - ProtoLocs.push_back(SourceLocation::getFromRawEncoding(Record[Idx++])); - FPD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(), - *Reader.getContext()); -} - -void PCHDeclReader::VisitObjCCategoryDecl(ObjCCategoryDecl *CD) { - VisitObjCContainerDecl(CD); - CD->setClassInterface(cast<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++]))); - unsigned NumProtoRefs = Record[Idx++]; - llvm::SmallVector<ObjCProtocolDecl *, 16> ProtoRefs; - ProtoRefs.reserve(NumProtoRefs); - for (unsigned I = 0; I != NumProtoRefs; ++I) - ProtoRefs.push_back(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++]))); - llvm::SmallVector<SourceLocation, 16> ProtoLocs; - ProtoLocs.reserve(NumProtoRefs); - for (unsigned I = 0; I != NumProtoRefs; ++I) - ProtoLocs.push_back(SourceLocation::getFromRawEncoding(Record[Idx++])); - CD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(), - *Reader.getContext()); - CD->setNextClassCategory(cast_or_null<ObjCCategoryDecl>(Reader.GetDecl(Record[Idx++]))); - CD->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - CD->setCategoryNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHDeclReader::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *CAD) { - VisitNamedDecl(CAD); - CAD->setClassInterface(cast<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++]))); -} - -void PCHDeclReader::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { - VisitNamedDecl(D); - D->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - D->setType(Reader.GetTypeSourceInfo(Record, Idx)); - // FIXME: stable encoding - D->setPropertyAttributes( - (ObjCPropertyDecl::PropertyAttributeKind)Record[Idx++]); - D->setPropertyAttributesAsWritten( - (ObjCPropertyDecl::PropertyAttributeKind)Record[Idx++]); - // FIXME: stable encoding - D->setPropertyImplementation( - (ObjCPropertyDecl::PropertyControl)Record[Idx++]); - D->setGetterName(Reader.ReadDeclarationName(Record, Idx).getObjCSelector()); - D->setSetterName(Reader.ReadDeclarationName(Record, Idx).getObjCSelector()); - D->setGetterMethodDecl( - cast_or_null<ObjCMethodDecl>(Reader.GetDecl(Record[Idx++]))); - D->setSetterMethodDecl( - cast_or_null<ObjCMethodDecl>(Reader.GetDecl(Record[Idx++]))); - D->setPropertyIvarDecl( - cast_or_null<ObjCIvarDecl>(Reader.GetDecl(Record[Idx++]))); -} - -void PCHDeclReader::VisitObjCImplDecl(ObjCImplDecl *D) { - VisitObjCContainerDecl(D); - D->setClassInterface( - cast_or_null<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++]))); -} - -void PCHDeclReader::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) { - VisitObjCImplDecl(D); - D->setIdentifier(Reader.GetIdentifierInfo(Record, Idx)); -} - -void PCHDeclReader::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { - VisitObjCImplDecl(D); - D->setSuperClass( - cast_or_null<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++]))); - // FIXME. Add reading of IvarInitializers and NumIvarInitializers. -} - - -void PCHDeclReader::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { - VisitDecl(D); - D->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - D->setPropertyDecl( - cast_or_null<ObjCPropertyDecl>(Reader.GetDecl(Record[Idx++]))); - D->setPropertyIvarDecl( - cast_or_null<ObjCIvarDecl>(Reader.GetDecl(Record[Idx++]))); - // FIXME. read GetterCXXConstructor and SetterCXXAssignment -} - -void PCHDeclReader::VisitFieldDecl(FieldDecl *FD) { - VisitDeclaratorDecl(FD); - FD->setMutable(Record[Idx++]); - if (Record[Idx++]) - FD->setBitWidth(Reader.ReadExpr()); - if (!FD->getDeclName()) { - FieldDecl *Tmpl = cast_or_null<FieldDecl>(Reader.GetDecl(Record[Idx++])); - if (Tmpl) - Reader.getContext()->setInstantiatedFromUnnamedFieldDecl(FD, Tmpl); - } -} - -void PCHDeclReader::VisitVarDecl(VarDecl *VD) { - VisitDeclaratorDecl(VD); - VD->setStorageClass((VarDecl::StorageClass)Record[Idx++]); - VD->setStorageClassAsWritten((VarDecl::StorageClass)Record[Idx++]); - VD->setThreadSpecified(Record[Idx++]); - VD->setCXXDirectInitializer(Record[Idx++]); - VD->setDeclaredInCondition(Record[Idx++]); - VD->setExceptionVariable(Record[Idx++]); - VD->setNRVOVariable(Record[Idx++]); - VD->setPreviousDeclaration( - cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++]))); - if (Record[Idx++]) - VD->setInit(Reader.ReadExpr()); - - if (Record[Idx++]) { // HasMemberSpecializationInfo. - VarDecl *Tmpl = cast<VarDecl>(Reader.GetDecl(Record[Idx++])); - TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++]; - SourceLocation POI = Reader.ReadSourceLocation(Record, Idx); - Reader.getContext()->setInstantiatedFromStaticDataMember(VD, Tmpl, TSK,POI); - } -} - -void PCHDeclReader::VisitImplicitParamDecl(ImplicitParamDecl *PD) { - VisitVarDecl(PD); -} - -void PCHDeclReader::VisitParmVarDecl(ParmVarDecl *PD) { - VisitVarDecl(PD); - PD->setObjCDeclQualifier((Decl::ObjCDeclQualifier)Record[Idx++]); - PD->setHasInheritedDefaultArg(Record[Idx++]); - if (Record[Idx++]) // hasUninstantiatedDefaultArg. - PD->setUninstantiatedDefaultArg(Reader.ReadExpr()); -} - -void PCHDeclReader::VisitFileScopeAsmDecl(FileScopeAsmDecl *AD) { - VisitDecl(AD); - AD->setAsmString(cast<StringLiteral>(Reader.ReadExpr())); -} - -void PCHDeclReader::VisitBlockDecl(BlockDecl *BD) { - VisitDecl(BD); - BD->setBody(cast_or_null<CompoundStmt>(Reader.ReadStmt())); - BD->setSignatureAsWritten(Reader.GetTypeSourceInfo(Record, Idx)); - unsigned NumParams = Record[Idx++]; - llvm::SmallVector<ParmVarDecl *, 16> Params; - Params.reserve(NumParams); - for (unsigned I = 0; I != NumParams; ++I) - Params.push_back(cast<ParmVarDecl>(Reader.GetDecl(Record[Idx++]))); - BD->setParams(Params.data(), NumParams); -} - -void PCHDeclReader::VisitLinkageSpecDecl(LinkageSpecDecl *D) { - VisitDecl(D); - D->setLanguage((LinkageSpecDecl::LanguageIDs)Record[Idx++]); - D->setHasBraces(Record[Idx++]); -} - -void PCHDeclReader::VisitNamespaceDecl(NamespaceDecl *D) { - VisitNamedDecl(D); - D->setLBracLoc(Reader.ReadSourceLocation(Record, Idx)); - D->setRBracLoc(Reader.ReadSourceLocation(Record, Idx)); - D->setNextNamespace( - cast_or_null<NamespaceDecl>(Reader.GetDecl(Record[Idx++]))); - - bool IsOriginal = Record[Idx++]; - D->OrigOrAnonNamespace.setInt(IsOriginal); - D->OrigOrAnonNamespace.setPointer( - cast_or_null<NamespaceDecl>(Reader.GetDecl(Record[Idx++]))); -} - -void PCHDeclReader::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { - VisitNamedDecl(D); - - D->setAliasLoc(Reader.ReadSourceLocation(Record, Idx)); - D->setQualifierRange(Reader.ReadSourceRange(Record, Idx)); - D->setQualifier(Reader.ReadNestedNameSpecifier(Record, Idx)); - D->setTargetNameLoc(Reader.ReadSourceLocation(Record, Idx)); - D->setAliasedNamespace(cast<NamedDecl>(Reader.GetDecl(Record[Idx++]))); -} - -void PCHDeclReader::VisitUsingDecl(UsingDecl *D) { - VisitNamedDecl(D); - D->setUsingLocation(Reader.ReadSourceLocation(Record, Idx)); - D->setNestedNameRange(Reader.ReadSourceRange(Record, Idx)); - D->setTargetNestedNameDecl(Reader.ReadNestedNameSpecifier(Record, Idx)); - - // FIXME: It would probably be more efficient to read these into a vector - // and then re-cosntruct the shadow decl set over that vector since it - // would avoid existence checks. - unsigned NumShadows = Record[Idx++]; - for(unsigned I = 0; I != NumShadows; ++I) { - // Avoid invariant checking of UsingDecl::addShadowDecl, the decl may still - // be initializing. - D->Shadows.insert(cast<UsingShadowDecl>(Reader.GetDecl(Record[Idx++]))); - } - D->setTypeName(Record[Idx++]); - NamedDecl *Pattern = cast_or_null<NamedDecl>(Reader.GetDecl(Record[Idx++])); - if (Pattern) - Reader.getContext()->setInstantiatedFromUsingDecl(D, Pattern); -} - -void PCHDeclReader::VisitUsingShadowDecl(UsingShadowDecl *D) { - VisitNamedDecl(D); - D->setTargetDecl(cast<NamedDecl>(Reader.GetDecl(Record[Idx++]))); - D->setUsingDecl(cast<UsingDecl>(Reader.GetDecl(Record[Idx++]))); - UsingShadowDecl *Pattern - = cast_or_null<UsingShadowDecl>(Reader.GetDecl(Record[Idx++])); - if (Pattern) - Reader.getContext()->setInstantiatedFromUsingShadowDecl(D, Pattern); -} - -void PCHDeclReader::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { - VisitNamedDecl(D); - D->setNamespaceKeyLocation(Reader.ReadSourceLocation(Record, Idx)); - D->setQualifierRange(Reader.ReadSourceRange(Record, Idx)); - D->setQualifier(Reader.ReadNestedNameSpecifier(Record, Idx)); - D->setIdentLocation(Reader.ReadSourceLocation(Record, Idx)); - D->setNominatedNamespace(cast<NamedDecl>(Reader.GetDecl(Record[Idx++]))); - D->setCommonAncestor(cast_or_null<DeclContext>( - Reader.GetDecl(Record[Idx++]))); -} - -void PCHDeclReader::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { - VisitValueDecl(D); - D->setTargetNestedNameRange(Reader.ReadSourceRange(Record, Idx)); - D->setUsingLoc(Reader.ReadSourceLocation(Record, Idx)); - D->setTargetNestedNameSpecifier(Reader.ReadNestedNameSpecifier(Record, Idx)); -} - -void PCHDeclReader::VisitUnresolvedUsingTypenameDecl( - UnresolvedUsingTypenameDecl *D) { - VisitTypeDecl(D); - D->setTargetNestedNameRange(Reader.ReadSourceRange(Record, Idx)); - D->setUsingLoc(Reader.ReadSourceLocation(Record, Idx)); - D->setTypenameLoc(Reader.ReadSourceLocation(Record, Idx)); - D->setTargetNestedNameSpecifier(Reader.ReadNestedNameSpecifier(Record, Idx)); -} - -void PCHDeclReader::VisitCXXRecordDecl(CXXRecordDecl *D) { - ASTContext &C = *Reader.getContext(); - - // We need to allocate the DefinitionData struct ahead of VisitRecordDecl - // so that the other CXXRecordDecls can get a pointer even when the owner - // is still initializing. - bool OwnsDefinitionData = false; - enum DataOwnership { Data_NoDefData, Data_Owner, Data_NotOwner }; - switch ((DataOwnership)Record[Idx++]) { - default: - assert(0 && "Out of sync with PCHDeclWriter or messed up reading"); - case Data_NoDefData: - break; - case Data_Owner: - OwnsDefinitionData = true; - D->DefinitionData = new (C) struct CXXRecordDecl::DefinitionData(D); - break; - case Data_NotOwner: - D->DefinitionData - = cast<CXXRecordDecl>(Reader.GetDecl(Record[Idx++]))->DefinitionData; - break; - } - - VisitRecordDecl(D); - - if (OwnsDefinitionData) { - assert(D->DefinitionData); - struct CXXRecordDecl::DefinitionData &Data = *D->DefinitionData; - - Data.UserDeclaredConstructor = Record[Idx++]; - Data.UserDeclaredCopyConstructor = Record[Idx++]; - Data.UserDeclaredCopyAssignment = Record[Idx++]; - Data.UserDeclaredDestructor = Record[Idx++]; - Data.Aggregate = Record[Idx++]; - Data.PlainOldData = Record[Idx++]; - Data.Empty = Record[Idx++]; - Data.Polymorphic = Record[Idx++]; - Data.Abstract = Record[Idx++]; - Data.HasTrivialConstructor = Record[Idx++]; - Data.HasTrivialCopyConstructor = Record[Idx++]; - Data.HasTrivialCopyAssignment = Record[Idx++]; - Data.HasTrivialDestructor = Record[Idx++]; - Data.ComputedVisibleConversions = Record[Idx++]; - Data.DeclaredDefaultConstructor = Record[Idx++]; - Data.DeclaredCopyConstructor = Record[Idx++]; - Data.DeclaredCopyAssignment = Record[Idx++]; - Data.DeclaredDestructor = Record[Idx++]; - - // setBases() is unsuitable since it may try to iterate the bases of an - // unitialized base. - Data.NumBases = Record[Idx++]; - Data.Bases = new(C) CXXBaseSpecifier [Data.NumBases]; - for (unsigned i = 0; i != Data.NumBases; ++i) - Data.Bases[i] = Reader.ReadCXXBaseSpecifier(Record, Idx); - - // FIXME: Make VBases lazily computed when needed to avoid storing them. - Data.NumVBases = Record[Idx++]; - Data.VBases = new(C) CXXBaseSpecifier [Data.NumVBases]; - for (unsigned i = 0; i != Data.NumVBases; ++i) - Data.VBases[i] = Reader.ReadCXXBaseSpecifier(Record, Idx); - - Reader.ReadUnresolvedSet(Data.Conversions, Record, Idx); - Reader.ReadUnresolvedSet(Data.VisibleConversions, Record, Idx); - assert(Data.Definition && "Data.Definition should be already set!"); - Data.FirstFriend - = cast_or_null<FriendDecl>(Reader.GetDecl(Record[Idx++])); - } - - enum CXXRecKind { - CXXRecNotTemplate = 0, CXXRecTemplate, CXXRecMemberSpecialization - }; - switch ((CXXRecKind)Record[Idx++]) { - default: - assert(false && "Out of sync with PCHDeclWriter::VisitCXXRecordDecl?"); - case CXXRecNotTemplate: - break; - case CXXRecTemplate: - D->setDescribedClassTemplate( - cast<ClassTemplateDecl>(Reader.GetDecl(Record[Idx++]))); - break; - case CXXRecMemberSpecialization: { - CXXRecordDecl *RD = cast<CXXRecordDecl>(Reader.GetDecl(Record[Idx++])); - TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++]; - SourceLocation POI = Reader.ReadSourceLocation(Record, Idx); - D->setInstantiationOfMemberClass(RD, TSK); - D->getMemberSpecializationInfo()->setPointOfInstantiation(POI); - break; - } - } -} - -void PCHDeclReader::VisitCXXMethodDecl(CXXMethodDecl *D) { - VisitFunctionDecl(D); - unsigned NumOverridenMethods = Record[Idx++]; - while (NumOverridenMethods--) { - CXXMethodDecl *MD = cast<CXXMethodDecl>(Reader.GetDecl(Record[Idx++])); - // Avoid invariant checking of CXXMethodDecl::addOverriddenMethod, - // MD may be initializing. - Reader.getContext()->addOverriddenMethod(D, MD); - } -} - -void PCHDeclReader::VisitCXXConstructorDecl(CXXConstructorDecl *D) { - VisitCXXMethodDecl(D); - - D->IsExplicitSpecified = Record[Idx++]; - D->ImplicitlyDefined = Record[Idx++]; - - unsigned NumInitializers = Record[Idx++]; - D->NumBaseOrMemberInitializers = NumInitializers; - if (NumInitializers) { - ASTContext &C = *Reader.getContext(); - - D->BaseOrMemberInitializers - = new (C) CXXBaseOrMemberInitializer*[NumInitializers]; - for (unsigned i=0; i != NumInitializers; ++i) { - TypeSourceInfo *BaseClassInfo = 0; - bool IsBaseVirtual = false; - FieldDecl *Member = 0; - - bool IsBaseInitializer = Record[Idx++]; - if (IsBaseInitializer) { - BaseClassInfo = Reader.GetTypeSourceInfo(Record, Idx); - IsBaseVirtual = Record[Idx++]; - } else { - Member = cast<FieldDecl>(Reader.GetDecl(Record[Idx++])); - } - SourceLocation MemberLoc = Reader.ReadSourceLocation(Record, Idx); - Expr *Init = Reader.ReadExpr(); - FieldDecl *AnonUnionMember - = cast_or_null<FieldDecl>(Reader.GetDecl(Record[Idx++])); - SourceLocation LParenLoc = Reader.ReadSourceLocation(Record, Idx); - SourceLocation RParenLoc = Reader.ReadSourceLocation(Record, Idx); - bool IsWritten = Record[Idx++]; - unsigned SourceOrderOrNumArrayIndices; - llvm::SmallVector<VarDecl *, 8> Indices; - if (IsWritten) { - SourceOrderOrNumArrayIndices = Record[Idx++]; - } else { - SourceOrderOrNumArrayIndices = Record[Idx++]; - Indices.reserve(SourceOrderOrNumArrayIndices); - for (unsigned i=0; i != SourceOrderOrNumArrayIndices; ++i) - Indices.push_back(cast<VarDecl>(Reader.GetDecl(Record[Idx++]))); - } - - CXXBaseOrMemberInitializer *BOMInit; - if (IsBaseInitializer) { - BOMInit = new (C) CXXBaseOrMemberInitializer(C, BaseClassInfo, - IsBaseVirtual, LParenLoc, - Init, RParenLoc); - } else if (IsWritten) { - BOMInit = new (C) CXXBaseOrMemberInitializer(C, Member, MemberLoc, - LParenLoc, Init, RParenLoc); - } else { - BOMInit = CXXBaseOrMemberInitializer::Create(C, Member, MemberLoc, - LParenLoc, Init, RParenLoc, - Indices.data(), - Indices.size()); - } - - BOMInit->setAnonUnionMember(AnonUnionMember); - D->BaseOrMemberInitializers[i] = BOMInit; - } - } -} - -void PCHDeclReader::VisitCXXDestructorDecl(CXXDestructorDecl *D) { - VisitCXXMethodDecl(D); - - D->ImplicitlyDefined = Record[Idx++]; - D->OperatorDelete = cast_or_null<FunctionDecl>(Reader.GetDecl(Record[Idx++])); -} - -void PCHDeclReader::VisitCXXConversionDecl(CXXConversionDecl *D) { - VisitCXXMethodDecl(D); - D->IsExplicitSpecified = Record[Idx++]; -} - -void PCHDeclReader::VisitAccessSpecDecl(AccessSpecDecl *D) { - VisitDecl(D); - D->setColonLoc(Reader.ReadSourceLocation(Record, Idx)); -} - -void PCHDeclReader::VisitFriendDecl(FriendDecl *D) { - VisitDecl(D); - if (Record[Idx++]) - D->Friend = Reader.GetTypeSourceInfo(Record, Idx); - else - D->Friend = cast<NamedDecl>(Reader.GetDecl(Record[Idx++])); - D->NextFriend = cast_or_null<FriendDecl>(Reader.GetDecl(Record[Idx++])); - D->FriendLoc = Reader.ReadSourceLocation(Record, Idx); -} - -void PCHDeclReader::VisitFriendTemplateDecl(FriendTemplateDecl *D) { - assert(false && "cannot read FriendTemplateDecl"); -} - -void PCHDeclReader::VisitTemplateDecl(TemplateDecl *D) { - VisitNamedDecl(D); - - NamedDecl *TemplatedDecl - = cast_or_null<NamedDecl>(Reader.GetDecl(Record[Idx++])); - TemplateParameterList* TemplateParams - = Reader.ReadTemplateParameterList(Record, Idx); - D->init(TemplatedDecl, TemplateParams); -} - -void PCHDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) { - VisitTemplateDecl(D); - - D->IdentifierNamespace = Record[Idx++]; - ClassTemplateDecl *PrevDecl = - cast_or_null<ClassTemplateDecl>(Reader.GetDecl(Record[Idx++])); - D->setPreviousDeclaration(PrevDecl); - if (PrevDecl == 0) { - // This ClassTemplateDecl owns a CommonPtr; read it. - - // FoldingSets are filled in VisitClassTemplateSpecializationDecl. - unsigned size = Record[Idx++]; - while (size--) - cast<ClassTemplateSpecializationDecl>(Reader.GetDecl(Record[Idx++])); - - size = Record[Idx++]; - while (size--) - cast<ClassTemplatePartialSpecializationDecl>( - Reader.GetDecl(Record[Idx++])); - - // InjectedClassNameType is computed. - - if (ClassTemplateDecl *CTD - = cast_or_null<ClassTemplateDecl>(Reader.GetDecl(Record[Idx++]))) { - D->setInstantiatedFromMemberTemplate(CTD); - if (Record[Idx++]) - D->setMemberSpecialization(); - } - } -} - -void PCHDeclReader::VisitClassTemplateSpecializationDecl( - ClassTemplateSpecializationDecl *D) { - VisitCXXRecordDecl(D); - - if (Decl *InstD = Reader.GetDecl(Record[Idx++])) { - if (ClassTemplateDecl *CTD = dyn_cast<ClassTemplateDecl>(InstD)) { - D->setInstantiationOf(CTD); - } else { - llvm::SmallVector<TemplateArgument, 8> TemplArgs; - Reader.ReadTemplateArgumentList(TemplArgs, Record, Idx); - D->setInstantiationOf(cast<ClassTemplatePartialSpecializationDecl>(InstD), - TemplArgs.data(), TemplArgs.size()); - } - } - - // Explicit info. - if (TypeSourceInfo *TyInfo = Reader.GetTypeSourceInfo(Record, Idx)) { - D->setTypeAsWritten(TyInfo); - D->setExternLoc(Reader.ReadSourceLocation(Record, Idx)); - D->setTemplateKeywordLoc(Reader.ReadSourceLocation(Record, Idx)); - } - - llvm::SmallVector<TemplateArgument, 8> TemplArgs; - Reader.ReadTemplateArgumentList(TemplArgs, Record, Idx); - D->initTemplateArgs(TemplArgs.data(), TemplArgs.size()); - SourceLocation POI = Reader.ReadSourceLocation(Record, Idx); - if (POI.isValid()) - D->setPointOfInstantiation(POI); - D->setSpecializationKind((TemplateSpecializationKind)Record[Idx++]); - - if (Record[Idx++]) { // IsKeptInFoldingSet. - ClassTemplateDecl *CanonPattern - = cast<ClassTemplateDecl>(Reader.GetDecl(Record[Idx++])); - if (ClassTemplatePartialSpecializationDecl *Partial - = dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) { - CanonPattern->getPartialSpecializations().InsertNode(Partial); - } else { - CanonPattern->getSpecializations().InsertNode(D); - } - } -} - -void PCHDeclReader::VisitClassTemplatePartialSpecializationDecl( - ClassTemplatePartialSpecializationDecl *D) { - VisitClassTemplateSpecializationDecl(D); - - D->initTemplateParameters(Reader.ReadTemplateParameterList(Record, Idx)); - - TemplateArgumentListInfo ArgInfos; - unsigned NumArgs = Record[Idx++]; - while (NumArgs--) - ArgInfos.addArgument(Reader.ReadTemplateArgumentLoc(Record, Idx)); - D->initTemplateArgsAsWritten(ArgInfos); - - D->setSequenceNumber(Record[Idx++]); - - // These are read/set from/to the first declaration. - if (D->getPreviousDeclaration() == 0) { - D->setInstantiatedFromMember( - cast_or_null<ClassTemplatePartialSpecializationDecl>( - Reader.GetDecl(Record[Idx++]))); - if (Record[Idx++]) - D->setMemberSpecialization(); - } -} - -void PCHDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { - VisitTemplateDecl(D); - - D->IdentifierNamespace = Record[Idx++]; - FunctionTemplateDecl *PrevDecl = - cast_or_null<FunctionTemplateDecl>(Reader.GetDecl(Record[Idx++])); - D->setPreviousDeclaration(PrevDecl); - if (PrevDecl == 0) { - // This FunctionTemplateDecl owns a CommonPtr; read it. - - // Read the function specialization declarations. - // FunctionTemplateDecl's FunctionTemplateSpecializationInfos are filled - // through the specialized FunctionDecl's setFunctionTemplateSpecialization. - unsigned NumSpecs = Record[Idx++]; - while (NumSpecs--) - Reader.GetDecl(Record[Idx++]); - - if (FunctionTemplateDecl *CTD - = cast_or_null<FunctionTemplateDecl>(Reader.GetDecl(Record[Idx++]))) { - D->setInstantiatedFromMemberTemplate(CTD); - if (Record[Idx++]) - D->setMemberSpecialization(); - } - } -} - -void PCHDeclReader::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { - VisitTypeDecl(D); - - D->setDeclaredWithTypename(Record[Idx++]); - D->setParameterPack(Record[Idx++]); - - bool Inherited = Record[Idx++]; - TypeSourceInfo *DefArg = Reader.GetTypeSourceInfo(Record, Idx); - D->setDefaultArgument(DefArg, Inherited); -} - -void PCHDeclReader::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) { - VisitVarDecl(D); - // TemplateParmPosition. - D->setDepth(Record[Idx++]); - D->setPosition(Record[Idx++]); - // Rest of NonTypeTemplateParmDecl. - if (Record[Idx++]) { - Expr *DefArg = Reader.ReadExpr(); - bool Inherited = Record[Idx++]; - D->setDefaultArgument(DefArg, Inherited); - } -} - -void PCHDeclReader::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) { - VisitTemplateDecl(D); - // TemplateParmPosition. - D->setDepth(Record[Idx++]); - D->setPosition(Record[Idx++]); - // Rest of TemplateTemplateParmDecl. - TemplateArgumentLoc Arg = Reader.ReadTemplateArgumentLoc(Record, Idx); - bool IsInherited = Record[Idx++]; - D->setDefaultArgument(Arg, IsInherited); -} - -void PCHDeclReader::VisitStaticAssertDecl(StaticAssertDecl *D) { - assert(false && "cannot read StaticAssertDecl"); -} - -std::pair<uint64_t, uint64_t> -PCHDeclReader::VisitDeclContext(DeclContext *DC) { - uint64_t LexicalOffset = Record[Idx++]; - uint64_t VisibleOffset = Record[Idx++]; - return std::make_pair(LexicalOffset, VisibleOffset); -} - -//===----------------------------------------------------------------------===// -// Attribute Reading -//===----------------------------------------------------------------------===// - -/// \brief Reads attributes from the current stream position. -Attr *PCHReader::ReadAttributes() { - unsigned Code = DeclsCursor.ReadCode(); - assert(Code == llvm::bitc::UNABBREV_RECORD && - "Expected unabbreviated record"); (void)Code; - - RecordData Record; - unsigned Idx = 0; - unsigned RecCode = DeclsCursor.ReadRecord(Code, Record); - assert(RecCode == pch::DECL_ATTR && "Expected attribute record"); - (void)RecCode; - -#define SIMPLE_ATTR(Name) \ - case attr::Name: \ - New = ::new (*Context) Name##Attr(); \ - break - -#define STRING_ATTR(Name) \ - case attr::Name: \ - New = ::new (*Context) Name##Attr(*Context, ReadString(Record, Idx)); \ - break - -#define UNSIGNED_ATTR(Name) \ - case attr::Name: \ - New = ::new (*Context) Name##Attr(Record[Idx++]); \ - break - - Attr *Attrs = 0; - while (Idx < Record.size()) { - Attr *New = 0; - attr::Kind Kind = (attr::Kind)Record[Idx++]; - bool IsInherited = Record[Idx++]; - - switch (Kind) { - default: - assert(0 && "Unknown attribute!"); - break; - STRING_ATTR(Alias); - SIMPLE_ATTR(AlignMac68k); - UNSIGNED_ATTR(Aligned); - SIMPLE_ATTR(AlwaysInline); - SIMPLE_ATTR(AnalyzerNoReturn); - STRING_ATTR(Annotate); - STRING_ATTR(AsmLabel); - SIMPLE_ATTR(BaseCheck); - - case attr::Blocks: - New = ::new (*Context) BlocksAttr( - (BlocksAttr::BlocksAttrTypes)Record[Idx++]); - break; - - SIMPLE_ATTR(CDecl); - - case attr::Cleanup: - New = ::new (*Context) CleanupAttr( - cast<FunctionDecl>(GetDecl(Record[Idx++]))); - break; - - SIMPLE_ATTR(Const); - UNSIGNED_ATTR(Constructor); - SIMPLE_ATTR(DLLExport); - SIMPLE_ATTR(DLLImport); - SIMPLE_ATTR(Deprecated); - UNSIGNED_ATTR(Destructor); - SIMPLE_ATTR(FastCall); - SIMPLE_ATTR(Final); - - case attr::Format: { - std::string Type = ReadString(Record, Idx); - unsigned FormatIdx = Record[Idx++]; - unsigned FirstArg = Record[Idx++]; - New = ::new (*Context) FormatAttr(*Context, Type, FormatIdx, FirstArg); - break; - } - - case attr::FormatArg: { - unsigned FormatIdx = Record[Idx++]; - New = ::new (*Context) FormatArgAttr(FormatIdx); - break; - } - - case attr::Sentinel: { - int sentinel = Record[Idx++]; - int nullPos = Record[Idx++]; - New = ::new (*Context) SentinelAttr(sentinel, nullPos); - break; - } - - SIMPLE_ATTR(GNUInline); - SIMPLE_ATTR(Hiding); - - case attr::IBAction: - New = ::new (*Context) IBActionAttr(); - break; - - case attr::IBOutlet: - New = ::new (*Context) IBOutletAttr(); - break; - - case attr::IBOutletCollection: { - ObjCInterfaceDecl *D = - cast_or_null<ObjCInterfaceDecl>(GetDecl(Record[Idx++])); - New = ::new (*Context) IBOutletCollectionAttr(D); - break; - } - - SIMPLE_ATTR(Malloc); - SIMPLE_ATTR(NoDebug); - SIMPLE_ATTR(NoInline); - SIMPLE_ATTR(NoReturn); - SIMPLE_ATTR(NoThrow); - - case attr::NonNull: { - unsigned Size = Record[Idx++]; - llvm::SmallVector<unsigned, 16> ArgNums; - ArgNums.insert(ArgNums.end(), &Record[Idx], &Record[Idx] + Size); - Idx += Size; - New = ::new (*Context) NonNullAttr(*Context, ArgNums.data(), Size); - break; - } - - case attr::ReqdWorkGroupSize: { - unsigned X = Record[Idx++]; - unsigned Y = Record[Idx++]; - unsigned Z = Record[Idx++]; - New = ::new (*Context) ReqdWorkGroupSizeAttr(X, Y, Z); - break; - } - - SIMPLE_ATTR(ObjCException); - SIMPLE_ATTR(ObjCNSObject); - SIMPLE_ATTR(CFReturnsNotRetained); - SIMPLE_ATTR(CFReturnsRetained); - SIMPLE_ATTR(NSReturnsNotRetained); - SIMPLE_ATTR(NSReturnsRetained); - SIMPLE_ATTR(Overloadable); - SIMPLE_ATTR(Override); - SIMPLE_ATTR(Packed); - UNSIGNED_ATTR(MaxFieldAlignment); - SIMPLE_ATTR(Pure); - UNSIGNED_ATTR(Regparm); - STRING_ATTR(Section); - SIMPLE_ATTR(StdCall); - SIMPLE_ATTR(ThisCall); - SIMPLE_ATTR(TransparentUnion); - SIMPLE_ATTR(Unavailable); - SIMPLE_ATTR(Unused); - SIMPLE_ATTR(Used); - - case attr::Visibility: - New = ::new (*Context) VisibilityAttr( - (VisibilityAttr::VisibilityTypes)Record[Idx++]); - break; - - SIMPLE_ATTR(WarnUnusedResult); - SIMPLE_ATTR(Weak); - SIMPLE_ATTR(WeakRef); - SIMPLE_ATTR(WeakImport); - } - - assert(New && "Unable to decode attribute?"); - New->setInherited(IsInherited); - New->setNext(Attrs); - Attrs = New; - } -#undef UNSIGNED_ATTR -#undef STRING_ATTR -#undef SIMPLE_ATTR - - // The list of attributes was built backwards. Reverse the list - // before returning it. - Attr *PrevAttr = 0, *NextAttr = 0; - while (Attrs) { - NextAttr = Attrs->getNext(); - Attrs->setNext(PrevAttr); - PrevAttr = Attrs; - Attrs = NextAttr; - } - - return PrevAttr; -} - -//===----------------------------------------------------------------------===// -// PCHReader Implementation -//===----------------------------------------------------------------------===// - -/// \brief Note that we have loaded the declaration with the given -/// Index. -/// -/// This routine notes that this declaration has already been loaded, -/// so that future GetDecl calls will return this declaration rather -/// than trying to load a new declaration. -inline void PCHReader::LoadedDecl(unsigned Index, Decl *D) { - assert(!DeclsLoaded[Index] && "Decl loaded twice?"); - DeclsLoaded[Index] = D; -} - - -/// \brief Determine whether the consumer will be interested in seeing -/// this declaration (via HandleTopLevelDecl). -/// -/// This routine should return true for anything that might affect -/// code generation, e.g., inline function definitions, Objective-C -/// declarations with metadata, etc. -static bool isConsumerInterestedIn(Decl *D) { - if (isa<FileScopeAsmDecl>(D)) - return true; - if (VarDecl *Var = dyn_cast<VarDecl>(D)) - return Var->isFileVarDecl() && Var->getInit(); - if (FunctionDecl *Func = dyn_cast<FunctionDecl>(D)) - return Func->isThisDeclarationADefinition(); - return isa<ObjCProtocolDecl>(D); -} - -/// \brief Read the declaration at the given offset from the PCH file. -Decl *PCHReader::ReadDeclRecord(uint64_t Offset, unsigned Index) { - // Keep track of where we are in the stream, then jump back there - // after reading this declaration. - SavedStreamPosition SavedPosition(DeclsCursor); - - ReadingKindTracker ReadingKind(Read_Decl, *this); - - // Note that we are loading a declaration record. - LoadingTypeOrDecl Loading(*this); - - DeclsCursor.JumpToBit(Offset); - RecordData Record; - unsigned Code = DeclsCursor.ReadCode(); - unsigned Idx = 0; - PCHDeclReader Reader(*this, Record, Idx); - - Decl *D = 0; - switch ((pch::DeclCode)DeclsCursor.ReadRecord(Code, Record)) { - case pch::DECL_ATTR: - case pch::DECL_CONTEXT_LEXICAL: - case pch::DECL_CONTEXT_VISIBLE: - assert(false && "Record cannot be de-serialized with ReadDeclRecord"); - break; - case pch::DECL_TRANSLATION_UNIT: - assert(Index == 0 && "Translation unit must be at index 0"); - D = Context->getTranslationUnitDecl(); - break; - case pch::DECL_TYPEDEF: - D = TypedefDecl::Create(*Context, 0, SourceLocation(), 0, 0); - break; - case pch::DECL_ENUM: - D = EnumDecl::Create(*Context, Decl::EmptyShell()); - break; - case pch::DECL_RECORD: - D = RecordDecl::Create(*Context, Decl::EmptyShell()); - break; - case pch::DECL_ENUM_CONSTANT: - D = EnumConstantDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), - 0, llvm::APSInt()); - break; - case pch::DECL_FUNCTION: - D = FunctionDecl::Create(*Context, 0, SourceLocation(), DeclarationName(), - QualType(), 0); - break; - case pch::DECL_LINKAGE_SPEC: - D = LinkageSpecDecl::Create(*Context, 0, SourceLocation(), - (LinkageSpecDecl::LanguageIDs)0, - false); - break; - case pch::DECL_NAMESPACE: - D = NamespaceDecl::Create(*Context, 0, SourceLocation(), 0); - break; - case pch::DECL_NAMESPACE_ALIAS: - D = NamespaceAliasDecl::Create(*Context, 0, SourceLocation(), - SourceLocation(), 0, SourceRange(), 0, - SourceLocation(), 0); - break; - case pch::DECL_USING: - D = UsingDecl::Create(*Context, 0, SourceLocation(), SourceRange(), - SourceLocation(), 0, DeclarationName(), false); - break; - case pch::DECL_USING_SHADOW: - D = UsingShadowDecl::Create(*Context, 0, SourceLocation(), 0, 0); - break; - case pch::DECL_USING_DIRECTIVE: - D = UsingDirectiveDecl::Create(*Context, 0, SourceLocation(), - SourceLocation(), SourceRange(), 0, - SourceLocation(), 0, 0); - break; - case pch::DECL_UNRESOLVED_USING_VALUE: - D = UnresolvedUsingValueDecl::Create(*Context, 0, SourceLocation(), - SourceRange(), 0, SourceLocation(), - DeclarationName()); - break; - case pch::DECL_UNRESOLVED_USING_TYPENAME: - D = UnresolvedUsingTypenameDecl::Create(*Context, 0, SourceLocation(), - SourceLocation(), SourceRange(), - 0, SourceLocation(), - DeclarationName()); - break; - case pch::DECL_CXX_RECORD: - D = CXXRecordDecl::Create(*Context, Decl::EmptyShell()); - break; - case pch::DECL_CXX_METHOD: - D = CXXMethodDecl::Create(*Context, 0, SourceLocation(), DeclarationName(), - QualType(), 0); - break; - case pch::DECL_CXX_CONSTRUCTOR: - D = CXXConstructorDecl::Create(*Context, Decl::EmptyShell()); - break; - case pch::DECL_CXX_DESTRUCTOR: - D = CXXDestructorDecl::Create(*Context, Decl::EmptyShell()); - break; - case pch::DECL_CXX_CONVERSION: - D = CXXConversionDecl::Create(*Context, Decl::EmptyShell()); - break; - case pch::DECL_ACCESS_SPEC: - D = AccessSpecDecl::Create(*Context, AS_none, 0, SourceLocation(), - SourceLocation()); - break; - case pch::DECL_FRIEND: - D = FriendDecl::Create(*Context, Decl::EmptyShell()); - break; - case pch::DECL_FRIEND_TEMPLATE: - assert(false && "cannot read FriendTemplateDecl"); - break; - case pch::DECL_CLASS_TEMPLATE: - D = ClassTemplateDecl::Create(*Context, 0, SourceLocation(), - DeclarationName(), 0, 0, 0); - break; - case pch::DECL_CLASS_TEMPLATE_SPECIALIZATION: - D = ClassTemplateSpecializationDecl::Create(*Context, Decl::EmptyShell()); - break; - case pch::DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION: - D = ClassTemplatePartialSpecializationDecl::Create(*Context, - Decl::EmptyShell()); - break; - case pch::DECL_FUNCTION_TEMPLATE: - D = FunctionTemplateDecl::Create(*Context, 0, SourceLocation(), - DeclarationName(), 0, 0); - break; - case pch::DECL_TEMPLATE_TYPE_PARM: - D = TemplateTypeParmDecl::Create(*Context, Decl::EmptyShell()); - break; - case pch::DECL_NON_TYPE_TEMPLATE_PARM: - D = NonTypeTemplateParmDecl::Create(*Context, 0, SourceLocation(), 0,0,0, - QualType(),0); - break; - case pch::DECL_TEMPLATE_TEMPLATE_PARM: - D = TemplateTemplateParmDecl::Create(*Context, 0, SourceLocation(),0,0,0,0); - break; - case pch::DECL_STATIC_ASSERT: - assert(false && "cannot read StaticAssertDecl"); - break; - - case pch::DECL_OBJC_METHOD: - D = ObjCMethodDecl::Create(*Context, SourceLocation(), SourceLocation(), - Selector(), QualType(), 0, 0); - break; - case pch::DECL_OBJC_INTERFACE: - D = ObjCInterfaceDecl::Create(*Context, 0, SourceLocation(), 0); - break; - case pch::DECL_OBJC_IVAR: - D = ObjCIvarDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0, - ObjCIvarDecl::None); - break; - case pch::DECL_OBJC_PROTOCOL: - D = ObjCProtocolDecl::Create(*Context, 0, SourceLocation(), 0); - break; - case pch::DECL_OBJC_AT_DEFS_FIELD: - D = ObjCAtDefsFieldDecl::Create(*Context, 0, SourceLocation(), 0, - QualType(), 0); - break; - case pch::DECL_OBJC_CLASS: - D = ObjCClassDecl::Create(*Context, 0, SourceLocation()); - break; - case pch::DECL_OBJC_FORWARD_PROTOCOL: - D = ObjCForwardProtocolDecl::Create(*Context, 0, SourceLocation()); - break; - case pch::DECL_OBJC_CATEGORY: - D = ObjCCategoryDecl::Create(*Context, 0, SourceLocation(), - SourceLocation(), SourceLocation(), 0); - break; - case pch::DECL_OBJC_CATEGORY_IMPL: - D = ObjCCategoryImplDecl::Create(*Context, 0, SourceLocation(), 0, 0); - break; - case pch::DECL_OBJC_IMPLEMENTATION: - D = ObjCImplementationDecl::Create(*Context, 0, SourceLocation(), 0, 0); - break; - case pch::DECL_OBJC_COMPATIBLE_ALIAS: - D = ObjCCompatibleAliasDecl::Create(*Context, 0, SourceLocation(), 0, 0); - break; - case pch::DECL_OBJC_PROPERTY: - D = ObjCPropertyDecl::Create(*Context, 0, SourceLocation(), 0, SourceLocation(), - 0); - break; - case pch::DECL_OBJC_PROPERTY_IMPL: - D = ObjCPropertyImplDecl::Create(*Context, 0, SourceLocation(), - SourceLocation(), 0, - ObjCPropertyImplDecl::Dynamic, 0); - break; - case pch::DECL_FIELD: - D = FieldDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0, 0, - false); - break; - case pch::DECL_VAR: - D = VarDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0, - VarDecl::None, VarDecl::None); - break; - - case pch::DECL_IMPLICIT_PARAM: - D = ImplicitParamDecl::Create(*Context, 0, SourceLocation(), 0, QualType()); - break; - - case pch::DECL_PARM_VAR: - D = ParmVarDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0, - VarDecl::None, VarDecl::None, 0); - break; - case pch::DECL_FILE_SCOPE_ASM: - D = FileScopeAsmDecl::Create(*Context, 0, SourceLocation(), 0); - break; - case pch::DECL_BLOCK: - D = BlockDecl::Create(*Context, 0, SourceLocation()); - break; - } - - assert(D && "Unknown declaration reading PCH file"); - LoadedDecl(Index, D); - Reader.Visit(D); - - // If this declaration is also a declaration context, get the - // offsets for its tables of lexical and visible declarations. - if (DeclContext *DC = dyn_cast<DeclContext>(D)) { - std::pair<uint64_t, uint64_t> Offsets = Reader.VisitDeclContext(DC); - if (Offsets.first || Offsets.second) { - DC->setHasExternalLexicalStorage(Offsets.first != 0); - DC->setHasExternalVisibleStorage(Offsets.second != 0); - DeclContextOffsets[DC] = Offsets; - } - } - assert(Idx == Record.size()); - - // If we have deserialized a declaration that has a definition the - // AST consumer might need to know about, queue it. - // We don't pass it to the consumer immediately because we may be in recursive - // loading, and some declarations may still be initializing. - if (isConsumerInterestedIn(D)) - InterestingDecls.push_back(D); - - return D; -} diff --git a/lib/Frontend/PCHReaderStmt.cpp b/lib/Frontend/PCHReaderStmt.cpp deleted file mode 100644 index ace62d7..0000000 --- a/lib/Frontend/PCHReaderStmt.cpp +++ /dev/null @@ -1,1727 +0,0 @@ -//===--- PCHReaderStmt.cpp - Stmt/Expr Deserialization ----------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Statement/expression deserialization. This implements the -// PCHReader::ReadStmt method. -// -//===----------------------------------------------------------------------===// - -#include "clang/Frontend/PCHReader.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/StmtVisitor.h" -using namespace clang; - -namespace clang { - - class PCHStmtReader : public StmtVisitor<PCHStmtReader> { - PCHReader &Reader; - const PCHReader::RecordData &Record; - unsigned &Idx; - - public: - PCHStmtReader(PCHReader &Reader, const PCHReader::RecordData &Record, - unsigned &Idx) - : Reader(Reader), Record(Record), Idx(Idx) { } - - /// \brief The number of record fields required for the Stmt class - /// itself. - static const unsigned NumStmtFields = 0; - - /// \brief The number of record fields required for the Expr class - /// itself. - static const unsigned NumExprFields = NumStmtFields + 3; - - /// \brief Read and initialize a ExplicitTemplateArgumentList structure. - void ReadExplicitTemplateArgumentList(ExplicitTemplateArgumentList &ArgList, - unsigned NumTemplateArgs); - - void VisitStmt(Stmt *S); - void VisitNullStmt(NullStmt *S); - void VisitCompoundStmt(CompoundStmt *S); - void VisitSwitchCase(SwitchCase *S); - void VisitCaseStmt(CaseStmt *S); - void VisitDefaultStmt(DefaultStmt *S); - void VisitLabelStmt(LabelStmt *S); - void VisitIfStmt(IfStmt *S); - void VisitSwitchStmt(SwitchStmt *S); - void VisitWhileStmt(WhileStmt *S); - void VisitDoStmt(DoStmt *S); - void VisitForStmt(ForStmt *S); - void VisitGotoStmt(GotoStmt *S); - void VisitIndirectGotoStmt(IndirectGotoStmt *S); - void VisitContinueStmt(ContinueStmt *S); - void VisitBreakStmt(BreakStmt *S); - void VisitReturnStmt(ReturnStmt *S); - void VisitDeclStmt(DeclStmt *S); - void VisitAsmStmt(AsmStmt *S); - void VisitExpr(Expr *E); - void VisitPredefinedExpr(PredefinedExpr *E); - void VisitDeclRefExpr(DeclRefExpr *E); - void VisitIntegerLiteral(IntegerLiteral *E); - void VisitFloatingLiteral(FloatingLiteral *E); - void VisitImaginaryLiteral(ImaginaryLiteral *E); - void VisitStringLiteral(StringLiteral *E); - void VisitCharacterLiteral(CharacterLiteral *E); - void VisitParenExpr(ParenExpr *E); - void VisitParenListExpr(ParenListExpr *E); - void VisitUnaryOperator(UnaryOperator *E); - void VisitOffsetOfExpr(OffsetOfExpr *E); - void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E); - void VisitArraySubscriptExpr(ArraySubscriptExpr *E); - void VisitCallExpr(CallExpr *E); - void VisitMemberExpr(MemberExpr *E); - void VisitCastExpr(CastExpr *E); - void VisitBinaryOperator(BinaryOperator *E); - void VisitCompoundAssignOperator(CompoundAssignOperator *E); - void VisitConditionalOperator(ConditionalOperator *E); - void VisitImplicitCastExpr(ImplicitCastExpr *E); - void VisitExplicitCastExpr(ExplicitCastExpr *E); - void VisitCStyleCastExpr(CStyleCastExpr *E); - void VisitCompoundLiteralExpr(CompoundLiteralExpr *E); - void VisitExtVectorElementExpr(ExtVectorElementExpr *E); - void VisitInitListExpr(InitListExpr *E); - void VisitDesignatedInitExpr(DesignatedInitExpr *E); - void VisitImplicitValueInitExpr(ImplicitValueInitExpr *E); - void VisitVAArgExpr(VAArgExpr *E); - void VisitAddrLabelExpr(AddrLabelExpr *E); - void VisitStmtExpr(StmtExpr *E); - void VisitTypesCompatibleExpr(TypesCompatibleExpr *E); - void VisitChooseExpr(ChooseExpr *E); - void VisitGNUNullExpr(GNUNullExpr *E); - void VisitShuffleVectorExpr(ShuffleVectorExpr *E); - void VisitBlockExpr(BlockExpr *E); - void VisitBlockDeclRefExpr(BlockDeclRefExpr *E); - void VisitObjCStringLiteral(ObjCStringLiteral *E); - void VisitObjCEncodeExpr(ObjCEncodeExpr *E); - void VisitObjCSelectorExpr(ObjCSelectorExpr *E); - void VisitObjCProtocolExpr(ObjCProtocolExpr *E); - void VisitObjCIvarRefExpr(ObjCIvarRefExpr *E); - void VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E); - void VisitObjCImplicitSetterGetterRefExpr( - ObjCImplicitSetterGetterRefExpr *E); - void VisitObjCMessageExpr(ObjCMessageExpr *E); - void VisitObjCSuperExpr(ObjCSuperExpr *E); - void VisitObjCIsaExpr(ObjCIsaExpr *E); - - void VisitObjCForCollectionStmt(ObjCForCollectionStmt *); - void VisitObjCAtCatchStmt(ObjCAtCatchStmt *); - void VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *); - void VisitObjCAtTryStmt(ObjCAtTryStmt *); - void VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *); - void VisitObjCAtThrowStmt(ObjCAtThrowStmt *); - - void VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E); - void VisitCXXConstructExpr(CXXConstructExpr *E); - void VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E); - void VisitCXXNamedCastExpr(CXXNamedCastExpr *E); - void VisitCXXStaticCastExpr(CXXStaticCastExpr *E); - void VisitCXXDynamicCastExpr(CXXDynamicCastExpr *E); - void VisitCXXReinterpretCastExpr(CXXReinterpretCastExpr *E); - void VisitCXXConstCastExpr(CXXConstCastExpr *E); - void VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E); - void VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E); - void VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E); - void VisitCXXTypeidExpr(CXXTypeidExpr *E); - void VisitCXXThisExpr(CXXThisExpr *E); - void VisitCXXThrowExpr(CXXThrowExpr *E); - void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E); - void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E); - void VisitCXXBindReferenceExpr(CXXBindReferenceExpr *E); - - void VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E); - void VisitCXXNewExpr(CXXNewExpr *E); - void VisitCXXDeleteExpr(CXXDeleteExpr *E); - void VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E); - - void VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E); - - void VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E); - void VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E); - void VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E); - - void VisitOverloadExpr(OverloadExpr *E); - void VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E); - void VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E); - - void VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E); - }; -} - -void PCHStmtReader:: -ReadExplicitTemplateArgumentList(ExplicitTemplateArgumentList &ArgList, - unsigned NumTemplateArgs) { - TemplateArgumentListInfo ArgInfo; - ArgInfo.setLAngleLoc(Reader.ReadSourceLocation(Record, Idx)); - ArgInfo.setRAngleLoc(Reader.ReadSourceLocation(Record, Idx)); - for (unsigned i = 0; i != NumTemplateArgs; ++i) - ArgInfo.addArgument(Reader.ReadTemplateArgumentLoc(Record, Idx)); - ArgList.initializeFrom(ArgInfo); -} - -void PCHStmtReader::VisitStmt(Stmt *S) { - assert(Idx == NumStmtFields && "Incorrect statement field count"); -} - -void PCHStmtReader::VisitNullStmt(NullStmt *S) { - VisitStmt(S); - S->setSemiLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitCompoundStmt(CompoundStmt *S) { - VisitStmt(S); - llvm::SmallVector<Stmt *, 16> Stmts; - unsigned NumStmts = Record[Idx++]; - while (NumStmts--) - Stmts.push_back(Reader.ReadSubStmt()); - S->setStmts(*Reader.getContext(), Stmts.data(), Stmts.size()); - S->setLBracLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - S->setRBracLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitSwitchCase(SwitchCase *S) { - VisitStmt(S); - Reader.RecordSwitchCaseID(S, Record[Idx++]); -} - -void PCHStmtReader::VisitCaseStmt(CaseStmt *S) { - VisitSwitchCase(S); - S->setLHS(Reader.ReadSubExpr()); - S->setRHS(Reader.ReadSubExpr()); - S->setSubStmt(Reader.ReadSubStmt()); - S->setCaseLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - S->setEllipsisLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - S->setColonLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitDefaultStmt(DefaultStmt *S) { - VisitSwitchCase(S); - S->setSubStmt(Reader.ReadSubStmt()); - S->setDefaultLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - S->setColonLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitLabelStmt(LabelStmt *S) { - VisitStmt(S); - S->setID(Reader.GetIdentifierInfo(Record, Idx)); - S->setSubStmt(Reader.ReadSubStmt()); - S->setIdentLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - Reader.RecordLabelStmt(S, Record[Idx++]); -} - -void PCHStmtReader::VisitIfStmt(IfStmt *S) { - VisitStmt(S); - S->setConditionVariable(*Reader.getContext(), - cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++]))); - S->setCond(Reader.ReadSubExpr()); - S->setThen(Reader.ReadSubStmt()); - S->setElse(Reader.ReadSubStmt()); - S->setIfLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - S->setElseLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitSwitchStmt(SwitchStmt *S) { - VisitStmt(S); - S->setConditionVariable(*Reader.getContext(), - cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++]))); - S->setCond(Reader.ReadSubExpr()); - S->setBody(Reader.ReadSubStmt()); - S->setSwitchLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - SwitchCase *PrevSC = 0; - for (unsigned N = Record.size(); Idx != N; ++Idx) { - SwitchCase *SC = Reader.getSwitchCaseWithID(Record[Idx]); - if (PrevSC) - PrevSC->setNextSwitchCase(SC); - else - S->setSwitchCaseList(SC); - - // Retain this SwitchCase, since SwitchStmt::addSwitchCase() would - // normally retain it (but we aren't calling addSwitchCase). - SC->Retain(); - PrevSC = SC; - } -} - -void PCHStmtReader::VisitWhileStmt(WhileStmt *S) { - VisitStmt(S); - S->setConditionVariable(*Reader.getContext(), - cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++]))); - S->setCond(Reader.ReadSubExpr()); - S->setBody(Reader.ReadSubStmt()); - S->setWhileLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitDoStmt(DoStmt *S) { - VisitStmt(S); - S->setCond(Reader.ReadSubExpr()); - S->setBody(Reader.ReadSubStmt()); - S->setDoLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - S->setWhileLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - S->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitForStmt(ForStmt *S) { - VisitStmt(S); - S->setInit(Reader.ReadSubStmt()); - S->setCond(Reader.ReadSubExpr()); - S->setConditionVariable(*Reader.getContext(), - cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++]))); - S->setInc(Reader.ReadSubExpr()); - S->setBody(Reader.ReadSubStmt()); - S->setForLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - S->setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - S->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitGotoStmt(GotoStmt *S) { - VisitStmt(S); - Reader.SetLabelOf(S, Record[Idx++]); - S->setGotoLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - S->setLabelLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitIndirectGotoStmt(IndirectGotoStmt *S) { - VisitStmt(S); - S->setGotoLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - S->setStarLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - S->setTarget(Reader.ReadSubExpr()); -} - -void PCHStmtReader::VisitContinueStmt(ContinueStmt *S) { - VisitStmt(S); - S->setContinueLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitBreakStmt(BreakStmt *S) { - VisitStmt(S); - S->setBreakLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitReturnStmt(ReturnStmt *S) { - VisitStmt(S); - S->setRetValue(Reader.ReadSubExpr()); - S->setReturnLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - S->setNRVOCandidate(cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++]))); -} - -void PCHStmtReader::VisitDeclStmt(DeclStmt *S) { - VisitStmt(S); - S->setStartLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - S->setEndLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - - if (Idx + 1 == Record.size()) { - // Single declaration - S->setDeclGroup(DeclGroupRef(Reader.GetDecl(Record[Idx++]))); - } else { - llvm::SmallVector<Decl *, 16> Decls; - Decls.reserve(Record.size() - Idx); - for (unsigned N = Record.size(); Idx != N; ++Idx) - Decls.push_back(Reader.GetDecl(Record[Idx])); - S->setDeclGroup(DeclGroupRef(DeclGroup::Create(*Reader.getContext(), - Decls.data(), - Decls.size()))); - } -} - -void PCHStmtReader::VisitAsmStmt(AsmStmt *S) { - VisitStmt(S); - unsigned NumOutputs = Record[Idx++]; - unsigned NumInputs = Record[Idx++]; - unsigned NumClobbers = Record[Idx++]; - S->setAsmLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - S->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - S->setVolatile(Record[Idx++]); - S->setSimple(Record[Idx++]); - S->setMSAsm(Record[Idx++]); - - S->setAsmString(cast_or_null<StringLiteral>(Reader.ReadSubStmt())); - - // Outputs and inputs - llvm::SmallVector<IdentifierInfo *, 16> Names; - llvm::SmallVector<StringLiteral*, 16> Constraints; - llvm::SmallVector<Stmt*, 16> Exprs; - for (unsigned I = 0, N = NumOutputs + NumInputs; I != N; ++I) { - Names.push_back(Reader.GetIdentifierInfo(Record, Idx)); - Constraints.push_back(cast_or_null<StringLiteral>(Reader.ReadSubStmt())); - Exprs.push_back(Reader.ReadSubStmt()); - } - - // Constraints - llvm::SmallVector<StringLiteral*, 16> Clobbers; - for (unsigned I = 0; I != NumClobbers; ++I) - Clobbers.push_back(cast_or_null<StringLiteral>(Reader.ReadSubStmt())); - - S->setOutputsAndInputsAndClobbers(*Reader.getContext(), - Names.data(), Constraints.data(), - Exprs.data(), NumOutputs, NumInputs, - Clobbers.data(), NumClobbers); -} - -void PCHStmtReader::VisitExpr(Expr *E) { - VisitStmt(E); - E->setType(Reader.GetType(Record[Idx++])); - E->setTypeDependent(Record[Idx++]); - E->setValueDependent(Record[Idx++]); - assert(Idx == NumExprFields && "Incorrect expression field count"); -} - -void PCHStmtReader::VisitPredefinedExpr(PredefinedExpr *E) { - VisitExpr(E); - E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setIdentType((PredefinedExpr::IdentType)Record[Idx++]); -} - -void PCHStmtReader::VisitDeclRefExpr(DeclRefExpr *E) { - VisitExpr(E); - - bool HasQualifier = Record[Idx++]; - unsigned NumTemplateArgs = Record[Idx++]; - - E->DecoratedD.setInt((HasQualifier? DeclRefExpr::HasQualifierFlag : 0) | - (NumTemplateArgs ? DeclRefExpr::HasExplicitTemplateArgumentListFlag : 0)); - - if (HasQualifier) { - E->getNameQualifier()->NNS = Reader.ReadNestedNameSpecifier(Record, Idx); - E->getNameQualifier()->Range = Reader.ReadSourceRange(Record, Idx); - } - - if (NumTemplateArgs) - ReadExplicitTemplateArgumentList(*E->getExplicitTemplateArgumentList(), - NumTemplateArgs); - - E->setDecl(cast<ValueDecl>(Reader.GetDecl(Record[Idx++]))); - E->setLocation(Reader.ReadSourceLocation(Record, Idx)); -} - -void PCHStmtReader::VisitIntegerLiteral(IntegerLiteral *E) { - VisitExpr(E); - E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setValue(Reader.ReadAPInt(Record, Idx)); -} - -void PCHStmtReader::VisitFloatingLiteral(FloatingLiteral *E) { - VisitExpr(E); - E->setValue(Reader.ReadAPFloat(Record, Idx)); - E->setExact(Record[Idx++]); - E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitImaginaryLiteral(ImaginaryLiteral *E) { - VisitExpr(E); - E->setSubExpr(Reader.ReadSubExpr()); -} - -void PCHStmtReader::VisitStringLiteral(StringLiteral *E) { - VisitExpr(E); - unsigned Len = Record[Idx++]; - assert(Record[Idx] == E->getNumConcatenated() && - "Wrong number of concatenated tokens!"); - ++Idx; - E->setWide(Record[Idx++]); - - // Read string data - llvm::SmallString<16> Str(&Record[Idx], &Record[Idx] + Len); - E->setString(*Reader.getContext(), Str.str()); - Idx += Len; - - // Read source locations - for (unsigned I = 0, N = E->getNumConcatenated(); I != N; ++I) - E->setStrTokenLoc(I, SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitCharacterLiteral(CharacterLiteral *E) { - VisitExpr(E); - E->setValue(Record[Idx++]); - E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setWide(Record[Idx++]); -} - -void PCHStmtReader::VisitParenExpr(ParenExpr *E) { - VisitExpr(E); - E->setLParen(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setRParen(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setSubExpr(Reader.ReadSubExpr()); -} - -void PCHStmtReader::VisitParenListExpr(ParenListExpr *E) { - VisitExpr(E); - unsigned NumExprs = Record[Idx++]; - E->Exprs = new (*Reader.getContext()) Stmt*[NumExprs]; - for (unsigned i = 0; i != NumExprs; ++i) - E->Exprs[i] = Reader.ReadSubStmt(); - E->NumExprs = NumExprs; - E->LParenLoc = Reader.ReadSourceLocation(Record, Idx); - E->RParenLoc = Reader.ReadSourceLocation(Record, Idx); -} - -void PCHStmtReader::VisitUnaryOperator(UnaryOperator *E) { - VisitExpr(E); - E->setSubExpr(Reader.ReadSubExpr()); - E->setOpcode((UnaryOperator::Opcode)Record[Idx++]); - E->setOperatorLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitOffsetOfExpr(OffsetOfExpr *E) { - typedef OffsetOfExpr::OffsetOfNode Node; - VisitExpr(E); - assert(E->getNumComponents() == Record[Idx]); - ++Idx; - assert(E->getNumExpressions() == Record[Idx]); - ++Idx; - E->setOperatorLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setTypeSourceInfo(Reader.GetTypeSourceInfo(Record, Idx)); - for (unsigned I = 0, N = E->getNumComponents(); I != N; ++I) { - Node::Kind Kind = static_cast<Node::Kind>(Record[Idx++]); - SourceLocation Start = SourceLocation::getFromRawEncoding(Record[Idx++]); - SourceLocation End = SourceLocation::getFromRawEncoding(Record[Idx++]); - switch (Kind) { - case Node::Array: - E->setComponent(I, Node(Start, Record[Idx++], End)); - break; - - case Node::Field: - E->setComponent(I, - Node(Start, - dyn_cast_or_null<FieldDecl>(Reader.GetDecl(Record[Idx++])), - End)); - break; - - case Node::Identifier: - E->setComponent(I, Node(Start, Reader.GetIdentifier(Record[Idx++]), End)); - break; - - case Node::Base: - // FIXME: Implement this! - llvm_unreachable("PCH for offsetof(base-specifier) not implemented"); - break; - } - } - - for (unsigned I = 0, N = E->getNumExpressions(); I != N; ++I) - E->setIndexExpr(I, Reader.ReadSubExpr()); -} - -void PCHStmtReader::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) { - VisitExpr(E); - E->setSizeof(Record[Idx++]); - if (Record[Idx] == 0) { - E->setArgument(Reader.ReadSubExpr()); - ++Idx; - } else { - E->setArgument(Reader.GetTypeSourceInfo(Record, Idx)); - } - E->setOperatorLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitArraySubscriptExpr(ArraySubscriptExpr *E) { - VisitExpr(E); - E->setLHS(Reader.ReadSubExpr()); - E->setRHS(Reader.ReadSubExpr()); - E->setRBracketLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitCallExpr(CallExpr *E) { - VisitExpr(E); - E->setNumArgs(*Reader.getContext(), Record[Idx++]); - E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setCallee(Reader.ReadSubExpr()); - for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) - E->setArg(I, Reader.ReadSubExpr()); -} - -void PCHStmtReader::VisitMemberExpr(MemberExpr *E) { - // Don't call VisitExpr, this is fully initialized at creation. - assert(E->getStmtClass() == Stmt::MemberExprClass && - "It's a subclass, we must advance Idx!"); -} - -void PCHStmtReader::VisitObjCIsaExpr(ObjCIsaExpr *E) { - VisitExpr(E); - E->setBase(Reader.ReadSubExpr()); - E->setIsaMemberLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setArrow(Record[Idx++]); -} - -void PCHStmtReader::VisitCastExpr(CastExpr *E) { - VisitExpr(E); - E->setSubExpr(Reader.ReadSubExpr()); - E->setCastKind((CastExpr::CastKind)Record[Idx++]); - CXXBaseSpecifierArray &BasePath = E->getBasePath(); - unsigned NumBaseSpecs = Record[Idx++]; - while (NumBaseSpecs--) { - // FIXME: These gets leaked. - CXXBaseSpecifier *BaseSpec = new (*Reader.getContext()) CXXBaseSpecifier; - *BaseSpec = Reader.ReadCXXBaseSpecifier(Record, Idx); - BasePath.push_back(BaseSpec); - } -} - -void PCHStmtReader::VisitBinaryOperator(BinaryOperator *E) { - VisitExpr(E); - E->setLHS(Reader.ReadSubExpr()); - E->setRHS(Reader.ReadSubExpr()); - E->setOpcode((BinaryOperator::Opcode)Record[Idx++]); - E->setOperatorLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitCompoundAssignOperator(CompoundAssignOperator *E) { - VisitBinaryOperator(E); - E->setComputationLHSType(Reader.GetType(Record[Idx++])); - E->setComputationResultType(Reader.GetType(Record[Idx++])); -} - -void PCHStmtReader::VisitConditionalOperator(ConditionalOperator *E) { - VisitExpr(E); - E->setCond(Reader.ReadSubExpr()); - E->setLHS(Reader.ReadSubExpr()); - E->setRHS(Reader.ReadSubExpr()); - E->setQuestionLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setColonLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitImplicitCastExpr(ImplicitCastExpr *E) { - VisitCastExpr(E); - E->setLvalueCast(Record[Idx++]); -} - -void PCHStmtReader::VisitExplicitCastExpr(ExplicitCastExpr *E) { - VisitCastExpr(E); - E->setTypeInfoAsWritten(Reader.GetTypeSourceInfo(Record, Idx)); -} - -void PCHStmtReader::VisitCStyleCastExpr(CStyleCastExpr *E) { - VisitExplicitCastExpr(E); - E->setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) { - VisitExpr(E); - E->setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setTypeSourceInfo(Reader.GetTypeSourceInfo(Record, Idx)); - E->setInitializer(Reader.ReadSubExpr()); - E->setFileScope(Record[Idx++]); -} - -void PCHStmtReader::VisitExtVectorElementExpr(ExtVectorElementExpr *E) { - VisitExpr(E); - E->setBase(Reader.ReadSubExpr()); - E->setAccessor(Reader.GetIdentifierInfo(Record, Idx)); - E->setAccessorLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitInitListExpr(InitListExpr *E) { - VisitExpr(E); - unsigned NumInits = Record[Idx++]; - E->reserveInits(*Reader.getContext(), NumInits); - for (unsigned I = 0; I != NumInits; ++I) - E->updateInit(*Reader.getContext(), I, Reader.ReadSubExpr()); - E->setSyntacticForm(cast_or_null<InitListExpr>(Reader.ReadSubStmt())); - E->setLBraceLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setRBraceLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setInitializedFieldInUnion( - cast_or_null<FieldDecl>(Reader.GetDecl(Record[Idx++]))); - E->sawArrayRangeDesignator(Record[Idx++]); -} - -void PCHStmtReader::VisitDesignatedInitExpr(DesignatedInitExpr *E) { - typedef DesignatedInitExpr::Designator Designator; - - VisitExpr(E); - unsigned NumSubExprs = Record[Idx++]; - assert(NumSubExprs == E->getNumSubExprs() && "Wrong number of subexprs"); - for (unsigned I = 0; I != NumSubExprs; ++I) - E->setSubExpr(I, Reader.ReadSubExpr()); - E->setEqualOrColonLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setGNUSyntax(Record[Idx++]); - - llvm::SmallVector<Designator, 4> Designators; - while (Idx < Record.size()) { - switch ((pch::DesignatorTypes)Record[Idx++]) { - case pch::DESIG_FIELD_DECL: { - FieldDecl *Field = cast<FieldDecl>(Reader.GetDecl(Record[Idx++])); - SourceLocation DotLoc - = SourceLocation::getFromRawEncoding(Record[Idx++]); - SourceLocation FieldLoc - = SourceLocation::getFromRawEncoding(Record[Idx++]); - Designators.push_back(Designator(Field->getIdentifier(), DotLoc, - FieldLoc)); - Designators.back().setField(Field); - break; - } - - case pch::DESIG_FIELD_NAME: { - const IdentifierInfo *Name = Reader.GetIdentifierInfo(Record, Idx); - SourceLocation DotLoc - = SourceLocation::getFromRawEncoding(Record[Idx++]); - SourceLocation FieldLoc - = SourceLocation::getFromRawEncoding(Record[Idx++]); - Designators.push_back(Designator(Name, DotLoc, FieldLoc)); - break; - } - - case pch::DESIG_ARRAY: { - unsigned Index = Record[Idx++]; - SourceLocation LBracketLoc - = SourceLocation::getFromRawEncoding(Record[Idx++]); - SourceLocation RBracketLoc - = SourceLocation::getFromRawEncoding(Record[Idx++]); - Designators.push_back(Designator(Index, LBracketLoc, RBracketLoc)); - break; - } - - case pch::DESIG_ARRAY_RANGE: { - unsigned Index = Record[Idx++]; - SourceLocation LBracketLoc - = SourceLocation::getFromRawEncoding(Record[Idx++]); - SourceLocation EllipsisLoc - = SourceLocation::getFromRawEncoding(Record[Idx++]); - SourceLocation RBracketLoc - = SourceLocation::getFromRawEncoding(Record[Idx++]); - Designators.push_back(Designator(Index, LBracketLoc, EllipsisLoc, - RBracketLoc)); - break; - } - } - } - E->setDesignators(*Reader.getContext(), - Designators.data(), Designators.size()); -} - -void PCHStmtReader::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) { - VisitExpr(E); -} - -void PCHStmtReader::VisitVAArgExpr(VAArgExpr *E) { - VisitExpr(E); - E->setSubExpr(Reader.ReadSubExpr()); - E->setBuiltinLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitAddrLabelExpr(AddrLabelExpr *E) { - VisitExpr(E); - E->setAmpAmpLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setLabelLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - Reader.SetLabelOf(E, Record[Idx++]); -} - -void PCHStmtReader::VisitStmtExpr(StmtExpr *E) { - VisitExpr(E); - E->setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setSubStmt(cast_or_null<CompoundStmt>(Reader.ReadSubStmt())); -} - -void PCHStmtReader::VisitTypesCompatibleExpr(TypesCompatibleExpr *E) { - VisitExpr(E); - E->setArgType1(Reader.GetType(Record[Idx++])); - E->setArgType2(Reader.GetType(Record[Idx++])); - E->setBuiltinLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitChooseExpr(ChooseExpr *E) { - VisitExpr(E); - E->setCond(Reader.ReadSubExpr()); - E->setLHS(Reader.ReadSubExpr()); - E->setRHS(Reader.ReadSubExpr()); - E->setBuiltinLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitGNUNullExpr(GNUNullExpr *E) { - VisitExpr(E); - E->setTokenLocation(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitShuffleVectorExpr(ShuffleVectorExpr *E) { - VisitExpr(E); - llvm::SmallVector<Expr *, 16> Exprs; - unsigned NumExprs = Record[Idx++]; - while (NumExprs--) - Exprs.push_back(Reader.ReadSubExpr()); - E->setExprs(*Reader.getContext(), Exprs.data(), Exprs.size()); - E->setBuiltinLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitBlockExpr(BlockExpr *E) { - VisitExpr(E); - E->setBlockDecl(cast_or_null<BlockDecl>(Reader.GetDecl(Record[Idx++]))); - E->setHasBlockDeclRefExprs(Record[Idx++]); -} - -void PCHStmtReader::VisitBlockDeclRefExpr(BlockDeclRefExpr *E) { - VisitExpr(E); - E->setDecl(cast<ValueDecl>(Reader.GetDecl(Record[Idx++]))); - E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setByRef(Record[Idx++]); - E->setConstQualAdded(Record[Idx++]); - E->setCopyConstructorExpr(Reader.ReadSubExpr()); -} - -//===----------------------------------------------------------------------===// -// Objective-C Expressions and Statements - -void PCHStmtReader::VisitObjCStringLiteral(ObjCStringLiteral *E) { - VisitExpr(E); - E->setString(cast<StringLiteral>(Reader.ReadSubStmt())); - E->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitObjCEncodeExpr(ObjCEncodeExpr *E) { - VisitExpr(E); - E->setEncodedTypeSourceInfo(Reader.GetTypeSourceInfo(Record, Idx)); - E->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitObjCSelectorExpr(ObjCSelectorExpr *E) { - VisitExpr(E); - E->setSelector(Reader.GetSelector(Record, Idx)); - E->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitObjCProtocolExpr(ObjCProtocolExpr *E) { - VisitExpr(E); - E->setProtocol(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++]))); - E->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) { - VisitExpr(E); - E->setDecl(cast<ObjCIvarDecl>(Reader.GetDecl(Record[Idx++]))); - E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setBase(Reader.ReadSubExpr()); - E->setIsArrow(Record[Idx++]); - E->setIsFreeIvar(Record[Idx++]); -} - -void PCHStmtReader::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { - VisitExpr(E); - E->setProperty(cast<ObjCPropertyDecl>(Reader.GetDecl(Record[Idx++]))); - E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setBase(Reader.ReadSubExpr()); -} - -void PCHStmtReader::VisitObjCImplicitSetterGetterRefExpr( - ObjCImplicitSetterGetterRefExpr *E) { - VisitExpr(E); - E->setGetterMethod( - cast_or_null<ObjCMethodDecl>(Reader.GetDecl(Record[Idx++]))); - E->setSetterMethod( - cast_or_null<ObjCMethodDecl>(Reader.GetDecl(Record[Idx++]))); - E->setInterfaceDecl( - cast_or_null<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++]))); - E->setBase(Reader.ReadSubExpr()); - E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setClassLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitObjCMessageExpr(ObjCMessageExpr *E) { - VisitExpr(E); - assert(Record[Idx] == E->getNumArgs()); - ++Idx; - ObjCMessageExpr::ReceiverKind Kind - = static_cast<ObjCMessageExpr::ReceiverKind>(Record[Idx++]); - switch (Kind) { - case ObjCMessageExpr::Instance: - E->setInstanceReceiver(Reader.ReadSubExpr()); - break; - - case ObjCMessageExpr::Class: - E->setClassReceiver(Reader.GetTypeSourceInfo(Record, Idx)); - break; - - case ObjCMessageExpr::SuperClass: - case ObjCMessageExpr::SuperInstance: { - QualType T = Reader.GetType(Record[Idx++]); - SourceLocation SuperLoc = SourceLocation::getFromRawEncoding(Record[Idx++]); - E->setSuper(SuperLoc, T, Kind == ObjCMessageExpr::SuperInstance); - break; - } - } - - assert(Kind == E->getReceiverKind()); - - if (Record[Idx++]) - E->setMethodDecl(cast_or_null<ObjCMethodDecl>(Reader.GetDecl(Record[Idx++]))); - else - E->setSelector(Reader.GetSelector(Record, Idx)); - - E->setLeftLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setRightLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - - for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) - E->setArg(I, Reader.ReadSubExpr()); -} - -void PCHStmtReader::VisitObjCSuperExpr(ObjCSuperExpr *E) { - VisitExpr(E); - E->setLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) { - VisitStmt(S); - S->setElement(Reader.ReadSubStmt()); - S->setCollection(Reader.ReadSubExpr()); - S->setBody(Reader.ReadSubStmt()); - S->setForLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - S->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) { - VisitStmt(S); - S->setCatchBody(Reader.ReadSubStmt()); - S->setCatchParamDecl(cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++]))); - S->setAtCatchLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - S->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S) { - VisitStmt(S); - S->setFinallyBody(Reader.ReadSubStmt()); - S->setAtFinallyLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitObjCAtTryStmt(ObjCAtTryStmt *S) { - VisitStmt(S); - assert(Record[Idx] == S->getNumCatchStmts()); - ++Idx; - bool HasFinally = Record[Idx++]; - S->setTryBody(Reader.ReadSubStmt()); - for (unsigned I = 0, N = S->getNumCatchStmts(); I != N; ++I) - S->setCatchStmt(I, cast_or_null<ObjCAtCatchStmt>(Reader.ReadSubStmt())); - - if (HasFinally) - S->setFinallyStmt(Reader.ReadSubStmt()); - S->setAtTryLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S) { - VisitStmt(S); - S->setSynchExpr(Reader.ReadSubStmt()); - S->setSynchBody(Reader.ReadSubStmt()); - S->setAtSynchronizedLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) { - VisitStmt(S); - S->setThrowExpr(Reader.ReadSubStmt()); - S->setThrowLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -//===----------------------------------------------------------------------===// -// C++ Expressions and Statements - -void PCHStmtReader::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) { - VisitCallExpr(E); - E->setOperator((OverloadedOperatorKind)Record[Idx++]); -} - -void PCHStmtReader::VisitCXXConstructExpr(CXXConstructExpr *E) { - VisitExpr(E); - E->NumArgs = Record[Idx++]; - if (E->NumArgs) - E->Args = new (*Reader.getContext()) Stmt*[E->NumArgs]; - for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) - E->setArg(I, Reader.ReadSubExpr()); - E->setConstructor(cast<CXXConstructorDecl>(Reader.GetDecl(Record[Idx++]))); - E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setElidable(Record[Idx++]); - E->setRequiresZeroInitialization(Record[Idx++]); - E->setConstructionKind((CXXConstructExpr::ConstructionKind)Record[Idx++]); -} - -void PCHStmtReader::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E) { - VisitCXXConstructExpr(E); - E->TyBeginLoc = Reader.ReadSourceLocation(Record, Idx); - E->RParenLoc = Reader.ReadSourceLocation(Record, Idx); -} - -void PCHStmtReader::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) { - VisitExplicitCastExpr(E); - E->setOperatorLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitCXXStaticCastExpr(CXXStaticCastExpr *E) { - return VisitCXXNamedCastExpr(E); -} - -void PCHStmtReader::VisitCXXDynamicCastExpr(CXXDynamicCastExpr *E) { - return VisitCXXNamedCastExpr(E); -} - -void PCHStmtReader::VisitCXXReinterpretCastExpr(CXXReinterpretCastExpr *E) { - return VisitCXXNamedCastExpr(E); -} - -void PCHStmtReader::VisitCXXConstCastExpr(CXXConstCastExpr *E) { - return VisitCXXNamedCastExpr(E); -} - -void PCHStmtReader::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E) { - VisitExplicitCastExpr(E); - E->setTypeBeginLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) { - VisitExpr(E); - E->setValue(Record[Idx++]); - E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E) { - VisitExpr(E); - E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitCXXTypeidExpr(CXXTypeidExpr *E) { - VisitExpr(E); - E->setSourceRange(Reader.ReadSourceRange(Record, Idx)); - if (E->isTypeOperand()) { // typeid(int) - E->setTypeOperandSourceInfo(Reader.GetTypeSourceInfo(Record, Idx)); - return; - } - - // typeid(42+2) - E->setExprOperand(Reader.ReadSubExpr()); -} - -void PCHStmtReader::VisitCXXThisExpr(CXXThisExpr *E) { - VisitExpr(E); - E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setImplicit(Record[Idx++]); -} - -void PCHStmtReader::VisitCXXThrowExpr(CXXThrowExpr *E) { - VisitExpr(E); - E->setThrowLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setSubExpr(Reader.ReadSubExpr()); -} - -void PCHStmtReader::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { - VisitExpr(E); - - assert(Record[Idx] == E->Param.getInt() && "We messed up at creation ?"); - ++Idx; // HasOtherExprStored and SubExpr was handled during creation. - E->Param.setPointer(cast<ParmVarDecl>(Reader.GetDecl(Record[Idx++]))); - E->Loc = Reader.ReadSourceLocation(Record, Idx); -} - -void PCHStmtReader::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) { - VisitExpr(E); - E->setTemporary(Reader.ReadCXXTemporary(Record, Idx)); - E->setSubExpr(Reader.ReadSubExpr()); -} - -void PCHStmtReader::VisitCXXBindReferenceExpr(CXXBindReferenceExpr *E) { - VisitExpr(E); - E->SubExpr = Reader.ReadSubExpr(); - E->ExtendsLifetime = Record[Idx++]; - E->RequiresTemporaryCopy = Record[Idx++]; -} - -void PCHStmtReader::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) { - VisitExpr(E); - E->setTypeBeginLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitCXXNewExpr(CXXNewExpr *E) { - VisitExpr(E); - E->setGlobalNew(Record[Idx++]); - E->setHasInitializer(Record[Idx++]); - bool isArray = Record[Idx++]; - unsigned NumPlacementArgs = Record[Idx++]; - unsigned NumCtorArgs = Record[Idx++]; - E->setOperatorNew(cast_or_null<FunctionDecl>(Reader.GetDecl(Record[Idx++]))); - E->setOperatorDelete( - cast_or_null<FunctionDecl>(Reader.GetDecl(Record[Idx++]))); - E->setConstructor( - cast_or_null<CXXConstructorDecl>(Reader.GetDecl(Record[Idx++]))); - SourceRange TypeIdParens; - TypeIdParens.setBegin(SourceLocation::getFromRawEncoding(Record[Idx++])); - TypeIdParens.setEnd(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->TypeIdParens = TypeIdParens; - E->setStartLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setEndLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - - E->AllocateArgsArray(*Reader.getContext(), isArray, NumPlacementArgs, - NumCtorArgs); - - // Install all the subexpressions. - for (CXXNewExpr::raw_arg_iterator I = E->raw_arg_begin(),e = E->raw_arg_end(); - I != e; ++I) - *I = Reader.ReadSubStmt(); -} - -void PCHStmtReader::VisitCXXDeleteExpr(CXXDeleteExpr *E) { - VisitExpr(E); - E->setGlobalDelete(Record[Idx++]); - E->setArrayForm(Record[Idx++]); - E->setOperatorDelete( - cast_or_null<FunctionDecl>(Reader.GetDecl(Record[Idx++]))); - E->setArgument(Reader.ReadSubExpr()); - E->setStartLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) { - VisitExpr(E); - - E->setBase(Reader.ReadSubExpr()); - E->setArrow(Record[Idx++]); - E->setOperatorLoc(Reader.ReadSourceLocation(Record, Idx)); - E->setQualifier(Reader.ReadNestedNameSpecifier(Record, Idx)); - E->setQualifierRange(Reader.ReadSourceRange(Record, Idx)); - E->setScopeTypeInfo(Reader.GetTypeSourceInfo(Record, Idx)); - E->setColonColonLoc(Reader.ReadSourceLocation(Record, Idx)); - E->setTildeLoc(Reader.ReadSourceLocation(Record, Idx)); - - IdentifierInfo *II = Reader.GetIdentifierInfo(Record, Idx); - if (II) - E->setDestroyedType(II, Reader.ReadSourceLocation(Record, Idx)); - else - E->setDestroyedType(Reader.GetTypeSourceInfo(Record, Idx)); -} - -void PCHStmtReader::VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E) { - VisitExpr(E); - unsigned NumTemps = Record[Idx++]; - if (NumTemps) { - E->setNumTemporaries(*Reader.getContext(), NumTemps); - for (unsigned i = 0; i != NumTemps; ++i) - E->setTemporary(i, Reader.ReadCXXTemporary(Record, Idx)); - } - E->setSubExpr(Reader.ReadSubExpr()); -} - -void -PCHStmtReader::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E){ - VisitExpr(E); - - unsigned NumTemplateArgs = Record[Idx++]; - assert((NumTemplateArgs != 0) == E->hasExplicitTemplateArgs() && - "Read wrong record during creation ?"); - if (E->hasExplicitTemplateArgs()) - ReadExplicitTemplateArgumentList(*E->getExplicitTemplateArgumentList(), - NumTemplateArgs); - - E->setBase(Reader.ReadSubExpr()); - E->setBaseType(Reader.GetType(Record[Idx++])); - E->setArrow(Record[Idx++]); - E->setOperatorLoc(Reader.ReadSourceLocation(Record, Idx)); - E->setQualifier(Reader.ReadNestedNameSpecifier(Record, Idx)); - E->setQualifierRange(Reader.ReadSourceRange(Record, Idx)); - E->setFirstQualifierFoundInScope( - cast_or_null<NamedDecl>(Reader.GetDecl(Record[Idx++]))); - E->setMember(Reader.ReadDeclarationName(Record, Idx)); - E->setMemberLoc(Reader.ReadSourceLocation(Record, Idx)); -} - -void -PCHStmtReader::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) { - VisitExpr(E); - - unsigned NumTemplateArgs = Record[Idx++]; - assert((NumTemplateArgs != 0) == E->hasExplicitTemplateArgs() && - "Read wrong record during creation ?"); - if (E->hasExplicitTemplateArgs()) - ReadExplicitTemplateArgumentList(E->getExplicitTemplateArgs(), - NumTemplateArgs); - - E->setDeclName(Reader.ReadDeclarationName(Record, Idx)); - E->setLocation(Reader.ReadSourceLocation(Record, Idx)); - E->setQualifierRange(Reader.ReadSourceRange(Record, Idx)); - E->setQualifier(Reader.ReadNestedNameSpecifier(Record, Idx)); -} - -void -PCHStmtReader::VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E) { - VisitExpr(E); - assert(Record[Idx] == E->arg_size() && "Read wrong record during creation ?"); - ++Idx; // NumArgs; - for (unsigned I = 0, N = E->arg_size(); I != N; ++I) - E->setArg(I, Reader.ReadSubExpr()); - E->setTypeBeginLoc(Reader.ReadSourceLocation(Record, Idx)); - E->setTypeAsWritten(Reader.GetType(Record[Idx++])); - E->setLParenLoc(Reader.ReadSourceLocation(Record, Idx)); - E->setRParenLoc(Reader.ReadSourceLocation(Record, Idx)); -} - -void PCHStmtReader::VisitOverloadExpr(OverloadExpr *E) { - VisitExpr(E); - - unsigned NumTemplateArgs = Record[Idx++]; - assert((NumTemplateArgs != 0) == E->hasExplicitTemplateArgs() && - "Read wrong record during creation ?"); - if (E->hasExplicitTemplateArgs()) - ReadExplicitTemplateArgumentList(E->getExplicitTemplateArgs(), - NumTemplateArgs); - - unsigned NumDecls = Record[Idx++]; - UnresolvedSet<8> Decls; - for (unsigned i = 0; i != NumDecls; ++i) { - NamedDecl *D = cast<NamedDecl>(Reader.GetDecl(Record[Idx++])); - AccessSpecifier AS = (AccessSpecifier)Record[Idx++]; - Decls.addDecl(D, AS); - } - E->initializeResults(*Reader.getContext(), Decls.begin(), Decls.end()); - - E->setName(Reader.ReadDeclarationName(Record, Idx)); - E->setQualifier(Reader.ReadNestedNameSpecifier(Record, Idx)); - E->setQualifierRange(Reader.ReadSourceRange(Record, Idx)); - E->setNameLoc(Reader.ReadSourceLocation(Record, Idx)); -} - -void PCHStmtReader::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) { - VisitOverloadExpr(E); - E->setArrow(Record[Idx++]); - E->setHasUnresolvedUsing(Record[Idx++]); - E->setBase(Reader.ReadSubExpr()); - E->setBaseType(Reader.GetType(Record[Idx++])); - E->setOperatorLoc(Reader.ReadSourceLocation(Record, Idx)); -} - -void PCHStmtReader::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) { - VisitOverloadExpr(E); - E->setRequiresADL(Record[Idx++]); - E->setOverloaded(Record[Idx++]); - E->setNamingClass(cast_or_null<CXXRecordDecl>(Reader.GetDecl(Record[Idx++]))); -} - -void PCHStmtReader::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) { - VisitExpr(E); - E->UTT = (UnaryTypeTrait)Record[Idx++]; - SourceRange Range = Reader.ReadSourceRange(Record, Idx); - E->Loc = Range.getBegin(); - E->RParen = Range.getEnd(); - E->QueriedType = Reader.GetType(Record[Idx++]); -} - -Stmt *PCHReader::ReadStmt() { - switch (ReadingKind) { - case Read_Decl: - case Read_Type: - // Read a statement from the current DeclCursor. - return ReadStmtFromStream(DeclsCursor); - case Read_Stmt: - return ReadSubStmt(); - } - - llvm_unreachable("ReadingKind not set ?"); - return 0; -} - -Expr *PCHReader::ReadExpr() { - return cast_or_null<Expr>(ReadStmt()); -} - -Expr *PCHReader::ReadSubExpr() { - return cast_or_null<Expr>(ReadSubStmt()); -} - -// Within the bitstream, expressions are stored in Reverse Polish -// Notation, with each of the subexpressions preceding the -// expression they are stored in. Subexpressions are stored from last to first. -// To evaluate expressions, we continue reading expressions and placing them on -// the stack, with expressions having operands removing those operands from the -// stack. Evaluation terminates when we see a STMT_STOP record, and -// the single remaining expression on the stack is our result. -Stmt *PCHReader::ReadStmtFromStream(llvm::BitstreamCursor &Cursor) { - - ReadingKindTracker ReadingKind(Read_Stmt, *this); - -#ifndef NDEBUG - unsigned PrevNumStmts = StmtStack.size(); -#endif - - RecordData Record; - unsigned Idx; - PCHStmtReader Reader(*this, Record, Idx); - Stmt::EmptyShell Empty; - - while (true) { - unsigned Code = Cursor.ReadCode(); - if (Code == llvm::bitc::END_BLOCK) { - if (Cursor.ReadBlockEnd()) { - Error("error at end of block in PCH file"); - return 0; - } - break; - } - - if (Code == llvm::bitc::ENTER_SUBBLOCK) { - // No known subblocks, always skip them. - Cursor.ReadSubBlockID(); - if (Cursor.SkipBlock()) { - Error("malformed block record in PCH file"); - return 0; - } - continue; - } - - if (Code == llvm::bitc::DEFINE_ABBREV) { - Cursor.ReadAbbrevRecord(); - continue; - } - - Stmt *S = 0; - Idx = 0; - Record.clear(); - bool Finished = false; - switch ((pch::StmtCode)Cursor.ReadRecord(Code, Record)) { - case pch::STMT_STOP: - Finished = true; - break; - - case pch::STMT_NULL_PTR: - S = 0; - break; - - case pch::STMT_NULL: - S = new (Context) NullStmt(Empty); - break; - - case pch::STMT_COMPOUND: - S = new (Context) CompoundStmt(Empty); - break; - - case pch::STMT_CASE: - S = new (Context) CaseStmt(Empty); - break; - - case pch::STMT_DEFAULT: - S = new (Context) DefaultStmt(Empty); - break; - - case pch::STMT_LABEL: - S = new (Context) LabelStmt(Empty); - break; - - case pch::STMT_IF: - S = new (Context) IfStmt(Empty); - break; - - case pch::STMT_SWITCH: - S = new (Context) SwitchStmt(Empty); - break; - - case pch::STMT_WHILE: - S = new (Context) WhileStmt(Empty); - break; - - case pch::STMT_DO: - S = new (Context) DoStmt(Empty); - break; - - case pch::STMT_FOR: - S = new (Context) ForStmt(Empty); - break; - - case pch::STMT_GOTO: - S = new (Context) GotoStmt(Empty); - break; - - case pch::STMT_INDIRECT_GOTO: - S = new (Context) IndirectGotoStmt(Empty); - break; - - case pch::STMT_CONTINUE: - S = new (Context) ContinueStmt(Empty); - break; - - case pch::STMT_BREAK: - S = new (Context) BreakStmt(Empty); - break; - - case pch::STMT_RETURN: - S = new (Context) ReturnStmt(Empty); - break; - - case pch::STMT_DECL: - S = new (Context) DeclStmt(Empty); - break; - - case pch::STMT_ASM: - S = new (Context) AsmStmt(Empty); - break; - - case pch::EXPR_PREDEFINED: - S = new (Context) PredefinedExpr(Empty); - break; - - case pch::EXPR_DECL_REF: - S = DeclRefExpr::CreateEmpty(*Context, - /*HasQualifier=*/Record[PCHStmtReader::NumExprFields], - /*NumTemplateArgs=*/Record[PCHStmtReader::NumExprFields + 1]); - break; - - case pch::EXPR_INTEGER_LITERAL: - S = new (Context) IntegerLiteral(Empty); - break; - - case pch::EXPR_FLOATING_LITERAL: - S = new (Context) FloatingLiteral(Empty); - break; - - case pch::EXPR_IMAGINARY_LITERAL: - S = new (Context) ImaginaryLiteral(Empty); - break; - - case pch::EXPR_STRING_LITERAL: - S = StringLiteral::CreateEmpty(*Context, - Record[PCHStmtReader::NumExprFields + 1]); - break; - - case pch::EXPR_CHARACTER_LITERAL: - S = new (Context) CharacterLiteral(Empty); - break; - - case pch::EXPR_PAREN: - S = new (Context) ParenExpr(Empty); - break; - - case pch::EXPR_PAREN_LIST: - S = new (Context) ParenListExpr(Empty); - break; - - case pch::EXPR_UNARY_OPERATOR: - S = new (Context) UnaryOperator(Empty); - break; - - case pch::EXPR_OFFSETOF: - S = OffsetOfExpr::CreateEmpty(*Context, - Record[PCHStmtReader::NumExprFields], - Record[PCHStmtReader::NumExprFields + 1]); - break; - - case pch::EXPR_SIZEOF_ALIGN_OF: - S = new (Context) SizeOfAlignOfExpr(Empty); - break; - - case pch::EXPR_ARRAY_SUBSCRIPT: - S = new (Context) ArraySubscriptExpr(Empty); - break; - - case pch::EXPR_CALL: - S = new (Context) CallExpr(*Context, Stmt::CallExprClass, Empty); - break; - - case pch::EXPR_MEMBER: { - // We load everything here and fully initialize it at creation. - // That way we can use MemberExpr::Create and don't have to duplicate its - // logic with a MemberExpr::CreateEmpty. - - assert(Idx == 0); - NestedNameSpecifier *NNS = 0; - SourceRange QualifierRange; - if (Record[Idx++]) { // HasQualifier. - NNS = ReadNestedNameSpecifier(Record, Idx); - QualifierRange = ReadSourceRange(Record, Idx); - } - - TemplateArgumentListInfo ArgInfo; - unsigned NumTemplateArgs = Record[Idx++]; - if (NumTemplateArgs) { - ArgInfo.setLAngleLoc(ReadSourceLocation(Record, Idx)); - ArgInfo.setRAngleLoc(ReadSourceLocation(Record, Idx)); - for (unsigned i = 0; i != NumTemplateArgs; ++i) - ArgInfo.addArgument(ReadTemplateArgumentLoc(Record, Idx)); - } - - NamedDecl *FoundD = cast_or_null<NamedDecl>(GetDecl(Record[Idx++])); - AccessSpecifier AS = (AccessSpecifier)Record[Idx++]; - DeclAccessPair FoundDecl = DeclAccessPair::make(FoundD, AS); - - QualType T = GetType(Record[Idx++]); - Expr *Base = ReadSubExpr(); - ValueDecl *MemberD = cast<ValueDecl>(GetDecl(Record[Idx++])); - SourceLocation MemberLoc = ReadSourceLocation(Record, Idx); - bool IsArrow = Record[Idx++]; - - S = MemberExpr::Create(*Context, Base, IsArrow, NNS, QualifierRange, - MemberD, FoundDecl, MemberLoc, - NumTemplateArgs ? &ArgInfo : 0, T); - break; - } - - case pch::EXPR_BINARY_OPERATOR: - S = new (Context) BinaryOperator(Empty); - break; - - case pch::EXPR_COMPOUND_ASSIGN_OPERATOR: - S = new (Context) CompoundAssignOperator(Empty); - break; - - case pch::EXPR_CONDITIONAL_OPERATOR: - S = new (Context) ConditionalOperator(Empty); - break; - - case pch::EXPR_IMPLICIT_CAST: - S = new (Context) ImplicitCastExpr(Empty); - break; - - case pch::EXPR_CSTYLE_CAST: - S = new (Context) CStyleCastExpr(Empty); - break; - - case pch::EXPR_COMPOUND_LITERAL: - S = new (Context) CompoundLiteralExpr(Empty); - break; - - case pch::EXPR_EXT_VECTOR_ELEMENT: - S = new (Context) ExtVectorElementExpr(Empty); - break; - - case pch::EXPR_INIT_LIST: - S = new (Context) InitListExpr(*getContext(), Empty); - break; - - case pch::EXPR_DESIGNATED_INIT: - S = DesignatedInitExpr::CreateEmpty(*Context, - Record[PCHStmtReader::NumExprFields] - 1); - - break; - - case pch::EXPR_IMPLICIT_VALUE_INIT: - S = new (Context) ImplicitValueInitExpr(Empty); - break; - - case pch::EXPR_VA_ARG: - S = new (Context) VAArgExpr(Empty); - break; - - case pch::EXPR_ADDR_LABEL: - S = new (Context) AddrLabelExpr(Empty); - break; - - case pch::EXPR_STMT: - S = new (Context) StmtExpr(Empty); - break; - - case pch::EXPR_TYPES_COMPATIBLE: - S = new (Context) TypesCompatibleExpr(Empty); - break; - - case pch::EXPR_CHOOSE: - S = new (Context) ChooseExpr(Empty); - break; - - case pch::EXPR_GNU_NULL: - S = new (Context) GNUNullExpr(Empty); - break; - - case pch::EXPR_SHUFFLE_VECTOR: - S = new (Context) ShuffleVectorExpr(Empty); - break; - - case pch::EXPR_BLOCK: - S = new (Context) BlockExpr(Empty); - break; - - case pch::EXPR_BLOCK_DECL_REF: - S = new (Context) BlockDeclRefExpr(Empty); - break; - - case pch::EXPR_OBJC_STRING_LITERAL: - S = new (Context) ObjCStringLiteral(Empty); - break; - case pch::EXPR_OBJC_ENCODE: - S = new (Context) ObjCEncodeExpr(Empty); - break; - case pch::EXPR_OBJC_SELECTOR_EXPR: - S = new (Context) ObjCSelectorExpr(Empty); - break; - case pch::EXPR_OBJC_PROTOCOL_EXPR: - S = new (Context) ObjCProtocolExpr(Empty); - break; - case pch::EXPR_OBJC_IVAR_REF_EXPR: - S = new (Context) ObjCIvarRefExpr(Empty); - break; - case pch::EXPR_OBJC_PROPERTY_REF_EXPR: - S = new (Context) ObjCPropertyRefExpr(Empty); - break; - case pch::EXPR_OBJC_KVC_REF_EXPR: - S = new (Context) ObjCImplicitSetterGetterRefExpr(Empty); - break; - case pch::EXPR_OBJC_MESSAGE_EXPR: - S = ObjCMessageExpr::CreateEmpty(*Context, - Record[PCHStmtReader::NumExprFields]); - break; - case pch::EXPR_OBJC_SUPER_EXPR: - S = new (Context) ObjCSuperExpr(Empty); - break; - case pch::EXPR_OBJC_ISA: - S = new (Context) ObjCIsaExpr(Empty); - break; - case pch::STMT_OBJC_FOR_COLLECTION: - S = new (Context) ObjCForCollectionStmt(Empty); - break; - case pch::STMT_OBJC_CATCH: - S = new (Context) ObjCAtCatchStmt(Empty); - break; - case pch::STMT_OBJC_FINALLY: - S = new (Context) ObjCAtFinallyStmt(Empty); - break; - case pch::STMT_OBJC_AT_TRY: - S = ObjCAtTryStmt::CreateEmpty(*Context, - Record[PCHStmtReader::NumStmtFields], - Record[PCHStmtReader::NumStmtFields + 1]); - break; - case pch::STMT_OBJC_AT_SYNCHRONIZED: - S = new (Context) ObjCAtSynchronizedStmt(Empty); - break; - case pch::STMT_OBJC_AT_THROW: - S = new (Context) ObjCAtThrowStmt(Empty); - break; - - case pch::EXPR_CXX_OPERATOR_CALL: - S = new (Context) CXXOperatorCallExpr(*Context, Empty); - break; - - case pch::EXPR_CXX_MEMBER_CALL: - S = new (Context) CXXMemberCallExpr(*Context, Empty); - break; - - case pch::EXPR_CXX_CONSTRUCT: - S = new (Context) CXXConstructExpr(Empty); - break; - - case pch::EXPR_CXX_TEMPORARY_OBJECT: - S = new (Context) CXXTemporaryObjectExpr(Empty); - break; - - case pch::EXPR_CXX_STATIC_CAST: - S = new (Context) CXXStaticCastExpr(Empty); - break; - - case pch::EXPR_CXX_DYNAMIC_CAST: - S = new (Context) CXXDynamicCastExpr(Empty); - break; - - case pch::EXPR_CXX_REINTERPRET_CAST: - S = new (Context) CXXReinterpretCastExpr(Empty); - break; - - case pch::EXPR_CXX_CONST_CAST: - S = new (Context) CXXConstCastExpr(Empty); - break; - - case pch::EXPR_CXX_FUNCTIONAL_CAST: - S = new (Context) CXXFunctionalCastExpr(Empty); - break; - - case pch::EXPR_CXX_BOOL_LITERAL: - S = new (Context) CXXBoolLiteralExpr(Empty); - break; - - case pch::EXPR_CXX_NULL_PTR_LITERAL: - S = new (Context) CXXNullPtrLiteralExpr(Empty); - break; - case pch::EXPR_CXX_TYPEID_EXPR: - S = new (Context) CXXTypeidExpr(Empty, true); - break; - case pch::EXPR_CXX_TYPEID_TYPE: - S = new (Context) CXXTypeidExpr(Empty, false); - break; - case pch::EXPR_CXX_THIS: - S = new (Context) CXXThisExpr(Empty); - break; - case pch::EXPR_CXX_THROW: - S = new (Context) CXXThrowExpr(Empty); - break; - case pch::EXPR_CXX_DEFAULT_ARG: { - bool HasOtherExprStored = Record[PCHStmtReader::NumExprFields]; - if (HasOtherExprStored) { - Expr *SubExpr = ReadSubExpr(); - S = CXXDefaultArgExpr::Create(*Context, SourceLocation(), 0, SubExpr); - } else - S = new (Context) CXXDefaultArgExpr(Empty); - break; - } - case pch::EXPR_CXX_BIND_TEMPORARY: - S = new (Context) CXXBindTemporaryExpr(Empty); - break; - case pch::EXPR_CXX_BIND_REFERENCE: - S = new (Context) CXXBindReferenceExpr(Empty); - break; - - case pch::EXPR_CXX_SCALAR_VALUE_INIT: - S = new (Context) CXXScalarValueInitExpr(Empty); - break; - case pch::EXPR_CXX_NEW: - S = new (Context) CXXNewExpr(Empty); - break; - case pch::EXPR_CXX_DELETE: - S = new (Context) CXXDeleteExpr(Empty); - break; - case pch::EXPR_CXX_PSEUDO_DESTRUCTOR: - S = new (Context) CXXPseudoDestructorExpr(Empty); - break; - - case pch::EXPR_CXX_EXPR_WITH_TEMPORARIES: - S = new (Context) CXXExprWithTemporaries(Empty); - break; - - case pch::EXPR_CXX_DEPENDENT_SCOPE_MEMBER: - S = CXXDependentScopeMemberExpr::CreateEmpty(*Context, - /*NumTemplateArgs=*/Record[PCHStmtReader::NumExprFields]); - break; - - case pch::EXPR_CXX_DEPENDENT_SCOPE_DECL_REF: - S = DependentScopeDeclRefExpr::CreateEmpty(*Context, - /*NumTemplateArgs=*/Record[PCHStmtReader::NumExprFields]); - break; - - case pch::EXPR_CXX_UNRESOLVED_CONSTRUCT: - S = CXXUnresolvedConstructExpr::CreateEmpty(*Context, - /*NumArgs=*/Record[PCHStmtReader::NumExprFields]); - break; - - case pch::EXPR_CXX_UNRESOLVED_MEMBER: - S = UnresolvedMemberExpr::CreateEmpty(*Context, - /*NumTemplateArgs=*/Record[PCHStmtReader::NumExprFields]); - break; - - case pch::EXPR_CXX_UNRESOLVED_LOOKUP: - S = UnresolvedLookupExpr::CreateEmpty(*Context, - /*NumTemplateArgs=*/Record[PCHStmtReader::NumExprFields]); - break; - - case pch::EXPR_CXX_UNARY_TYPE_TRAIT: - S = new (Context) UnaryTypeTraitExpr(Empty); - break; - } - - // We hit a STMT_STOP, so we're done with this expression. - if (Finished) - break; - - ++NumStatementsRead; - - if (S) - Reader.Visit(S); - - assert(Idx == Record.size() && "Invalid deserialization of statement"); - StmtStack.push_back(S); - } - -#ifndef NDEBUG - assert(StmtStack.size() > PrevNumStmts && "Read too many sub stmts!"); - assert(StmtStack.size() == PrevNumStmts + 1 && "Extra expressions on stack!"); -#endif - - return StmtStack.pop_back_val(); -} diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp deleted file mode 100644 index 093c1e3..0000000 --- a/lib/Frontend/PCHWriter.cpp +++ /dev/null @@ -1,2748 +0,0 @@ -//===--- PCHWriter.cpp - Precompiled Headers Writer -----------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the PCHWriter class, which writes a precompiled header. -// -//===----------------------------------------------------------------------===// - -#include "clang/Frontend/PCHWriter.h" -#include "../Sema/Sema.h" // FIXME: move header into include/clang/Sema -#include "../Sema/IdentifierResolver.h" // FIXME: move header -#include "clang/AST/ASTContext.h" -#include "clang/AST/Decl.h" -#include "clang/AST/DeclContextInternals.h" -#include "clang/AST/Expr.h" -#include "clang/AST/Type.h" -#include "clang/AST/TypeLocVisitor.h" -#include "clang/Frontend/PCHReader.h" -#include "clang/Lex/MacroInfo.h" -#include "clang/Lex/PreprocessingRecord.h" -#include "clang/Lex/Preprocessor.h" -#include "clang/Lex/HeaderSearch.h" -#include "clang/Basic/FileManager.h" -#include "clang/Basic/OnDiskHashTable.h" -#include "clang/Basic/SourceManager.h" -#include "clang/Basic/SourceManagerInternals.h" -#include "clang/Basic/TargetInfo.h" -#include "clang/Basic/Version.h" -#include "llvm/ADT/APFloat.h" -#include "llvm/ADT/APInt.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/Bitcode/BitstreamWriter.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/System/Path.h" -#include <cstdio> -using namespace clang; - -//===----------------------------------------------------------------------===// -// Type serialization -//===----------------------------------------------------------------------===// - -namespace { - class PCHTypeWriter { - PCHWriter &Writer; - PCHWriter::RecordData &Record; - - public: - /// \brief Type code that corresponds to the record generated. - pch::TypeCode Code; - - PCHTypeWriter(PCHWriter &Writer, PCHWriter::RecordData &Record) - : Writer(Writer), Record(Record), Code(pch::TYPE_EXT_QUAL) { } - - void VisitArrayType(const ArrayType *T); - void VisitFunctionType(const FunctionType *T); - void VisitTagType(const TagType *T); - -#define TYPE(Class, Base) void Visit##Class##Type(const Class##Type *T); -#define ABSTRACT_TYPE(Class, Base) -#include "clang/AST/TypeNodes.def" - }; -} - -void PCHTypeWriter::VisitBuiltinType(const BuiltinType *T) { - assert(false && "Built-in types are never serialized"); -} - -void PCHTypeWriter::VisitComplexType(const ComplexType *T) { - Writer.AddTypeRef(T->getElementType(), Record); - Code = pch::TYPE_COMPLEX; -} - -void PCHTypeWriter::VisitPointerType(const PointerType *T) { - Writer.AddTypeRef(T->getPointeeType(), Record); - Code = pch::TYPE_POINTER; -} - -void PCHTypeWriter::VisitBlockPointerType(const BlockPointerType *T) { - Writer.AddTypeRef(T->getPointeeType(), Record); - Code = pch::TYPE_BLOCK_POINTER; -} - -void PCHTypeWriter::VisitLValueReferenceType(const LValueReferenceType *T) { - Writer.AddTypeRef(T->getPointeeType(), Record); - Code = pch::TYPE_LVALUE_REFERENCE; -} - -void PCHTypeWriter::VisitRValueReferenceType(const RValueReferenceType *T) { - Writer.AddTypeRef(T->getPointeeType(), Record); - Code = pch::TYPE_RVALUE_REFERENCE; -} - -void PCHTypeWriter::VisitMemberPointerType(const MemberPointerType *T) { - Writer.AddTypeRef(T->getPointeeType(), Record); - Writer.AddTypeRef(QualType(T->getClass(), 0), Record); - Code = pch::TYPE_MEMBER_POINTER; -} - -void PCHTypeWriter::VisitArrayType(const ArrayType *T) { - Writer.AddTypeRef(T->getElementType(), Record); - Record.push_back(T->getSizeModifier()); // FIXME: stable values - Record.push_back(T->getIndexTypeCVRQualifiers()); // FIXME: stable values -} - -void PCHTypeWriter::VisitConstantArrayType(const ConstantArrayType *T) { - VisitArrayType(T); - Writer.AddAPInt(T->getSize(), Record); - Code = pch::TYPE_CONSTANT_ARRAY; -} - -void PCHTypeWriter::VisitIncompleteArrayType(const IncompleteArrayType *T) { - VisitArrayType(T); - Code = pch::TYPE_INCOMPLETE_ARRAY; -} - -void PCHTypeWriter::VisitVariableArrayType(const VariableArrayType *T) { - VisitArrayType(T); - Writer.AddSourceLocation(T->getLBracketLoc(), Record); - Writer.AddSourceLocation(T->getRBracketLoc(), Record); - Writer.AddStmt(T->getSizeExpr()); - Code = pch::TYPE_VARIABLE_ARRAY; -} - -void PCHTypeWriter::VisitVectorType(const VectorType *T) { - Writer.AddTypeRef(T->getElementType(), Record); - Record.push_back(T->getNumElements()); - Record.push_back(T->getAltiVecSpecific()); - Code = pch::TYPE_VECTOR; -} - -void PCHTypeWriter::VisitExtVectorType(const ExtVectorType *T) { - VisitVectorType(T); - Code = pch::TYPE_EXT_VECTOR; -} - -void PCHTypeWriter::VisitFunctionType(const FunctionType *T) { - Writer.AddTypeRef(T->getResultType(), Record); - FunctionType::ExtInfo C = T->getExtInfo(); - Record.push_back(C.getNoReturn()); - Record.push_back(C.getRegParm()); - // FIXME: need to stabilize encoding of calling convention... - Record.push_back(C.getCC()); -} - -void PCHTypeWriter::VisitFunctionNoProtoType(const FunctionNoProtoType *T) { - VisitFunctionType(T); - Code = pch::TYPE_FUNCTION_NO_PROTO; -} - -void PCHTypeWriter::VisitFunctionProtoType(const FunctionProtoType *T) { - VisitFunctionType(T); - Record.push_back(T->getNumArgs()); - for (unsigned I = 0, N = T->getNumArgs(); I != N; ++I) - Writer.AddTypeRef(T->getArgType(I), Record); - Record.push_back(T->isVariadic()); - Record.push_back(T->getTypeQuals()); - Record.push_back(T->hasExceptionSpec()); - Record.push_back(T->hasAnyExceptionSpec()); - Record.push_back(T->getNumExceptions()); - for (unsigned I = 0, N = T->getNumExceptions(); I != N; ++I) - Writer.AddTypeRef(T->getExceptionType(I), Record); - Code = pch::TYPE_FUNCTION_PROTO; -} - -void PCHTypeWriter::VisitUnresolvedUsingType(const UnresolvedUsingType *T) { - Writer.AddDeclRef(T->getDecl(), Record); - Code = pch::TYPE_UNRESOLVED_USING; -} - -void PCHTypeWriter::VisitTypedefType(const TypedefType *T) { - Writer.AddDeclRef(T->getDecl(), Record); - assert(!T->isCanonicalUnqualified() && "Invalid typedef ?"); - Writer.AddTypeRef(T->getCanonicalTypeInternal(), Record); - Code = pch::TYPE_TYPEDEF; -} - -void PCHTypeWriter::VisitTypeOfExprType(const TypeOfExprType *T) { - Writer.AddStmt(T->getUnderlyingExpr()); - Code = pch::TYPE_TYPEOF_EXPR; -} - -void PCHTypeWriter::VisitTypeOfType(const TypeOfType *T) { - Writer.AddTypeRef(T->getUnderlyingType(), Record); - Code = pch::TYPE_TYPEOF; -} - -void PCHTypeWriter::VisitDecltypeType(const DecltypeType *T) { - Writer.AddStmt(T->getUnderlyingExpr()); - Code = pch::TYPE_DECLTYPE; -} - -void PCHTypeWriter::VisitTagType(const TagType *T) { - Record.push_back(T->isDependentType()); - Writer.AddDeclRef(T->getDecl(), Record); - assert(!T->isBeingDefined() && - "Cannot serialize in the middle of a type definition"); -} - -void PCHTypeWriter::VisitRecordType(const RecordType *T) { - VisitTagType(T); - Code = pch::TYPE_RECORD; -} - -void PCHTypeWriter::VisitEnumType(const EnumType *T) { - VisitTagType(T); - Code = pch::TYPE_ENUM; -} - -void -PCHTypeWriter::VisitSubstTemplateTypeParmType( - const SubstTemplateTypeParmType *T) { - Writer.AddTypeRef(QualType(T->getReplacedParameter(), 0), Record); - Writer.AddTypeRef(T->getReplacementType(), Record); - Code = pch::TYPE_SUBST_TEMPLATE_TYPE_PARM; -} - -void -PCHTypeWriter::VisitTemplateSpecializationType( - const TemplateSpecializationType *T) { - Record.push_back(T->isDependentType()); - Writer.AddTemplateName(T->getTemplateName(), Record); - Record.push_back(T->getNumArgs()); - for (TemplateSpecializationType::iterator ArgI = T->begin(), ArgE = T->end(); - ArgI != ArgE; ++ArgI) - Writer.AddTemplateArgument(*ArgI, Record); - Writer.AddTypeRef(T->isCanonicalUnqualified() ? QualType() - : T->getCanonicalTypeInternal(), - Record); - Code = pch::TYPE_TEMPLATE_SPECIALIZATION; -} - -void -PCHTypeWriter::VisitDependentSizedArrayType(const DependentSizedArrayType *T) { - VisitArrayType(T); - Writer.AddStmt(T->getSizeExpr()); - Writer.AddSourceRange(T->getBracketsRange(), Record); - Code = pch::TYPE_DEPENDENT_SIZED_ARRAY; -} - -void -PCHTypeWriter::VisitDependentSizedExtVectorType( - const DependentSizedExtVectorType *T) { - // FIXME: Serialize this type (C++ only) - assert(false && "Cannot serialize dependent sized extended vector types"); -} - -void -PCHTypeWriter::VisitTemplateTypeParmType(const TemplateTypeParmType *T) { - Record.push_back(T->getDepth()); - Record.push_back(T->getIndex()); - Record.push_back(T->isParameterPack()); - Writer.AddIdentifierRef(T->getName(), Record); - Code = pch::TYPE_TEMPLATE_TYPE_PARM; -} - -void -PCHTypeWriter::VisitDependentNameType(const DependentNameType *T) { - Record.push_back(T->getKeyword()); - Writer.AddNestedNameSpecifier(T->getQualifier(), Record); - Writer.AddIdentifierRef(T->getIdentifier(), Record); - Writer.AddTypeRef(T->isCanonicalUnqualified() ? QualType() - : T->getCanonicalTypeInternal(), - Record); - Code = pch::TYPE_DEPENDENT_NAME; -} - -void -PCHTypeWriter::VisitDependentTemplateSpecializationType( - const DependentTemplateSpecializationType *T) { - Record.push_back(T->getKeyword()); - Writer.AddNestedNameSpecifier(T->getQualifier(), Record); - Writer.AddIdentifierRef(T->getIdentifier(), Record); - Record.push_back(T->getNumArgs()); - for (DependentTemplateSpecializationType::iterator - I = T->begin(), E = T->end(); I != E; ++I) - Writer.AddTemplateArgument(*I, Record); - Code = pch::TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION; -} - -void PCHTypeWriter::VisitElaboratedType(const ElaboratedType *T) { - Record.push_back(T->getKeyword()); - Writer.AddNestedNameSpecifier(T->getQualifier(), Record); - Writer.AddTypeRef(T->getNamedType(), Record); - Code = pch::TYPE_ELABORATED; -} - -void PCHTypeWriter::VisitInjectedClassNameType(const InjectedClassNameType *T) { - Writer.AddDeclRef(T->getDecl(), Record); - Writer.AddTypeRef(T->getInjectedSpecializationType(), Record); - Code = pch::TYPE_INJECTED_CLASS_NAME; -} - -void PCHTypeWriter::VisitObjCInterfaceType(const ObjCInterfaceType *T) { - Writer.AddDeclRef(T->getDecl(), Record); - Code = pch::TYPE_OBJC_INTERFACE; -} - -void PCHTypeWriter::VisitObjCObjectType(const ObjCObjectType *T) { - Writer.AddTypeRef(T->getBaseType(), Record); - Record.push_back(T->getNumProtocols()); - for (ObjCObjectType::qual_iterator I = T->qual_begin(), - E = T->qual_end(); I != E; ++I) - Writer.AddDeclRef(*I, Record); - Code = pch::TYPE_OBJC_OBJECT; -} - -void -PCHTypeWriter::VisitObjCObjectPointerType(const ObjCObjectPointerType *T) { - Writer.AddTypeRef(T->getPointeeType(), Record); - Code = pch::TYPE_OBJC_OBJECT_POINTER; -} - -namespace { - -class TypeLocWriter : public TypeLocVisitor<TypeLocWriter> { - PCHWriter &Writer; - PCHWriter::RecordData &Record; - -public: - TypeLocWriter(PCHWriter &Writer, PCHWriter::RecordData &Record) - : Writer(Writer), Record(Record) { } - -#define ABSTRACT_TYPELOC(CLASS, PARENT) -#define TYPELOC(CLASS, PARENT) \ - void Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc); -#include "clang/AST/TypeLocNodes.def" - - void VisitArrayTypeLoc(ArrayTypeLoc TyLoc); - void VisitFunctionTypeLoc(FunctionTypeLoc TyLoc); -}; - -} - -void TypeLocWriter::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) { - // nothing to do -} -void TypeLocWriter::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) { - Writer.AddSourceLocation(TL.getBuiltinLoc(), Record); - if (TL.needsExtraLocalData()) { - Record.push_back(TL.getWrittenTypeSpec()); - Record.push_back(TL.getWrittenSignSpec()); - Record.push_back(TL.getWrittenWidthSpec()); - Record.push_back(TL.hasModeAttr()); - } -} -void TypeLocWriter::VisitComplexTypeLoc(ComplexTypeLoc TL) { - Writer.AddSourceLocation(TL.getNameLoc(), Record); -} -void TypeLocWriter::VisitPointerTypeLoc(PointerTypeLoc TL) { - Writer.AddSourceLocation(TL.getStarLoc(), Record); -} -void TypeLocWriter::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) { - Writer.AddSourceLocation(TL.getCaretLoc(), Record); -} -void TypeLocWriter::VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) { - Writer.AddSourceLocation(TL.getAmpLoc(), Record); -} -void TypeLocWriter::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) { - Writer.AddSourceLocation(TL.getAmpAmpLoc(), Record); -} -void TypeLocWriter::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) { - Writer.AddSourceLocation(TL.getStarLoc(), Record); -} -void TypeLocWriter::VisitArrayTypeLoc(ArrayTypeLoc TL) { - Writer.AddSourceLocation(TL.getLBracketLoc(), Record); - Writer.AddSourceLocation(TL.getRBracketLoc(), Record); - Record.push_back(TL.getSizeExpr() ? 1 : 0); - if (TL.getSizeExpr()) - Writer.AddStmt(TL.getSizeExpr()); -} -void TypeLocWriter::VisitConstantArrayTypeLoc(ConstantArrayTypeLoc TL) { - VisitArrayTypeLoc(TL); -} -void TypeLocWriter::VisitIncompleteArrayTypeLoc(IncompleteArrayTypeLoc TL) { - VisitArrayTypeLoc(TL); -} -void TypeLocWriter::VisitVariableArrayTypeLoc(VariableArrayTypeLoc TL) { - VisitArrayTypeLoc(TL); -} -void TypeLocWriter::VisitDependentSizedArrayTypeLoc( - DependentSizedArrayTypeLoc TL) { - VisitArrayTypeLoc(TL); -} -void TypeLocWriter::VisitDependentSizedExtVectorTypeLoc( - DependentSizedExtVectorTypeLoc TL) { - Writer.AddSourceLocation(TL.getNameLoc(), Record); -} -void TypeLocWriter::VisitVectorTypeLoc(VectorTypeLoc TL) { - Writer.AddSourceLocation(TL.getNameLoc(), Record); -} -void TypeLocWriter::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) { - Writer.AddSourceLocation(TL.getNameLoc(), Record); -} -void TypeLocWriter::VisitFunctionTypeLoc(FunctionTypeLoc TL) { - Writer.AddSourceLocation(TL.getLParenLoc(), Record); - Writer.AddSourceLocation(TL.getRParenLoc(), Record); - for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) - Writer.AddDeclRef(TL.getArg(i), Record); -} -void TypeLocWriter::VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc TL) { - VisitFunctionTypeLoc(TL); -} -void TypeLocWriter::VisitFunctionNoProtoTypeLoc(FunctionNoProtoTypeLoc TL) { - VisitFunctionTypeLoc(TL); -} -void TypeLocWriter::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) { - Writer.AddSourceLocation(TL.getNameLoc(), Record); -} -void TypeLocWriter::VisitTypedefTypeLoc(TypedefTypeLoc TL) { - Writer.AddSourceLocation(TL.getNameLoc(), Record); -} -void TypeLocWriter::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) { - Writer.AddSourceLocation(TL.getTypeofLoc(), Record); - Writer.AddSourceLocation(TL.getLParenLoc(), Record); - Writer.AddSourceLocation(TL.getRParenLoc(), Record); -} -void TypeLocWriter::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) { - Writer.AddSourceLocation(TL.getTypeofLoc(), Record); - Writer.AddSourceLocation(TL.getLParenLoc(), Record); - Writer.AddSourceLocation(TL.getRParenLoc(), Record); - Writer.AddTypeSourceInfo(TL.getUnderlyingTInfo(), Record); -} -void TypeLocWriter::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) { - Writer.AddSourceLocation(TL.getNameLoc(), Record); -} -void TypeLocWriter::VisitRecordTypeLoc(RecordTypeLoc TL) { - Writer.AddSourceLocation(TL.getNameLoc(), Record); -} -void TypeLocWriter::VisitEnumTypeLoc(EnumTypeLoc TL) { - Writer.AddSourceLocation(TL.getNameLoc(), Record); -} -void TypeLocWriter::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) { - Writer.AddSourceLocation(TL.getNameLoc(), Record); -} -void TypeLocWriter::VisitSubstTemplateTypeParmTypeLoc( - SubstTemplateTypeParmTypeLoc TL) { - Writer.AddSourceLocation(TL.getNameLoc(), Record); -} -void TypeLocWriter::VisitTemplateSpecializationTypeLoc( - TemplateSpecializationTypeLoc TL) { - Writer.AddSourceLocation(TL.getTemplateNameLoc(), Record); - Writer.AddSourceLocation(TL.getLAngleLoc(), Record); - Writer.AddSourceLocation(TL.getRAngleLoc(), Record); - for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) - Writer.AddTemplateArgumentLocInfo(TL.getArgLoc(i).getArgument().getKind(), - TL.getArgLoc(i).getLocInfo(), Record); -} -void TypeLocWriter::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) { - Writer.AddSourceLocation(TL.getKeywordLoc(), Record); - Writer.AddSourceRange(TL.getQualifierRange(), Record); -} -void TypeLocWriter::VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) { - Writer.AddSourceLocation(TL.getNameLoc(), Record); -} -void TypeLocWriter::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) { - Writer.AddSourceLocation(TL.getKeywordLoc(), Record); - Writer.AddSourceRange(TL.getQualifierRange(), Record); - Writer.AddSourceLocation(TL.getNameLoc(), Record); -} -void TypeLocWriter::VisitDependentTemplateSpecializationTypeLoc( - DependentTemplateSpecializationTypeLoc TL) { - Writer.AddSourceLocation(TL.getKeywordLoc(), Record); - Writer.AddSourceRange(TL.getQualifierRange(), Record); - Writer.AddSourceLocation(TL.getNameLoc(), Record); - Writer.AddSourceLocation(TL.getLAngleLoc(), Record); - Writer.AddSourceLocation(TL.getRAngleLoc(), Record); - for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) - Writer.AddTemplateArgumentLocInfo(TL.getArgLoc(I).getArgument().getKind(), - TL.getArgLoc(I).getLocInfo(), Record); -} -void TypeLocWriter::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) { - Writer.AddSourceLocation(TL.getNameLoc(), Record); -} -void TypeLocWriter::VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) { - Record.push_back(TL.hasBaseTypeAsWritten()); - Writer.AddSourceLocation(TL.getLAngleLoc(), Record); - Writer.AddSourceLocation(TL.getRAngleLoc(), Record); - for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i) - Writer.AddSourceLocation(TL.getProtocolLoc(i), Record); -} -void TypeLocWriter::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) { - Writer.AddSourceLocation(TL.getStarLoc(), Record); -} - -//===----------------------------------------------------------------------===// -// PCHWriter Implementation -//===----------------------------------------------------------------------===// - -static void EmitBlockID(unsigned ID, const char *Name, - llvm::BitstreamWriter &Stream, - PCHWriter::RecordData &Record) { - Record.clear(); - Record.push_back(ID); - Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record); - - // Emit the block name if present. - if (Name == 0 || Name[0] == 0) return; - Record.clear(); - while (*Name) - Record.push_back(*Name++); - Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_BLOCKNAME, Record); -} - -static void EmitRecordID(unsigned ID, const char *Name, - llvm::BitstreamWriter &Stream, - PCHWriter::RecordData &Record) { - Record.clear(); - Record.push_back(ID); - while (*Name) - Record.push_back(*Name++); - Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Record); -} - -static void AddStmtsExprs(llvm::BitstreamWriter &Stream, - PCHWriter::RecordData &Record) { -#define RECORD(X) EmitRecordID(pch::X, #X, Stream, Record) - RECORD(STMT_STOP); - RECORD(STMT_NULL_PTR); - RECORD(STMT_NULL); - RECORD(STMT_COMPOUND); - RECORD(STMT_CASE); - RECORD(STMT_DEFAULT); - RECORD(STMT_LABEL); - RECORD(STMT_IF); - RECORD(STMT_SWITCH); - RECORD(STMT_WHILE); - RECORD(STMT_DO); - RECORD(STMT_FOR); - RECORD(STMT_GOTO); - RECORD(STMT_INDIRECT_GOTO); - RECORD(STMT_CONTINUE); - RECORD(STMT_BREAK); - RECORD(STMT_RETURN); - RECORD(STMT_DECL); - RECORD(STMT_ASM); - RECORD(EXPR_PREDEFINED); - RECORD(EXPR_DECL_REF); - RECORD(EXPR_INTEGER_LITERAL); - RECORD(EXPR_FLOATING_LITERAL); - RECORD(EXPR_IMAGINARY_LITERAL); - RECORD(EXPR_STRING_LITERAL); - RECORD(EXPR_CHARACTER_LITERAL); - RECORD(EXPR_PAREN); - RECORD(EXPR_UNARY_OPERATOR); - RECORD(EXPR_SIZEOF_ALIGN_OF); - RECORD(EXPR_ARRAY_SUBSCRIPT); - RECORD(EXPR_CALL); - RECORD(EXPR_MEMBER); - RECORD(EXPR_BINARY_OPERATOR); - RECORD(EXPR_COMPOUND_ASSIGN_OPERATOR); - RECORD(EXPR_CONDITIONAL_OPERATOR); - RECORD(EXPR_IMPLICIT_CAST); - RECORD(EXPR_CSTYLE_CAST); - RECORD(EXPR_COMPOUND_LITERAL); - RECORD(EXPR_EXT_VECTOR_ELEMENT); - RECORD(EXPR_INIT_LIST); - RECORD(EXPR_DESIGNATED_INIT); - RECORD(EXPR_IMPLICIT_VALUE_INIT); - RECORD(EXPR_VA_ARG); - RECORD(EXPR_ADDR_LABEL); - RECORD(EXPR_STMT); - RECORD(EXPR_TYPES_COMPATIBLE); - RECORD(EXPR_CHOOSE); - RECORD(EXPR_GNU_NULL); - RECORD(EXPR_SHUFFLE_VECTOR); - RECORD(EXPR_BLOCK); - RECORD(EXPR_BLOCK_DECL_REF); - RECORD(EXPR_OBJC_STRING_LITERAL); - RECORD(EXPR_OBJC_ENCODE); - RECORD(EXPR_OBJC_SELECTOR_EXPR); - RECORD(EXPR_OBJC_PROTOCOL_EXPR); - RECORD(EXPR_OBJC_IVAR_REF_EXPR); - RECORD(EXPR_OBJC_PROPERTY_REF_EXPR); - RECORD(EXPR_OBJC_KVC_REF_EXPR); - RECORD(EXPR_OBJC_MESSAGE_EXPR); - RECORD(EXPR_OBJC_SUPER_EXPR); - RECORD(STMT_OBJC_FOR_COLLECTION); - RECORD(STMT_OBJC_CATCH); - RECORD(STMT_OBJC_FINALLY); - RECORD(STMT_OBJC_AT_TRY); - RECORD(STMT_OBJC_AT_SYNCHRONIZED); - RECORD(STMT_OBJC_AT_THROW); - RECORD(EXPR_CXX_OPERATOR_CALL); - RECORD(EXPR_CXX_CONSTRUCT); - RECORD(EXPR_CXX_STATIC_CAST); - RECORD(EXPR_CXX_DYNAMIC_CAST); - RECORD(EXPR_CXX_REINTERPRET_CAST); - RECORD(EXPR_CXX_CONST_CAST); - RECORD(EXPR_CXX_FUNCTIONAL_CAST); - RECORD(EXPR_CXX_BOOL_LITERAL); - RECORD(EXPR_CXX_NULL_PTR_LITERAL); -#undef RECORD -} - -void PCHWriter::WriteBlockInfoBlock() { - RecordData Record; - Stream.EnterSubblock(llvm::bitc::BLOCKINFO_BLOCK_ID, 3); - -#define BLOCK(X) EmitBlockID(pch::X ## _ID, #X, Stream, Record) -#define RECORD(X) EmitRecordID(pch::X, #X, Stream, Record) - - // PCH Top-Level Block. - BLOCK(PCH_BLOCK); - RECORD(ORIGINAL_FILE_NAME); - RECORD(TYPE_OFFSET); - RECORD(DECL_OFFSET); - RECORD(LANGUAGE_OPTIONS); - RECORD(METADATA); - RECORD(IDENTIFIER_OFFSET); - RECORD(IDENTIFIER_TABLE); - RECORD(EXTERNAL_DEFINITIONS); - RECORD(SPECIAL_TYPES); - RECORD(STATISTICS); - RECORD(TENTATIVE_DEFINITIONS); - RECORD(UNUSED_STATIC_FUNCS); - RECORD(LOCALLY_SCOPED_EXTERNAL_DECLS); - RECORD(SELECTOR_OFFSETS); - RECORD(METHOD_POOL); - RECORD(PP_COUNTER_VALUE); - RECORD(SOURCE_LOCATION_OFFSETS); - RECORD(SOURCE_LOCATION_PRELOADS); - RECORD(STAT_CACHE); - RECORD(EXT_VECTOR_DECLS); - RECORD(VERSION_CONTROL_BRANCH_REVISION); - RECORD(UNUSED_STATIC_FUNCS); - RECORD(MACRO_DEFINITION_OFFSETS); - RECORD(CHAINED_METADATA); - - // SourceManager Block. - BLOCK(SOURCE_MANAGER_BLOCK); - RECORD(SM_SLOC_FILE_ENTRY); - RECORD(SM_SLOC_BUFFER_ENTRY); - RECORD(SM_SLOC_BUFFER_BLOB); - RECORD(SM_SLOC_INSTANTIATION_ENTRY); - RECORD(SM_LINE_TABLE); - - // Preprocessor Block. - BLOCK(PREPROCESSOR_BLOCK); - RECORD(PP_MACRO_OBJECT_LIKE); - RECORD(PP_MACRO_FUNCTION_LIKE); - RECORD(PP_TOKEN); - RECORD(PP_MACRO_INSTANTIATION); - RECORD(PP_MACRO_DEFINITION); - - // Decls and Types block. - BLOCK(DECLTYPES_BLOCK); - RECORD(TYPE_EXT_QUAL); - RECORD(TYPE_COMPLEX); - RECORD(TYPE_POINTER); - RECORD(TYPE_BLOCK_POINTER); - RECORD(TYPE_LVALUE_REFERENCE); - RECORD(TYPE_RVALUE_REFERENCE); - RECORD(TYPE_MEMBER_POINTER); - RECORD(TYPE_CONSTANT_ARRAY); - RECORD(TYPE_INCOMPLETE_ARRAY); - RECORD(TYPE_VARIABLE_ARRAY); - RECORD(TYPE_VECTOR); - RECORD(TYPE_EXT_VECTOR); - RECORD(TYPE_FUNCTION_PROTO); - RECORD(TYPE_FUNCTION_NO_PROTO); - RECORD(TYPE_TYPEDEF); - RECORD(TYPE_TYPEOF_EXPR); - RECORD(TYPE_TYPEOF); - RECORD(TYPE_RECORD); - RECORD(TYPE_ENUM); - RECORD(TYPE_OBJC_INTERFACE); - RECORD(TYPE_OBJC_OBJECT); - RECORD(TYPE_OBJC_OBJECT_POINTER); - RECORD(DECL_ATTR); - RECORD(DECL_TRANSLATION_UNIT); - RECORD(DECL_TYPEDEF); - RECORD(DECL_ENUM); - RECORD(DECL_RECORD); - RECORD(DECL_ENUM_CONSTANT); - RECORD(DECL_FUNCTION); - RECORD(DECL_OBJC_METHOD); - RECORD(DECL_OBJC_INTERFACE); - RECORD(DECL_OBJC_PROTOCOL); - RECORD(DECL_OBJC_IVAR); - RECORD(DECL_OBJC_AT_DEFS_FIELD); - RECORD(DECL_OBJC_CLASS); - RECORD(DECL_OBJC_FORWARD_PROTOCOL); - RECORD(DECL_OBJC_CATEGORY); - RECORD(DECL_OBJC_CATEGORY_IMPL); - RECORD(DECL_OBJC_IMPLEMENTATION); - RECORD(DECL_OBJC_COMPATIBLE_ALIAS); - RECORD(DECL_OBJC_PROPERTY); - RECORD(DECL_OBJC_PROPERTY_IMPL); - RECORD(DECL_FIELD); - RECORD(DECL_VAR); - RECORD(DECL_IMPLICIT_PARAM); - RECORD(DECL_PARM_VAR); - RECORD(DECL_FILE_SCOPE_ASM); - RECORD(DECL_BLOCK); - RECORD(DECL_CONTEXT_LEXICAL); - RECORD(DECL_CONTEXT_VISIBLE); - // Statements and Exprs can occur in the Decls and Types block. - AddStmtsExprs(Stream, Record); -#undef RECORD -#undef BLOCK - Stream.ExitBlock(); -} - -/// \brief Adjusts the given filename to only write out the portion of the -/// filename that is not part of the system root directory. -/// -/// \param Filename the file name to adjust. -/// -/// \param isysroot When non-NULL, the PCH file is a relocatable PCH file and -/// the returned filename will be adjusted by this system root. -/// -/// \returns either the original filename (if it needs no adjustment) or the -/// adjusted filename (which points into the @p Filename parameter). -static const char * -adjustFilenameForRelocatablePCH(const char *Filename, const char *isysroot) { - assert(Filename && "No file name to adjust?"); - - if (!isysroot) - return Filename; - - // Verify that the filename and the system root have the same prefix. - unsigned Pos = 0; - for (; Filename[Pos] && isysroot[Pos]; ++Pos) - if (Filename[Pos] != isysroot[Pos]) - return Filename; // Prefixes don't match. - - // We hit the end of the filename before we hit the end of the system root. - if (!Filename[Pos]) - return Filename; - - // If the file name has a '/' at the current position, skip over the '/'. - // We distinguish sysroot-based includes from absolute includes by the - // absence of '/' at the beginning of sysroot-based includes. - if (Filename[Pos] == '/') - ++Pos; - - return Filename + Pos; -} - -/// \brief Write the PCH metadata (e.g., i686-apple-darwin9). -void PCHWriter::WriteMetadata(ASTContext &Context, const char *isysroot) { - using namespace llvm; - - // Metadata - const TargetInfo &Target = Context.Target; - BitCodeAbbrev *MetaAbbrev = new BitCodeAbbrev(); - MetaAbbrev->Add(BitCodeAbbrevOp( - Chain ? pch::CHAINED_METADATA : pch::METADATA)); - MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // PCH major - MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // PCH minor - MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang major - MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang minor - MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Relocatable - // Target triple or chained PCH name - MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); - unsigned MetaAbbrevCode = Stream.EmitAbbrev(MetaAbbrev); - - RecordData Record; - Record.push_back(Chain ? pch::CHAINED_METADATA : pch::METADATA); - Record.push_back(pch::VERSION_MAJOR); - Record.push_back(pch::VERSION_MINOR); - Record.push_back(CLANG_VERSION_MAJOR); - Record.push_back(CLANG_VERSION_MINOR); - Record.push_back(isysroot != 0); - // FIXME: This writes the absolute path for chained headers. - const std::string &BlobStr = Chain ? Chain->getFileName() : Target.getTriple().getTriple(); - Stream.EmitRecordWithBlob(MetaAbbrevCode, Record, BlobStr); - - // Original file name - SourceManager &SM = Context.getSourceManager(); - if (const FileEntry *MainFile = SM.getFileEntryForID(SM.getMainFileID())) { - BitCodeAbbrev *FileAbbrev = new BitCodeAbbrev(); - FileAbbrev->Add(BitCodeAbbrevOp(pch::ORIGINAL_FILE_NAME)); - FileAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name - unsigned FileAbbrevCode = Stream.EmitAbbrev(FileAbbrev); - - llvm::sys::Path MainFilePath(MainFile->getName()); - - MainFilePath.makeAbsolute(); - - const char *MainFileNameStr = MainFilePath.c_str(); - MainFileNameStr = adjustFilenameForRelocatablePCH(MainFileNameStr, - isysroot); - RecordData Record; - Record.push_back(pch::ORIGINAL_FILE_NAME); - Stream.EmitRecordWithBlob(FileAbbrevCode, Record, MainFileNameStr); - } - - // Repository branch/version information. - BitCodeAbbrev *RepoAbbrev = new BitCodeAbbrev(); - RepoAbbrev->Add(BitCodeAbbrevOp(pch::VERSION_CONTROL_BRANCH_REVISION)); - RepoAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // SVN branch/tag - unsigned RepoAbbrevCode = Stream.EmitAbbrev(RepoAbbrev); - Record.clear(); - Record.push_back(pch::VERSION_CONTROL_BRANCH_REVISION); - Stream.EmitRecordWithBlob(RepoAbbrevCode, Record, - getClangFullRepositoryVersion()); -} - -/// \brief Write the LangOptions structure. -void PCHWriter::WriteLanguageOptions(const LangOptions &LangOpts) { - RecordData Record; - Record.push_back(LangOpts.Trigraphs); - Record.push_back(LangOpts.BCPLComment); // BCPL-style '//' comments. - Record.push_back(LangOpts.DollarIdents); // '$' allowed in identifiers. - Record.push_back(LangOpts.AsmPreprocessor); // Preprocessor in asm mode. - Record.push_back(LangOpts.GNUMode); // True in gnu99 mode false in c99 mode (etc) - Record.push_back(LangOpts.GNUKeywords); // Allow GNU-extension keywords - Record.push_back(LangOpts.ImplicitInt); // C89 implicit 'int'. - Record.push_back(LangOpts.Digraphs); // C94, C99 and C++ - Record.push_back(LangOpts.HexFloats); // C99 Hexadecimal float constants. - Record.push_back(LangOpts.C99); // C99 Support - Record.push_back(LangOpts.Microsoft); // Microsoft extensions. - Record.push_back(LangOpts.CPlusPlus); // C++ Support - Record.push_back(LangOpts.CPlusPlus0x); // C++0x Support - Record.push_back(LangOpts.CXXOperatorNames); // Treat C++ operator names as keywords. - - Record.push_back(LangOpts.ObjC1); // Objective-C 1 support enabled. - Record.push_back(LangOpts.ObjC2); // Objective-C 2 support enabled. - Record.push_back(LangOpts.ObjCNonFragileABI); // Objective-C - // modern abi enabled. - Record.push_back(LangOpts.ObjCNonFragileABI2); // Objective-C enhanced - // modern abi enabled. - Record.push_back(LangOpts.NoConstantCFStrings); // non cfstring generation enabled.. - - Record.push_back(LangOpts.PascalStrings); // Allow Pascal strings - Record.push_back(LangOpts.WritableStrings); // Allow writable strings - Record.push_back(LangOpts.LaxVectorConversions); - Record.push_back(LangOpts.AltiVec); - Record.push_back(LangOpts.Exceptions); // Support exception handling. - Record.push_back(LangOpts.SjLjExceptions); - - Record.push_back(LangOpts.NeXTRuntime); // Use NeXT runtime. - Record.push_back(LangOpts.Freestanding); // Freestanding implementation - Record.push_back(LangOpts.NoBuiltin); // Do not use builtin functions (-fno-builtin) - - // Whether static initializers are protected by locks. - Record.push_back(LangOpts.ThreadsafeStatics); - Record.push_back(LangOpts.POSIXThreads); - Record.push_back(LangOpts.Blocks); // block extension to C - Record.push_back(LangOpts.EmitAllDecls); // Emit all declarations, even if - // they are unused. - Record.push_back(LangOpts.MathErrno); // Math functions must respect errno - // (modulo the platform support). - - Record.push_back(LangOpts.getSignedOverflowBehavior()); - Record.push_back(LangOpts.HeinousExtensions); - - Record.push_back(LangOpts.Optimize); // Whether __OPTIMIZE__ should be defined. - Record.push_back(LangOpts.OptimizeSize); // Whether __OPTIMIZE_SIZE__ should be - // defined. - Record.push_back(LangOpts.Static); // Should __STATIC__ be defined (as - // opposed to __DYNAMIC__). - Record.push_back(LangOpts.PICLevel); // The value for __PIC__, if non-zero. - - Record.push_back(LangOpts.GNUInline); // Should GNU inline semantics be - // used (instead of C99 semantics). - Record.push_back(LangOpts.NoInline); // Should __NO_INLINE__ be defined. - Record.push_back(LangOpts.AccessControl); // Whether C++ access control should - // be enabled. - Record.push_back(LangOpts.CharIsSigned); // Whether char is a signed or - // unsigned type - Record.push_back(LangOpts.ShortWChar); // force wchar_t to be unsigned short - Record.push_back(LangOpts.getGCMode()); - Record.push_back(LangOpts.getVisibilityMode()); - Record.push_back(LangOpts.getStackProtectorMode()); - Record.push_back(LangOpts.InstantiationDepth); - Record.push_back(LangOpts.OpenCL); - Record.push_back(LangOpts.CatchUndefined); - Record.push_back(LangOpts.ElideConstructors); - Record.push_back(LangOpts.SpellChecking); - Stream.EmitRecord(pch::LANGUAGE_OPTIONS, Record); -} - -//===----------------------------------------------------------------------===// -// stat cache Serialization -//===----------------------------------------------------------------------===// - -namespace { -// Trait used for the on-disk hash table of stat cache results. -class PCHStatCacheTrait { -public: - typedef const char * key_type; - typedef key_type key_type_ref; - - typedef std::pair<int, struct stat> data_type; - typedef const data_type& data_type_ref; - - static unsigned ComputeHash(const char *path) { - return llvm::HashString(path); - } - - std::pair<unsigned,unsigned> - EmitKeyDataLength(llvm::raw_ostream& Out, const char *path, - data_type_ref Data) { - unsigned StrLen = strlen(path); - clang::io::Emit16(Out, StrLen); - unsigned DataLen = 1; // result value - if (Data.first == 0) - DataLen += 4 + 4 + 2 + 8 + 8; - clang::io::Emit8(Out, DataLen); - return std::make_pair(StrLen + 1, DataLen); - } - - void EmitKey(llvm::raw_ostream& Out, const char *path, unsigned KeyLen) { - Out.write(path, KeyLen); - } - - void EmitData(llvm::raw_ostream& Out, key_type_ref, - data_type_ref Data, unsigned DataLen) { - using namespace clang::io; - uint64_t Start = Out.tell(); (void)Start; - - // Result of stat() - Emit8(Out, Data.first? 1 : 0); - - if (Data.first == 0) { - Emit32(Out, (uint32_t) Data.second.st_ino); - Emit32(Out, (uint32_t) Data.second.st_dev); - Emit16(Out, (uint16_t) Data.second.st_mode); - Emit64(Out, (uint64_t) Data.second.st_mtime); - Emit64(Out, (uint64_t) Data.second.st_size); - } - - assert(Out.tell() - Start == DataLen && "Wrong data length"); - } -}; -} // end anonymous namespace - -/// \brief Write the stat() system call cache to the PCH file. -void PCHWriter::WriteStatCache(MemorizeStatCalls &StatCalls) { - // Build the on-disk hash table containing information about every - // stat() call. - OnDiskChainedHashTableGenerator<PCHStatCacheTrait> Generator; - unsigned NumStatEntries = 0; - for (MemorizeStatCalls::iterator Stat = StatCalls.begin(), - StatEnd = StatCalls.end(); - Stat != StatEnd; ++Stat, ++NumStatEntries) { - const char *Filename = Stat->first(); - Generator.insert(Filename, Stat->second); - } - - // Create the on-disk hash table in a buffer. - llvm::SmallString<4096> StatCacheData; - uint32_t BucketOffset; - { - llvm::raw_svector_ostream Out(StatCacheData); - // Make sure that no bucket is at offset 0 - clang::io::Emit32(Out, 0); - BucketOffset = Generator.Emit(Out); - } - - // Create a blob abbreviation - using namespace llvm; - BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); - Abbrev->Add(BitCodeAbbrevOp(pch::STAT_CACHE)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); - unsigned StatCacheAbbrev = Stream.EmitAbbrev(Abbrev); - - // Write the stat cache - RecordData Record; - Record.push_back(pch::STAT_CACHE); - Record.push_back(BucketOffset); - Record.push_back(NumStatEntries); - Stream.EmitRecordWithBlob(StatCacheAbbrev, Record, StatCacheData.str()); -} - -//===----------------------------------------------------------------------===// -// Source Manager Serialization -//===----------------------------------------------------------------------===// - -/// \brief Create an abbreviation for the SLocEntry that refers to a -/// file. -static unsigned CreateSLocFileAbbrev(llvm::BitstreamWriter &Stream) { - using namespace llvm; - BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); - Abbrev->Add(BitCodeAbbrevOp(pch::SM_SLOC_FILE_ENTRY)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Include location - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Characteristic - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Line directives - // FileEntry fields. - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 12)); // Size - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 32)); // Modification time - // HeaderFileInfo fields. - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isImport - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // DirInfo - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // NumIncludes - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // ControllingMacro - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name - return Stream.EmitAbbrev(Abbrev); -} - -/// \brief Create an abbreviation for the SLocEntry that refers to a -/// buffer. -static unsigned CreateSLocBufferAbbrev(llvm::BitstreamWriter &Stream) { - using namespace llvm; - BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); - Abbrev->Add(BitCodeAbbrevOp(pch::SM_SLOC_BUFFER_ENTRY)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Include location - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Characteristic - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Line directives - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Buffer name blob - return Stream.EmitAbbrev(Abbrev); -} - -/// \brief Create an abbreviation for the SLocEntry that refers to a -/// buffer's blob. -static unsigned CreateSLocBufferBlobAbbrev(llvm::BitstreamWriter &Stream) { - using namespace llvm; - BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); - Abbrev->Add(BitCodeAbbrevOp(pch::SM_SLOC_BUFFER_BLOB)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Blob - return Stream.EmitAbbrev(Abbrev); -} - -/// \brief Create an abbreviation for the SLocEntry that refers to an -/// buffer. -static unsigned CreateSLocInstantiationAbbrev(llvm::BitstreamWriter &Stream) { - using namespace llvm; - BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); - Abbrev->Add(BitCodeAbbrevOp(pch::SM_SLOC_INSTANTIATION_ENTRY)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Spelling location - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Start location - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // End location - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Token length - return Stream.EmitAbbrev(Abbrev); -} - -/// \brief Writes the block containing the serialized form of the -/// source manager. -/// -/// TODO: We should probably use an on-disk hash table (stored in a -/// blob), indexed based on the file name, so that we only create -/// entries for files that we actually need. In the common case (no -/// errors), we probably won't have to create file entries for any of -/// the files in the AST. -void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, - const Preprocessor &PP, - const char *isysroot) { - RecordData Record; - - // Enter the source manager block. - Stream.EnterSubblock(pch::SOURCE_MANAGER_BLOCK_ID, 3); - - // Abbreviations for the various kinds of source-location entries. - unsigned SLocFileAbbrv = CreateSLocFileAbbrev(Stream); - unsigned SLocBufferAbbrv = CreateSLocBufferAbbrev(Stream); - unsigned SLocBufferBlobAbbrv = CreateSLocBufferBlobAbbrev(Stream); - unsigned SLocInstantiationAbbrv = CreateSLocInstantiationAbbrev(Stream); - - // Write the line table. - if (SourceMgr.hasLineTable()) { - LineTableInfo &LineTable = SourceMgr.getLineTable(); - - // Emit the file names - Record.push_back(LineTable.getNumFilenames()); - for (unsigned I = 0, N = LineTable.getNumFilenames(); I != N; ++I) { - // Emit the file name - const char *Filename = LineTable.getFilename(I); - Filename = adjustFilenameForRelocatablePCH(Filename, isysroot); - unsigned FilenameLen = Filename? strlen(Filename) : 0; - Record.push_back(FilenameLen); - if (FilenameLen) - Record.insert(Record.end(), Filename, Filename + FilenameLen); - } - - // Emit the line entries - for (LineTableInfo::iterator L = LineTable.begin(), LEnd = LineTable.end(); - L != LEnd; ++L) { - // Emit the file ID - Record.push_back(L->first); - - // Emit the line entries - Record.push_back(L->second.size()); - for (std::vector<LineEntry>::iterator LE = L->second.begin(), - LEEnd = L->second.end(); - LE != LEEnd; ++LE) { - Record.push_back(LE->FileOffset); - Record.push_back(LE->LineNo); - Record.push_back(LE->FilenameID); - Record.push_back((unsigned)LE->FileKind); - Record.push_back(LE->IncludeOffset); - } - } - Stream.EmitRecord(pch::SM_LINE_TABLE, Record); - } - - // Write out the source location entry table. We skip the first - // entry, which is always the same dummy entry. - std::vector<uint32_t> SLocEntryOffsets; - RecordData PreloadSLocs; - SLocEntryOffsets.reserve(SourceMgr.sloc_entry_size() - 1); - for (unsigned I = 1, N = SourceMgr.sloc_entry_size(); I != N; ++I) { - // Get this source location entry. - const SrcMgr::SLocEntry *SLoc = &SourceMgr.getSLocEntry(I); - - // Record the offset of this source-location entry. - SLocEntryOffsets.push_back(Stream.GetCurrentBitNo()); - - // Figure out which record code to use. - unsigned Code; - if (SLoc->isFile()) { - if (SLoc->getFile().getContentCache()->Entry) - Code = pch::SM_SLOC_FILE_ENTRY; - else - Code = pch::SM_SLOC_BUFFER_ENTRY; - } else - Code = pch::SM_SLOC_INSTANTIATION_ENTRY; - Record.clear(); - Record.push_back(Code); - - Record.push_back(SLoc->getOffset()); - if (SLoc->isFile()) { - const SrcMgr::FileInfo &File = SLoc->getFile(); - Record.push_back(File.getIncludeLoc().getRawEncoding()); - Record.push_back(File.getFileCharacteristic()); // FIXME: stable encoding - Record.push_back(File.hasLineDirectives()); - - const SrcMgr::ContentCache *Content = File.getContentCache(); - if (Content->Entry) { - // The source location entry is a file. The blob associated - // with this entry is the file name. - - // Emit size/modification time for this file. - Record.push_back(Content->Entry->getSize()); - Record.push_back(Content->Entry->getModificationTime()); - - // Emit header-search information associated with this file. - HeaderFileInfo HFI; - HeaderSearch &HS = PP.getHeaderSearchInfo(); - if (Content->Entry->getUID() < HS.header_file_size()) - HFI = HS.header_file_begin()[Content->Entry->getUID()]; - Record.push_back(HFI.isImport); - Record.push_back(HFI.DirInfo); - Record.push_back(HFI.NumIncludes); - AddIdentifierRef(HFI.ControllingMacro, Record); - - // Turn the file name into an absolute path, if it isn't already. - const char *Filename = Content->Entry->getName(); - llvm::sys::Path FilePath(Filename, strlen(Filename)); - FilePath.makeAbsolute(); - Filename = FilePath.c_str(); - - Filename = adjustFilenameForRelocatablePCH(Filename, isysroot); - Stream.EmitRecordWithBlob(SLocFileAbbrv, Record, Filename); - - // FIXME: For now, preload all file source locations, so that - // we get the appropriate File entries in the reader. This is - // a temporary measure. - PreloadSLocs.push_back(SLocEntryOffsets.size()); - } else { - // The source location entry is a buffer. The blob associated - // with this entry contains the contents of the buffer. - - // We add one to the size so that we capture the trailing NULL - // that is required by llvm::MemoryBuffer::getMemBuffer (on - // the reader side). - const llvm::MemoryBuffer *Buffer - = Content->getBuffer(PP.getDiagnostics(), PP.getSourceManager()); - const char *Name = Buffer->getBufferIdentifier(); - Stream.EmitRecordWithBlob(SLocBufferAbbrv, Record, - llvm::StringRef(Name, strlen(Name) + 1)); - Record.clear(); - Record.push_back(pch::SM_SLOC_BUFFER_BLOB); - Stream.EmitRecordWithBlob(SLocBufferBlobAbbrv, Record, - llvm::StringRef(Buffer->getBufferStart(), - Buffer->getBufferSize() + 1)); - - if (strcmp(Name, "<built-in>") == 0) - PreloadSLocs.push_back(SLocEntryOffsets.size()); - } - } else { - // The source location entry is an instantiation. - const SrcMgr::InstantiationInfo &Inst = SLoc->getInstantiation(); - Record.push_back(Inst.getSpellingLoc().getRawEncoding()); - Record.push_back(Inst.getInstantiationLocStart().getRawEncoding()); - Record.push_back(Inst.getInstantiationLocEnd().getRawEncoding()); - - // Compute the token length for this macro expansion. - unsigned NextOffset = SourceMgr.getNextOffset(); - if (I + 1 != N) - NextOffset = SourceMgr.getSLocEntry(I + 1).getOffset(); - Record.push_back(NextOffset - SLoc->getOffset() - 1); - Stream.EmitRecordWithAbbrev(SLocInstantiationAbbrv, Record); - } - } - - Stream.ExitBlock(); - - if (SLocEntryOffsets.empty()) - return; - - // Write the source-location offsets table into the PCH block. This - // table is used for lazily loading source-location information. - using namespace llvm; - BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); - Abbrev->Add(BitCodeAbbrevOp(pch::SOURCE_LOCATION_OFFSETS)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 16)); // # of slocs - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 16)); // next offset - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // offsets - unsigned SLocOffsetsAbbrev = Stream.EmitAbbrev(Abbrev); - - Record.clear(); - Record.push_back(pch::SOURCE_LOCATION_OFFSETS); - Record.push_back(SLocEntryOffsets.size()); - Record.push_back(SourceMgr.getNextOffset()); - Stream.EmitRecordWithBlob(SLocOffsetsAbbrev, Record, - (const char *)&SLocEntryOffsets.front(), - SLocEntryOffsets.size()*sizeof(SLocEntryOffsets[0])); - - // Write the source location entry preloads array, telling the PCH - // reader which source locations entries it should load eagerly. - Stream.EmitRecord(pch::SOURCE_LOCATION_PRELOADS, PreloadSLocs); -} - -//===----------------------------------------------------------------------===// -// Preprocessor Serialization -//===----------------------------------------------------------------------===// - -/// \brief Writes the block containing the serialized form of the -/// preprocessor. -/// -void PCHWriter::WritePreprocessor(const Preprocessor &PP) { - RecordData Record; - - // If the preprocessor __COUNTER__ value has been bumped, remember it. - if (PP.getCounterValue() != 0) { - Record.push_back(PP.getCounterValue()); - Stream.EmitRecord(pch::PP_COUNTER_VALUE, Record); - Record.clear(); - } - - // Enter the preprocessor block. - Stream.EnterSubblock(pch::PREPROCESSOR_BLOCK_ID, 2); - - // If the PCH file contains __DATE__ or __TIME__ emit a warning about this. - // FIXME: use diagnostics subsystem for localization etc. - if (PP.SawDateOrTime()) - fprintf(stderr, "warning: precompiled header used __DATE__ or __TIME__.\n"); - - // Loop over all the macro definitions that are live at the end of the file, - // emitting each to the PP section. - PreprocessingRecord *PPRec = PP.getPreprocessingRecord(); - for (Preprocessor::macro_iterator I = PP.macro_begin(), E = PP.macro_end(); - I != E; ++I) { - // FIXME: This emits macros in hash table order, we should do it in a stable - // order so that output is reproducible. - MacroInfo *MI = I->second; - - // Don't emit builtin macros like __LINE__ to the PCH file unless they have - // been redefined by the header (in which case they are not isBuiltinMacro). - if (MI->isBuiltinMacro()) - continue; - - AddIdentifierRef(I->first, Record); - MacroOffsets[I->first] = Stream.GetCurrentBitNo(); - Record.push_back(MI->getDefinitionLoc().getRawEncoding()); - Record.push_back(MI->isUsed()); - - unsigned Code; - if (MI->isObjectLike()) { - Code = pch::PP_MACRO_OBJECT_LIKE; - } else { - Code = pch::PP_MACRO_FUNCTION_LIKE; - - Record.push_back(MI->isC99Varargs()); - Record.push_back(MI->isGNUVarargs()); - Record.push_back(MI->getNumArgs()); - for (MacroInfo::arg_iterator I = MI->arg_begin(), E = MI->arg_end(); - I != E; ++I) - AddIdentifierRef(*I, Record); - } - - // If we have a detailed preprocessing record, record the macro definition - // ID that corresponds to this macro. - if (PPRec) - Record.push_back(getMacroDefinitionID(PPRec->findMacroDefinition(MI))); - - Stream.EmitRecord(Code, Record); - Record.clear(); - - // Emit the tokens array. - for (unsigned TokNo = 0, e = MI->getNumTokens(); TokNo != e; ++TokNo) { - // Note that we know that the preprocessor does not have any annotation - // tokens in it because they are created by the parser, and thus can't be - // in a macro definition. - const Token &Tok = MI->getReplacementToken(TokNo); - - Record.push_back(Tok.getLocation().getRawEncoding()); - Record.push_back(Tok.getLength()); - - // FIXME: When reading literal tokens, reconstruct the literal pointer if - // it is needed. - AddIdentifierRef(Tok.getIdentifierInfo(), Record); - - // FIXME: Should translate token kind to a stable encoding. - Record.push_back(Tok.getKind()); - // FIXME: Should translate token flags to a stable encoding. - Record.push_back(Tok.getFlags()); - - Stream.EmitRecord(pch::PP_TOKEN, Record); - Record.clear(); - } - ++NumMacros; - } - - // If the preprocessor has a preprocessing record, emit it. - unsigned NumPreprocessingRecords = 0; - if (PPRec) { - for (PreprocessingRecord::iterator E = PPRec->begin(), EEnd = PPRec->end(); - E != EEnd; ++E) { - Record.clear(); - - if (MacroInstantiation *MI = dyn_cast<MacroInstantiation>(*E)) { - Record.push_back(NumPreprocessingRecords++); - AddSourceLocation(MI->getSourceRange().getBegin(), Record); - AddSourceLocation(MI->getSourceRange().getEnd(), Record); - AddIdentifierRef(MI->getName(), Record); - Record.push_back(getMacroDefinitionID(MI->getDefinition())); - Stream.EmitRecord(pch::PP_MACRO_INSTANTIATION, Record); - continue; - } - - if (MacroDefinition *MD = dyn_cast<MacroDefinition>(*E)) { - // Record this macro definition's location. - pch::IdentID ID = getMacroDefinitionID(MD); - if (ID != MacroDefinitionOffsets.size()) { - if (ID > MacroDefinitionOffsets.size()) - MacroDefinitionOffsets.resize(ID + 1); - - MacroDefinitionOffsets[ID] = Stream.GetCurrentBitNo(); - } else - MacroDefinitionOffsets.push_back(Stream.GetCurrentBitNo()); - - Record.push_back(NumPreprocessingRecords++); - Record.push_back(ID); - AddSourceLocation(MD->getSourceRange().getBegin(), Record); - AddSourceLocation(MD->getSourceRange().getEnd(), Record); - AddIdentifierRef(MD->getName(), Record); - AddSourceLocation(MD->getLocation(), Record); - Stream.EmitRecord(pch::PP_MACRO_DEFINITION, Record); - continue; - } - } - } - - Stream.ExitBlock(); - - // Write the offsets table for the preprocessing record. - if (NumPreprocessingRecords > 0) { - // Write the offsets table for identifier IDs. - using namespace llvm; - BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); - Abbrev->Add(BitCodeAbbrevOp(pch::MACRO_DEFINITION_OFFSETS)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of records - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of macro defs - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); - unsigned MacroDefOffsetAbbrev = Stream.EmitAbbrev(Abbrev); - - Record.clear(); - Record.push_back(pch::MACRO_DEFINITION_OFFSETS); - Record.push_back(NumPreprocessingRecords); - Record.push_back(MacroDefinitionOffsets.size()); - Stream.EmitRecordWithBlob(MacroDefOffsetAbbrev, Record, - (const char *)&MacroDefinitionOffsets.front(), - MacroDefinitionOffsets.size() * sizeof(uint32_t)); - } -} - -//===----------------------------------------------------------------------===// -// Type Serialization -//===----------------------------------------------------------------------===// - -/// \brief Write the representation of a type to the PCH stream. -void PCHWriter::WriteType(QualType T) { - pch::TypeID &ID = TypeIDs[T]; - if (ID == 0) // we haven't seen this type before. - ID = NextTypeID++; - - // Record the offset for this type. - if (TypeOffsets.size() == ID - pch::NUM_PREDEF_TYPE_IDS) - TypeOffsets.push_back(Stream.GetCurrentBitNo()); - else if (TypeOffsets.size() < ID - pch::NUM_PREDEF_TYPE_IDS) { - TypeOffsets.resize(ID + 1 - pch::NUM_PREDEF_TYPE_IDS); - TypeOffsets[ID - pch::NUM_PREDEF_TYPE_IDS] = Stream.GetCurrentBitNo(); - } - - RecordData Record; - - // Emit the type's representation. - PCHTypeWriter W(*this, Record); - - if (T.hasLocalNonFastQualifiers()) { - Qualifiers Qs = T.getLocalQualifiers(); - AddTypeRef(T.getLocalUnqualifiedType(), Record); - Record.push_back(Qs.getAsOpaqueValue()); - W.Code = pch::TYPE_EXT_QUAL; - } else { - switch (T->getTypeClass()) { - // For all of the concrete, non-dependent types, call the - // appropriate visitor function. -#define TYPE(Class, Base) \ - case Type::Class: W.Visit##Class##Type(cast<Class##Type>(T)); break; -#define ABSTRACT_TYPE(Class, Base) -#include "clang/AST/TypeNodes.def" - } - } - - // Emit the serialized record. - Stream.EmitRecord(W.Code, Record); - - // Flush any expressions that were written as part of this type. - FlushStmts(); -} - -//===----------------------------------------------------------------------===// -// Declaration Serialization -//===----------------------------------------------------------------------===// - -/// \brief Write the block containing all of the declaration IDs -/// lexically declared within the given DeclContext. -/// -/// \returns the offset of the DECL_CONTEXT_LEXICAL block within the -/// bistream, or 0 if no block was written. -uint64_t PCHWriter::WriteDeclContextLexicalBlock(ASTContext &Context, - DeclContext *DC) { - if (DC->decls_empty()) - return 0; - - uint64_t Offset = Stream.GetCurrentBitNo(); - RecordData Record; - for (DeclContext::decl_iterator D = DC->decls_begin(), DEnd = DC->decls_end(); - D != DEnd; ++D) - AddDeclRef(*D, Record); - - ++NumLexicalDeclContexts; - Stream.EmitRecord(pch::DECL_CONTEXT_LEXICAL, Record); - return Offset; -} - -/// \brief Write the block containing all of the declaration IDs -/// visible from the given DeclContext. -/// -/// \returns the offset of the DECL_CONTEXT_VISIBLE block within the -/// bistream, or 0 if no block was written. -uint64_t PCHWriter::WriteDeclContextVisibleBlock(ASTContext &Context, - DeclContext *DC) { - if (DC->getPrimaryContext() != DC) - return 0; - - // Since there is no name lookup into functions or methods, don't bother to - // build a visible-declarations table for these entities. - if (DC->isFunctionOrMethod()) - return 0; - - // If not in C++, we perform name lookup for the translation unit via the - // IdentifierInfo chains, don't bother to build a visible-declarations table. - // FIXME: In C++ we need the visible declarations in order to "see" the - // friend declarations, is there a way to do this without writing the table ? - if (DC->isTranslationUnit() && !Context.getLangOptions().CPlusPlus) - return 0; - - // Force the DeclContext to build a its name-lookup table. - DC->lookup(DeclarationName()); - - // Serialize the contents of the mapping used for lookup. Note that, - // although we have two very different code paths, the serialized - // representation is the same for both cases: a declaration name, - // followed by a size, followed by references to the visible - // declarations that have that name. - uint64_t Offset = Stream.GetCurrentBitNo(); - RecordData Record; - StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(DC->getLookupPtr()); - if (!Map) - return 0; - - for (StoredDeclsMap::iterator D = Map->begin(), DEnd = Map->end(); - D != DEnd; ++D) { - AddDeclarationName(D->first, Record); - DeclContext::lookup_result Result = D->second.getLookupResult(Context); - Record.push_back(Result.second - Result.first); - for (; Result.first != Result.second; ++Result.first) - AddDeclRef(*Result.first, Record); - } - - if (Record.size() == 0) - return 0; - - Stream.EmitRecord(pch::DECL_CONTEXT_VISIBLE, Record); - ++NumVisibleDeclContexts; - return Offset; -} - -//===----------------------------------------------------------------------===// -// Global Method Pool and Selector Serialization -//===----------------------------------------------------------------------===// - -namespace { -// Trait used for the on-disk hash table used in the method pool. -class PCHMethodPoolTrait { - PCHWriter &Writer; - -public: - typedef Selector key_type; - typedef key_type key_type_ref; - - typedef std::pair<ObjCMethodList, ObjCMethodList> data_type; - typedef const data_type& data_type_ref; - - explicit PCHMethodPoolTrait(PCHWriter &Writer) : Writer(Writer) { } - - static unsigned ComputeHash(Selector Sel) { - unsigned N = Sel.getNumArgs(); - if (N == 0) - ++N; - unsigned R = 5381; - for (unsigned I = 0; I != N; ++I) - if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(I)) - R = llvm::HashString(II->getName(), R); - return R; - } - - std::pair<unsigned,unsigned> - EmitKeyDataLength(llvm::raw_ostream& Out, Selector Sel, - data_type_ref Methods) { - unsigned KeyLen = 2 + (Sel.getNumArgs()? Sel.getNumArgs() * 4 : 4); - clang::io::Emit16(Out, KeyLen); - unsigned DataLen = 2 + 2; // 2 bytes for each of the method counts - for (const ObjCMethodList *Method = &Methods.first; Method; - Method = Method->Next) - if (Method->Method) - DataLen += 4; - for (const ObjCMethodList *Method = &Methods.second; Method; - Method = Method->Next) - if (Method->Method) - DataLen += 4; - clang::io::Emit16(Out, DataLen); - return std::make_pair(KeyLen, DataLen); - } - - void EmitKey(llvm::raw_ostream& Out, Selector Sel, unsigned) { - uint64_t Start = Out.tell(); - assert((Start >> 32) == 0 && "Selector key offset too large"); - Writer.SetSelectorOffset(Sel, Start); - unsigned N = Sel.getNumArgs(); - clang::io::Emit16(Out, N); - if (N == 0) - N = 1; - for (unsigned I = 0; I != N; ++I) - clang::io::Emit32(Out, - Writer.getIdentifierRef(Sel.getIdentifierInfoForSlot(I))); - } - - void EmitData(llvm::raw_ostream& Out, key_type_ref, - data_type_ref Methods, unsigned DataLen) { - uint64_t Start = Out.tell(); (void)Start; - unsigned NumInstanceMethods = 0; - for (const ObjCMethodList *Method = &Methods.first; Method; - Method = Method->Next) - if (Method->Method) - ++NumInstanceMethods; - - unsigned NumFactoryMethods = 0; - for (const ObjCMethodList *Method = &Methods.second; Method; - Method = Method->Next) - if (Method->Method) - ++NumFactoryMethods; - - clang::io::Emit16(Out, NumInstanceMethods); - clang::io::Emit16(Out, NumFactoryMethods); - for (const ObjCMethodList *Method = &Methods.first; Method; - Method = Method->Next) - if (Method->Method) - clang::io::Emit32(Out, Writer.getDeclID(Method->Method)); - for (const ObjCMethodList *Method = &Methods.second; Method; - Method = Method->Next) - if (Method->Method) - clang::io::Emit32(Out, Writer.getDeclID(Method->Method)); - - assert(Out.tell() - Start == DataLen && "Data length is wrong"); - } -}; -} // end anonymous namespace - -/// \brief Write the method pool into the PCH file. -/// -/// The method pool contains both instance and factory methods, stored -/// in an on-disk hash table indexed by the selector. -void PCHWriter::WriteMethodPool(Sema &SemaRef) { - using namespace llvm; - - // Create and write out the blob that contains the instance and - // factor method pools. - bool Empty = true; - { - OnDiskChainedHashTableGenerator<PCHMethodPoolTrait> Generator; - - // Create the on-disk hash table representation. Start by - // iterating through the instance method pool. - PCHMethodPoolTrait::key_type Key; - unsigned NumSelectorsInMethodPool = 0; - for (llvm::DenseMap<Selector, ObjCMethodList>::iterator - Instance = SemaRef.InstanceMethodPool.begin(), - InstanceEnd = SemaRef.InstanceMethodPool.end(); - Instance != InstanceEnd; ++Instance) { - // Check whether there is a factory method with the same - // selector. - llvm::DenseMap<Selector, ObjCMethodList>::iterator Factory - = SemaRef.FactoryMethodPool.find(Instance->first); - - if (Factory == SemaRef.FactoryMethodPool.end()) - Generator.insert(Instance->first, - std::make_pair(Instance->second, - ObjCMethodList())); - else - Generator.insert(Instance->first, - std::make_pair(Instance->second, Factory->second)); - - ++NumSelectorsInMethodPool; - Empty = false; - } - - // Now iterate through the factory method pool, to pick up any - // selectors that weren't already in the instance method pool. - for (llvm::DenseMap<Selector, ObjCMethodList>::iterator - Factory = SemaRef.FactoryMethodPool.begin(), - FactoryEnd = SemaRef.FactoryMethodPool.end(); - Factory != FactoryEnd; ++Factory) { - // Check whether there is an instance method with the same - // selector. If so, there is no work to do here. - llvm::DenseMap<Selector, ObjCMethodList>::iterator Instance - = SemaRef.InstanceMethodPool.find(Factory->first); - - if (Instance == SemaRef.InstanceMethodPool.end()) { - Generator.insert(Factory->first, - std::make_pair(ObjCMethodList(), Factory->second)); - ++NumSelectorsInMethodPool; - } - - Empty = false; - } - - if (Empty && SelectorOffsets.empty()) - return; - - // Create the on-disk hash table in a buffer. - llvm::SmallString<4096> MethodPool; - uint32_t BucketOffset; - SelectorOffsets.resize(SelVector.size()); - { - PCHMethodPoolTrait Trait(*this); - llvm::raw_svector_ostream Out(MethodPool); - // Make sure that no bucket is at offset 0 - clang::io::Emit32(Out, 0); - BucketOffset = Generator.Emit(Out, Trait); - - // For every selector that we have seen but which was not - // written into the hash table, write the selector itself and - // record it's offset. - for (unsigned I = 0, N = SelVector.size(); I != N; ++I) - if (SelectorOffsets[I] == 0) - Trait.EmitKey(Out, SelVector[I], 0); - } - - // Create a blob abbreviation - BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); - Abbrev->Add(BitCodeAbbrevOp(pch::METHOD_POOL)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); - unsigned MethodPoolAbbrev = Stream.EmitAbbrev(Abbrev); - - // Write the method pool - RecordData Record; - Record.push_back(pch::METHOD_POOL); - Record.push_back(BucketOffset); - Record.push_back(NumSelectorsInMethodPool); - Stream.EmitRecordWithBlob(MethodPoolAbbrev, Record, MethodPool.str()); - - // Create a blob abbreviation for the selector table offsets. - Abbrev = new BitCodeAbbrev(); - Abbrev->Add(BitCodeAbbrevOp(pch::SELECTOR_OFFSETS)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // index - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); - unsigned SelectorOffsetAbbrev = Stream.EmitAbbrev(Abbrev); - - // Write the selector offsets table. - Record.clear(); - Record.push_back(pch::SELECTOR_OFFSETS); - Record.push_back(SelectorOffsets.size()); - Stream.EmitRecordWithBlob(SelectorOffsetAbbrev, Record, - (const char *)&SelectorOffsets.front(), - SelectorOffsets.size() * 4); - } -} - -//===----------------------------------------------------------------------===// -// Identifier Table Serialization -//===----------------------------------------------------------------------===// - -namespace { -class PCHIdentifierTableTrait { - PCHWriter &Writer; - Preprocessor &PP; - - /// \brief Determines whether this is an "interesting" identifier - /// that needs a full IdentifierInfo structure written into the hash - /// table. - static bool isInterestingIdentifier(const IdentifierInfo *II) { - return II->isPoisoned() || - II->isExtensionToken() || - II->hasMacroDefinition() || - II->getObjCOrBuiltinID() || - II->getFETokenInfo<void>(); - } - -public: - typedef const IdentifierInfo* key_type; - typedef key_type key_type_ref; - - typedef pch::IdentID data_type; - typedef data_type data_type_ref; - - PCHIdentifierTableTrait(PCHWriter &Writer, Preprocessor &PP) - : Writer(Writer), PP(PP) { } - - static unsigned ComputeHash(const IdentifierInfo* II) { - return llvm::HashString(II->getName()); - } - - std::pair<unsigned,unsigned> - EmitKeyDataLength(llvm::raw_ostream& Out, const IdentifierInfo* II, - pch::IdentID ID) { - unsigned KeyLen = II->getLength() + 1; - unsigned DataLen = 4; // 4 bytes for the persistent ID << 1 - if (isInterestingIdentifier(II)) { - DataLen += 2; // 2 bytes for builtin ID, flags - if (II->hasMacroDefinition() && - !PP.getMacroInfo(const_cast<IdentifierInfo *>(II))->isBuiltinMacro()) - DataLen += 4; - for (IdentifierResolver::iterator D = IdentifierResolver::begin(II), - DEnd = IdentifierResolver::end(); - D != DEnd; ++D) - DataLen += sizeof(pch::DeclID); - } - clang::io::Emit16(Out, DataLen); - // We emit the key length after the data length so that every - // string is preceded by a 16-bit length. This matches the PTH - // format for storing identifiers. - clang::io::Emit16(Out, KeyLen); - return std::make_pair(KeyLen, DataLen); - } - - void EmitKey(llvm::raw_ostream& Out, const IdentifierInfo* II, - unsigned KeyLen) { - // Record the location of the key data. This is used when generating - // the mapping from persistent IDs to strings. - Writer.SetIdentifierOffset(II, Out.tell()); - Out.write(II->getNameStart(), KeyLen); - } - - void EmitData(llvm::raw_ostream& Out, const IdentifierInfo* II, - pch::IdentID ID, unsigned) { - if (!isInterestingIdentifier(II)) { - clang::io::Emit32(Out, ID << 1); - return; - } - - clang::io::Emit32(Out, (ID << 1) | 0x01); - uint32_t Bits = 0; - bool hasMacroDefinition = - II->hasMacroDefinition() && - !PP.getMacroInfo(const_cast<IdentifierInfo *>(II))->isBuiltinMacro(); - Bits = (uint32_t)II->getObjCOrBuiltinID(); - Bits = (Bits << 1) | unsigned(hasMacroDefinition); - Bits = (Bits << 1) | unsigned(II->isExtensionToken()); - Bits = (Bits << 1) | unsigned(II->isPoisoned()); - Bits = (Bits << 1) | unsigned(II->isCPlusPlusOperatorKeyword()); - clang::io::Emit16(Out, Bits); - - if (hasMacroDefinition) - clang::io::Emit32(Out, Writer.getMacroOffset(II)); - - // Emit the declaration IDs in reverse order, because the - // IdentifierResolver provides the declarations as they would be - // visible (e.g., the function "stat" would come before the struct - // "stat"), but IdentifierResolver::AddDeclToIdentifierChain() - // adds declarations to the end of the list (so we need to see the - // struct "status" before the function "status"). - llvm::SmallVector<Decl *, 16> Decls(IdentifierResolver::begin(II), - IdentifierResolver::end()); - for (llvm::SmallVector<Decl *, 16>::reverse_iterator D = Decls.rbegin(), - DEnd = Decls.rend(); - D != DEnd; ++D) - clang::io::Emit32(Out, Writer.getDeclID(*D)); - } -}; -} // end anonymous namespace - -/// \brief Write the identifier table into the PCH file. -/// -/// The identifier table consists of a blob containing string data -/// (the actual identifiers themselves) and a separate "offsets" index -/// that maps identifier IDs to locations within the blob. -void PCHWriter::WriteIdentifierTable(Preprocessor &PP) { - using namespace llvm; - - // Create and write out the blob that contains the identifier - // strings. - { - OnDiskChainedHashTableGenerator<PCHIdentifierTableTrait> Generator; - - // Look for any identifiers that were named while processing the - // headers, but are otherwise not needed. We add these to the hash - // table to enable checking of the predefines buffer in the case - // where the user adds new macro definitions when building the PCH - // file. - for (IdentifierTable::iterator ID = PP.getIdentifierTable().begin(), - IDEnd = PP.getIdentifierTable().end(); - ID != IDEnd; ++ID) - getIdentifierRef(ID->second); - - // Create the on-disk hash table representation. - IdentifierOffsets.resize(IdentifierIDs.size()); - for (llvm::DenseMap<const IdentifierInfo *, pch::IdentID>::iterator - ID = IdentifierIDs.begin(), IDEnd = IdentifierIDs.end(); - ID != IDEnd; ++ID) { - assert(ID->first && "NULL identifier in identifier table"); - Generator.insert(ID->first, ID->second); - } - - // Create the on-disk hash table in a buffer. - llvm::SmallString<4096> IdentifierTable; - uint32_t BucketOffset; - { - PCHIdentifierTableTrait Trait(*this, PP); - llvm::raw_svector_ostream Out(IdentifierTable); - // Make sure that no bucket is at offset 0 - clang::io::Emit32(Out, 0); - BucketOffset = Generator.Emit(Out, Trait); - } - - // Create a blob abbreviation - BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); - Abbrev->Add(BitCodeAbbrevOp(pch::IDENTIFIER_TABLE)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); - unsigned IDTableAbbrev = Stream.EmitAbbrev(Abbrev); - - // Write the identifier table - RecordData Record; - Record.push_back(pch::IDENTIFIER_TABLE); - Record.push_back(BucketOffset); - Stream.EmitRecordWithBlob(IDTableAbbrev, Record, IdentifierTable.str()); - } - - // Write the offsets table for identifier IDs. - BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); - Abbrev->Add(BitCodeAbbrevOp(pch::IDENTIFIER_OFFSET)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of identifiers - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); - unsigned IdentifierOffsetAbbrev = Stream.EmitAbbrev(Abbrev); - - RecordData Record; - Record.push_back(pch::IDENTIFIER_OFFSET); - Record.push_back(IdentifierOffsets.size()); - Stream.EmitRecordWithBlob(IdentifierOffsetAbbrev, Record, - (const char *)&IdentifierOffsets.front(), - IdentifierOffsets.size() * sizeof(uint32_t)); -} - -//===----------------------------------------------------------------------===// -// General Serialization Routines -//===----------------------------------------------------------------------===// - -/// \brief Write a record containing the given attributes. -void PCHWriter::WriteAttributeRecord(const Attr *Attr) { - RecordData Record; - for (; Attr; Attr = Attr->getNext()) { - Record.push_back(Attr->getKind()); // FIXME: stable encoding, target attrs - Record.push_back(Attr->isInherited()); - switch (Attr->getKind()) { - default: - assert(0 && "Does not support PCH writing for this attribute yet!"); - break; - case attr::Alias: - AddString(cast<AliasAttr>(Attr)->getAliasee(), Record); - break; - - case attr::AlignMac68k: - break; - - case attr::Aligned: - Record.push_back(cast<AlignedAttr>(Attr)->getAlignment()); - break; - - case attr::AlwaysInline: - break; - - case attr::AnalyzerNoReturn: - break; - - case attr::Annotate: - AddString(cast<AnnotateAttr>(Attr)->getAnnotation(), Record); - break; - - case attr::AsmLabel: - AddString(cast<AsmLabelAttr>(Attr)->getLabel(), Record); - break; - - case attr::BaseCheck: - break; - - case attr::Blocks: - Record.push_back(cast<BlocksAttr>(Attr)->getType()); // FIXME: stable - break; - - case attr::CDecl: - break; - - case attr::Cleanup: - AddDeclRef(cast<CleanupAttr>(Attr)->getFunctionDecl(), Record); - break; - - case attr::Const: - break; - - case attr::Constructor: - Record.push_back(cast<ConstructorAttr>(Attr)->getPriority()); - break; - - case attr::DLLExport: - case attr::DLLImport: - case attr::Deprecated: - break; - - case attr::Destructor: - Record.push_back(cast<DestructorAttr>(Attr)->getPriority()); - break; - - case attr::FastCall: - case attr::Final: - break; - - case attr::Format: { - const FormatAttr *Format = cast<FormatAttr>(Attr); - AddString(Format->getType(), Record); - Record.push_back(Format->getFormatIdx()); - Record.push_back(Format->getFirstArg()); - break; - } - - case attr::FormatArg: { - const FormatArgAttr *Format = cast<FormatArgAttr>(Attr); - Record.push_back(Format->getFormatIdx()); - break; - } - - case attr::Sentinel : { - const SentinelAttr *Sentinel = cast<SentinelAttr>(Attr); - Record.push_back(Sentinel->getSentinel()); - Record.push_back(Sentinel->getNullPos()); - break; - } - - case attr::GNUInline: - case attr::Hiding: - case attr::IBAction: - case attr::IBOutlet: - case attr::Malloc: - case attr::NoDebug: - case attr::NoInline: - case attr::NoReturn: - case attr::NoThrow: - break; - - case attr::IBOutletCollection: { - const IBOutletCollectionAttr *ICA = cast<IBOutletCollectionAttr>(Attr); - AddDeclRef(ICA->getClass(), Record); - break; - } - - case attr::NonNull: { - const NonNullAttr *NonNull = cast<NonNullAttr>(Attr); - Record.push_back(NonNull->size()); - Record.insert(Record.end(), NonNull->begin(), NonNull->end()); - break; - } - - case attr::CFReturnsNotRetained: - case attr::CFReturnsRetained: - case attr::NSReturnsNotRetained: - case attr::NSReturnsRetained: - case attr::ObjCException: - case attr::ObjCNSObject: - case attr::Overloadable: - case attr::Override: - break; - - case attr::MaxFieldAlignment: - Record.push_back(cast<MaxFieldAlignmentAttr>(Attr)->getAlignment()); - break; - - case attr::Packed: - break; - - case attr::Pure: - break; - - case attr::Regparm: - Record.push_back(cast<RegparmAttr>(Attr)->getNumParams()); - break; - - case attr::ReqdWorkGroupSize: - Record.push_back(cast<ReqdWorkGroupSizeAttr>(Attr)->getXDim()); - Record.push_back(cast<ReqdWorkGroupSizeAttr>(Attr)->getYDim()); - Record.push_back(cast<ReqdWorkGroupSizeAttr>(Attr)->getZDim()); - break; - - case attr::Section: - AddString(cast<SectionAttr>(Attr)->getName(), Record); - break; - - case attr::StdCall: - case attr::TransparentUnion: - case attr::Unavailable: - case attr::Unused: - case attr::Used: - break; - - case attr::Visibility: - // FIXME: stable encoding - Record.push_back(cast<VisibilityAttr>(Attr)->getVisibility()); - break; - - case attr::WarnUnusedResult: - case attr::Weak: - case attr::WeakRef: - case attr::WeakImport: - break; - } - } - - Stream.EmitRecord(pch::DECL_ATTR, Record); -} - -void PCHWriter::AddString(const std::string &Str, RecordData &Record) { - Record.push_back(Str.size()); - Record.insert(Record.end(), Str.begin(), Str.end()); -} - -/// \brief Note that the identifier II occurs at the given offset -/// within the identifier table. -void PCHWriter::SetIdentifierOffset(const IdentifierInfo *II, uint32_t Offset) { - IdentifierOffsets[IdentifierIDs[II] - 1] = Offset; -} - -/// \brief Note that the selector Sel occurs at the given offset -/// within the method pool/selector table. -void PCHWriter::SetSelectorOffset(Selector Sel, uint32_t Offset) { - unsigned ID = SelectorIDs[Sel]; - assert(ID && "Unknown selector"); - SelectorOffsets[ID - 1] = Offset; -} - -PCHWriter::PCHWriter(llvm::BitstreamWriter &Stream, PCHReader *Chain) - : Stream(Stream), Chain(Chain), NextTypeID(pch::NUM_PREDEF_TYPE_IDS), - CollectedStmts(&StmtsToEmit), NumStatements(0), NumMacros(0), - NumLexicalDeclContexts(0), NumVisibleDeclContexts(0) { - if (Chain) - Chain->setDeserializationListener(this); -} - -void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls, - const char *isysroot) { - // Emit the file header. - Stream.Emit((unsigned)'C', 8); - Stream.Emit((unsigned)'P', 8); - Stream.Emit((unsigned)'C', 8); - Stream.Emit((unsigned)'H', 8); - - WriteBlockInfoBlock(); - - if (Chain) - WritePCHChain(SemaRef, StatCalls, isysroot); - else - WritePCHCore(SemaRef, StatCalls, isysroot); -} - -void PCHWriter::WritePCHCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, - const char *isysroot) { - using namespace llvm; - - ASTContext &Context = SemaRef.Context; - Preprocessor &PP = SemaRef.PP; - - // The translation unit is the first declaration we'll emit. - DeclIDs[Context.getTranslationUnitDecl()] = 1; - DeclTypesToEmit.push(Context.getTranslationUnitDecl()); - - // Make sure that we emit IdentifierInfos (and any attached - // declarations) for builtins. - { - IdentifierTable &Table = PP.getIdentifierTable(); - llvm::SmallVector<const char *, 32> BuiltinNames; - Context.BuiltinInfo.GetBuiltinNames(BuiltinNames, - Context.getLangOptions().NoBuiltin); - for (unsigned I = 0, N = BuiltinNames.size(); I != N; ++I) - getIdentifierRef(&Table.get(BuiltinNames[I])); - } - - // Build a record containing all of the tentative definitions in this file, in - // TentativeDefinitions order. Generally, this record will be empty for - // headers. - RecordData TentativeDefinitions; - for (unsigned i = 0, e = SemaRef.TentativeDefinitions.size(); i != e; ++i) { - AddDeclRef(SemaRef.TentativeDefinitions[i], TentativeDefinitions); - } - - // Build a record containing all of the static unused functions in this file. - RecordData UnusedStaticFuncs; - for (unsigned i=0, e = SemaRef.UnusedStaticFuncs.size(); i !=e; ++i) - AddDeclRef(SemaRef.UnusedStaticFuncs[i], UnusedStaticFuncs); - - // Build a record containing all of the locally-scoped external - // declarations in this header file. Generally, this record will be - // empty. - RecordData LocallyScopedExternalDecls; - // FIXME: This is filling in the PCH file in densemap order which is - // nondeterminstic! - for (llvm::DenseMap<DeclarationName, NamedDecl *>::iterator - TD = SemaRef.LocallyScopedExternalDecls.begin(), - TDEnd = SemaRef.LocallyScopedExternalDecls.end(); - TD != TDEnd; ++TD) - AddDeclRef(TD->second, LocallyScopedExternalDecls); - - // Build a record containing all of the ext_vector declarations. - RecordData ExtVectorDecls; - for (unsigned I = 0, N = SemaRef.ExtVectorDecls.size(); I != N; ++I) - AddDeclRef(SemaRef.ExtVectorDecls[I], ExtVectorDecls); - - // Build a record containing all of the VTable uses information. - RecordData VTableUses; - VTableUses.push_back(SemaRef.VTableUses.size()); - for (unsigned I = 0, N = SemaRef.VTableUses.size(); I != N; ++I) { - AddDeclRef(SemaRef.VTableUses[I].first, VTableUses); - AddSourceLocation(SemaRef.VTableUses[I].second, VTableUses); - VTableUses.push_back(SemaRef.VTablesUsed[SemaRef.VTableUses[I].first]); - } - - // Build a record containing all of dynamic classes declarations. - RecordData DynamicClasses; - for (unsigned I = 0, N = SemaRef.DynamicClasses.size(); I != N; ++I) - AddDeclRef(SemaRef.DynamicClasses[I], DynamicClasses); - - // Write the remaining PCH contents. - RecordData Record; - Stream.EnterSubblock(pch::PCH_BLOCK_ID, 5); - WriteMetadata(Context, isysroot); - WriteLanguageOptions(Context.getLangOptions()); - if (StatCalls && !isysroot) - WriteStatCache(*StatCalls); - WriteSourceManagerBlock(Context.getSourceManager(), PP, isysroot); - // Write the record of special types. - Record.clear(); - - AddTypeRef(Context.getBuiltinVaListType(), Record); - AddTypeRef(Context.getObjCIdType(), Record); - AddTypeRef(Context.getObjCSelType(), Record); - AddTypeRef(Context.getObjCProtoType(), Record); - AddTypeRef(Context.getObjCClassType(), Record); - AddTypeRef(Context.getRawCFConstantStringType(), Record); - AddTypeRef(Context.getRawObjCFastEnumerationStateType(), Record); - AddTypeRef(Context.getFILEType(), Record); - AddTypeRef(Context.getjmp_bufType(), Record); - AddTypeRef(Context.getsigjmp_bufType(), Record); - AddTypeRef(Context.ObjCIdRedefinitionType, Record); - AddTypeRef(Context.ObjCClassRedefinitionType, Record); - AddTypeRef(Context.getRawBlockdescriptorType(), Record); - AddTypeRef(Context.getRawBlockdescriptorExtendedType(), Record); - AddTypeRef(Context.ObjCSelRedefinitionType, Record); - AddTypeRef(Context.getRawNSConstantStringType(), Record); - Record.push_back(Context.isInt128Installed()); - Stream.EmitRecord(pch::SPECIAL_TYPES, Record); - - // Keep writing types and declarations until all types and - // declarations have been written. - Stream.EnterSubblock(pch::DECLTYPES_BLOCK_ID, 3); - WriteDeclsBlockAbbrevs(); - while (!DeclTypesToEmit.empty()) { - DeclOrType DOT = DeclTypesToEmit.front(); - DeclTypesToEmit.pop(); - if (DOT.isType()) - WriteType(DOT.getType()); - else - WriteDecl(Context, DOT.getDecl()); - } - Stream.ExitBlock(); - - WritePreprocessor(PP); - WriteMethodPool(SemaRef); - WriteIdentifierTable(PP); - - // Write the type offsets array - BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); - Abbrev->Add(BitCodeAbbrevOp(pch::TYPE_OFFSET)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of types - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // types block - unsigned TypeOffsetAbbrev = Stream.EmitAbbrev(Abbrev); - Record.clear(); - Record.push_back(pch::TYPE_OFFSET); - Record.push_back(TypeOffsets.size()); - Stream.EmitRecordWithBlob(TypeOffsetAbbrev, Record, - (const char *)&TypeOffsets.front(), - TypeOffsets.size() * sizeof(TypeOffsets[0])); - - // Write the declaration offsets array - Abbrev = new BitCodeAbbrev(); - Abbrev->Add(BitCodeAbbrevOp(pch::DECL_OFFSET)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of declarations - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // declarations block - unsigned DeclOffsetAbbrev = Stream.EmitAbbrev(Abbrev); - Record.clear(); - Record.push_back(pch::DECL_OFFSET); - Record.push_back(DeclOffsets.size()); - Stream.EmitRecordWithBlob(DeclOffsetAbbrev, Record, - (const char *)&DeclOffsets.front(), - DeclOffsets.size() * sizeof(DeclOffsets[0])); - - // Write the record containing external, unnamed definitions. - if (!ExternalDefinitions.empty()) - Stream.EmitRecord(pch::EXTERNAL_DEFINITIONS, ExternalDefinitions); - - // Write the record containing tentative definitions. - if (!TentativeDefinitions.empty()) - Stream.EmitRecord(pch::TENTATIVE_DEFINITIONS, TentativeDefinitions); - - // Write the record containing unused static functions. - if (!UnusedStaticFuncs.empty()) - Stream.EmitRecord(pch::UNUSED_STATIC_FUNCS, UnusedStaticFuncs); - - // Write the record containing locally-scoped external definitions. - if (!LocallyScopedExternalDecls.empty()) - Stream.EmitRecord(pch::LOCALLY_SCOPED_EXTERNAL_DECLS, - LocallyScopedExternalDecls); - - // Write the record containing ext_vector type names. - if (!ExtVectorDecls.empty()) - Stream.EmitRecord(pch::EXT_VECTOR_DECLS, ExtVectorDecls); - - // Write the record containing VTable uses information. - if (!VTableUses.empty()) - Stream.EmitRecord(pch::VTABLE_USES, VTableUses); - - // Write the record containing dynamic classes declarations. - if (!DynamicClasses.empty()) - Stream.EmitRecord(pch::DYNAMIC_CLASSES, DynamicClasses); - - // Some simple statistics - Record.clear(); - Record.push_back(NumStatements); - Record.push_back(NumMacros); - Record.push_back(NumLexicalDeclContexts); - Record.push_back(NumVisibleDeclContexts); - Stream.EmitRecord(pch::STATISTICS, Record); - Stream.ExitBlock(); -} - -void PCHWriter::WritePCHChain(Sema &SemaRef, MemorizeStatCalls *StatCalls, - const char *isysroot) { - using namespace llvm; - - ASTContext &Context = SemaRef.Context; - Preprocessor &PP = SemaRef.PP; - (void)PP; - - RecordData Record; - Stream.EnterSubblock(pch::PCH_BLOCK_ID, 5); - WriteMetadata(Context, isysroot); - // FIXME: StatCache - // FIXME: Source manager block - - // The special types are in the chained PCH. - - // We don't start with the translation unit, but with its decls that - // don't come from the other PCH. - const TranslationUnitDecl *TU = Context.getTranslationUnitDecl(); - // FIXME: We don't want to iterate over everything here, because it needlessly - // deserializes the entire original PCH. Instead we only want to iterate over - // the stuff that's already there. - // All in good time, though. - for (DeclContext::decl_iterator I = TU->decls_begin(), E = TU->decls_end(); - I != E; ++I) { - if ((*I)->getPCHLevel() == 0) { - (*I)->dump(); - DeclTypesToEmit.push(*I); - } - } - - Stream.EnterSubblock(pch::DECLTYPES_BLOCK_ID, 3); - WriteDeclsBlockAbbrevs(); - while (!DeclTypesToEmit.empty()) { - DeclOrType DOT = DeclTypesToEmit.front(); - DeclTypesToEmit.pop(); - if (DOT.isType()) - WriteType(DOT.getType()); - else - WriteDecl(Context, DOT.getDecl()); - } - Stream.ExitBlock(); - - // FIXME: Preprocessor - // FIXME: Method pool - // FIXME: Identifier table - // FIXME: Type offsets - // FIXME: Declaration offsets - // FIXME: External unnamed definitions - // FIXME: Tentative definitions - // FIXME: Unused static functions - // FIXME: Locally-scoped external definitions - // FIXME: ext_vector type names - // FIXME: Dynamic classes declarations - // FIXME: Statistics - Stream.ExitBlock(); -} - -void PCHWriter::AddSourceLocation(SourceLocation Loc, RecordData &Record) { - Record.push_back(Loc.getRawEncoding()); -} - -void PCHWriter::AddSourceRange(SourceRange Range, RecordData &Record) { - AddSourceLocation(Range.getBegin(), Record); - AddSourceLocation(Range.getEnd(), Record); -} - -void PCHWriter::AddAPInt(const llvm::APInt &Value, RecordData &Record) { - Record.push_back(Value.getBitWidth()); - unsigned N = Value.getNumWords(); - const uint64_t* Words = Value.getRawData(); - for (unsigned I = 0; I != N; ++I) - Record.push_back(Words[I]); -} - -void PCHWriter::AddAPSInt(const llvm::APSInt &Value, RecordData &Record) { - Record.push_back(Value.isUnsigned()); - AddAPInt(Value, Record); -} - -void PCHWriter::AddAPFloat(const llvm::APFloat &Value, RecordData &Record) { - AddAPInt(Value.bitcastToAPInt(), Record); -} - -void PCHWriter::AddIdentifierRef(const IdentifierInfo *II, RecordData &Record) { - Record.push_back(getIdentifierRef(II)); -} - -pch::IdentID PCHWriter::getIdentifierRef(const IdentifierInfo *II) { - if (II == 0) - return 0; - - pch::IdentID &ID = IdentifierIDs[II]; - if (ID == 0) - ID = IdentifierIDs.size(); - return ID; -} - -pch::IdentID PCHWriter::getMacroDefinitionID(MacroDefinition *MD) { - if (MD == 0) - return 0; - - pch::IdentID &ID = MacroDefinitions[MD]; - if (ID == 0) - ID = MacroDefinitions.size(); - return ID; -} - -void PCHWriter::AddSelectorRef(const Selector SelRef, RecordData &Record) { - if (SelRef.getAsOpaquePtr() == 0) { - Record.push_back(0); - return; - } - - pch::SelectorID &SID = SelectorIDs[SelRef]; - if (SID == 0) { - SID = SelectorIDs.size(); - SelVector.push_back(SelRef); - } - Record.push_back(SID); -} - -void PCHWriter::AddCXXTemporary(const CXXTemporary *Temp, RecordData &Record) { - AddDeclRef(Temp->getDestructor(), Record); -} - -void PCHWriter::AddTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind, - const TemplateArgumentLocInfo &Arg, - RecordData &Record) { - switch (Kind) { - case TemplateArgument::Expression: - AddStmt(Arg.getAsExpr()); - break; - case TemplateArgument::Type: - AddTypeSourceInfo(Arg.getAsTypeSourceInfo(), Record); - break; - case TemplateArgument::Template: - AddSourceRange(Arg.getTemplateQualifierRange(), Record); - AddSourceLocation(Arg.getTemplateNameLoc(), Record); - break; - case TemplateArgument::Null: - case TemplateArgument::Integral: - case TemplateArgument::Declaration: - case TemplateArgument::Pack: - break; - } -} - -void PCHWriter::AddTemplateArgumentLoc(const TemplateArgumentLoc &Arg, - RecordData &Record) { - AddTemplateArgument(Arg.getArgument(), Record); - - if (Arg.getArgument().getKind() == TemplateArgument::Expression) { - bool InfoHasSameExpr - = Arg.getArgument().getAsExpr() == Arg.getLocInfo().getAsExpr(); - Record.push_back(InfoHasSameExpr); - if (InfoHasSameExpr) - return; // Avoid storing the same expr twice. - } - AddTemplateArgumentLocInfo(Arg.getArgument().getKind(), Arg.getLocInfo(), - Record); -} - -void PCHWriter::AddTypeSourceInfo(TypeSourceInfo *TInfo, RecordData &Record) { - if (TInfo == 0) { - AddTypeRef(QualType(), Record); - return; - } - - AddTypeRef(TInfo->getType(), Record); - TypeLocWriter TLW(*this, Record); - for (TypeLoc TL = TInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc()) - TLW.Visit(TL); -} - -void PCHWriter::AddTypeRef(QualType T, RecordData &Record) { - if (T.isNull()) { - Record.push_back(pch::PREDEF_TYPE_NULL_ID); - return; - } - - unsigned FastQuals = T.getLocalFastQualifiers(); - T.removeFastQualifiers(); - - if (T.hasLocalNonFastQualifiers()) { - pch::TypeID &ID = TypeIDs[T]; - if (ID == 0) { - // We haven't seen these qualifiers applied to this type before. - // Assign it a new ID. This is the only time we enqueue a - // qualified type, and it has no CV qualifiers. - ID = NextTypeID++; - DeclTypesToEmit.push(T); - } - - // Encode the type qualifiers in the type reference. - Record.push_back((ID << Qualifiers::FastWidth) | FastQuals); - return; - } - - assert(!T.hasLocalQualifiers()); - - if (const BuiltinType *BT = dyn_cast<BuiltinType>(T.getTypePtr())) { - pch::TypeID ID = 0; - switch (BT->getKind()) { - case BuiltinType::Void: ID = pch::PREDEF_TYPE_VOID_ID; break; - case BuiltinType::Bool: ID = pch::PREDEF_TYPE_BOOL_ID; break; - case BuiltinType::Char_U: ID = pch::PREDEF_TYPE_CHAR_U_ID; break; - case BuiltinType::UChar: ID = pch::PREDEF_TYPE_UCHAR_ID; break; - case BuiltinType::UShort: ID = pch::PREDEF_TYPE_USHORT_ID; break; - case BuiltinType::UInt: ID = pch::PREDEF_TYPE_UINT_ID; break; - case BuiltinType::ULong: ID = pch::PREDEF_TYPE_ULONG_ID; break; - case BuiltinType::ULongLong: ID = pch::PREDEF_TYPE_ULONGLONG_ID; break; - case BuiltinType::UInt128: ID = pch::PREDEF_TYPE_UINT128_ID; break; - case BuiltinType::Char_S: ID = pch::PREDEF_TYPE_CHAR_S_ID; break; - case BuiltinType::SChar: ID = pch::PREDEF_TYPE_SCHAR_ID; break; - case BuiltinType::WChar: ID = pch::PREDEF_TYPE_WCHAR_ID; break; - case BuiltinType::Short: ID = pch::PREDEF_TYPE_SHORT_ID; break; - case BuiltinType::Int: ID = pch::PREDEF_TYPE_INT_ID; break; - case BuiltinType::Long: ID = pch::PREDEF_TYPE_LONG_ID; break; - case BuiltinType::LongLong: ID = pch::PREDEF_TYPE_LONGLONG_ID; break; - case BuiltinType::Int128: ID = pch::PREDEF_TYPE_INT128_ID; break; - case BuiltinType::Float: ID = pch::PREDEF_TYPE_FLOAT_ID; break; - case BuiltinType::Double: ID = pch::PREDEF_TYPE_DOUBLE_ID; break; - case BuiltinType::LongDouble: ID = pch::PREDEF_TYPE_LONGDOUBLE_ID; break; - case BuiltinType::NullPtr: ID = pch::PREDEF_TYPE_NULLPTR_ID; break; - case BuiltinType::Char16: ID = pch::PREDEF_TYPE_CHAR16_ID; break; - case BuiltinType::Char32: ID = pch::PREDEF_TYPE_CHAR32_ID; break; - case BuiltinType::Overload: ID = pch::PREDEF_TYPE_OVERLOAD_ID; break; - case BuiltinType::Dependent: ID = pch::PREDEF_TYPE_DEPENDENT_ID; break; - case BuiltinType::ObjCId: ID = pch::PREDEF_TYPE_OBJC_ID; break; - case BuiltinType::ObjCClass: ID = pch::PREDEF_TYPE_OBJC_CLASS; break; - case BuiltinType::ObjCSel: ID = pch::PREDEF_TYPE_OBJC_SEL; break; - case BuiltinType::UndeducedAuto: - assert(0 && "Should not see undeduced auto here"); - break; - } - - Record.push_back((ID << Qualifiers::FastWidth) | FastQuals); - return; - } - - pch::TypeID &ID = TypeIDs[T]; - if (ID == 0) { - // We haven't seen this type before. Assign it a new ID and put it - // into the queue of types to emit. - ID = NextTypeID++; - DeclTypesToEmit.push(T); - } - - // Encode the type qualifiers in the type reference. - Record.push_back((ID << Qualifiers::FastWidth) | FastQuals); -} - -void PCHWriter::AddDeclRef(const Decl *D, RecordData &Record) { - if (D == 0) { - Record.push_back(0); - return; - } - - pch::DeclID &ID = DeclIDs[D]; - if (ID == 0) { - // We haven't seen this declaration before. Give it a new ID and - // enqueue it in the list of declarations to emit. - ID = DeclIDs.size(); - DeclTypesToEmit.push(const_cast<Decl *>(D)); - } - - Record.push_back(ID); -} - -pch::DeclID PCHWriter::getDeclID(const Decl *D) { - if (D == 0) - return 0; - - assert(DeclIDs.find(D) != DeclIDs.end() && "Declaration not emitted!"); - return DeclIDs[D]; -} - -void PCHWriter::AddDeclarationName(DeclarationName Name, RecordData &Record) { - // FIXME: Emit a stable enum for NameKind. 0 = Identifier etc. - Record.push_back(Name.getNameKind()); - switch (Name.getNameKind()) { - case DeclarationName::Identifier: - AddIdentifierRef(Name.getAsIdentifierInfo(), Record); - break; - - case DeclarationName::ObjCZeroArgSelector: - case DeclarationName::ObjCOneArgSelector: - case DeclarationName::ObjCMultiArgSelector: - AddSelectorRef(Name.getObjCSelector(), Record); - break; - - case DeclarationName::CXXConstructorName: - case DeclarationName::CXXDestructorName: - case DeclarationName::CXXConversionFunctionName: - AddTypeRef(Name.getCXXNameType(), Record); - break; - - case DeclarationName::CXXOperatorName: - Record.push_back(Name.getCXXOverloadedOperator()); - break; - - case DeclarationName::CXXLiteralOperatorName: - AddIdentifierRef(Name.getCXXLiteralIdentifier(), Record); - break; - - case DeclarationName::CXXUsingDirective: - // No extra data to emit - break; - } -} - -void PCHWriter::AddNestedNameSpecifier(NestedNameSpecifier *NNS, - RecordData &Record) { - // Nested name specifiers usually aren't too long. I think that 8 would - // typically accomodate the vast majority. - llvm::SmallVector<NestedNameSpecifier *, 8> NestedNames; - - // Push each of the NNS's onto a stack for serialization in reverse order. - while (NNS) { - NestedNames.push_back(NNS); - NNS = NNS->getPrefix(); - } - - Record.push_back(NestedNames.size()); - while(!NestedNames.empty()) { - NNS = NestedNames.pop_back_val(); - NestedNameSpecifier::SpecifierKind Kind = NNS->getKind(); - Record.push_back(Kind); - switch (Kind) { - case NestedNameSpecifier::Identifier: - AddIdentifierRef(NNS->getAsIdentifier(), Record); - break; - - case NestedNameSpecifier::Namespace: - AddDeclRef(NNS->getAsNamespace(), Record); - break; - - case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::TypeSpecWithTemplate: - AddTypeRef(QualType(NNS->getAsType(), 0), Record); - Record.push_back(Kind == NestedNameSpecifier::TypeSpecWithTemplate); - break; - - case NestedNameSpecifier::Global: - // Don't need to write an associated value. - break; - } - } -} - -void PCHWriter::AddTemplateName(TemplateName Name, RecordData &Record) { - TemplateName::NameKind Kind = Name.getKind(); - Record.push_back(Kind); - switch (Kind) { - case TemplateName::Template: - AddDeclRef(Name.getAsTemplateDecl(), Record); - break; - - case TemplateName::OverloadedTemplate: { - OverloadedTemplateStorage *OvT = Name.getAsOverloadedTemplate(); - Record.push_back(OvT->size()); - for (OverloadedTemplateStorage::iterator I = OvT->begin(), E = OvT->end(); - I != E; ++I) - AddDeclRef(*I, Record); - break; - } - - case TemplateName::QualifiedTemplate: { - QualifiedTemplateName *QualT = Name.getAsQualifiedTemplateName(); - AddNestedNameSpecifier(QualT->getQualifier(), Record); - Record.push_back(QualT->hasTemplateKeyword()); - AddDeclRef(QualT->getTemplateDecl(), Record); - break; - } - - case TemplateName::DependentTemplate: { - DependentTemplateName *DepT = Name.getAsDependentTemplateName(); - AddNestedNameSpecifier(DepT->getQualifier(), Record); - Record.push_back(DepT->isIdentifier()); - if (DepT->isIdentifier()) - AddIdentifierRef(DepT->getIdentifier(), Record); - else - Record.push_back(DepT->getOperator()); - break; - } - } -} - -void PCHWriter::AddTemplateArgument(const TemplateArgument &Arg, - RecordData &Record) { - Record.push_back(Arg.getKind()); - switch (Arg.getKind()) { - case TemplateArgument::Null: - break; - case TemplateArgument::Type: - AddTypeRef(Arg.getAsType(), Record); - break; - case TemplateArgument::Declaration: - AddDeclRef(Arg.getAsDecl(), Record); - break; - case TemplateArgument::Integral: - AddAPSInt(*Arg.getAsIntegral(), Record); - AddTypeRef(Arg.getIntegralType(), Record); - break; - case TemplateArgument::Template: - AddTemplateName(Arg.getAsTemplate(), Record); - break; - case TemplateArgument::Expression: - AddStmt(Arg.getAsExpr()); - break; - case TemplateArgument::Pack: - Record.push_back(Arg.pack_size()); - for (TemplateArgument::pack_iterator I=Arg.pack_begin(), E=Arg.pack_end(); - I != E; ++I) - AddTemplateArgument(*I, Record); - break; - } -} - -void -PCHWriter::AddTemplateParameterList(const TemplateParameterList *TemplateParams, - RecordData &Record) { - assert(TemplateParams && "No TemplateParams!"); - AddSourceLocation(TemplateParams->getTemplateLoc(), Record); - AddSourceLocation(TemplateParams->getLAngleLoc(), Record); - AddSourceLocation(TemplateParams->getRAngleLoc(), Record); - Record.push_back(TemplateParams->size()); - for (TemplateParameterList::const_iterator - P = TemplateParams->begin(), PEnd = TemplateParams->end(); - P != PEnd; ++P) - AddDeclRef(*P, Record); -} - -/// \brief Emit a template argument list. -void -PCHWriter::AddTemplateArgumentList(const TemplateArgumentList *TemplateArgs, - RecordData &Record) { - assert(TemplateArgs && "No TemplateArgs!"); - Record.push_back(TemplateArgs->flat_size()); - for (int i=0, e = TemplateArgs->flat_size(); i != e; ++i) - AddTemplateArgument(TemplateArgs->get(i), Record); -} - - -void -PCHWriter::AddUnresolvedSet(const UnresolvedSetImpl &Set, RecordData &Record) { - Record.push_back(Set.size()); - for (UnresolvedSetImpl::const_iterator - I = Set.begin(), E = Set.end(); I != E; ++I) { - AddDeclRef(I.getDecl(), Record); - Record.push_back(I.getAccess()); - } -} - -void PCHWriter::AddCXXBaseSpecifier(const CXXBaseSpecifier &Base, - RecordData &Record) { - Record.push_back(Base.isVirtual()); - Record.push_back(Base.isBaseOfClass()); - Record.push_back(Base.getAccessSpecifierAsWritten()); - AddTypeRef(Base.getType(), Record); - AddSourceRange(Base.getSourceRange(), Record); -} - -void PCHWriter::TypeRead(pch::TypeID ID, QualType T) { -} - -void PCHWriter::DeclRead(pch::DeclID ID, const Decl *D) { -} - diff --git a/lib/Frontend/PCHWriterDecl.cpp b/lib/Frontend/PCHWriterDecl.cpp deleted file mode 100644 index bc4452e..0000000 --- a/lib/Frontend/PCHWriterDecl.cpp +++ /dev/null @@ -1,1172 +0,0 @@ -//===--- PCHWriterDecl.cpp - Declaration Serialization --------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements serialization for Declarations. -// -//===----------------------------------------------------------------------===// - -#include "clang/Frontend/PCHWriter.h" -#include "clang/AST/DeclVisitor.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclTemplate.h" -#include "clang/AST/Expr.h" -#include "llvm/ADT/Twine.h" -#include "llvm/Bitcode/BitstreamWriter.h" -#include "llvm/Support/ErrorHandling.h" -using namespace clang; - -//===----------------------------------------------------------------------===// -// Declaration serialization -//===----------------------------------------------------------------------===// - -namespace clang { - class PCHDeclWriter : public DeclVisitor<PCHDeclWriter, void> { - - PCHWriter &Writer; - ASTContext &Context; - PCHWriter::RecordData &Record; - - public: - pch::DeclCode Code; - unsigned AbbrevToUse; - - PCHDeclWriter(PCHWriter &Writer, ASTContext &Context, - PCHWriter::RecordData &Record) - : Writer(Writer), Context(Context), Record(Record) { - } - - void Visit(Decl *D); - - void VisitDecl(Decl *D); - void VisitTranslationUnitDecl(TranslationUnitDecl *D); - void VisitNamedDecl(NamedDecl *D); - void VisitNamespaceDecl(NamespaceDecl *D); - void VisitUsingDirectiveDecl(UsingDirectiveDecl *D); - void VisitNamespaceAliasDecl(NamespaceAliasDecl *D); - void VisitTypeDecl(TypeDecl *D); - void VisitTypedefDecl(TypedefDecl *D); - void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D); - void VisitTagDecl(TagDecl *D); - void VisitEnumDecl(EnumDecl *D); - void VisitRecordDecl(RecordDecl *D); - void VisitCXXRecordDecl(CXXRecordDecl *D); - void VisitClassTemplateSpecializationDecl( - ClassTemplateSpecializationDecl *D); - void VisitClassTemplatePartialSpecializationDecl( - ClassTemplatePartialSpecializationDecl *D); - void VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D); - void VisitValueDecl(ValueDecl *D); - void VisitEnumConstantDecl(EnumConstantDecl *D); - void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D); - void VisitDeclaratorDecl(DeclaratorDecl *D); - void VisitFunctionDecl(FunctionDecl *D); - void VisitCXXMethodDecl(CXXMethodDecl *D); - void VisitCXXConstructorDecl(CXXConstructorDecl *D); - void VisitCXXDestructorDecl(CXXDestructorDecl *D); - void VisitCXXConversionDecl(CXXConversionDecl *D); - void VisitFieldDecl(FieldDecl *D); - void VisitVarDecl(VarDecl *D); - void VisitImplicitParamDecl(ImplicitParamDecl *D); - void VisitParmVarDecl(ParmVarDecl *D); - void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D); - void VisitTemplateDecl(TemplateDecl *D); - void VisitClassTemplateDecl(ClassTemplateDecl *D); - void VisitFunctionTemplateDecl(FunctionTemplateDecl *D); - void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D); - void VisitUsingDecl(UsingDecl *D); - void VisitUsingShadowDecl(UsingShadowDecl *D); - void VisitLinkageSpecDecl(LinkageSpecDecl *D); - void VisitFileScopeAsmDecl(FileScopeAsmDecl *D); - void VisitAccessSpecDecl(AccessSpecDecl *D); - void VisitFriendDecl(FriendDecl *D); - void VisitFriendTemplateDecl(FriendTemplateDecl *D); - void VisitStaticAssertDecl(StaticAssertDecl *D); - void VisitBlockDecl(BlockDecl *D); - - void VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset, - uint64_t VisibleOffset); - - - // FIXME: Put in the same order is DeclNodes.td? - void VisitObjCMethodDecl(ObjCMethodDecl *D); - void VisitObjCContainerDecl(ObjCContainerDecl *D); - void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D); - void VisitObjCIvarDecl(ObjCIvarDecl *D); - void VisitObjCProtocolDecl(ObjCProtocolDecl *D); - void VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *D); - void VisitObjCClassDecl(ObjCClassDecl *D); - void VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D); - void VisitObjCCategoryDecl(ObjCCategoryDecl *D); - void VisitObjCImplDecl(ObjCImplDecl *D); - void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D); - void VisitObjCImplementationDecl(ObjCImplementationDecl *D); - void VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D); - void VisitObjCPropertyDecl(ObjCPropertyDecl *D); - void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D); - }; -} - -void PCHDeclWriter::Visit(Decl *D) { - DeclVisitor<PCHDeclWriter>::Visit(D); - - // Handle FunctionDecl's body here and write it after all other Stmts/Exprs - // have been written. We want it last because we will not read it back when - // retrieving it from the PCH, we'll just lazily set the offset. - if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { - Record.push_back(FD->isThisDeclarationADefinition()); - if (FD->isThisDeclarationADefinition()) - Writer.AddStmt(FD->getBody()); - } -} - -void PCHDeclWriter::VisitDecl(Decl *D) { - Writer.AddDeclRef(cast_or_null<Decl>(D->getDeclContext()), Record); - Writer.AddDeclRef(cast_or_null<Decl>(D->getLexicalDeclContext()), Record); - Writer.AddSourceLocation(D->getLocation(), Record); - Record.push_back(D->isInvalidDecl()); - Record.push_back(D->hasAttrs()); - Record.push_back(D->isImplicit()); - Record.push_back(D->isUsed(false)); - Record.push_back(D->getAccess()); - Record.push_back(D->getPCHLevel()); -} - -void PCHDeclWriter::VisitTranslationUnitDecl(TranslationUnitDecl *D) { - VisitDecl(D); - Writer.AddDeclRef(D->getAnonymousNamespace(), Record); - Code = pch::DECL_TRANSLATION_UNIT; -} - -void PCHDeclWriter::VisitNamedDecl(NamedDecl *D) { - VisitDecl(D); - Writer.AddDeclarationName(D->getDeclName(), Record); -} - -void PCHDeclWriter::VisitTypeDecl(TypeDecl *D) { - VisitNamedDecl(D); - Writer.AddTypeRef(QualType(D->getTypeForDecl(), 0), Record); -} - -void PCHDeclWriter::VisitTypedefDecl(TypedefDecl *D) { - VisitTypeDecl(D); - Writer.AddTypeSourceInfo(D->getTypeSourceInfo(), Record); - Code = pch::DECL_TYPEDEF; -} - -void PCHDeclWriter::VisitTagDecl(TagDecl *D) { - VisitTypeDecl(D); - Record.push_back(D->getIdentifierNamespace()); - Writer.AddDeclRef(D->getPreviousDeclaration(), Record); - Record.push_back((unsigned)D->getTagKind()); // FIXME: stable encoding - Record.push_back(D->isDefinition()); - Record.push_back(D->isEmbeddedInDeclarator()); - Writer.AddSourceLocation(D->getRBraceLoc(), Record); - Writer.AddSourceLocation(D->getTagKeywordLoc(), Record); - // FIXME: maybe write optional qualifier and its range. - Writer.AddDeclRef(D->getTypedefForAnonDecl(), Record); -} - -void PCHDeclWriter::VisitEnumDecl(EnumDecl *D) { - VisitTagDecl(D); - Writer.AddTypeRef(D->getIntegerType(), Record); - Writer.AddTypeRef(D->getPromotionType(), Record); - Record.push_back(D->getNumPositiveBits()); - Record.push_back(D->getNumNegativeBits()); - Writer.AddDeclRef(D->getInstantiatedFromMemberEnum(), Record); - Code = pch::DECL_ENUM; -} - -void PCHDeclWriter::VisitRecordDecl(RecordDecl *D) { - VisitTagDecl(D); - Record.push_back(D->hasFlexibleArrayMember()); - Record.push_back(D->isAnonymousStructOrUnion()); - Record.push_back(D->hasObjectMember()); - Code = pch::DECL_RECORD; -} - -void PCHDeclWriter::VisitValueDecl(ValueDecl *D) { - VisitNamedDecl(D); - Writer.AddTypeRef(D->getType(), Record); -} - -void PCHDeclWriter::VisitEnumConstantDecl(EnumConstantDecl *D) { - VisitValueDecl(D); - Record.push_back(D->getInitExpr()? 1 : 0); - if (D->getInitExpr()) - Writer.AddStmt(D->getInitExpr()); - Writer.AddAPSInt(D->getInitVal(), Record); - Code = pch::DECL_ENUM_CONSTANT; -} - -void PCHDeclWriter::VisitDeclaratorDecl(DeclaratorDecl *D) { - VisitValueDecl(D); - Writer.AddTypeSourceInfo(D->getTypeSourceInfo(), Record); - // FIXME: write optional qualifier and its range. -} - -void PCHDeclWriter::VisitFunctionDecl(FunctionDecl *D) { - VisitDeclaratorDecl(D); - - Record.push_back(D->getIdentifierNamespace()); - Record.push_back(D->getTemplatedKind()); - switch (D->getTemplatedKind()) { - default: assert(false && "Unhandled TemplatedKind!"); - break; - case FunctionDecl::TK_NonTemplate: - break; - case FunctionDecl::TK_FunctionTemplate: - Writer.AddDeclRef(D->getDescribedFunctionTemplate(), Record); - break; - case FunctionDecl::TK_MemberSpecialization: { - MemberSpecializationInfo *MemberInfo = D->getMemberSpecializationInfo(); - Writer.AddDeclRef(MemberInfo->getInstantiatedFrom(), Record); - Record.push_back(MemberInfo->getTemplateSpecializationKind()); - Writer.AddSourceLocation(MemberInfo->getPointOfInstantiation(), Record); - break; - } - case FunctionDecl::TK_FunctionTemplateSpecialization: { - FunctionTemplateSpecializationInfo * - FTSInfo = D->getTemplateSpecializationInfo(); - // We want it canonical to guarantee that it has a Common*. - Writer.AddDeclRef(FTSInfo->getTemplate()->getCanonicalDecl(), Record); - Record.push_back(FTSInfo->getTemplateSpecializationKind()); - - // Template arguments. - Writer.AddTemplateArgumentList(FTSInfo->TemplateArguments, Record); - - // Template args as written. - Record.push_back(FTSInfo->TemplateArgumentsAsWritten != 0); - if (FTSInfo->TemplateArgumentsAsWritten) { - Record.push_back(FTSInfo->TemplateArgumentsAsWritten->size()); - for (int i=0, e = FTSInfo->TemplateArgumentsAsWritten->size(); i!=e; ++i) - Writer.AddTemplateArgumentLoc((*FTSInfo->TemplateArgumentsAsWritten)[i], - Record); - Writer.AddSourceLocation(FTSInfo->TemplateArgumentsAsWritten->getLAngleLoc(), - Record); - Writer.AddSourceLocation(FTSInfo->TemplateArgumentsAsWritten->getRAngleLoc(), - Record); - } - - Writer.AddSourceLocation(FTSInfo->getPointOfInstantiation(), Record); - break; - } - case FunctionDecl::TK_DependentFunctionTemplateSpecialization: { - DependentFunctionTemplateSpecializationInfo * - DFTSInfo = D->getDependentSpecializationInfo(); - - // Templates. - Record.push_back(DFTSInfo->getNumTemplates()); - for (int i=0, e = DFTSInfo->getNumTemplates(); i != e; ++i) - Writer.AddDeclRef(DFTSInfo->getTemplate(i), Record); - - // Templates args. - Record.push_back(DFTSInfo->getNumTemplateArgs()); - for (int i=0, e = DFTSInfo->getNumTemplateArgs(); i != e; ++i) - Writer.AddTemplateArgumentLoc(DFTSInfo->getTemplateArg(i), Record); - Writer.AddSourceLocation(DFTSInfo->getLAngleLoc(), Record); - Writer.AddSourceLocation(DFTSInfo->getRAngleLoc(), Record); - break; - } - } - - // FunctionDecl's body is handled last at PCHWriterDecl::Visit, - // after everything else is written. - - Writer.AddDeclRef(D->getPreviousDeclaration(), Record); - Record.push_back(D->getStorageClass()); // FIXME: stable encoding - Record.push_back(D->getStorageClassAsWritten()); - Record.push_back(D->isInlineSpecified()); - Record.push_back(D->isVirtualAsWritten()); - Record.push_back(D->isPure()); - Record.push_back(D->hasInheritedPrototype()); - Record.push_back(D->hasWrittenPrototype()); - Record.push_back(D->isDeleted()); - Record.push_back(D->isTrivial()); - Record.push_back(D->isCopyAssignment()); - Record.push_back(D->hasImplicitReturnZero()); - Writer.AddSourceLocation(D->getLocEnd(), Record); - - Record.push_back(D->param_size()); - for (FunctionDecl::param_iterator P = D->param_begin(), PEnd = D->param_end(); - P != PEnd; ++P) - Writer.AddDeclRef(*P, Record); - Code = pch::DECL_FUNCTION; -} - -void PCHDeclWriter::VisitObjCMethodDecl(ObjCMethodDecl *D) { - VisitNamedDecl(D); - // FIXME: convert to LazyStmtPtr? - // Unlike C/C++, method bodies will never be in header files. - Record.push_back(D->getBody() != 0); - if (D->getBody() != 0) { - Writer.AddStmt(D->getBody()); - Writer.AddDeclRef(D->getSelfDecl(), Record); - Writer.AddDeclRef(D->getCmdDecl(), Record); - } - Record.push_back(D->isInstanceMethod()); - Record.push_back(D->isVariadic()); - Record.push_back(D->isSynthesized()); - // FIXME: stable encoding for @required/@optional - Record.push_back(D->getImplementationControl()); - // FIXME: stable encoding for in/out/inout/bycopy/byref/oneway - Record.push_back(D->getObjCDeclQualifier()); - Record.push_back(D->getNumSelectorArgs()); - Writer.AddTypeRef(D->getResultType(), Record); - Writer.AddTypeSourceInfo(D->getResultTypeSourceInfo(), Record); - Writer.AddSourceLocation(D->getLocEnd(), Record); - Record.push_back(D->param_size()); - for (ObjCMethodDecl::param_iterator P = D->param_begin(), - PEnd = D->param_end(); P != PEnd; ++P) - Writer.AddDeclRef(*P, Record); - Code = pch::DECL_OBJC_METHOD; -} - -void PCHDeclWriter::VisitObjCContainerDecl(ObjCContainerDecl *D) { - VisitNamedDecl(D); - Writer.AddSourceRange(D->getAtEndRange(), Record); - // Abstract class (no need to define a stable pch::DECL code). -} - -void PCHDeclWriter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { - VisitObjCContainerDecl(D); - Writer.AddTypeRef(QualType(D->getTypeForDecl(), 0), Record); - Writer.AddDeclRef(D->getSuperClass(), Record); - Record.push_back(D->protocol_size()); - for (ObjCInterfaceDecl::protocol_iterator P = D->protocol_begin(), - PEnd = D->protocol_end(); - P != PEnd; ++P) - Writer.AddDeclRef(*P, Record); - for (ObjCInterfaceDecl::protocol_loc_iterator PL = D->protocol_loc_begin(), - PLEnd = D->protocol_loc_end(); - PL != PLEnd; ++PL) - Writer.AddSourceLocation(*PL, Record); - Record.push_back(D->ivar_size()); - for (ObjCInterfaceDecl::ivar_iterator I = D->ivar_begin(), - IEnd = D->ivar_end(); I != IEnd; ++I) - Writer.AddDeclRef(*I, Record); - Writer.AddDeclRef(D->getCategoryList(), Record); - Record.push_back(D->isForwardDecl()); - Record.push_back(D->isImplicitInterfaceDecl()); - Writer.AddSourceLocation(D->getClassLoc(), Record); - Writer.AddSourceLocation(D->getSuperClassLoc(), Record); - Writer.AddSourceLocation(D->getLocEnd(), Record); - Code = pch::DECL_OBJC_INTERFACE; -} - -void PCHDeclWriter::VisitObjCIvarDecl(ObjCIvarDecl *D) { - VisitFieldDecl(D); - // FIXME: stable encoding for @public/@private/@protected/@package - Record.push_back(D->getAccessControl()); - Code = pch::DECL_OBJC_IVAR; -} - -void PCHDeclWriter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) { - VisitObjCContainerDecl(D); - Record.push_back(D->isForwardDecl()); - Writer.AddSourceLocation(D->getLocEnd(), Record); - Record.push_back(D->protocol_size()); - for (ObjCProtocolDecl::protocol_iterator - I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I) - Writer.AddDeclRef(*I, Record); - for (ObjCProtocolDecl::protocol_loc_iterator PL = D->protocol_loc_begin(), - PLEnd = D->protocol_loc_end(); - PL != PLEnd; ++PL) - Writer.AddSourceLocation(*PL, Record); - Code = pch::DECL_OBJC_PROTOCOL; -} - -void PCHDeclWriter::VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *D) { - VisitFieldDecl(D); - Code = pch::DECL_OBJC_AT_DEFS_FIELD; -} - -void PCHDeclWriter::VisitObjCClassDecl(ObjCClassDecl *D) { - VisitDecl(D); - Record.push_back(D->size()); - for (ObjCClassDecl::iterator I = D->begin(), IEnd = D->end(); I != IEnd; ++I) - Writer.AddDeclRef(I->getInterface(), Record); - for (ObjCClassDecl::iterator I = D->begin(), IEnd = D->end(); I != IEnd; ++I) - Writer.AddSourceLocation(I->getLocation(), Record); - Code = pch::DECL_OBJC_CLASS; -} - -void PCHDeclWriter::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) { - VisitDecl(D); - Record.push_back(D->protocol_size()); - for (ObjCForwardProtocolDecl::protocol_iterator - I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I) - Writer.AddDeclRef(*I, Record); - for (ObjCForwardProtocolDecl::protocol_loc_iterator - PL = D->protocol_loc_begin(), PLEnd = D->protocol_loc_end(); - PL != PLEnd; ++PL) - Writer.AddSourceLocation(*PL, Record); - Code = pch::DECL_OBJC_FORWARD_PROTOCOL; -} - -void PCHDeclWriter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) { - VisitObjCContainerDecl(D); - Writer.AddDeclRef(D->getClassInterface(), Record); - Record.push_back(D->protocol_size()); - for (ObjCCategoryDecl::protocol_iterator - I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I) - Writer.AddDeclRef(*I, Record); - for (ObjCCategoryDecl::protocol_loc_iterator - PL = D->protocol_loc_begin(), PLEnd = D->protocol_loc_end(); - PL != PLEnd; ++PL) - Writer.AddSourceLocation(*PL, Record); - Writer.AddDeclRef(D->getNextClassCategory(), Record); - Writer.AddSourceLocation(D->getAtLoc(), Record); - Writer.AddSourceLocation(D->getCategoryNameLoc(), Record); - Code = pch::DECL_OBJC_CATEGORY; -} - -void PCHDeclWriter::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D) { - VisitNamedDecl(D); - Writer.AddDeclRef(D->getClassInterface(), Record); - Code = pch::DECL_OBJC_COMPATIBLE_ALIAS; -} - -void PCHDeclWriter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { - VisitNamedDecl(D); - Writer.AddSourceLocation(D->getAtLoc(), Record); - Writer.AddTypeSourceInfo(D->getTypeSourceInfo(), Record); - // FIXME: stable encoding - Record.push_back((unsigned)D->getPropertyAttributes()); - Record.push_back((unsigned)D->getPropertyAttributesAsWritten()); - // FIXME: stable encoding - Record.push_back((unsigned)D->getPropertyImplementation()); - Writer.AddDeclarationName(D->getGetterName(), Record); - Writer.AddDeclarationName(D->getSetterName(), Record); - Writer.AddDeclRef(D->getGetterMethodDecl(), Record); - Writer.AddDeclRef(D->getSetterMethodDecl(), Record); - Writer.AddDeclRef(D->getPropertyIvarDecl(), Record); - Code = pch::DECL_OBJC_PROPERTY; -} - -void PCHDeclWriter::VisitObjCImplDecl(ObjCImplDecl *D) { - VisitObjCContainerDecl(D); - Writer.AddDeclRef(D->getClassInterface(), Record); - // Abstract class (no need to define a stable pch::DECL code). -} - -void PCHDeclWriter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) { - VisitObjCImplDecl(D); - Writer.AddIdentifierRef(D->getIdentifier(), Record); - Code = pch::DECL_OBJC_CATEGORY_IMPL; -} - -void PCHDeclWriter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { - VisitObjCImplDecl(D); - Writer.AddDeclRef(D->getSuperClass(), Record); - // FIXME add writing of IvarInitializers and NumIvarInitializers. - Code = pch::DECL_OBJC_IMPLEMENTATION; -} - -void PCHDeclWriter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { - VisitDecl(D); - Writer.AddSourceLocation(D->getLocStart(), Record); - Writer.AddDeclRef(D->getPropertyDecl(), Record); - Writer.AddDeclRef(D->getPropertyIvarDecl(), Record); - // FIXME. write GetterCXXConstructor and SetterCXXAssignment. - Code = pch::DECL_OBJC_PROPERTY_IMPL; -} - -void PCHDeclWriter::VisitFieldDecl(FieldDecl *D) { - VisitDeclaratorDecl(D); - Record.push_back(D->isMutable()); - Record.push_back(D->getBitWidth()? 1 : 0); - if (D->getBitWidth()) - Writer.AddStmt(D->getBitWidth()); - if (!D->getDeclName()) - Writer.AddDeclRef(Context.getInstantiatedFromUnnamedFieldDecl(D), Record); - Code = pch::DECL_FIELD; -} - -void PCHDeclWriter::VisitVarDecl(VarDecl *D) { - VisitDeclaratorDecl(D); - Record.push_back(D->getStorageClass()); // FIXME: stable encoding - Record.push_back(D->getStorageClassAsWritten()); - Record.push_back(D->isThreadSpecified()); - Record.push_back(D->hasCXXDirectInitializer()); - Record.push_back(D->isDeclaredInCondition()); - Record.push_back(D->isExceptionVariable()); - Record.push_back(D->isNRVOVariable()); - Writer.AddDeclRef(D->getPreviousDeclaration(), Record); - Record.push_back(D->getInit() ? 1 : 0); - if (D->getInit()) - Writer.AddStmt(D->getInit()); - - MemberSpecializationInfo *SpecInfo - = D->isStaticDataMember() ? D->getMemberSpecializationInfo() : 0; - Record.push_back(SpecInfo != 0); - if (SpecInfo) { - Writer.AddDeclRef(SpecInfo->getInstantiatedFrom(), Record); - Record.push_back(SpecInfo->getTemplateSpecializationKind()); - Writer.AddSourceLocation(SpecInfo->getPointOfInstantiation(), Record); - } - - Code = pch::DECL_VAR; -} - -void PCHDeclWriter::VisitImplicitParamDecl(ImplicitParamDecl *D) { - VisitVarDecl(D); - Code = pch::DECL_IMPLICIT_PARAM; -} - -void PCHDeclWriter::VisitParmVarDecl(ParmVarDecl *D) { - VisitVarDecl(D); - Record.push_back(D->getObjCDeclQualifier()); // FIXME: stable encoding - Record.push_back(D->hasInheritedDefaultArg()); - Record.push_back(D->hasUninstantiatedDefaultArg()); - if (D->hasUninstantiatedDefaultArg()) - Writer.AddStmt(D->getUninstantiatedDefaultArg()); - Code = pch::DECL_PARM_VAR; - - // If the assumptions about the DECL_PARM_VAR abbrev are true, use it. Here - // we dynamically check for the properties that we optimize for, but don't - // know are true of all PARM_VAR_DECLs. - if (!D->getTypeSourceInfo() && - !D->hasAttrs() && - !D->isImplicit() && - !D->isUsed(false) && - D->getAccess() == AS_none && - D->getPCHLevel() == 0 && - D->getStorageClass() == 0 && - !D->hasCXXDirectInitializer() && // Can params have this ever? - D->getObjCDeclQualifier() == 0 && - !D->hasInheritedDefaultArg() && - D->getInit() == 0 && - !D->hasUninstantiatedDefaultArg()) // No default expr. - AbbrevToUse = Writer.getParmVarDeclAbbrev(); - - // Check things we know are true of *every* PARM_VAR_DECL, which is more than - // just us assuming it. - assert(!D->isInvalidDecl() && "Shouldn't emit invalid decls"); - assert(!D->isThreadSpecified() && "PARM_VAR_DECL can't be __thread"); - assert(D->getAccess() == AS_none && "PARM_VAR_DECL can't be public/private"); - assert(!D->isDeclaredInCondition() && "PARM_VAR_DECL can't be in condition"); - assert(!D->isExceptionVariable() && "PARM_VAR_DECL can't be exception var"); - assert(D->getPreviousDeclaration() == 0 && "PARM_VAR_DECL can't be redecl"); - assert(!D->isStaticDataMember() && - "PARM_VAR_DECL can't be static data member"); -} - -void PCHDeclWriter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) { - VisitDecl(D); - Writer.AddStmt(D->getAsmString()); - Code = pch::DECL_FILE_SCOPE_ASM; -} - -void PCHDeclWriter::VisitBlockDecl(BlockDecl *D) { - VisitDecl(D); - Writer.AddStmt(D->getBody()); - Writer.AddTypeSourceInfo(D->getSignatureAsWritten(), Record); - Record.push_back(D->param_size()); - for (FunctionDecl::param_iterator P = D->param_begin(), PEnd = D->param_end(); - P != PEnd; ++P) - Writer.AddDeclRef(*P, Record); - Code = pch::DECL_BLOCK; -} - -void PCHDeclWriter::VisitLinkageSpecDecl(LinkageSpecDecl *D) { - VisitDecl(D); - // FIXME: It might be nice to serialize the brace locations for this - // declaration, which don't seem to be readily available in the AST. - Record.push_back(D->getLanguage()); - Record.push_back(D->hasBraces()); - Code = pch::DECL_LINKAGE_SPEC; -} - -void PCHDeclWriter::VisitNamespaceDecl(NamespaceDecl *D) { - VisitNamedDecl(D); - Writer.AddSourceLocation(D->getLBracLoc(), Record); - Writer.AddSourceLocation(D->getRBracLoc(), Record); - Writer.AddDeclRef(D->getNextNamespace(), Record); - - // Only write one reference--original or anonymous - Record.push_back(D->isOriginalNamespace()); - if (D->isOriginalNamespace()) - Writer.AddDeclRef(D->getAnonymousNamespace(), Record); - else - Writer.AddDeclRef(D->getOriginalNamespace(), Record); - Code = pch::DECL_NAMESPACE; -} - -void PCHDeclWriter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { - VisitNamedDecl(D); - Writer.AddSourceLocation(D->getAliasLoc(), Record); - Writer.AddSourceRange(D->getQualifierRange(), Record); - Writer.AddNestedNameSpecifier(D->getQualifier(), Record); - Writer.AddSourceLocation(D->getTargetNameLoc(), Record); - Writer.AddDeclRef(D->getNamespace(), Record); - Code = pch::DECL_NAMESPACE_ALIAS; -} - -void PCHDeclWriter::VisitUsingDecl(UsingDecl *D) { - VisitNamedDecl(D); - Writer.AddSourceRange(D->getNestedNameRange(), Record); - Writer.AddSourceLocation(D->getUsingLocation(), Record); - Writer.AddNestedNameSpecifier(D->getTargetNestedNameDecl(), Record); - Record.push_back(D->getNumShadowDecls()); - for (UsingDecl::shadow_iterator P = D->shadow_begin(), - PEnd = D->shadow_end(); P != PEnd; ++P) - Writer.AddDeclRef(*P, Record); - Record.push_back(D->isTypeName()); - Writer.AddDeclRef(Context.getInstantiatedFromUsingDecl(D), Record); - Code = pch::DECL_USING; -} - -void PCHDeclWriter::VisitUsingShadowDecl(UsingShadowDecl *D) { - VisitNamedDecl(D); - Writer.AddDeclRef(D->getTargetDecl(), Record); - Writer.AddDeclRef(D->getUsingDecl(), Record); - Writer.AddDeclRef(Context.getInstantiatedFromUsingShadowDecl(D), Record); - Code = pch::DECL_USING_SHADOW; -} - -void PCHDeclWriter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { - VisitNamedDecl(D); - Writer.AddSourceLocation(D->getNamespaceKeyLocation(), Record); - Writer.AddSourceRange(D->getQualifierRange(), Record); - Writer.AddNestedNameSpecifier(D->getQualifier(), Record); - Writer.AddSourceLocation(D->getIdentLocation(), Record); - Writer.AddDeclRef(D->getNominatedNamespace(), Record); - Writer.AddDeclRef(dyn_cast<Decl>(D->getCommonAncestor()), Record); - Code = pch::DECL_USING_DIRECTIVE; -} - -void PCHDeclWriter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { - VisitValueDecl(D); - Writer.AddSourceRange(D->getTargetNestedNameRange(), Record); - Writer.AddSourceLocation(D->getUsingLoc(), Record); - Writer.AddNestedNameSpecifier(D->getTargetNestedNameSpecifier(), Record); - Code = pch::DECL_UNRESOLVED_USING_VALUE; -} - -void PCHDeclWriter::VisitUnresolvedUsingTypenameDecl( - UnresolvedUsingTypenameDecl *D) { - VisitTypeDecl(D); - Writer.AddSourceRange(D->getTargetNestedNameRange(), Record); - Writer.AddSourceLocation(D->getUsingLoc(), Record); - Writer.AddSourceLocation(D->getTypenameLoc(), Record); - Writer.AddNestedNameSpecifier(D->getTargetNestedNameSpecifier(), Record); - Code = pch::DECL_UNRESOLVED_USING_TYPENAME; -} - -void PCHDeclWriter::VisitCXXRecordDecl(CXXRecordDecl *D) { - // See comments at PCHDeclReader::VisitCXXRecordDecl about why this happens - // before VisitRecordDecl. - enum { Data_NoDefData, Data_Owner, Data_NotOwner }; - bool OwnsDefinitionData = false; - if (D->DefinitionData) { - assert(D->DefinitionData->Definition && - "DefinitionData don't point to a definition decl!"); - OwnsDefinitionData = D->DefinitionData->Definition == D; - if (OwnsDefinitionData) { - Record.push_back(Data_Owner); - } else { - Record.push_back(Data_NotOwner); - Writer.AddDeclRef(D->DefinitionData->Definition, Record); - } - } else - Record.push_back(Data_NoDefData); - - VisitRecordDecl(D); - - if (OwnsDefinitionData) { - assert(D->DefinitionData); - struct CXXRecordDecl::DefinitionData &Data = *D->DefinitionData; - - Record.push_back(Data.UserDeclaredConstructor); - Record.push_back(Data.UserDeclaredCopyConstructor); - Record.push_back(Data.UserDeclaredCopyAssignment); - Record.push_back(Data.UserDeclaredDestructor); - Record.push_back(Data.Aggregate); - Record.push_back(Data.PlainOldData); - Record.push_back(Data.Empty); - Record.push_back(Data.Polymorphic); - Record.push_back(Data.Abstract); - Record.push_back(Data.HasTrivialConstructor); - Record.push_back(Data.HasTrivialCopyConstructor); - Record.push_back(Data.HasTrivialCopyAssignment); - Record.push_back(Data.HasTrivialDestructor); - Record.push_back(Data.ComputedVisibleConversions); - Record.push_back(Data.DeclaredDefaultConstructor); - Record.push_back(Data.DeclaredCopyConstructor); - Record.push_back(Data.DeclaredCopyAssignment); - Record.push_back(Data.DeclaredDestructor); - - Record.push_back(D->getNumBases()); - for (CXXRecordDecl::base_class_iterator I = D->bases_begin(), - E = D->bases_end(); I != E; ++I) - Writer.AddCXXBaseSpecifier(*I, Record); - - // FIXME: Make VBases lazily computed when needed to avoid storing them. - Record.push_back(D->getNumVBases()); - for (CXXRecordDecl::base_class_iterator I = D->vbases_begin(), - E = D->vbases_end(); I != E; ++I) - Writer.AddCXXBaseSpecifier(*I, Record); - - Writer.AddUnresolvedSet(Data.Conversions, Record); - Writer.AddUnresolvedSet(Data.VisibleConversions, Record); - // Data.Definition is written at the top. - Writer.AddDeclRef(Data.FirstFriend, Record); - } - - enum { - CXXRecNotTemplate = 0, CXXRecTemplate, CXXRecMemberSpecialization - }; - if (ClassTemplateDecl *TemplD = D->getDescribedClassTemplate()) { - Record.push_back(CXXRecTemplate); - Writer.AddDeclRef(TemplD, Record); - } else if (MemberSpecializationInfo *MSInfo - = D->getMemberSpecializationInfo()) { - Record.push_back(CXXRecMemberSpecialization); - Writer.AddDeclRef(MSInfo->getInstantiatedFrom(), Record); - Record.push_back(MSInfo->getTemplateSpecializationKind()); - Writer.AddSourceLocation(MSInfo->getPointOfInstantiation(), Record); - } else { - Record.push_back(CXXRecNotTemplate); - } - - Code = pch::DECL_CXX_RECORD; -} - -void PCHDeclWriter::VisitCXXMethodDecl(CXXMethodDecl *D) { - VisitFunctionDecl(D); - Record.push_back(D->size_overridden_methods()); - for (CXXMethodDecl::method_iterator - I = D->begin_overridden_methods(), E = D->end_overridden_methods(); - I != E; ++I) - Writer.AddDeclRef(*I, Record); - Code = pch::DECL_CXX_METHOD; -} - -void PCHDeclWriter::VisitCXXConstructorDecl(CXXConstructorDecl *D) { - VisitCXXMethodDecl(D); - - Record.push_back(D->IsExplicitSpecified); - Record.push_back(D->ImplicitlyDefined); - - Record.push_back(D->NumBaseOrMemberInitializers); - for (unsigned i=0; i != D->NumBaseOrMemberInitializers; ++i) { - CXXBaseOrMemberInitializer *Init = D->BaseOrMemberInitializers[i]; - - Record.push_back(Init->isBaseInitializer()); - if (Init->isBaseInitializer()) { - Writer.AddTypeSourceInfo(Init->getBaseClassInfo(), Record); - Record.push_back(Init->isBaseVirtual()); - } else { - Writer.AddDeclRef(Init->getMember(), Record); - } - Writer.AddSourceLocation(Init->getMemberLocation(), Record); - Writer.AddStmt(Init->getInit()); - Writer.AddDeclRef(Init->getAnonUnionMember(), Record); - Writer.AddSourceLocation(Init->getLParenLoc(), Record); - Writer.AddSourceLocation(Init->getRParenLoc(), Record); - Record.push_back(Init->isWritten()); - if (Init->isWritten()) { - Record.push_back(Init->getSourceOrder()); - } else { - Record.push_back(Init->getNumArrayIndices()); - for (unsigned i=0, e=Init->getNumArrayIndices(); i != e; ++i) - Writer.AddDeclRef(Init->getArrayIndex(i), Record); - } - } - - Code = pch::DECL_CXX_CONSTRUCTOR; -} - -void PCHDeclWriter::VisitCXXDestructorDecl(CXXDestructorDecl *D) { - VisitCXXMethodDecl(D); - - Record.push_back(D->ImplicitlyDefined); - Writer.AddDeclRef(D->OperatorDelete, Record); - - Code = pch::DECL_CXX_DESTRUCTOR; -} - -void PCHDeclWriter::VisitCXXConversionDecl(CXXConversionDecl *D) { - VisitCXXMethodDecl(D); - Record.push_back(D->IsExplicitSpecified); - Code = pch::DECL_CXX_CONVERSION; -} - -void PCHDeclWriter::VisitAccessSpecDecl(AccessSpecDecl *D) { - VisitDecl(D); - Writer.AddSourceLocation(D->getColonLoc(), Record); - Code = pch::DECL_ACCESS_SPEC; -} - -void PCHDeclWriter::VisitFriendDecl(FriendDecl *D) { - VisitDecl(D); - Record.push_back(D->Friend.is<TypeSourceInfo*>()); - if (D->Friend.is<TypeSourceInfo*>()) - Writer.AddTypeSourceInfo(D->Friend.get<TypeSourceInfo*>(), Record); - else - Writer.AddDeclRef(D->Friend.get<NamedDecl*>(), Record); - Writer.AddDeclRef(D->NextFriend, Record); - Writer.AddSourceLocation(D->FriendLoc, Record); - Code = pch::DECL_FRIEND; -} - -void PCHDeclWriter::VisitFriendTemplateDecl(FriendTemplateDecl *D) { - assert(false && "cannot write FriendTemplateDecl"); -} - -void PCHDeclWriter::VisitTemplateDecl(TemplateDecl *D) { - VisitNamedDecl(D); - - Writer.AddDeclRef(D->getTemplatedDecl(), Record); - Writer.AddTemplateParameterList(D->getTemplateParameters(), Record); -} - -static bool IsKeptInFoldingSet(ClassTemplateSpecializationDecl *D) { - return D->getTypeForDecl()->getAsCXXRecordDecl() == D; -} - -void PCHDeclWriter::VisitClassTemplateDecl(ClassTemplateDecl *D) { - VisitTemplateDecl(D); - - Record.push_back(D->getIdentifierNamespace()); - Writer.AddDeclRef(D->getPreviousDeclaration(), Record); - if (D->getPreviousDeclaration() == 0) { - // This ClassTemplateDecl owns the CommonPtr; write it. - assert(D->isCanonicalDecl()); - - typedef llvm::FoldingSet<ClassTemplateSpecializationDecl> CTSDSetTy; - CTSDSetTy &CTSDSet = D->getSpecializations(); - Record.push_back(CTSDSet.size()); - for (CTSDSetTy::iterator I=CTSDSet.begin(), E = CTSDSet.end(); I!=E; ++I) { - assert(IsKeptInFoldingSet(&*I)); - Writer.AddDeclRef(&*I, Record); - } - - typedef llvm::FoldingSet<ClassTemplatePartialSpecializationDecl> CTPSDSetTy; - CTPSDSetTy &CTPSDSet = D->getPartialSpecializations(); - Record.push_back(CTPSDSet.size()); - for (CTPSDSetTy::iterator I=CTPSDSet.begin(), E=CTPSDSet.end(); I!=E; ++I) { - assert(IsKeptInFoldingSet(&*I)); - Writer.AddDeclRef(&*I, Record); - } - - // InjectedClassNameType is computed, no need to write it. - - Writer.AddDeclRef(D->getInstantiatedFromMemberTemplate(), Record); - if (D->getInstantiatedFromMemberTemplate()) - Record.push_back(D->isMemberSpecialization()); - } - Code = pch::DECL_CLASS_TEMPLATE; -} - -void PCHDeclWriter::VisitClassTemplateSpecializationDecl( - ClassTemplateSpecializationDecl *D) { - VisitCXXRecordDecl(D); - - llvm::PointerUnion<ClassTemplateDecl *, - ClassTemplatePartialSpecializationDecl *> InstFrom - = D->getSpecializedTemplateOrPartial(); - if (InstFrom.is<ClassTemplateDecl *>()) { - Writer.AddDeclRef(InstFrom.get<ClassTemplateDecl *>(), Record); - } else { - Writer.AddDeclRef(InstFrom.get<ClassTemplatePartialSpecializationDecl *>(), - Record); - Writer.AddTemplateArgumentList(&D->getTemplateInstantiationArgs(), Record); - } - - // Explicit info. - Writer.AddTypeSourceInfo(D->getTypeAsWritten(), Record); - if (D->getTypeAsWritten()) { - Writer.AddSourceLocation(D->getExternLoc(), Record); - Writer.AddSourceLocation(D->getTemplateKeywordLoc(), Record); - } - - Writer.AddTemplateArgumentList(&D->getTemplateArgs(), Record); - Writer.AddSourceLocation(D->getPointOfInstantiation(), Record); - Record.push_back(D->getSpecializationKind()); - - bool IsInInFoldingSet = IsKeptInFoldingSet(D); - Record.push_back(IsInInFoldingSet); - if (IsInInFoldingSet) { - // When reading, we'll add it to the folding set of this one. - Writer.AddDeclRef(D->getSpecializedTemplate()->getCanonicalDecl(), Record); - } - - Code = pch::DECL_CLASS_TEMPLATE_SPECIALIZATION; -} - -void PCHDeclWriter::VisitClassTemplatePartialSpecializationDecl( - ClassTemplatePartialSpecializationDecl *D) { - VisitClassTemplateSpecializationDecl(D); - - Writer.AddTemplateParameterList(D->getTemplateParameters(), Record); - - Record.push_back(D->getNumTemplateArgsAsWritten()); - for (int i = 0, e = D->getNumTemplateArgsAsWritten(); i != e; ++i) - Writer.AddTemplateArgumentLoc(D->getTemplateArgsAsWritten()[i], Record); - - Record.push_back(D->getSequenceNumber()); - - // These are read/set from/to the first declaration. - if (D->getPreviousDeclaration() == 0) { - Writer.AddDeclRef(D->getInstantiatedFromMember(), Record); - Record.push_back(D->isMemberSpecialization()); - } - - Code = pch::DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION; -} - -void PCHDeclWriter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { - VisitTemplateDecl(D); - - Record.push_back(D->getIdentifierNamespace()); - Writer.AddDeclRef(D->getPreviousDeclaration(), Record); - if (D->getPreviousDeclaration() == 0) { - // This FunctionTemplateDecl owns the CommonPtr; write it. - - // Write the function specialization declarations. - Record.push_back(D->getSpecializations().size()); - for (llvm::FoldingSet<FunctionTemplateSpecializationInfo>::iterator - I = D->getSpecializations().begin(), - E = D->getSpecializations().end() ; I != E; ++I) - Writer.AddDeclRef(I->Function, Record); - - Writer.AddDeclRef(D->getInstantiatedFromMemberTemplate(), Record); - if (D->getInstantiatedFromMemberTemplate()) - Record.push_back(D->isMemberSpecialization()); - } - Code = pch::DECL_FUNCTION_TEMPLATE; -} - -void PCHDeclWriter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { - VisitTypeDecl(D); - - Record.push_back(D->wasDeclaredWithTypename()); - Record.push_back(D->isParameterPack()); - Record.push_back(D->defaultArgumentWasInherited()); - Writer.AddTypeSourceInfo(D->getDefaultArgumentInfo(), Record); - - Code = pch::DECL_TEMPLATE_TYPE_PARM; -} - -void PCHDeclWriter::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) { - VisitVarDecl(D); - // TemplateParmPosition. - Record.push_back(D->getDepth()); - Record.push_back(D->getPosition()); - // Rest of NonTypeTemplateParmDecl. - Record.push_back(D->getDefaultArgument() != 0); - if (D->getDefaultArgument()) { - Writer.AddStmt(D->getDefaultArgument()); - Record.push_back(D->defaultArgumentWasInherited()); - } - Code = pch::DECL_NON_TYPE_TEMPLATE_PARM; -} - -void PCHDeclWriter::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) { - VisitTemplateDecl(D); - // TemplateParmPosition. - Record.push_back(D->getDepth()); - Record.push_back(D->getPosition()); - // Rest of TemplateTemplateParmDecl. - Writer.AddTemplateArgumentLoc(D->getDefaultArgument(), Record); - Record.push_back(D->defaultArgumentWasInherited()); - Code = pch::DECL_TEMPLATE_TEMPLATE_PARM; -} - -void PCHDeclWriter::VisitStaticAssertDecl(StaticAssertDecl *D) { - assert(false && "cannot write StaticAssertDecl"); -} - -/// \brief Emit the DeclContext part of a declaration context decl. -/// -/// \param LexicalOffset the offset at which the DECL_CONTEXT_LEXICAL -/// block for this declaration context is stored. May be 0 to indicate -/// that there are no declarations stored within this context. -/// -/// \param VisibleOffset the offset at which the DECL_CONTEXT_VISIBLE -/// block for this declaration context is stored. May be 0 to indicate -/// that there are no declarations visible from this context. Note -/// that this value will not be emitted for non-primary declaration -/// contexts. -void PCHDeclWriter::VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset, - uint64_t VisibleOffset) { - Record.push_back(LexicalOffset); - Record.push_back(VisibleOffset); -} - - -//===----------------------------------------------------------------------===// -// PCHWriter Implementation -//===----------------------------------------------------------------------===// - -void PCHWriter::WriteDeclsBlockAbbrevs() { - using namespace llvm; - // Abbreviation for DECL_PARM_VAR. - BitCodeAbbrev *Abv = new BitCodeAbbrev(); - Abv->Add(BitCodeAbbrevOp(pch::DECL_PARM_VAR)); - - // Decl - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Location - Abv->Add(BitCodeAbbrevOp(0)); // isInvalidDecl (!?) - Abv->Add(BitCodeAbbrevOp(0)); // HasAttrs - Abv->Add(BitCodeAbbrevOp(0)); // isImplicit - Abv->Add(BitCodeAbbrevOp(0)); // isUsed - Abv->Add(BitCodeAbbrevOp(AS_none)); // C++ AccessSpecifier - Abv->Add(BitCodeAbbrevOp(0)); // PCH level - - // NamedDecl - Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name - // ValueDecl - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type - // DeclaratorDecl - Abv->Add(BitCodeAbbrevOp(pch::PREDEF_TYPE_NULL_ID)); // InfoType - // VarDecl - Abv->Add(BitCodeAbbrevOp(0)); // StorageClass - Abv->Add(BitCodeAbbrevOp(0)); // StorageClassAsWritten - Abv->Add(BitCodeAbbrevOp(0)); // isThreadSpecified - Abv->Add(BitCodeAbbrevOp(0)); // hasCXXDirectInitializer - Abv->Add(BitCodeAbbrevOp(0)); // isDeclaredInCondition - Abv->Add(BitCodeAbbrevOp(0)); // isExceptionVariable - Abv->Add(BitCodeAbbrevOp(0)); // isNRVOVariable - Abv->Add(BitCodeAbbrevOp(0)); // PrevDecl - Abv->Add(BitCodeAbbrevOp(0)); // HasInit - Abv->Add(BitCodeAbbrevOp(0)); // HasMemberSpecializationInfo - // ParmVarDecl - Abv->Add(BitCodeAbbrevOp(0)); // ObjCDeclQualifier - Abv->Add(BitCodeAbbrevOp(0)); // HasInheritedDefaultArg - Abv->Add(BitCodeAbbrevOp(0)); // HasUninstantiatedDefaultArg - - ParmVarDeclAbbrev = Stream.EmitAbbrev(Abv); -} - -/// isRequiredDecl - Check if this is a "required" Decl, which must be seen by -/// consumers of the AST. -/// -/// Such decls will always be deserialized from the PCH file, so we would like -/// this to be as restrictive as possible. Currently the predicate is driven by -/// code generation requirements, if other clients have a different notion of -/// what is "required" then we may have to consider an alternate scheme where -/// clients can iterate over the top-level decls and get information on them, -/// without necessary deserializing them. We could explicitly require such -/// clients to use a separate API call to "realize" the decl. This should be -/// relatively painless since they would presumably only do it for top-level -/// decls. -// -// FIXME: This predicate is essentially IRgen's predicate to determine whether a -// declaration can be deferred. Merge them somehow. -static bool isRequiredDecl(const Decl *D, ASTContext &Context) { - // File scoped assembly must be seen. - if (isa<FileScopeAsmDecl>(D)) - return true; - - // Otherwise if this isn't a function or a file scoped variable it doesn't - // need to be seen. - if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { - if (!VD->isFileVarDecl()) - return false; - } else if (!isa<FunctionDecl>(D)) - return false; - - // Aliases and used decls must be seen. - if (D->hasAttr<AliasAttr>() || D->hasAttr<UsedAttr>()) - return true; - - if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { - // Forward declarations don't need to be seen. - if (!FD->isThisDeclarationADefinition()) - return false; - - // Constructors and destructors must be seen. - if (FD->hasAttr<ConstructorAttr>() || FD->hasAttr<DestructorAttr>()) - return true; - - // Otherwise, this is required unless it is static. - // - // FIXME: Inlines. - return FD->getStorageClass() != FunctionDecl::Static; - } else { - const VarDecl *VD = cast<VarDecl>(D); - - // In C++, this doesn't need to be seen if it is marked "extern". - if (Context.getLangOptions().CPlusPlus && !VD->getInit() && - (VD->getStorageClass() == VarDecl::Extern || - VD->isExternC())) - return false; - - // In C, this doesn't need to be seen unless it is a definition. - if (!Context.getLangOptions().CPlusPlus && !VD->getInit()) - return false; - - // Otherwise, this is required unless it is static. - return VD->getStorageClass() != VarDecl::Static; - } -} - -void PCHWriter::WriteDecl(ASTContext &Context, Decl *D) { - RecordData Record; - PCHDeclWriter W(*this, Context, Record); - - // If this declaration is also a DeclContext, write blocks for the - // declarations that lexically stored inside its context and those - // declarations that are visible from its context. These blocks - // are written before the declaration itself so that we can put - // their offsets into the record for the declaration. - uint64_t LexicalOffset = 0; - uint64_t VisibleOffset = 0; - DeclContext *DC = dyn_cast<DeclContext>(D); - if (DC) { - LexicalOffset = WriteDeclContextLexicalBlock(Context, DC); - VisibleOffset = WriteDeclContextVisibleBlock(Context, DC); - } - - // Determine the ID for this declaration - pch::DeclID &ID = DeclIDs[D]; - if (ID == 0) - ID = DeclIDs.size(); - - unsigned Index = ID - 1; - - // Record the offset for this declaration - if (DeclOffsets.size() == Index) - DeclOffsets.push_back(Stream.GetCurrentBitNo()); - else if (DeclOffsets.size() < Index) { - DeclOffsets.resize(Index+1); - DeclOffsets[Index] = Stream.GetCurrentBitNo(); - } - - // Build and emit a record for this declaration - Record.clear(); - W.Code = (pch::DeclCode)0; - W.AbbrevToUse = 0; - W.Visit(D); - if (DC) W.VisitDeclContext(DC, LexicalOffset, VisibleOffset); - - if (!W.Code) - llvm::report_fatal_error(llvm::StringRef("unexpected declaration kind '") + - D->getDeclKindName() + "'"); - Stream.EmitRecord(W.Code, Record, W.AbbrevToUse); - - // If the declaration had any attributes, write them now. - if (D->hasAttrs()) - WriteAttributeRecord(D->getAttrs()); - - // Flush any expressions that were written as part of this declaration. - FlushStmts(); - - // Note "external" declarations so that we can add them to a record in the - // PCH file later. - // - // FIXME: This should be renamed, the predicate is much more complicated. - if (isRequiredDecl(D, Context)) - ExternalDefinitions.push_back(Index + 1); -} diff --git a/lib/Frontend/PCHWriterStmt.cpp b/lib/Frontend/PCHWriterStmt.cpp deleted file mode 100644 index 7537728..0000000 --- a/lib/Frontend/PCHWriterStmt.cpp +++ /dev/null @@ -1,1345 +0,0 @@ -//===--- PCHWriterStmt.cpp - Statement and Expression Serialization -------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements serialization for Statements and Expressions. -// -//===----------------------------------------------------------------------===// - -#include "clang/Frontend/PCHWriter.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclObjC.h" -#include "clang/AST/StmtVisitor.h" -#include "llvm/Bitcode/BitstreamWriter.h" -using namespace clang; - -//===----------------------------------------------------------------------===// -// Statement/expression serialization -//===----------------------------------------------------------------------===// - -namespace clang { - class PCHStmtWriter : public StmtVisitor<PCHStmtWriter, void> { - PCHWriter &Writer; - PCHWriter::RecordData &Record; - - public: - pch::StmtCode Code; - - PCHStmtWriter(PCHWriter &Writer, PCHWriter::RecordData &Record) - : Writer(Writer), Record(Record) { } - - void - AddExplicitTemplateArgumentList(const ExplicitTemplateArgumentList &Args); - - void VisitStmt(Stmt *S); - void VisitNullStmt(NullStmt *S); - void VisitCompoundStmt(CompoundStmt *S); - void VisitSwitchCase(SwitchCase *S); - void VisitCaseStmt(CaseStmt *S); - void VisitDefaultStmt(DefaultStmt *S); - void VisitLabelStmt(LabelStmt *S); - void VisitIfStmt(IfStmt *S); - void VisitSwitchStmt(SwitchStmt *S); - void VisitWhileStmt(WhileStmt *S); - void VisitDoStmt(DoStmt *S); - void VisitForStmt(ForStmt *S); - void VisitGotoStmt(GotoStmt *S); - void VisitIndirectGotoStmt(IndirectGotoStmt *S); - void VisitContinueStmt(ContinueStmt *S); - void VisitBreakStmt(BreakStmt *S); - void VisitReturnStmt(ReturnStmt *S); - void VisitDeclStmt(DeclStmt *S); - void VisitAsmStmt(AsmStmt *S); - void VisitExpr(Expr *E); - void VisitPredefinedExpr(PredefinedExpr *E); - void VisitDeclRefExpr(DeclRefExpr *E); - void VisitIntegerLiteral(IntegerLiteral *E); - void VisitFloatingLiteral(FloatingLiteral *E); - void VisitImaginaryLiteral(ImaginaryLiteral *E); - void VisitStringLiteral(StringLiteral *E); - void VisitCharacterLiteral(CharacterLiteral *E); - void VisitParenExpr(ParenExpr *E); - void VisitParenListExpr(ParenListExpr *E); - void VisitUnaryOperator(UnaryOperator *E); - void VisitOffsetOfExpr(OffsetOfExpr *E); - void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E); - void VisitArraySubscriptExpr(ArraySubscriptExpr *E); - void VisitCallExpr(CallExpr *E); - void VisitMemberExpr(MemberExpr *E); - void VisitCastExpr(CastExpr *E); - void VisitBinaryOperator(BinaryOperator *E); - void VisitCompoundAssignOperator(CompoundAssignOperator *E); - void VisitConditionalOperator(ConditionalOperator *E); - void VisitImplicitCastExpr(ImplicitCastExpr *E); - void VisitExplicitCastExpr(ExplicitCastExpr *E); - void VisitCStyleCastExpr(CStyleCastExpr *E); - void VisitCompoundLiteralExpr(CompoundLiteralExpr *E); - void VisitExtVectorElementExpr(ExtVectorElementExpr *E); - void VisitInitListExpr(InitListExpr *E); - void VisitDesignatedInitExpr(DesignatedInitExpr *E); - void VisitImplicitValueInitExpr(ImplicitValueInitExpr *E); - void VisitVAArgExpr(VAArgExpr *E); - void VisitAddrLabelExpr(AddrLabelExpr *E); - void VisitStmtExpr(StmtExpr *E); - void VisitTypesCompatibleExpr(TypesCompatibleExpr *E); - void VisitChooseExpr(ChooseExpr *E); - void VisitGNUNullExpr(GNUNullExpr *E); - void VisitShuffleVectorExpr(ShuffleVectorExpr *E); - void VisitBlockExpr(BlockExpr *E); - void VisitBlockDeclRefExpr(BlockDeclRefExpr *E); - - // Objective-C Expressions - void VisitObjCStringLiteral(ObjCStringLiteral *E); - void VisitObjCEncodeExpr(ObjCEncodeExpr *E); - void VisitObjCSelectorExpr(ObjCSelectorExpr *E); - void VisitObjCProtocolExpr(ObjCProtocolExpr *E); - void VisitObjCIvarRefExpr(ObjCIvarRefExpr *E); - void VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E); - void VisitObjCImplicitSetterGetterRefExpr( - ObjCImplicitSetterGetterRefExpr *E); - void VisitObjCMessageExpr(ObjCMessageExpr *E); - void VisitObjCSuperExpr(ObjCSuperExpr *E); - void VisitObjCIsaExpr(ObjCIsaExpr *E); - - // Objective-C Statements - void VisitObjCForCollectionStmt(ObjCForCollectionStmt *); - void VisitObjCAtCatchStmt(ObjCAtCatchStmt *); - void VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *); - void VisitObjCAtTryStmt(ObjCAtTryStmt *); - void VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *); - void VisitObjCAtThrowStmt(ObjCAtThrowStmt *); - - // C++ Statements - void VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E); - void VisitCXXMemberCallExpr(CXXMemberCallExpr *E); - void VisitCXXConstructExpr(CXXConstructExpr *E); - void VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E); - void VisitCXXNamedCastExpr(CXXNamedCastExpr *E); - void VisitCXXStaticCastExpr(CXXStaticCastExpr *E); - void VisitCXXDynamicCastExpr(CXXDynamicCastExpr *E); - void VisitCXXReinterpretCastExpr(CXXReinterpretCastExpr *E); - void VisitCXXConstCastExpr(CXXConstCastExpr *E); - void VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E); - void VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E); - void VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E); - void VisitCXXTypeidExpr(CXXTypeidExpr *E); - void VisitCXXThisExpr(CXXThisExpr *E); - void VisitCXXThrowExpr(CXXThrowExpr *E); - void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E); - void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E); - void VisitCXXBindReferenceExpr(CXXBindReferenceExpr *E); - - void VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E); - void VisitCXXNewExpr(CXXNewExpr *E); - void VisitCXXDeleteExpr(CXXDeleteExpr *E); - void VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E); - - void VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E); - void VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E); - void VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E); - void VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E); - - void VisitOverloadExpr(OverloadExpr *E); - void VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E); - void VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E); - - void VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E); - }; -} - -void PCHStmtWriter:: -AddExplicitTemplateArgumentList(const ExplicitTemplateArgumentList &Args) { - Writer.AddSourceLocation(Args.LAngleLoc, Record); - Writer.AddSourceLocation(Args.RAngleLoc, Record); - for (unsigned i=0; i != Args.NumTemplateArgs; ++i) - Writer.AddTemplateArgumentLoc(Args.getTemplateArgs()[i], Record); -} - -void PCHStmtWriter::VisitStmt(Stmt *S) { -} - -void PCHStmtWriter::VisitNullStmt(NullStmt *S) { - VisitStmt(S); - Writer.AddSourceLocation(S->getSemiLoc(), Record); - Code = pch::STMT_NULL; -} - -void PCHStmtWriter::VisitCompoundStmt(CompoundStmt *S) { - VisitStmt(S); - Record.push_back(S->size()); - for (CompoundStmt::body_iterator CS = S->body_begin(), CSEnd = S->body_end(); - CS != CSEnd; ++CS) - Writer.AddStmt(*CS); - Writer.AddSourceLocation(S->getLBracLoc(), Record); - Writer.AddSourceLocation(S->getRBracLoc(), Record); - Code = pch::STMT_COMPOUND; -} - -void PCHStmtWriter::VisitSwitchCase(SwitchCase *S) { - VisitStmt(S); - Record.push_back(Writer.getSwitchCaseID(S)); -} - -void PCHStmtWriter::VisitCaseStmt(CaseStmt *S) { - VisitSwitchCase(S); - Writer.AddStmt(S->getLHS()); - Writer.AddStmt(S->getRHS()); - Writer.AddStmt(S->getSubStmt()); - Writer.AddSourceLocation(S->getCaseLoc(), Record); - Writer.AddSourceLocation(S->getEllipsisLoc(), Record); - Writer.AddSourceLocation(S->getColonLoc(), Record); - Code = pch::STMT_CASE; -} - -void PCHStmtWriter::VisitDefaultStmt(DefaultStmt *S) { - VisitSwitchCase(S); - Writer.AddStmt(S->getSubStmt()); - Writer.AddSourceLocation(S->getDefaultLoc(), Record); - Writer.AddSourceLocation(S->getColonLoc(), Record); - Code = pch::STMT_DEFAULT; -} - -void PCHStmtWriter::VisitLabelStmt(LabelStmt *S) { - VisitStmt(S); - Writer.AddIdentifierRef(S->getID(), Record); - Writer.AddStmt(S->getSubStmt()); - Writer.AddSourceLocation(S->getIdentLoc(), Record); - Record.push_back(Writer.GetLabelID(S)); - Code = pch::STMT_LABEL; -} - -void PCHStmtWriter::VisitIfStmt(IfStmt *S) { - VisitStmt(S); - Writer.AddDeclRef(S->getConditionVariable(), Record); - Writer.AddStmt(S->getCond()); - Writer.AddStmt(S->getThen()); - Writer.AddStmt(S->getElse()); - Writer.AddSourceLocation(S->getIfLoc(), Record); - Writer.AddSourceLocation(S->getElseLoc(), Record); - Code = pch::STMT_IF; -} - -void PCHStmtWriter::VisitSwitchStmt(SwitchStmt *S) { - VisitStmt(S); - Writer.AddDeclRef(S->getConditionVariable(), Record); - Writer.AddStmt(S->getCond()); - Writer.AddStmt(S->getBody()); - Writer.AddSourceLocation(S->getSwitchLoc(), Record); - for (SwitchCase *SC = S->getSwitchCaseList(); SC; - SC = SC->getNextSwitchCase()) - Record.push_back(Writer.RecordSwitchCaseID(SC)); - Code = pch::STMT_SWITCH; -} - -void PCHStmtWriter::VisitWhileStmt(WhileStmt *S) { - VisitStmt(S); - Writer.AddDeclRef(S->getConditionVariable(), Record); - Writer.AddStmt(S->getCond()); - Writer.AddStmt(S->getBody()); - Writer.AddSourceLocation(S->getWhileLoc(), Record); - Code = pch::STMT_WHILE; -} - -void PCHStmtWriter::VisitDoStmt(DoStmt *S) { - VisitStmt(S); - Writer.AddStmt(S->getCond()); - Writer.AddStmt(S->getBody()); - Writer.AddSourceLocation(S->getDoLoc(), Record); - Writer.AddSourceLocation(S->getWhileLoc(), Record); - Writer.AddSourceLocation(S->getRParenLoc(), Record); - Code = pch::STMT_DO; -} - -void PCHStmtWriter::VisitForStmt(ForStmt *S) { - VisitStmt(S); - Writer.AddStmt(S->getInit()); - Writer.AddStmt(S->getCond()); - Writer.AddDeclRef(S->getConditionVariable(), Record); - Writer.AddStmt(S->getInc()); - Writer.AddStmt(S->getBody()); - Writer.AddSourceLocation(S->getForLoc(), Record); - Writer.AddSourceLocation(S->getLParenLoc(), Record); - Writer.AddSourceLocation(S->getRParenLoc(), Record); - Code = pch::STMT_FOR; -} - -void PCHStmtWriter::VisitGotoStmt(GotoStmt *S) { - VisitStmt(S); - Record.push_back(Writer.GetLabelID(S->getLabel())); - Writer.AddSourceLocation(S->getGotoLoc(), Record); - Writer.AddSourceLocation(S->getLabelLoc(), Record); - Code = pch::STMT_GOTO; -} - -void PCHStmtWriter::VisitIndirectGotoStmt(IndirectGotoStmt *S) { - VisitStmt(S); - Writer.AddSourceLocation(S->getGotoLoc(), Record); - Writer.AddSourceLocation(S->getStarLoc(), Record); - Writer.AddStmt(S->getTarget()); - Code = pch::STMT_INDIRECT_GOTO; -} - -void PCHStmtWriter::VisitContinueStmt(ContinueStmt *S) { - VisitStmt(S); - Writer.AddSourceLocation(S->getContinueLoc(), Record); - Code = pch::STMT_CONTINUE; -} - -void PCHStmtWriter::VisitBreakStmt(BreakStmt *S) { - VisitStmt(S); - Writer.AddSourceLocation(S->getBreakLoc(), Record); - Code = pch::STMT_BREAK; -} - -void PCHStmtWriter::VisitReturnStmt(ReturnStmt *S) { - VisitStmt(S); - Writer.AddStmt(S->getRetValue()); - Writer.AddSourceLocation(S->getReturnLoc(), Record); - Writer.AddDeclRef(S->getNRVOCandidate(), Record); - Code = pch::STMT_RETURN; -} - -void PCHStmtWriter::VisitDeclStmt(DeclStmt *S) { - VisitStmt(S); - Writer.AddSourceLocation(S->getStartLoc(), Record); - Writer.AddSourceLocation(S->getEndLoc(), Record); - DeclGroupRef DG = S->getDeclGroup(); - for (DeclGroupRef::iterator D = DG.begin(), DEnd = DG.end(); D != DEnd; ++D) - Writer.AddDeclRef(*D, Record); - Code = pch::STMT_DECL; -} - -void PCHStmtWriter::VisitAsmStmt(AsmStmt *S) { - VisitStmt(S); - Record.push_back(S->getNumOutputs()); - Record.push_back(S->getNumInputs()); - Record.push_back(S->getNumClobbers()); - Writer.AddSourceLocation(S->getAsmLoc(), Record); - Writer.AddSourceLocation(S->getRParenLoc(), Record); - Record.push_back(S->isVolatile()); - Record.push_back(S->isSimple()); - Record.push_back(S->isMSAsm()); - Writer.AddStmt(S->getAsmString()); - - // Outputs - for (unsigned I = 0, N = S->getNumOutputs(); I != N; ++I) { - Writer.AddIdentifierRef(S->getOutputIdentifier(I), Record); - Writer.AddStmt(S->getOutputConstraintLiteral(I)); - Writer.AddStmt(S->getOutputExpr(I)); - } - - // Inputs - for (unsigned I = 0, N = S->getNumInputs(); I != N; ++I) { - Writer.AddIdentifierRef(S->getInputIdentifier(I), Record); - Writer.AddStmt(S->getInputConstraintLiteral(I)); - Writer.AddStmt(S->getInputExpr(I)); - } - - // Clobbers - for (unsigned I = 0, N = S->getNumClobbers(); I != N; ++I) - Writer.AddStmt(S->getClobber(I)); - - Code = pch::STMT_ASM; -} - -void PCHStmtWriter::VisitExpr(Expr *E) { - VisitStmt(E); - Writer.AddTypeRef(E->getType(), Record); - Record.push_back(E->isTypeDependent()); - Record.push_back(E->isValueDependent()); -} - -void PCHStmtWriter::VisitPredefinedExpr(PredefinedExpr *E) { - VisitExpr(E); - Writer.AddSourceLocation(E->getLocation(), Record); - Record.push_back(E->getIdentType()); // FIXME: stable encoding - Code = pch::EXPR_PREDEFINED; -} - -void PCHStmtWriter::VisitDeclRefExpr(DeclRefExpr *E) { - VisitExpr(E); - - Record.push_back(E->hasQualifier()); - unsigned NumTemplateArgs = E->getNumTemplateArgs(); - assert((NumTemplateArgs != 0) == E->hasExplicitTemplateArgumentList() && - "Template args list with no args ?"); - Record.push_back(NumTemplateArgs); - - if (E->hasQualifier()) { - Writer.AddNestedNameSpecifier(E->getQualifier(), Record); - Writer.AddSourceRange(E->getQualifierRange(), Record); - } - - if (NumTemplateArgs) - AddExplicitTemplateArgumentList(*E->getExplicitTemplateArgumentList()); - - Writer.AddDeclRef(E->getDecl(), Record); - Writer.AddSourceLocation(E->getLocation(), Record); - Code = pch::EXPR_DECL_REF; -} - -void PCHStmtWriter::VisitIntegerLiteral(IntegerLiteral *E) { - VisitExpr(E); - Writer.AddSourceLocation(E->getLocation(), Record); - Writer.AddAPInt(E->getValue(), Record); - Code = pch::EXPR_INTEGER_LITERAL; -} - -void PCHStmtWriter::VisitFloatingLiteral(FloatingLiteral *E) { - VisitExpr(E); - Writer.AddAPFloat(E->getValue(), Record); - Record.push_back(E->isExact()); - Writer.AddSourceLocation(E->getLocation(), Record); - Code = pch::EXPR_FLOATING_LITERAL; -} - -void PCHStmtWriter::VisitImaginaryLiteral(ImaginaryLiteral *E) { - VisitExpr(E); - Writer.AddStmt(E->getSubExpr()); - Code = pch::EXPR_IMAGINARY_LITERAL; -} - -void PCHStmtWriter::VisitStringLiteral(StringLiteral *E) { - VisitExpr(E); - Record.push_back(E->getByteLength()); - Record.push_back(E->getNumConcatenated()); - Record.push_back(E->isWide()); - // FIXME: String data should be stored as a blob at the end of the - // StringLiteral. However, we can't do so now because we have no - // provision for coping with abbreviations when we're jumping around - // the PCH file during deserialization. - Record.insert(Record.end(), - E->getStrData(), E->getStrData() + E->getByteLength()); - for (unsigned I = 0, N = E->getNumConcatenated(); I != N; ++I) - Writer.AddSourceLocation(E->getStrTokenLoc(I), Record); - Code = pch::EXPR_STRING_LITERAL; -} - -void PCHStmtWriter::VisitCharacterLiteral(CharacterLiteral *E) { - VisitExpr(E); - Record.push_back(E->getValue()); - Writer.AddSourceLocation(E->getLocation(), Record); - Record.push_back(E->isWide()); - Code = pch::EXPR_CHARACTER_LITERAL; -} - -void PCHStmtWriter::VisitParenExpr(ParenExpr *E) { - VisitExpr(E); - Writer.AddSourceLocation(E->getLParen(), Record); - Writer.AddSourceLocation(E->getRParen(), Record); - Writer.AddStmt(E->getSubExpr()); - Code = pch::EXPR_PAREN; -} - -void PCHStmtWriter::VisitParenListExpr(ParenListExpr *E) { - VisitExpr(E); - Record.push_back(E->NumExprs); - for (unsigned i=0; i != E->NumExprs; ++i) - Writer.AddStmt(E->Exprs[i]); - Writer.AddSourceLocation(E->LParenLoc, Record); - Writer.AddSourceLocation(E->RParenLoc, Record); - Code = pch::EXPR_PAREN_LIST; -} - -void PCHStmtWriter::VisitUnaryOperator(UnaryOperator *E) { - VisitExpr(E); - Writer.AddStmt(E->getSubExpr()); - Record.push_back(E->getOpcode()); // FIXME: stable encoding - Writer.AddSourceLocation(E->getOperatorLoc(), Record); - Code = pch::EXPR_UNARY_OPERATOR; -} - -void PCHStmtWriter::VisitOffsetOfExpr(OffsetOfExpr *E) { - VisitExpr(E); - Record.push_back(E->getNumComponents()); - Record.push_back(E->getNumExpressions()); - Writer.AddSourceLocation(E->getOperatorLoc(), Record); - Writer.AddSourceLocation(E->getRParenLoc(), Record); - Writer.AddTypeSourceInfo(E->getTypeSourceInfo(), Record); - for (unsigned I = 0, N = E->getNumComponents(); I != N; ++I) { - const OffsetOfExpr::OffsetOfNode &ON = E->getComponent(I); - Record.push_back(ON.getKind()); // FIXME: Stable encoding - Writer.AddSourceLocation(ON.getRange().getBegin(), Record); - Writer.AddSourceLocation(ON.getRange().getEnd(), Record); - switch (ON.getKind()) { - case OffsetOfExpr::OffsetOfNode::Array: - Record.push_back(ON.getArrayExprIndex()); - break; - - case OffsetOfExpr::OffsetOfNode::Field: - Writer.AddDeclRef(ON.getField(), Record); - break; - - case OffsetOfExpr::OffsetOfNode::Identifier: - Writer.AddIdentifierRef(ON.getFieldName(), Record); - break; - - case OffsetOfExpr::OffsetOfNode::Base: - // FIXME: Implement this! - llvm_unreachable("PCH for offsetof(base-specifier) not implemented"); - break; - } - } - for (unsigned I = 0, N = E->getNumExpressions(); I != N; ++I) - Writer.AddStmt(E->getIndexExpr(I)); - Code = pch::EXPR_OFFSETOF; -} - -void PCHStmtWriter::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) { - VisitExpr(E); - Record.push_back(E->isSizeOf()); - if (E->isArgumentType()) - Writer.AddTypeSourceInfo(E->getArgumentTypeInfo(), Record); - else { - Record.push_back(0); - Writer.AddStmt(E->getArgumentExpr()); - } - Writer.AddSourceLocation(E->getOperatorLoc(), Record); - Writer.AddSourceLocation(E->getRParenLoc(), Record); - Code = pch::EXPR_SIZEOF_ALIGN_OF; -} - -void PCHStmtWriter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) { - VisitExpr(E); - Writer.AddStmt(E->getLHS()); - Writer.AddStmt(E->getRHS()); - Writer.AddSourceLocation(E->getRBracketLoc(), Record); - Code = pch::EXPR_ARRAY_SUBSCRIPT; -} - -void PCHStmtWriter::VisitCallExpr(CallExpr *E) { - VisitExpr(E); - Record.push_back(E->getNumArgs()); - Writer.AddSourceLocation(E->getRParenLoc(), Record); - Writer.AddStmt(E->getCallee()); - for (CallExpr::arg_iterator Arg = E->arg_begin(), ArgEnd = E->arg_end(); - Arg != ArgEnd; ++Arg) - Writer.AddStmt(*Arg); - Code = pch::EXPR_CALL; -} - -void PCHStmtWriter::VisitMemberExpr(MemberExpr *E) { - // Don't call VisitExpr, we'll write everything here. - - Record.push_back(E->hasQualifier()); - if (E->hasQualifier()) { - Writer.AddNestedNameSpecifier(E->getQualifier(), Record); - Writer.AddSourceRange(E->getQualifierRange(), Record); - } - - unsigned NumTemplateArgs = E->getNumTemplateArgs(); - assert((NumTemplateArgs != 0) == E->hasExplicitTemplateArgumentList() && - "Template args list with no args ?"); - Record.push_back(NumTemplateArgs); - if (NumTemplateArgs) { - Writer.AddSourceLocation(E->getLAngleLoc(), Record); - Writer.AddSourceLocation(E->getRAngleLoc(), Record); - for (unsigned i=0; i != NumTemplateArgs; ++i) - Writer.AddTemplateArgumentLoc(E->getTemplateArgs()[i], Record); - } - - DeclAccessPair FoundDecl = E->getFoundDecl(); - Writer.AddDeclRef(FoundDecl.getDecl(), Record); - Record.push_back(FoundDecl.getAccess()); - - Writer.AddTypeRef(E->getType(), Record); - Writer.AddStmt(E->getBase()); - Writer.AddDeclRef(E->getMemberDecl(), Record); - Writer.AddSourceLocation(E->getMemberLoc(), Record); - Record.push_back(E->isArrow()); - Code = pch::EXPR_MEMBER; -} - -void PCHStmtWriter::VisitObjCIsaExpr(ObjCIsaExpr *E) { - VisitExpr(E); - Writer.AddStmt(E->getBase()); - Writer.AddSourceLocation(E->getIsaMemberLoc(), Record); - Record.push_back(E->isArrow()); - Code = pch::EXPR_OBJC_ISA; -} - -void PCHStmtWriter::VisitCastExpr(CastExpr *E) { - VisitExpr(E); - Writer.AddStmt(E->getSubExpr()); - Record.push_back(E->getCastKind()); // FIXME: stable encoding - CXXBaseSpecifierArray &BasePath = E->getBasePath(); - Record.push_back(BasePath.size()); - for (CXXBaseSpecifierArray::iterator I = BasePath.begin(), E = BasePath.end(); - I != E; ++I) - Writer.AddCXXBaseSpecifier(**I, Record); -} - -void PCHStmtWriter::VisitBinaryOperator(BinaryOperator *E) { - VisitExpr(E); - Writer.AddStmt(E->getLHS()); - Writer.AddStmt(E->getRHS()); - Record.push_back(E->getOpcode()); // FIXME: stable encoding - Writer.AddSourceLocation(E->getOperatorLoc(), Record); - Code = pch::EXPR_BINARY_OPERATOR; -} - -void PCHStmtWriter::VisitCompoundAssignOperator(CompoundAssignOperator *E) { - VisitBinaryOperator(E); - Writer.AddTypeRef(E->getComputationLHSType(), Record); - Writer.AddTypeRef(E->getComputationResultType(), Record); - Code = pch::EXPR_COMPOUND_ASSIGN_OPERATOR; -} - -void PCHStmtWriter::VisitConditionalOperator(ConditionalOperator *E) { - VisitExpr(E); - Writer.AddStmt(E->getCond()); - Writer.AddStmt(E->getLHS()); - Writer.AddStmt(E->getRHS()); - Writer.AddSourceLocation(E->getQuestionLoc(), Record); - Writer.AddSourceLocation(E->getColonLoc(), Record); - Code = pch::EXPR_CONDITIONAL_OPERATOR; -} - -void PCHStmtWriter::VisitImplicitCastExpr(ImplicitCastExpr *E) { - VisitCastExpr(E); - Record.push_back(E->isLvalueCast()); - Code = pch::EXPR_IMPLICIT_CAST; -} - -void PCHStmtWriter::VisitExplicitCastExpr(ExplicitCastExpr *E) { - VisitCastExpr(E); - Writer.AddTypeSourceInfo(E->getTypeInfoAsWritten(), Record); -} - -void PCHStmtWriter::VisitCStyleCastExpr(CStyleCastExpr *E) { - VisitExplicitCastExpr(E); - Writer.AddSourceLocation(E->getLParenLoc(), Record); - Writer.AddSourceLocation(E->getRParenLoc(), Record); - Code = pch::EXPR_CSTYLE_CAST; -} - -void PCHStmtWriter::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) { - VisitExpr(E); - Writer.AddSourceLocation(E->getLParenLoc(), Record); - Writer.AddTypeSourceInfo(E->getTypeSourceInfo(), Record); - Writer.AddStmt(E->getInitializer()); - Record.push_back(E->isFileScope()); - Code = pch::EXPR_COMPOUND_LITERAL; -} - -void PCHStmtWriter::VisitExtVectorElementExpr(ExtVectorElementExpr *E) { - VisitExpr(E); - Writer.AddStmt(E->getBase()); - Writer.AddIdentifierRef(&E->getAccessor(), Record); - Writer.AddSourceLocation(E->getAccessorLoc(), Record); - Code = pch::EXPR_EXT_VECTOR_ELEMENT; -} - -void PCHStmtWriter::VisitInitListExpr(InitListExpr *E) { - VisitExpr(E); - Record.push_back(E->getNumInits()); - for (unsigned I = 0, N = E->getNumInits(); I != N; ++I) - Writer.AddStmt(E->getInit(I)); - Writer.AddStmt(E->getSyntacticForm()); - Writer.AddSourceLocation(E->getLBraceLoc(), Record); - Writer.AddSourceLocation(E->getRBraceLoc(), Record); - Writer.AddDeclRef(E->getInitializedFieldInUnion(), Record); - Record.push_back(E->hadArrayRangeDesignator()); - Code = pch::EXPR_INIT_LIST; -} - -void PCHStmtWriter::VisitDesignatedInitExpr(DesignatedInitExpr *E) { - VisitExpr(E); - Record.push_back(E->getNumSubExprs()); - for (unsigned I = 0, N = E->getNumSubExprs(); I != N; ++I) - Writer.AddStmt(E->getSubExpr(I)); - Writer.AddSourceLocation(E->getEqualOrColonLoc(), Record); - Record.push_back(E->usesGNUSyntax()); - for (DesignatedInitExpr::designators_iterator D = E->designators_begin(), - DEnd = E->designators_end(); - D != DEnd; ++D) { - if (D->isFieldDesignator()) { - if (FieldDecl *Field = D->getField()) { - Record.push_back(pch::DESIG_FIELD_DECL); - Writer.AddDeclRef(Field, Record); - } else { - Record.push_back(pch::DESIG_FIELD_NAME); - Writer.AddIdentifierRef(D->getFieldName(), Record); - } - Writer.AddSourceLocation(D->getDotLoc(), Record); - Writer.AddSourceLocation(D->getFieldLoc(), Record); - } else if (D->isArrayDesignator()) { - Record.push_back(pch::DESIG_ARRAY); - Record.push_back(D->getFirstExprIndex()); - Writer.AddSourceLocation(D->getLBracketLoc(), Record); - Writer.AddSourceLocation(D->getRBracketLoc(), Record); - } else { - assert(D->isArrayRangeDesignator() && "Unknown designator"); - Record.push_back(pch::DESIG_ARRAY_RANGE); - Record.push_back(D->getFirstExprIndex()); - Writer.AddSourceLocation(D->getLBracketLoc(), Record); - Writer.AddSourceLocation(D->getEllipsisLoc(), Record); - Writer.AddSourceLocation(D->getRBracketLoc(), Record); - } - } - Code = pch::EXPR_DESIGNATED_INIT; -} - -void PCHStmtWriter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) { - VisitExpr(E); - Code = pch::EXPR_IMPLICIT_VALUE_INIT; -} - -void PCHStmtWriter::VisitVAArgExpr(VAArgExpr *E) { - VisitExpr(E); - Writer.AddStmt(E->getSubExpr()); - Writer.AddSourceLocation(E->getBuiltinLoc(), Record); - Writer.AddSourceLocation(E->getRParenLoc(), Record); - Code = pch::EXPR_VA_ARG; -} - -void PCHStmtWriter::VisitAddrLabelExpr(AddrLabelExpr *E) { - VisitExpr(E); - Writer.AddSourceLocation(E->getAmpAmpLoc(), Record); - Writer.AddSourceLocation(E->getLabelLoc(), Record); - Record.push_back(Writer.GetLabelID(E->getLabel())); - Code = pch::EXPR_ADDR_LABEL; -} - -void PCHStmtWriter::VisitStmtExpr(StmtExpr *E) { - VisitExpr(E); - Writer.AddStmt(E->getSubStmt()); - Writer.AddSourceLocation(E->getLParenLoc(), Record); - Writer.AddSourceLocation(E->getRParenLoc(), Record); - Code = pch::EXPR_STMT; -} - -void PCHStmtWriter::VisitTypesCompatibleExpr(TypesCompatibleExpr *E) { - VisitExpr(E); - Writer.AddTypeRef(E->getArgType1(), Record); - Writer.AddTypeRef(E->getArgType2(), Record); - Writer.AddSourceLocation(E->getBuiltinLoc(), Record); - Writer.AddSourceLocation(E->getRParenLoc(), Record); - Code = pch::EXPR_TYPES_COMPATIBLE; -} - -void PCHStmtWriter::VisitChooseExpr(ChooseExpr *E) { - VisitExpr(E); - Writer.AddStmt(E->getCond()); - Writer.AddStmt(E->getLHS()); - Writer.AddStmt(E->getRHS()); - Writer.AddSourceLocation(E->getBuiltinLoc(), Record); - Writer.AddSourceLocation(E->getRParenLoc(), Record); - Code = pch::EXPR_CHOOSE; -} - -void PCHStmtWriter::VisitGNUNullExpr(GNUNullExpr *E) { - VisitExpr(E); - Writer.AddSourceLocation(E->getTokenLocation(), Record); - Code = pch::EXPR_GNU_NULL; -} - -void PCHStmtWriter::VisitShuffleVectorExpr(ShuffleVectorExpr *E) { - VisitExpr(E); - Record.push_back(E->getNumSubExprs()); - for (unsigned I = 0, N = E->getNumSubExprs(); I != N; ++I) - Writer.AddStmt(E->getExpr(I)); - Writer.AddSourceLocation(E->getBuiltinLoc(), Record); - Writer.AddSourceLocation(E->getRParenLoc(), Record); - Code = pch::EXPR_SHUFFLE_VECTOR; -} - -void PCHStmtWriter::VisitBlockExpr(BlockExpr *E) { - VisitExpr(E); - Writer.AddDeclRef(E->getBlockDecl(), Record); - Record.push_back(E->hasBlockDeclRefExprs()); - Code = pch::EXPR_BLOCK; -} - -void PCHStmtWriter::VisitBlockDeclRefExpr(BlockDeclRefExpr *E) { - VisitExpr(E); - Writer.AddDeclRef(E->getDecl(), Record); - Writer.AddSourceLocation(E->getLocation(), Record); - Record.push_back(E->isByRef()); - Record.push_back(E->isConstQualAdded()); - Writer.AddStmt(E->getCopyConstructorExpr()); - Code = pch::EXPR_BLOCK_DECL_REF; -} - -//===----------------------------------------------------------------------===// -// Objective-C Expressions and Statements. -//===----------------------------------------------------------------------===// - -void PCHStmtWriter::VisitObjCStringLiteral(ObjCStringLiteral *E) { - VisitExpr(E); - Writer.AddStmt(E->getString()); - Writer.AddSourceLocation(E->getAtLoc(), Record); - Code = pch::EXPR_OBJC_STRING_LITERAL; -} - -void PCHStmtWriter::VisitObjCEncodeExpr(ObjCEncodeExpr *E) { - VisitExpr(E); - Writer.AddTypeSourceInfo(E->getEncodedTypeSourceInfo(), Record); - Writer.AddSourceLocation(E->getAtLoc(), Record); - Writer.AddSourceLocation(E->getRParenLoc(), Record); - Code = pch::EXPR_OBJC_ENCODE; -} - -void PCHStmtWriter::VisitObjCSelectorExpr(ObjCSelectorExpr *E) { - VisitExpr(E); - Writer.AddSelectorRef(E->getSelector(), Record); - Writer.AddSourceLocation(E->getAtLoc(), Record); - Writer.AddSourceLocation(E->getRParenLoc(), Record); - Code = pch::EXPR_OBJC_SELECTOR_EXPR; -} - -void PCHStmtWriter::VisitObjCProtocolExpr(ObjCProtocolExpr *E) { - VisitExpr(E); - Writer.AddDeclRef(E->getProtocol(), Record); - Writer.AddSourceLocation(E->getAtLoc(), Record); - Writer.AddSourceLocation(E->getRParenLoc(), Record); - Code = pch::EXPR_OBJC_PROTOCOL_EXPR; -} - -void PCHStmtWriter::VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) { - VisitExpr(E); - Writer.AddDeclRef(E->getDecl(), Record); - Writer.AddSourceLocation(E->getLocation(), Record); - Writer.AddStmt(E->getBase()); - Record.push_back(E->isArrow()); - Record.push_back(E->isFreeIvar()); - Code = pch::EXPR_OBJC_IVAR_REF_EXPR; -} - -void PCHStmtWriter::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { - VisitExpr(E); - Writer.AddDeclRef(E->getProperty(), Record); - Writer.AddSourceLocation(E->getLocation(), Record); - Writer.AddStmt(E->getBase()); - Code = pch::EXPR_OBJC_PROPERTY_REF_EXPR; -} - -void PCHStmtWriter::VisitObjCImplicitSetterGetterRefExpr( - ObjCImplicitSetterGetterRefExpr *E) { - VisitExpr(E); - Writer.AddDeclRef(E->getGetterMethod(), Record); - Writer.AddDeclRef(E->getSetterMethod(), Record); - - // NOTE: InterfaceDecl and Base are mutually exclusive. - Writer.AddDeclRef(E->getInterfaceDecl(), Record); - Writer.AddStmt(E->getBase()); - Writer.AddSourceLocation(E->getLocation(), Record); - Writer.AddSourceLocation(E->getClassLoc(), Record); - Code = pch::EXPR_OBJC_KVC_REF_EXPR; -} - -void PCHStmtWriter::VisitObjCMessageExpr(ObjCMessageExpr *E) { - VisitExpr(E); - Record.push_back(E->getNumArgs()); - Record.push_back((unsigned)E->getReceiverKind()); // FIXME: stable encoding - switch (E->getReceiverKind()) { - case ObjCMessageExpr::Instance: - Writer.AddStmt(E->getInstanceReceiver()); - break; - - case ObjCMessageExpr::Class: - Writer.AddTypeSourceInfo(E->getClassReceiverTypeInfo(), Record); - break; - - case ObjCMessageExpr::SuperClass: - case ObjCMessageExpr::SuperInstance: - Writer.AddTypeRef(E->getSuperType(), Record); - Writer.AddSourceLocation(E->getSuperLoc(), Record); - break; - } - - if (E->getMethodDecl()) { - Record.push_back(1); - Writer.AddDeclRef(E->getMethodDecl(), Record); - } else { - Record.push_back(0); - Writer.AddSelectorRef(E->getSelector(), Record); - } - - Writer.AddSourceLocation(E->getLeftLoc(), Record); - Writer.AddSourceLocation(E->getRightLoc(), Record); - - for (CallExpr::arg_iterator Arg = E->arg_begin(), ArgEnd = E->arg_end(); - Arg != ArgEnd; ++Arg) - Writer.AddStmt(*Arg); - Code = pch::EXPR_OBJC_MESSAGE_EXPR; -} - -void PCHStmtWriter::VisitObjCSuperExpr(ObjCSuperExpr *E) { - VisitExpr(E); - Writer.AddSourceLocation(E->getLoc(), Record); - Code = pch::EXPR_OBJC_SUPER_EXPR; -} - -void PCHStmtWriter::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) { - VisitStmt(S); - Writer.AddStmt(S->getElement()); - Writer.AddStmt(S->getCollection()); - Writer.AddStmt(S->getBody()); - Writer.AddSourceLocation(S->getForLoc(), Record); - Writer.AddSourceLocation(S->getRParenLoc(), Record); - Code = pch::STMT_OBJC_FOR_COLLECTION; -} - -void PCHStmtWriter::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) { - Writer.AddStmt(S->getCatchBody()); - Writer.AddDeclRef(S->getCatchParamDecl(), Record); - Writer.AddSourceLocation(S->getAtCatchLoc(), Record); - Writer.AddSourceLocation(S->getRParenLoc(), Record); - Code = pch::STMT_OBJC_CATCH; -} - -void PCHStmtWriter::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S) { - Writer.AddStmt(S->getFinallyBody()); - Writer.AddSourceLocation(S->getAtFinallyLoc(), Record); - Code = pch::STMT_OBJC_FINALLY; -} - -void PCHStmtWriter::VisitObjCAtTryStmt(ObjCAtTryStmt *S) { - Record.push_back(S->getNumCatchStmts()); - Record.push_back(S->getFinallyStmt() != 0); - Writer.AddStmt(S->getTryBody()); - for (unsigned I = 0, N = S->getNumCatchStmts(); I != N; ++I) - Writer.AddStmt(S->getCatchStmt(I)); - if (S->getFinallyStmt()) - Writer.AddStmt(S->getFinallyStmt()); - Writer.AddSourceLocation(S->getAtTryLoc(), Record); - Code = pch::STMT_OBJC_AT_TRY; -} - -void PCHStmtWriter::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S) { - Writer.AddStmt(S->getSynchExpr()); - Writer.AddStmt(S->getSynchBody()); - Writer.AddSourceLocation(S->getAtSynchronizedLoc(), Record); - Code = pch::STMT_OBJC_AT_SYNCHRONIZED; -} - -void PCHStmtWriter::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) { - Writer.AddStmt(S->getThrowExpr()); - Writer.AddSourceLocation(S->getThrowLoc(), Record); - Code = pch::STMT_OBJC_AT_THROW; -} - -//===----------------------------------------------------------------------===// -// C++ Expressions and Statements. -//===----------------------------------------------------------------------===// - -void PCHStmtWriter::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) { - VisitCallExpr(E); - Record.push_back(E->getOperator()); - Code = pch::EXPR_CXX_OPERATOR_CALL; -} - -void PCHStmtWriter::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) { - VisitCallExpr(E); - Code = pch::EXPR_CXX_MEMBER_CALL; -} - -void PCHStmtWriter::VisitCXXConstructExpr(CXXConstructExpr *E) { - VisitExpr(E); - Record.push_back(E->getNumArgs()); - for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) - Writer.AddStmt(E->getArg(I)); - Writer.AddDeclRef(E->getConstructor(), Record); - Writer.AddSourceLocation(E->getLocation(), Record); - Record.push_back(E->isElidable()); - Record.push_back(E->requiresZeroInitialization()); - Record.push_back(E->getConstructionKind()); // FIXME: stable encoding - Code = pch::EXPR_CXX_CONSTRUCT; -} - -void PCHStmtWriter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E) { - VisitCXXConstructExpr(E); - Writer.AddSourceLocation(E->getTypeBeginLoc(), Record); - Writer.AddSourceLocation(E->getRParenLoc(), Record); - Code = pch::EXPR_CXX_TEMPORARY_OBJECT; -} - -void PCHStmtWriter::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) { - VisitExplicitCastExpr(E); - Writer.AddSourceLocation(E->getOperatorLoc(), Record); -} - -void PCHStmtWriter::VisitCXXStaticCastExpr(CXXStaticCastExpr *E) { - VisitCXXNamedCastExpr(E); - Code = pch::EXPR_CXX_STATIC_CAST; -} - -void PCHStmtWriter::VisitCXXDynamicCastExpr(CXXDynamicCastExpr *E) { - VisitCXXNamedCastExpr(E); - Code = pch::EXPR_CXX_DYNAMIC_CAST; -} - -void PCHStmtWriter::VisitCXXReinterpretCastExpr(CXXReinterpretCastExpr *E) { - VisitCXXNamedCastExpr(E); - Code = pch::EXPR_CXX_REINTERPRET_CAST; -} - -void PCHStmtWriter::VisitCXXConstCastExpr(CXXConstCastExpr *E) { - VisitCXXNamedCastExpr(E); - Code = pch::EXPR_CXX_CONST_CAST; -} - -void PCHStmtWriter::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E) { - VisitExplicitCastExpr(E); - Writer.AddSourceLocation(E->getTypeBeginLoc(), Record); - Writer.AddSourceLocation(E->getRParenLoc(), Record); - Code = pch::EXPR_CXX_FUNCTIONAL_CAST; -} - -void PCHStmtWriter::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) { - VisitExpr(E); - Record.push_back(E->getValue()); - Writer.AddSourceLocation(E->getLocation(), Record); - Code = pch::EXPR_CXX_BOOL_LITERAL; -} - -void PCHStmtWriter::VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E) { - VisitExpr(E); - Writer.AddSourceLocation(E->getLocation(), Record); - Code = pch::EXPR_CXX_NULL_PTR_LITERAL; -} - -void PCHStmtWriter::VisitCXXTypeidExpr(CXXTypeidExpr *E) { - VisitExpr(E); - Writer.AddSourceRange(E->getSourceRange(), Record); - if (E->isTypeOperand()) { - Writer.AddTypeSourceInfo(E->getTypeOperandSourceInfo(), Record); - Code = pch::EXPR_CXX_TYPEID_TYPE; - } else { - Writer.AddStmt(E->getExprOperand()); - Code = pch::EXPR_CXX_TYPEID_EXPR; - } -} - -void PCHStmtWriter::VisitCXXThisExpr(CXXThisExpr *E) { - VisitExpr(E); - Writer.AddSourceLocation(E->getLocation(), Record); - Record.push_back(E->isImplicit()); - Code = pch::EXPR_CXX_THIS; -} - -void PCHStmtWriter::VisitCXXThrowExpr(CXXThrowExpr *E) { - VisitExpr(E); - Writer.AddSourceLocation(E->getThrowLoc(), Record); - Writer.AddStmt(E->getSubExpr()); - Code = pch::EXPR_CXX_THROW; -} - -void PCHStmtWriter::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { - VisitExpr(E); - - bool HasOtherExprStored = E->Param.getInt(); - // Store these first, the reader reads them before creation. - Record.push_back(HasOtherExprStored); - if (HasOtherExprStored) - Writer.AddStmt(E->getExpr()); - Writer.AddDeclRef(E->getParam(), Record); - Writer.AddSourceLocation(E->getUsedLocation(), Record); - - Code = pch::EXPR_CXX_DEFAULT_ARG; -} - -void PCHStmtWriter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) { - VisitExpr(E); - Writer.AddCXXTemporary(E->getTemporary(), Record); - Writer.AddStmt(E->getSubExpr()); - Code = pch::EXPR_CXX_BIND_TEMPORARY; -} - -void PCHStmtWriter::VisitCXXBindReferenceExpr(CXXBindReferenceExpr *E) { - VisitExpr(E); - Writer.AddStmt(E->getSubExpr()); - Record.push_back(E->extendsLifetime()); - Record.push_back(E->requiresTemporaryCopy()); - Code = pch::EXPR_CXX_BIND_REFERENCE; -} - -void PCHStmtWriter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) { - VisitExpr(E); - Writer.AddSourceLocation(E->getTypeBeginLoc(), Record); - Writer.AddSourceLocation(E->getRParenLoc(), Record); - Code = pch::EXPR_CXX_SCALAR_VALUE_INIT; -} - -void PCHStmtWriter::VisitCXXNewExpr(CXXNewExpr *E) { - VisitExpr(E); - Record.push_back(E->isGlobalNew()); - Record.push_back(E->hasInitializer()); - Record.push_back(E->isArray()); - Record.push_back(E->getNumPlacementArgs()); - Record.push_back(E->getNumConstructorArgs()); - Writer.AddDeclRef(E->getOperatorNew(), Record); - Writer.AddDeclRef(E->getOperatorDelete(), Record); - Writer.AddDeclRef(E->getConstructor(), Record); - Writer.AddSourceRange(E->getTypeIdParens(), Record); - Writer.AddSourceLocation(E->getStartLoc(), Record); - Writer.AddSourceLocation(E->getEndLoc(), Record); - for (CXXNewExpr::arg_iterator I = E->raw_arg_begin(), e = E->raw_arg_end(); - I != e; ++I) - Writer.AddStmt(*I); - - Code = pch::EXPR_CXX_NEW; -} - -void PCHStmtWriter::VisitCXXDeleteExpr(CXXDeleteExpr *E) { - VisitExpr(E); - Record.push_back(E->isGlobalDelete()); - Record.push_back(E->isArrayForm()); - Writer.AddDeclRef(E->getOperatorDelete(), Record); - Writer.AddStmt(E->getArgument()); - Writer.AddSourceLocation(E->getSourceRange().getBegin(), Record); - - Code = pch::EXPR_CXX_DELETE; -} - -void PCHStmtWriter::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) { - VisitExpr(E); - - Writer.AddStmt(E->getBase()); - Record.push_back(E->isArrow()); - Writer.AddSourceLocation(E->getOperatorLoc(), Record); - Writer.AddNestedNameSpecifier(E->getQualifier(), Record); - Writer.AddSourceRange(E->getQualifierRange(), Record); - Writer.AddTypeSourceInfo(E->getScopeTypeInfo(), Record); - Writer.AddSourceLocation(E->getColonColonLoc(), Record); - Writer.AddSourceLocation(E->getTildeLoc(), Record); - - // PseudoDestructorTypeStorage. - Writer.AddIdentifierRef(E->getDestroyedTypeIdentifier(), Record); - if (E->getDestroyedTypeIdentifier()) - Writer.AddSourceLocation(E->getDestroyedTypeLoc(), Record); - else - Writer.AddTypeSourceInfo(E->getDestroyedTypeInfo(), Record); - - Code = pch::EXPR_CXX_PSEUDO_DESTRUCTOR; -} - -void PCHStmtWriter::VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E) { - VisitExpr(E); - Record.push_back(E->getNumTemporaries()); - for (unsigned i = 0, e = E->getNumTemporaries(); i != e; ++i) - Writer.AddCXXTemporary(E->getTemporary(i), Record); - - Writer.AddStmt(E->getSubExpr()); - Code = pch::EXPR_CXX_EXPR_WITH_TEMPORARIES; -} - -void -PCHStmtWriter::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E){ - VisitExpr(E); - - // Don't emit anything here, NumTemplateArgs must be emitted first. - - if (E->hasExplicitTemplateArgs()) { - const ExplicitTemplateArgumentList &Args - = *E->getExplicitTemplateArgumentList(); - assert(Args.NumTemplateArgs && - "Num of template args was zero! PCH reading will mess up!"); - Record.push_back(Args.NumTemplateArgs); - AddExplicitTemplateArgumentList(Args); - } else { - Record.push_back(0); - } - - if (!E->isImplicitAccess()) - Writer.AddStmt(E->getBase()); - else - Writer.AddStmt(0); - Writer.AddTypeRef(E->getBaseType(), Record); - Record.push_back(E->isArrow()); - Writer.AddSourceLocation(E->getOperatorLoc(), Record); - Writer.AddNestedNameSpecifier(E->getQualifier(), Record); - Writer.AddSourceRange(E->getQualifierRange(), Record); - Writer.AddDeclRef(E->getFirstQualifierFoundInScope(), Record); - Writer.AddDeclarationName(E->getMember(), Record); - Writer.AddSourceLocation(E->getMemberLoc(), Record); - Code = pch::EXPR_CXX_DEPENDENT_SCOPE_MEMBER; -} - -void -PCHStmtWriter::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) { - VisitExpr(E); - - // Don't emit anything here, NumTemplateArgs must be emitted first. - - if (E->hasExplicitTemplateArgs()) { - const ExplicitTemplateArgumentList &Args = E->getExplicitTemplateArgs(); - assert(Args.NumTemplateArgs && - "Num of template args was zero! PCH reading will mess up!"); - Record.push_back(Args.NumTemplateArgs); - AddExplicitTemplateArgumentList(Args); - } else { - Record.push_back(0); - } - - Writer.AddDeclarationName(E->getDeclName(), Record); - Writer.AddSourceLocation(E->getLocation(), Record); - Writer.AddSourceRange(E->getQualifierRange(), Record); - Writer.AddNestedNameSpecifier(E->getQualifier(), Record); - Code = pch::EXPR_CXX_DEPENDENT_SCOPE_DECL_REF; -} - -void -PCHStmtWriter::VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E) { - VisitExpr(E); - Record.push_back(E->arg_size()); - for (CXXUnresolvedConstructExpr::arg_iterator - ArgI = E->arg_begin(), ArgE = E->arg_end(); ArgI != ArgE; ++ArgI) - Writer.AddStmt(*ArgI); - Writer.AddSourceLocation(E->getTypeBeginLoc(), Record); - Writer.AddTypeRef(E->getTypeAsWritten(), Record); - Writer.AddSourceLocation(E->getLParenLoc(), Record); - Writer.AddSourceLocation(E->getRParenLoc(), Record); - Code = pch::EXPR_CXX_UNRESOLVED_CONSTRUCT; -} - -void PCHStmtWriter::VisitOverloadExpr(OverloadExpr *E) { - VisitExpr(E); - - // Don't emit anything here, NumTemplateArgs must be emitted first. - - if (E->hasExplicitTemplateArgs()) { - const ExplicitTemplateArgumentList &Args = E->getExplicitTemplateArgs(); - assert(Args.NumTemplateArgs && - "Num of template args was zero! PCH reading will mess up!"); - Record.push_back(Args.NumTemplateArgs); - AddExplicitTemplateArgumentList(Args); - } else { - Record.push_back(0); - } - - Record.push_back(E->getNumDecls()); - for (OverloadExpr::decls_iterator - OvI = E->decls_begin(), OvE = E->decls_end(); OvI != OvE; ++OvI) { - Writer.AddDeclRef(OvI.getDecl(), Record); - Record.push_back(OvI.getAccess()); - } - - Writer.AddDeclarationName(E->getName(), Record); - Writer.AddNestedNameSpecifier(E->getQualifier(), Record); - Writer.AddSourceRange(E->getQualifierRange(), Record); - Writer.AddSourceLocation(E->getNameLoc(), Record); -} - -void PCHStmtWriter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) { - VisitOverloadExpr(E); - Record.push_back(E->isArrow()); - Record.push_back(E->hasUnresolvedUsing()); - Writer.AddStmt(!E->isImplicitAccess() ? E->getBase() : 0); - Writer.AddTypeRef(E->getBaseType(), Record); - Writer.AddSourceLocation(E->getOperatorLoc(), Record); - Code = pch::EXPR_CXX_UNRESOLVED_MEMBER; -} - -void PCHStmtWriter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) { - VisitOverloadExpr(E); - Record.push_back(E->requiresADL()); - Record.push_back(E->isOverloaded()); - Writer.AddDeclRef(E->getNamingClass(), Record); - Code = pch::EXPR_CXX_UNRESOLVED_LOOKUP; -} - -void PCHStmtWriter::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) { - VisitExpr(E); - Record.push_back(E->getTrait()); - Writer.AddSourceRange(E->getSourceRange(), Record); - Writer.AddTypeRef(E->getQueriedType(), Record); - Code = pch::EXPR_CXX_UNARY_TYPE_TRAIT; -} - -//===----------------------------------------------------------------------===// -// PCHWriter Implementation -//===----------------------------------------------------------------------===// - -unsigned PCHWriter::RecordSwitchCaseID(SwitchCase *S) { - assert(SwitchCaseIDs.find(S) == SwitchCaseIDs.end() && - "SwitchCase recorded twice"); - unsigned NextID = SwitchCaseIDs.size(); - SwitchCaseIDs[S] = NextID; - return NextID; -} - -unsigned PCHWriter::getSwitchCaseID(SwitchCase *S) { - assert(SwitchCaseIDs.find(S) != SwitchCaseIDs.end() && - "SwitchCase hasn't been seen yet"); - return SwitchCaseIDs[S]; -} - -/// \brief Retrieve the ID for the given label statement, which may -/// or may not have been emitted yet. -unsigned PCHWriter::GetLabelID(LabelStmt *S) { - std::map<LabelStmt *, unsigned>::iterator Pos = LabelIDs.find(S); - if (Pos != LabelIDs.end()) - return Pos->second; - - unsigned NextID = LabelIDs.size(); - LabelIDs[S] = NextID; - return NextID; -} - -/// \brief Write the given substatement or subexpression to the -/// bitstream. -void PCHWriter::WriteSubStmt(Stmt *S) { - RecordData Record; - PCHStmtWriter Writer(*this, Record); - ++NumStatements; - - if (!S) { - Stream.EmitRecord(pch::STMT_NULL_PTR, Record); - return; - } - - // Redirect PCHWriter::AddStmt to collect sub stmts. - llvm::SmallVector<Stmt *, 16> SubStmts; - CollectedStmts = &SubStmts; - - Writer.Code = pch::STMT_NULL_PTR; - Writer.Visit(S); - -#ifndef NDEBUG - if (Writer.Code == pch::STMT_NULL_PTR) { - SourceManager &SrcMgr - = DeclIDs.begin()->first->getASTContext().getSourceManager(); - S->dump(SrcMgr); - assert(0 && "Unhandled sub statement writing PCH file"); - } -#endif - - // Revert PCHWriter::AddStmt. - CollectedStmts = &StmtsToEmit; - - // Write the sub stmts in reverse order, last to first. When reading them back - // we will read them in correct order by "pop"ing them from the Stmts stack. - // This simplifies reading and allows to store a variable number of sub stmts - // without knowing it in advance. - while (!SubStmts.empty()) - WriteSubStmt(SubStmts.pop_back_val()); - - Stream.EmitRecord(Writer.Code, Record); -} - -/// \brief Flush all of the statements that have been added to the -/// queue via AddStmt(). -void PCHWriter::FlushStmts() { - RecordData Record; - - for (unsigned I = 0, N = StmtsToEmit.size(); I != N; ++I) { - WriteSubStmt(StmtsToEmit[I]); - - assert(N == StmtsToEmit.size() && - "Substatement writen via AddStmt rather than WriteSubStmt!"); - - // Note that we are at the end of a full expression. Any - // expression records that follow this one are part of a different - // expression. - Stream.EmitRecord(pch::STMT_STOP, Record); - } - - StmtsToEmit.clear(); -} diff --git a/lib/Frontend/PrintParserCallbacks.cpp b/lib/Frontend/PrintParserCallbacks.cpp deleted file mode 100644 index 9220677..0000000 --- a/lib/Frontend/PrintParserCallbacks.cpp +++ /dev/null @@ -1,852 +0,0 @@ -//===--- PrintParserActions.cpp - Implement -parse-print-callbacks mode ---===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This code simply runs the preprocessor on the input file and prints out the -// result. This is the traditional behavior of the -E option. -// -//===----------------------------------------------------------------------===// - -#include "clang/Frontend/Utils.h" -#include "clang/Parse/Action.h" -#include "clang/Parse/DeclSpec.h" -#include "llvm/Support/raw_ostream.h" -using namespace clang; - -namespace { - class ParserPrintActions : public MinimalAction { - llvm::raw_ostream& Out; - - public: - ParserPrintActions(Preprocessor &PP, llvm::raw_ostream& OS) - : MinimalAction(PP), Out(OS) {} - - // Printing Functions which also must call MinimalAction - - /// ActOnDeclarator - This callback is invoked when a declarator is parsed - /// and 'Init' specifies the initializer if any. This is for things like: - /// "int X = 4" or "typedef int foo". - virtual DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D) { - Out << __FUNCTION__ << " "; - if (IdentifierInfo *II = D.getIdentifier()) { - Out << "'" << II->getName() << "'"; - } else { - Out << "<anon>"; - } - Out << "\n"; - - // Pass up to EmptyActions so that the symbol table is maintained right. - return MinimalAction::ActOnDeclarator(S, D); - } - /// ActOnPopScope - This callback is called immediately before the specified - /// scope is popped and deleted. - virtual void ActOnPopScope(SourceLocation Loc, Scope *S) { - Out << __FUNCTION__ << "\n"; - return MinimalAction::ActOnPopScope(Loc, S); - } - - /// ActOnTranslationUnitScope - This callback is called once, immediately - /// after creating the translation unit scope (in Parser::Initialize). - virtual void ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) { - Out << __FUNCTION__ << "\n"; - MinimalAction::ActOnTranslationUnitScope(Loc, S); - } - - - Action::DeclPtrTy ActOnStartClassInterface(SourceLocation AtInterfaceLoc, - IdentifierInfo *ClassName, - SourceLocation ClassLoc, - IdentifierInfo *SuperName, - SourceLocation SuperLoc, - const DeclPtrTy *ProtoRefs, - unsigned NumProtocols, - const SourceLocation *ProtoLocs, - SourceLocation EndProtoLoc, - AttributeList *AttrList) { - Out << __FUNCTION__ << "\n"; - return MinimalAction::ActOnStartClassInterface(AtInterfaceLoc, - ClassName, ClassLoc, - SuperName, SuperLoc, - ProtoRefs, NumProtocols, - ProtoLocs, EndProtoLoc, - AttrList); - } - - /// ActOnForwardClassDeclaration - - /// Scope will always be top level file scope. - Action::DeclPtrTy ActOnForwardClassDeclaration(SourceLocation AtClassLoc, - IdentifierInfo **IdentList, - SourceLocation *IdentLocs, - unsigned NumElts) { - Out << __FUNCTION__ << "\n"; - return MinimalAction::ActOnForwardClassDeclaration(AtClassLoc, IdentList, - IdentLocs, NumElts); - } - - // Pure Printing - - /// ActOnParamDeclarator - This callback is invoked when a parameter - /// declarator is parsed. This callback only occurs for functions - /// with prototypes. S is the function prototype scope for the - /// parameters (C++ [basic.scope.proto]). - virtual DeclPtrTy ActOnParamDeclarator(Scope *S, Declarator &D) { - Out << __FUNCTION__ << " "; - if (IdentifierInfo *II = D.getIdentifier()) { - Out << "'" << II->getName() << "'"; - } else { - Out << "<anon>"; - } - Out << "\n"; - return DeclPtrTy(); - } - - /// AddInitializerToDecl - This action is called immediately after - /// ParseDeclarator (when an initializer is present). The code is factored - /// this way to make sure we are able to handle the following: - /// void func() { int xx = xx; } - /// This allows ActOnDeclarator to register "xx" prior to parsing the - /// initializer. The declaration above should still result in a warning, - /// since the reference to "xx" is uninitialized. - virtual void AddInitializerToDecl(DeclPtrTy Dcl, ExprArg Init) { - Out << __FUNCTION__ << "\n"; - } - - /// FinalizeDeclaratorGroup - After a sequence of declarators are parsed, - /// this gives the actions implementation a chance to process the group as - /// a whole. - virtual DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, const DeclSpec& DS, - DeclPtrTy *Group, - unsigned NumDecls) { - Out << __FUNCTION__ << "\n"; - return DeclGroupPtrTy(); - } - - /// ActOnStartOfFunctionDef - This is called at the start of a function - /// definition, instead of calling ActOnDeclarator. The Declarator includes - /// information about formal arguments that are part of this function. - virtual DeclPtrTy ActOnStartOfFunctionDef(Scope *FnBodyScope, - Declarator &D){ - Out << __FUNCTION__ << "\n"; - return DeclPtrTy(); - } - - /// ActOnStartOfFunctionDef - This is called at the start of a function - /// definition, after the FunctionDecl has already been created. - virtual DeclPtrTy ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) { - Out << __FUNCTION__ << "\n"; - return DeclPtrTy(); - } - - virtual void ActOnStartOfObjCMethodDef(Scope *FnBodyScope, DeclPtrTy D) { - Out << __FUNCTION__ << "\n"; - } - - /// ActOnFunctionDefBody - This is called when a function body has completed - /// parsing. Decl is the DeclTy returned by ParseStartOfFunctionDef. - virtual DeclPtrTy ActOnFinishFunctionBody(DeclPtrTy Decl, StmtArg Body) { - Out << __FUNCTION__ << "\n"; - return DeclPtrTy(); - } - - virtual DeclPtrTy ActOnFileScopeAsmDecl(SourceLocation Loc, - ExprArg AsmString) { - Out << __FUNCTION__ << "\n"; - return DeclPtrTy(); - } - - /// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with - /// no declarator (e.g. "struct foo;") is parsed. - virtual DeclPtrTy ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, - DeclSpec &DS) { - Out << __FUNCTION__ << "\n"; - return DeclPtrTy(); - } - - /// ActOnLinkageSpec - Parsed a C++ linkage-specification that - /// contained braces. Lang/StrSize contains the language string that - /// was parsed at location Loc. Decls/NumDecls provides the - /// declarations parsed inside the linkage specification. - virtual DeclPtrTy ActOnLinkageSpec(SourceLocation Loc, - SourceLocation LBrace, - SourceLocation RBrace, const char *Lang, - unsigned StrSize, - DeclPtrTy *Decls, unsigned NumDecls) { - Out << __FUNCTION__ << "\n"; - return DeclPtrTy(); - } - - /// ActOnLinkageSpec - Parsed a C++ linkage-specification without - /// braces. Lang/StrSize contains the language string that was - /// parsed at location Loc. D is the declaration parsed. - virtual DeclPtrTy ActOnLinkageSpec(SourceLocation Loc, const char *Lang, - unsigned StrSize, DeclPtrTy D) { - return DeclPtrTy(); - } - - //===------------------------------------------------------------------===// - // Type Parsing Callbacks. - //===------------------------------------------------------------------===// - - virtual TypeResult ActOnTypeName(Scope *S, Declarator &D) { - Out << __FUNCTION__ << "\n"; - return TypeResult(); - } - - virtual DeclPtrTy ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, - SourceLocation KWLoc, CXXScopeSpec &SS, - IdentifierInfo *Name, SourceLocation NameLoc, - AttributeList *Attr, AccessSpecifier AS, - MultiTemplateParamsArg TemplateParameterLists, - bool &OwnedDecl, bool &IsDependent) { - // TagType is an instance of DeclSpec::TST, indicating what kind of tag this - // is (struct/union/enum/class). - Out << __FUNCTION__ << "\n"; - return DeclPtrTy(); - } - - /// Act on @defs() element found when parsing a structure. ClassName is the - /// name of the referenced class. - virtual void ActOnDefs(Scope *S, DeclPtrTy TagD, SourceLocation DeclStart, - IdentifierInfo *ClassName, - llvm::SmallVectorImpl<DeclPtrTy> &Decls) { - Out << __FUNCTION__ << "\n"; - } - - virtual DeclPtrTy ActOnField(Scope *S, DeclPtrTy TagD, - SourceLocation DeclStart, - Declarator &D, ExprTy *BitfieldWidth) { - Out << __FUNCTION__ << "\n"; - return DeclPtrTy(); - } - - virtual DeclPtrTy ActOnIvar(Scope *S, SourceLocation DeclStart, - DeclPtrTy IntfDecl, - Declarator &D, ExprTy *BitfieldWidth, - tok::ObjCKeywordKind visibility) { - Out << __FUNCTION__ << "\n"; - return DeclPtrTy(); - } - - virtual void ActOnFields(Scope* S, SourceLocation RecLoc, DeclPtrTy TagDecl, - DeclPtrTy *Fields, unsigned NumFields, - SourceLocation LBrac, SourceLocation RBrac, - AttributeList *AttrList) { - Out << __FUNCTION__ << "\n"; - } - - virtual DeclPtrTy ActOnEnumConstant(Scope *S, DeclPtrTy EnumDecl, - DeclPtrTy LastEnumConstant, - SourceLocation IdLoc,IdentifierInfo *Id, - SourceLocation EqualLoc, ExprTy *Val) { - Out << __FUNCTION__ << "\n"; - return DeclPtrTy(); - } - - virtual void ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, - SourceLocation RBraceLoc, DeclPtrTy EnumDecl, - DeclPtrTy *Elements, unsigned NumElements, - Scope *S, AttributeList *AttrList) { - Out << __FUNCTION__ << "\n"; - } - - //===------------------------------------------------------------------===// - // Statement Parsing Callbacks. - //===------------------------------------------------------------------===// - - virtual OwningStmtResult ActOnNullStmt(SourceLocation SemiLoc) { - Out << __FUNCTION__ << "\n"; - return StmtEmpty(); - } - - virtual OwningStmtResult ActOnCompoundStmt(SourceLocation L, - SourceLocation R, - MultiStmtArg Elts, - bool isStmtExpr) { - Out << __FUNCTION__ << "\n"; - return StmtEmpty(); - } - virtual OwningStmtResult ActOnDeclStmt(DeclGroupPtrTy Decl, - SourceLocation StartLoc, - SourceLocation EndLoc) { - Out << __FUNCTION__ << "\n"; - return StmtEmpty(); - } - - virtual OwningStmtResult ActOnExprStmt(FullExprArg Expr) { - Out << __FUNCTION__ << "\n"; - return OwningStmtResult(*this, Expr->release()); - } - - /// ActOnCaseStmt - Note that this handles the GNU 'case 1 ... 4' extension, - /// which can specify an RHS value. - virtual OwningStmtResult ActOnCaseStmt(SourceLocation CaseLoc, - ExprArg LHSVal, - SourceLocation DotDotDotLoc, - ExprArg RHSVal, - SourceLocation ColonLoc) { - Out << __FUNCTION__ << "\n"; - return StmtEmpty(); - } - virtual OwningStmtResult ActOnDefaultStmt(SourceLocation DefaultLoc, - SourceLocation ColonLoc, - StmtArg SubStmt, Scope *CurScope){ - Out << __FUNCTION__ << "\n"; - return StmtEmpty(); - } - - virtual OwningStmtResult ActOnLabelStmt(SourceLocation IdentLoc, - IdentifierInfo *II, - SourceLocation ColonLoc, - StmtArg SubStmt) { - Out << __FUNCTION__ << "\n"; - return StmtEmpty(); - } - - virtual OwningStmtResult ActOnIfStmt(SourceLocation IfLoc, - FullExprArg CondVal, DeclPtrTy CondVar, - StmtArg ThenVal, - SourceLocation ElseLoc, - StmtArg ElseVal) { - Out << __FUNCTION__ << "\n"; - return StmtEmpty(); - } - - virtual OwningStmtResult ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, - ExprArg Cond, - DeclPtrTy CondVar) { - Out << __FUNCTION__ << "\n"; - return StmtEmpty(); - } - - virtual OwningStmtResult ActOnFinishSwitchStmt(SourceLocation SwitchLoc, - StmtArg Switch, - StmtArg Body) { - Out << __FUNCTION__ << "\n"; - return StmtEmpty(); - } - - virtual OwningStmtResult ActOnWhileStmt(SourceLocation WhileLoc, - FullExprArg Cond, DeclPtrTy CondVar, - StmtArg Body) { - Out << __FUNCTION__ << "\n"; - return StmtEmpty(); - } - virtual OwningStmtResult ActOnDoStmt(SourceLocation DoLoc, StmtArg Body, - SourceLocation WhileLoc, - SourceLocation LPLoc, ExprArg Cond, - SourceLocation RPLoc){ - Out << __FUNCTION__ << "\n"; - return StmtEmpty(); - } - virtual OwningStmtResult ActOnForStmt(SourceLocation ForLoc, - SourceLocation LParenLoc, - StmtArg First, FullExprArg Second, - DeclPtrTy SecondVar, - FullExprArg Third, - SourceLocation RParenLoc, - StmtArg Body) { - Out << __FUNCTION__ << "\n"; - return StmtEmpty(); - } - virtual OwningStmtResult ActOnObjCForCollectionStmt( - SourceLocation ForColLoc, - SourceLocation LParenLoc, - StmtArg First, ExprArg Second, - SourceLocation RParenLoc, StmtArg Body) { - Out << __FUNCTION__ << "\n"; - return StmtEmpty(); - } - virtual OwningStmtResult ActOnGotoStmt(SourceLocation GotoLoc, - SourceLocation LabelLoc, - IdentifierInfo *LabelII) { - Out << __FUNCTION__ << "\n"; - return StmtEmpty(); - } - virtual OwningStmtResult ActOnIndirectGotoStmt(SourceLocation GotoLoc, - SourceLocation StarLoc, - ExprArg DestExp) { - Out << __FUNCTION__ << "\n"; - return StmtEmpty(); - } - virtual OwningStmtResult ActOnContinueStmt(SourceLocation ContinueLoc, - Scope *CurScope) { - Out << __FUNCTION__ << "\n"; - return StmtEmpty(); - } - virtual OwningStmtResult ActOnBreakStmt(SourceLocation GotoLoc, - Scope *CurScope) { - Out << __FUNCTION__ << "\n"; - return StmtEmpty(); - } - virtual OwningStmtResult ActOnReturnStmt(SourceLocation ReturnLoc, - ExprArg RetValExp) { - Out << __FUNCTION__ << "\n"; - return StmtEmpty(); - } - virtual OwningStmtResult ActOnAsmStmt(SourceLocation AsmLoc, - bool IsSimple, - bool IsVolatile, - unsigned NumOutputs, - unsigned NumInputs, - IdentifierInfo **Names, - MultiExprArg Constraints, - MultiExprArg Exprs, - ExprArg AsmString, - MultiExprArg Clobbers, - SourceLocation RParenLoc, - bool MSAsm) { - Out << __FUNCTION__ << "\n"; - return StmtEmpty(); - } - - // Objective-c statements - virtual OwningStmtResult ActOnObjCAtCatchStmt(SourceLocation AtLoc, - SourceLocation RParen, - DeclPtrTy Parm, - StmtArg Body) { - Out << __FUNCTION__ << "\n"; - return StmtEmpty(); - } - - virtual OwningStmtResult ActOnObjCAtFinallyStmt(SourceLocation AtLoc, - StmtArg Body) { - Out << __FUNCTION__ << "\n"; - return StmtEmpty(); - } - - virtual OwningStmtResult ActOnObjCAtTryStmt(SourceLocation AtLoc, - StmtArg Try, - MultiStmtArg CatchStmts, - StmtArg Finally) { - Out << __FUNCTION__ << "\n"; - return StmtEmpty(); - } - - virtual OwningStmtResult ActOnObjCAtThrowStmt(SourceLocation AtLoc, - ExprArg Throw, - Scope *CurScope) { - Out << __FUNCTION__ << "\n"; - return StmtEmpty(); - } - - virtual OwningStmtResult ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc, - ExprArg SynchExpr, - StmtArg SynchBody) { - Out << __FUNCTION__ << "\n"; - return StmtEmpty(); - } - - // C++ Statements - virtual DeclPtrTy ActOnExceptionDeclarator(Scope *S, Declarator &D) { - Out << __FUNCTION__ << "\n"; - return DeclPtrTy(); - } - - virtual OwningStmtResult ActOnCXXCatchBlock(SourceLocation CatchLoc, - DeclPtrTy ExceptionDecl, - StmtArg HandlerBlock) { - Out << __FUNCTION__ << "\n"; - return StmtEmpty(); - } - - virtual OwningStmtResult ActOnCXXTryBlock(SourceLocation TryLoc, - StmtArg TryBlock, - MultiStmtArg Handlers) { - Out << __FUNCTION__ << "\n"; - return StmtEmpty(); - } - - //===------------------------------------------------------------------===// - // Expression Parsing Callbacks. - //===------------------------------------------------------------------===// - - // Primary Expressions. - - /// ActOnIdentifierExpr - Parse an identifier in expression context. - /// 'HasTrailingLParen' indicates whether or not the identifier has a '(' - /// token immediately after it. - virtual OwningExprResult ActOnIdentifierExpr(Scope *S, SourceLocation Loc, - IdentifierInfo &II, - bool HasTrailingLParen, - const CXXScopeSpec *SS, - bool isAddressOfOperand) { - Out << __FUNCTION__ << "\n"; - return ExprEmpty(); - } - - virtual OwningExprResult ActOnCXXOperatorFunctionIdExpr( - Scope *S, SourceLocation OperatorLoc, - OverloadedOperatorKind Op, - bool HasTrailingLParen, const CXXScopeSpec &SS, - bool isAddressOfOperand) { - Out << __FUNCTION__ << "\n"; - return ExprEmpty(); - } - - virtual OwningExprResult ActOnCXXConversionFunctionExpr( - Scope *S, SourceLocation OperatorLoc, - TypeTy *Type, bool HasTrailingLParen, - const CXXScopeSpec &SS,bool isAddressOfOperand) { - Out << __FUNCTION__ << "\n"; - return ExprEmpty(); - } - - virtual OwningExprResult ActOnPredefinedExpr(SourceLocation Loc, - tok::TokenKind Kind) { - Out << __FUNCTION__ << "\n"; - return ExprEmpty(); - } - - virtual OwningExprResult ActOnCharacterConstant(const Token &) { - Out << __FUNCTION__ << "\n"; - return ExprEmpty(); - } - - virtual OwningExprResult ActOnNumericConstant(const Token &) { - Out << __FUNCTION__ << "\n"; - return ExprEmpty(); - } - - /// ActOnStringLiteral - The specified tokens were lexed as pasted string - /// fragments (e.g. "foo" "bar" L"baz"). - virtual OwningExprResult ActOnStringLiteral(const Token *Toks, - unsigned NumToks) { - Out << __FUNCTION__ << "\n"; - return ExprEmpty(); - } - - virtual OwningExprResult ActOnParenExpr(SourceLocation L, SourceLocation R, - ExprArg Val) { - Out << __FUNCTION__ << "\n"; - return move(Val); // Default impl returns operand. - } - - // Postfix Expressions. - virtual OwningExprResult ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc, - tok::TokenKind Kind, - ExprArg Input) { - Out << __FUNCTION__ << "\n"; - return ExprEmpty(); - } - virtual OwningExprResult ActOnArraySubscriptExpr(Scope *S, ExprArg Base, - SourceLocation LLoc, - ExprArg Idx, - SourceLocation RLoc) { - Out << __FUNCTION__ << "\n"; - return ExprEmpty(); - } - virtual OwningExprResult ActOnMemberReferenceExpr(Scope *S, ExprArg Base, - SourceLocation OpLoc, - tok::TokenKind OpKind, - SourceLocation MemberLoc, - IdentifierInfo &Member, - DeclPtrTy ImplDecl, - const CXXScopeSpec *SS=0) { - Out << __FUNCTION__ << "\n"; - return ExprEmpty(); - } - - virtual OwningExprResult ActOnCallExpr(Scope *S, ExprArg Fn, - SourceLocation LParenLoc, - MultiExprArg Args, - SourceLocation *CommaLocs, - SourceLocation RParenLoc) { - Out << __FUNCTION__ << "\n"; - return ExprEmpty(); - } - - // Unary Operators. 'Tok' is the token for the operator. - virtual OwningExprResult ActOnUnaryOp(Scope *S, SourceLocation OpLoc, - tok::TokenKind Op, ExprArg Input) { - Out << __FUNCTION__ << "\n"; - return ExprEmpty(); - } - virtual OwningExprResult - ActOnSizeOfAlignOfExpr(SourceLocation OpLoc, bool isSizeof, bool isType, - void *TyOrEx, const SourceRange &ArgRange) { - Out << __FUNCTION__ << "\n"; - return ExprEmpty(); - } - - virtual OwningExprResult ActOnCompoundLiteral(SourceLocation LParen, - TypeTy *Ty, - SourceLocation RParen, - ExprArg Op) { - Out << __FUNCTION__ << "\n"; - return ExprEmpty(); - } - virtual OwningExprResult ActOnInitList(SourceLocation LParenLoc, - MultiExprArg InitList, - SourceLocation RParenLoc) { - Out << __FUNCTION__ << "\n"; - return ExprEmpty(); - } - virtual OwningExprResult ActOnCastExpr(Scope *S, SourceLocation LParenLoc, - TypeTy *Ty, SourceLocation RParenLoc, - ExprArg Op) { - Out << __FUNCTION__ << "\n"; - return ExprEmpty(); - } - - virtual OwningExprResult ActOnBinOp(Scope *S, SourceLocation TokLoc, - tok::TokenKind Kind, - ExprArg LHS, ExprArg RHS) { - Out << __FUNCTION__ << "\n"; - return ExprEmpty(); - } - - /// ActOnConditionalOp - Parse a ?: operation. Note that 'LHS' may be null - /// in the case of a the GNU conditional expr extension. - virtual OwningExprResult ActOnConditionalOp(SourceLocation QuestionLoc, - SourceLocation ColonLoc, - ExprArg Cond, ExprArg LHS, - ExprArg RHS) { - Out << __FUNCTION__ << "\n"; - return ExprEmpty(); - } - - //===--------------------- GNU Extension Expressions ------------------===// - - virtual OwningExprResult ActOnAddrLabel(SourceLocation OpLoc, - SourceLocation LabLoc, - IdentifierInfo *LabelII) {// "&&foo" - Out << __FUNCTION__ << "\n"; - return ExprEmpty(); - } - - virtual OwningExprResult ActOnStmtExpr(SourceLocation LPLoc, - StmtArg SubStmt, - SourceLocation RPLoc) { // "({..})" - Out << __FUNCTION__ << "\n"; - return ExprEmpty(); - } - - virtual OwningExprResult ActOnBuiltinOffsetOf(Scope *S, - SourceLocation BuiltinLoc, - SourceLocation TypeLoc, - TypeTy *Arg1, - OffsetOfComponent *CompPtr, - unsigned NumComponents, - SourceLocation RParenLoc) { - Out << __FUNCTION__ << "\n"; - return ExprEmpty(); - } - - // __builtin_types_compatible_p(type1, type2) - virtual OwningExprResult ActOnTypesCompatibleExpr(SourceLocation BuiltinLoc, - TypeTy *arg1,TypeTy *arg2, - SourceLocation RPLoc) { - Out << __FUNCTION__ << "\n"; - return ExprEmpty(); - } - // __builtin_choose_expr(constExpr, expr1, expr2) - virtual OwningExprResult ActOnChooseExpr(SourceLocation BuiltinLoc, - ExprArg cond, ExprArg expr1, - ExprArg expr2, - SourceLocation RPLoc) { - Out << __FUNCTION__ << "\n"; - return ExprEmpty(); - } - - // __builtin_va_arg(expr, type) - virtual OwningExprResult ActOnVAArg(SourceLocation BuiltinLoc, - ExprArg expr, TypeTy *type, - SourceLocation RPLoc) { - Out << __FUNCTION__ << "\n"; - return ExprEmpty(); - } - - virtual OwningExprResult ActOnGNUNullExpr(SourceLocation TokenLoc) { - Out << __FUNCTION__ << "\n"; - return ExprEmpty(); - } - - virtual void ActOnBlockStart(SourceLocation CaretLoc, Scope *CurScope) { - Out << __FUNCTION__ << "\n"; - } - - virtual void ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) { - Out << __FUNCTION__ << "\n"; - } - - virtual void ActOnBlockError(SourceLocation CaretLoc, Scope *CurScope) { - Out << __FUNCTION__ << "\n"; - } - - virtual OwningExprResult ActOnBlockStmtExpr(SourceLocation CaretLoc, - StmtArg Body, - Scope *CurScope) { - Out << __FUNCTION__ << "\n"; - return ExprEmpty(); - } - - virtual DeclPtrTy ActOnStartNamespaceDef(Scope *S, SourceLocation IdentLoc, - IdentifierInfo *Ident, - SourceLocation LBrace, - AttributeList *AttrList) { - Out << __FUNCTION__ << "\n"; - return DeclPtrTy(); - } - - virtual void ActOnFinishNamespaceDef(DeclPtrTy Dcl, SourceLocation RBrace) { - Out << __FUNCTION__ << "\n"; - return; - } - -#if 0 - // FIXME: AttrList should be deleted by this function, but the definition - // would have to be available. - virtual DeclPtrTy ActOnUsingDirective(Scope *CurScope, - SourceLocation UsingLoc, - SourceLocation NamespcLoc, - const CXXScopeSpec &SS, - SourceLocation IdentLoc, - IdentifierInfo *NamespcName, - AttributeList *AttrList) { - Out << __FUNCTION__ << "\n"; - return DeclPtrTy(); - } -#endif - - virtual void ActOnParamDefaultArgument(DeclPtrTy param, - SourceLocation EqualLoc, - ExprArg defarg) { - Out << __FUNCTION__ << "\n"; - } - - virtual void ActOnParamUnparsedDefaultArgument(DeclPtrTy param, - SourceLocation EqualLoc, - SourceLocation ArgLoc) { - Out << __FUNCTION__ << "\n"; - } - - virtual void ActOnParamDefaultArgumentError(DeclPtrTy param) { - Out << __FUNCTION__ << "\n"; - } - - virtual void AddCXXDirectInitializerToDecl(DeclPtrTy Dcl, - SourceLocation LParenLoc, - MultiExprArg Exprs, - SourceLocation *CommaLocs, - SourceLocation RParenLoc) { - Out << __FUNCTION__ << "\n"; - return; - } - - virtual void ActOnStartDelayedCXXMethodDeclaration(Scope *S, - DeclPtrTy Method) { - Out << __FUNCTION__ << "\n"; - } - - virtual void ActOnDelayedCXXMethodParameter(Scope *S, DeclPtrTy Param) { - Out << __FUNCTION__ << "\n"; - } - - virtual void ActOnFinishDelayedCXXMethodDeclaration(Scope *S, - DeclPtrTy Method) { - Out << __FUNCTION__ << "\n"; - } - - virtual DeclPtrTy ActOnStaticAssertDeclaration(SourceLocation AssertLoc, - ExprArg AssertExpr, - ExprArg AssertMessageExpr) { - Out << __FUNCTION__ << "\n"; - return DeclPtrTy(); - } - - virtual OwningExprResult ActOnCXXNamedCast(SourceLocation OpLoc, - tok::TokenKind Kind, - SourceLocation LAngleBracketLoc, - TypeTy *Ty, - SourceLocation RAngleBracketLoc, - SourceLocation LParenLoc, - ExprArg Op, - SourceLocation RParenLoc) { - Out << __FUNCTION__ << "\n"; - return ExprEmpty(); - } - - virtual OwningExprResult ActOnCXXTypeid(SourceLocation OpLoc, - SourceLocation LParenLoc, - bool isType, void *TyOrExpr, - SourceLocation RParenLoc) { - Out << __FUNCTION__ << "\n"; - return ExprEmpty(); - } - - virtual OwningExprResult ActOnCXXThis(SourceLocation ThisLoc) { - Out << __FUNCTION__ << "\n"; - return ExprEmpty(); - } - - virtual OwningExprResult ActOnCXXBoolLiteral(SourceLocation OpLoc, - tok::TokenKind Kind) { - Out << __FUNCTION__ << "\n"; - return ExprEmpty(); - } - - virtual OwningExprResult ActOnCXXThrow(SourceLocation OpLoc, ExprArg Op) { - Out << __FUNCTION__ << "\n"; - return ExprEmpty(); - } - - virtual OwningExprResult ActOnCXXTypeConstructExpr(SourceRange TypeRange, - TypeTy *TypeRep, - SourceLocation LParenLoc, - MultiExprArg Exprs, - SourceLocation *CommaLocs, - SourceLocation RParenLoc) { - Out << __FUNCTION__ << "\n"; - return ExprEmpty(); - } - - virtual OwningExprResult ActOnCXXConditionDeclarationExpr(Scope *S, - SourceLocation StartLoc, - Declarator &D, - SourceLocation EqualLoc, - ExprArg AssignExprVal) { - Out << __FUNCTION__ << "\n"; - return ExprEmpty(); - } - - virtual OwningExprResult ActOnCXXNew(SourceLocation StartLoc, - bool UseGlobal, - SourceLocation PlacementLParen, - MultiExprArg PlacementArgs, - SourceLocation PlacementRParen, - SourceRange TypeIdParens, - Declarator &D, - SourceLocation ConstructorLParen, - MultiExprArg ConstructorArgs, - SourceLocation ConstructorRParen) { - Out << __FUNCTION__ << "\n"; - return ExprEmpty(); - } - - virtual OwningExprResult ActOnCXXDelete(SourceLocation StartLoc, - bool UseGlobal, bool ArrayForm, - ExprArg Operand) { - Out << __FUNCTION__ << "\n"; - return ExprEmpty(); - } - - virtual OwningExprResult ActOnUnaryTypeTrait(UnaryTypeTrait OTT, - SourceLocation KWLoc, - SourceLocation LParen, - TypeTy *Ty, - SourceLocation RParen) { - Out << __FUNCTION__ << "\n"; - return ExprEmpty(); - } - }; -} - -MinimalAction *clang::CreatePrintParserActionsAction(Preprocessor &PP, - llvm::raw_ostream* OS) { - return new ParserPrintActions(PP, *OS); -} diff --git a/lib/Frontend/PrintPreprocessedOutput.cpp b/lib/Frontend/PrintPreprocessedOutput.cpp index 73bca9a..cfaf8a2 100644 --- a/lib/Frontend/PrintPreprocessedOutput.cpp +++ b/lib/Frontend/PrintPreprocessedOutput.cpp @@ -85,6 +85,10 @@ public: llvm::raw_ostream &OS; private: unsigned CurLine; + + /// The current include nesting level, used by header include dumping (-H). + unsigned CurrentIncludeDepth; + bool EmittedTokensOnThisLine; bool EmittedMacroOnThisLine; SrcMgr::CharacteristicKind FileType; @@ -92,19 +96,22 @@ private: bool Initialized; bool DisableLineMarkers; bool DumpDefines; + bool DumpHeaderIncludes; bool UseLineDirective; + bool HasProcessedPredefines; public: PrintPPOutputPPCallbacks(Preprocessor &pp, llvm::raw_ostream &os, - bool lineMarkers, bool defines) + bool lineMarkers, bool defines, bool headers) : PP(pp), SM(PP.getSourceManager()), ConcatInfo(PP), OS(os), DisableLineMarkers(lineMarkers), - DumpDefines(defines) { - CurLine = 0; + DumpDefines(defines), DumpHeaderIncludes(headers) { + CurLine = CurrentIncludeDepth = 0; CurFilename += "<uninit>"; EmittedTokensOnThisLine = false; EmittedMacroOnThisLine = false; FileType = SrcMgr::C_User; Initialized = false; + HasProcessedPredefines = false; // If we're in microsoft mode, use normal #line instead of line markers. UseLineDirective = PP.getLangOptions().Microsoft; @@ -137,6 +144,9 @@ public: /// MacroDefined - This hook is called whenever a macro definition is seen. void MacroDefined(const IdentifierInfo *II, const MacroInfo *MI); + /// MacroUndefined - This hook is called whenever a macro #undef is seen. + void MacroUndefined(SourceLocation Loc, const IdentifierInfo *II, + const MacroInfo *MI); }; } // end anonymous namespace @@ -216,7 +226,7 @@ void PrintPPOutputPPCallbacks::FileChanged(SourceLocation Loc, PresumedLoc UserLoc = SourceMgr.getPresumedLoc(Loc); unsigned NewLine = UserLoc.getLine(); - + if (Reason == PPCallbacks::EnterFile) { SourceLocation IncludeLoc = SourceMgr.getPresumedLoc(Loc).getIncludeLoc(); if (IncludeLoc.isValid()) @@ -228,16 +238,41 @@ void PrintPPOutputPPCallbacks::FileChanged(SourceLocation Loc, // directive and emits a bunch of spaces that aren't needed. Emulate this // strange behavior. } + + // Adjust the current include depth. + if (Reason == PPCallbacks::EnterFile) { + ++CurrentIncludeDepth; + } else { + if (CurrentIncludeDepth) + --CurrentIncludeDepth; + + // We track when we are done with the predefines by watching for the first + // place where we drop back to a nesting depth of 0. + if (CurrentIncludeDepth == 0 && !HasProcessedPredefines) + HasProcessedPredefines = true; + } CurLine = NewLine; - if (DisableLineMarkers) return; - CurFilename.clear(); CurFilename += UserLoc.getFilename(); Lexer::Stringify(CurFilename); FileType = NewFileType; + // Dump the header include information, if enabled and we are past the + // predefines buffer. + if (DumpHeaderIncludes && HasProcessedPredefines && + Reason == PPCallbacks::EnterFile) { + llvm::SmallString<256> Msg; + llvm::raw_svector_ostream OS(Msg); + for (unsigned i = 0; i != CurrentIncludeDepth; ++i) + OS << '.'; + OS << ' ' << CurFilename << '\n'; + llvm::errs() << OS.str(); + } + + if (DisableLineMarkers) return; + if (!Initialized) { WriteLineInfo(CurLine); Initialized = true; @@ -280,6 +315,16 @@ void PrintPPOutputPPCallbacks::MacroDefined(const IdentifierInfo *II, EmittedMacroOnThisLine = true; } +void PrintPPOutputPPCallbacks::MacroUndefined(SourceLocation Loc, + const IdentifierInfo *II, + const MacroInfo *MI) { + // Only print out macro definitions in -dD mode. + if (!DumpDefines) return; + + MoveToLine(Loc); + OS << "#undef " << II->getName(); + EmittedMacroOnThisLine = true; +} void PrintPPOutputPPCallbacks::PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind, @@ -516,7 +561,7 @@ void clang::DoPrintPreprocessedInput(Preprocessor &PP, llvm::raw_ostream *OS, PrintPPOutputPPCallbacks *Callbacks = new PrintPPOutputPPCallbacks(PP, *OS, !Opts.ShowLineMarkers, - Opts.ShowMacros); + Opts.ShowMacros, Opts.ShowHeaderIncludes); PP.AddPragmaHandler(new UnknownPragmaHandler("#pragma", Callbacks)); PP.AddPragmaHandler("GCC", new UnknownPragmaHandler("#pragma GCC", Callbacks)); diff --git a/lib/Frontend/StmtXML.cpp b/lib/Frontend/StmtXML.cpp index 21dc0ba..b660734 100644 --- a/lib/Frontend/StmtXML.cpp +++ b/lib/Frontend/StmtXML.cpp @@ -32,7 +32,8 @@ namespace { void addSpecialAttribute(const char* pName, StringLiteral* Str) { - Doc.addAttribute(pName, Doc.escapeString(Str->getStrData(), Str->getByteLength())); + Doc.addAttribute(pName, Doc.escapeString(Str->getString().data(), + Str->getString().size())); } void addSpecialAttribute(const char* pName, SizeOfAlignOfExpr* S) { @@ -261,7 +262,6 @@ const char *StmtXML::getOpcodeStr(UnaryOperator::Opcode Op) { case UnaryOperator::Real: return "__real"; case UnaryOperator::Imag: return "__imag"; case UnaryOperator::Extension: return "__extension__"; - case UnaryOperator::OffsetOf: return "__builtin_offsetof"; } } diff --git a/lib/Frontend/TextDiagnosticPrinter.cpp b/lib/Frontend/TextDiagnosticPrinter.cpp index 1b5b7e2..1e453a0 100644 --- a/lib/Frontend/TextDiagnosticPrinter.cpp +++ b/lib/Frontend/TextDiagnosticPrinter.cpp @@ -447,11 +447,11 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc, if (NumHints && DiagOpts->ShowFixits) { for (const FixItHint *Hint = Hints, *LastHint = Hints + NumHints; Hint != LastHint; ++Hint) { - if (Hint->InsertionLoc.isValid()) { + if (!Hint->CodeToInsert.empty()) { // We have an insertion hint. Determine whether the inserted // code is on the same line as the caret. std::pair<FileID, unsigned> HintLocInfo - = SM.getDecomposedInstantiationLoc(Hint->InsertionLoc); + = SM.getDecomposedInstantiationLoc(Hint->RemoveRange.getBegin()); if (SM.getLineNumber(HintLocInfo.first, HintLocInfo.second) == SM.getLineNumber(FID, FileOffset)) { // Insert the new code into the line just below the code @@ -537,6 +537,48 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc, if (DiagOpts->ShowColors) OS.resetColor(); } + + if (DiagOpts->ShowParseableFixits) { + + // We follow FixItRewriter's example in not (yet) handling + // fix-its in macros. + bool BadApples = false; + for (const FixItHint *Hint = Hints; Hint != Hints + NumHints; ++Hint) { + if (Hint->RemoveRange.isInvalid() || + Hint->RemoveRange.getBegin().isMacroID() || + Hint->RemoveRange.getEnd().isMacroID()) { + BadApples = true; + break; + } + } + + if (!BadApples) { + for (const FixItHint *Hint = Hints; Hint != Hints + NumHints; ++Hint) { + + SourceLocation B = Hint->RemoveRange.getBegin(); + SourceLocation E = Hint->RemoveRange.getEnd(); + + std::pair<FileID, unsigned> BInfo = SM.getDecomposedLoc(B); + std::pair<FileID, unsigned> EInfo = SM.getDecomposedLoc(E); + + // Adjust for token ranges. + if (Hint->RemoveRange.isTokenRange()) + EInfo.second += Lexer::MeasureTokenLength(E, SM, *LangOpts); + + // We specifically do not do word-wrapping or tab-expansion here, + // because this is supposed to be easy to parse. + OS << "fix-it:\""; + OS.write_escaped(SM.getPresumedLoc(B).getFilename()); + OS << "\":{" << SM.getLineNumber(BInfo.first, BInfo.second) + << ':' << SM.getColumnNumber(BInfo.first, BInfo.second) + << '-' << SM.getLineNumber(EInfo.first, EInfo.second) + << ':' << SM.getColumnNumber(EInfo.first, EInfo.second) + << "}:\""; + OS.write_escaped(Hint->CodeToInsert); + OS << "\"\n"; + } + } + } } /// \brief Skip over whitespace in the string, starting at the given diff --git a/lib/Frontend/VerifyDiagnosticsClient.cpp b/lib/Frontend/VerifyDiagnosticsClient.cpp index ae36481..31eb28f 100644 --- a/lib/Frontend/VerifyDiagnosticsClient.cpp +++ b/lib/Frontend/VerifyDiagnosticsClient.cpp @@ -171,13 +171,12 @@ public: : Begin(Begin), End(End), C(Begin), P(Begin), PEnd(NULL) { } // Return true if string literal is next. - bool Next(const std::string &S) { - std::string::size_type LEN = S.length(); + bool Next(llvm::StringRef S) { P = C; - PEnd = C + LEN; + PEnd = C + S.size(); if (PEnd > End) return false; - return !memcmp(P, S.c_str(), LEN); + return !memcmp(P, S.data(), S.size()); } // Return true if number is next. @@ -198,9 +197,9 @@ public: // Return true if string literal is found. // When true, P marks begin-position of S in content. - bool Search(const std::string &S) { + bool Search(llvm::StringRef S) { P = std::search(C, End, S.begin(), S.end()); - PEnd = P + S.length(); + PEnd = P + S.size(); return P != End; } @@ -484,7 +483,7 @@ void VerifyDiagnosticsClient::CheckDiagnostics() { ExpectedData ED; // Ensure any diagnostics go to the primary client. - DiagnosticClient *CurClient = Diags.getClient(); + DiagnosticClient *CurClient = Diags.takeClient(); Diags.setClient(PrimaryClient.get()); // If we have a preprocessor, scan the source for expected diagnostic @@ -507,6 +506,7 @@ void VerifyDiagnosticsClient::CheckDiagnostics() { "note", false)); } + Diags.takeClient(); Diags.setClient(CurClient); // Reset the buffer, we have processed all the diagnostics in it. |