@@ -512,152 +512,73 @@ namespace {
512512// / Gathers information from ASTReader that will be used to initialize
513513// / a Preprocessor.
514514class ASTInfoCollector : public ASTReaderListener {
515- Preprocessor &PP;
516- ASTContext *Context;
517515 HeaderSearchOptions &HSOpts;
516+ std::string &SpecificModuleCachePath;
518517 PreprocessorOptions &PPOpts;
519- LangOptions &LangOpt ;
518+ LangOptions &LangOpts ;
520519 CodeGenOptions &CodeGenOpts;
521- std::shared_ptr<TargetOptions> &TargetOpts;
522- IntrusiveRefCntPtr<TargetInfo> &Target;
520+ TargetOptions &TargetOpts;
523521 unsigned &Counter;
524- bool InitializedLanguage = false ;
525- bool InitializedHeaderSearchPaths = false ;
526522
527523public:
528- ASTInfoCollector (Preprocessor &PP, ASTContext *Context ,
529- HeaderSearchOptions &HSOpts, PreprocessorOptions &PPOpts ,
530- LangOptions &LangOpt, CodeGenOptions &CodeGenOpts ,
531- std::shared_ptr< TargetOptions> &TargetOpts,
532- IntrusiveRefCntPtr<TargetInfo> &Target, unsigned &Counter)
533- : PP(PP), Context(Context), HSOpts(HSOpts), PPOpts(PPOpts ),
534- LangOpt (LangOpt ), CodeGenOpts(CodeGenOpts ), TargetOpts(TargetOpts ),
535- Target(Target ), Counter(Counter) {}
536-
537- bool ReadLanguageOptions (const LangOptions &LangOpts ,
524+ ASTInfoCollector (HeaderSearchOptions &HSOpts ,
525+ std::string &SpecificModuleCachePath ,
526+ PreprocessorOptions &PPOpts, LangOptions &LangOpts ,
527+ CodeGenOptions &CodeGenOpts, TargetOptions &TargetOpts,
528+ unsigned &Counter)
529+ : HSOpts(HSOpts), SpecificModuleCachePath(SpecificModuleCachePath ),
530+ PPOpts (PPOpts ), LangOpts(LangOpts ), CodeGenOpts(CodeGenOpts ),
531+ TargetOpts(TargetOpts ), Counter(Counter) {}
532+
533+ bool ReadLanguageOptions (const LangOptions &NewLangOpts ,
538534 StringRef ModuleFilename, bool Complain,
539535 bool AllowCompatibleDifferences) override {
540- if (InitializedLanguage)
541- return false ;
542-
543- // FIXME: We did similar things in ReadHeaderSearchOptions too. But such
544- // style is not scaling. Probably we need to invite some mechanism to
545- // handle such patterns generally.
546- auto PICLevel = LangOpt.PICLevel ;
547- auto PIE = LangOpt.PIE ;
548-
549- LangOpt = LangOpts;
550-
551- LangOpt.PICLevel = PICLevel;
552- LangOpt.PIE = PIE;
553-
554- InitializedLanguage = true ;
555-
556- updated ();
536+ LangOpts = NewLangOpts;
557537 return false ;
558538 }
559539
560- bool ReadCodeGenOptions (const CodeGenOptions &CGOpts ,
540+ bool ReadCodeGenOptions (const CodeGenOptions &NewCodeGenOpts ,
561541 StringRef ModuleFilename, bool Complain,
562542 bool AllowCompatibleDifferences) override {
563- this -> CodeGenOpts = CGOpts ;
543+ CodeGenOpts = NewCodeGenOpts ;
564544 return false ;
565545 }
566546
567- bool ReadHeaderSearchOptions (const HeaderSearchOptions &HSOpts ,
547+ bool ReadHeaderSearchOptions (const HeaderSearchOptions &NewHSOpts ,
568548 StringRef ModuleFilename,
569- StringRef SpecificModuleCachePath ,
549+ StringRef NewSpecificModuleCachePath ,
570550 bool Complain) override {
571- // llvm::SaveAndRestore doesn't support bit field.
572- auto ForceCheckCXX20ModulesInputFiles =
573- this ->HSOpts .ForceCheckCXX20ModulesInputFiles ;
574- llvm::SaveAndRestore X (this ->HSOpts .UserEntries );
575- llvm::SaveAndRestore Y (this ->HSOpts .SystemHeaderPrefixes );
576- llvm::SaveAndRestore Z (this ->HSOpts .VFSOverlayFiles );
577-
578- this ->HSOpts = HSOpts;
579- this ->HSOpts .ForceCheckCXX20ModulesInputFiles =
580- ForceCheckCXX20ModulesInputFiles;
581-
551+ HSOpts = NewHSOpts;
552+ SpecificModuleCachePath = NewSpecificModuleCachePath;
582553 return false ;
583554 }
584555
585- bool ReadHeaderSearchPaths (const HeaderSearchOptions &HSOpts ,
556+ bool ReadHeaderSearchPaths (const HeaderSearchOptions &NewHSOpts ,
586557 bool Complain) override {
587- if (InitializedHeaderSearchPaths)
588- return false ;
589-
590- this ->HSOpts .UserEntries = HSOpts.UserEntries ;
591- this ->HSOpts .SystemHeaderPrefixes = HSOpts.SystemHeaderPrefixes ;
592- this ->HSOpts .VFSOverlayFiles = HSOpts.VFSOverlayFiles ;
593-
594- // Initialize the FileManager. We can't do this in update(), since that
595- // performs the initialization too late (once both target and language
596- // options are read).
597- PP.getFileManager ().setVirtualFileSystem (createVFSFromOverlayFiles (
598- HSOpts.VFSOverlayFiles , PP.getDiagnostics (),
599- PP.getFileManager ().getVirtualFileSystemPtr ()));
600-
601- InitializedHeaderSearchPaths = true ;
602-
558+ HSOpts.UserEntries = NewHSOpts.UserEntries ;
559+ HSOpts.SystemHeaderPrefixes = NewHSOpts.SystemHeaderPrefixes ;
560+ HSOpts.VFSOverlayFiles = NewHSOpts.VFSOverlayFiles ;
603561 return false ;
604562 }
605563
606- bool ReadPreprocessorOptions (const PreprocessorOptions &PPOpts ,
564+ bool ReadPreprocessorOptions (const PreprocessorOptions &NewPPOpts ,
607565 StringRef ModuleFilename, bool ReadMacros,
608566 bool Complain,
609567 std::string &SuggestedPredefines) override {
610- this -> PPOpts = PPOpts ;
568+ PPOpts = NewPPOpts ;
611569 return false ;
612570 }
613571
614- bool ReadTargetOptions (const TargetOptions &TargetOpts ,
572+ bool ReadTargetOptions (const TargetOptions &NewTargetOpts ,
615573 StringRef ModuleFilename, bool Complain,
616574 bool AllowCompatibleDifferences) override {
617- // If we've already initialized the target, don't do it again.
618- if (Target)
619- return false ;
620-
621- this ->TargetOpts = std::make_shared<TargetOptions>(TargetOpts);
622- Target =
623- TargetInfo::CreateTargetInfo (PP.getDiagnostics (), *this ->TargetOpts );
624-
625- updated ();
575+ TargetOpts = NewTargetOpts;
626576 return false ;
627577 }
628578
629579 void ReadCounter (const serialization::ModuleFile &M,
630- unsigned Value) override {
631- Counter = Value;
632- }
633-
634- private:
635- void updated () {
636- if (!Target || !InitializedLanguage)
637- return ;
638-
639- // Inform the target of the language options.
640- //
641- // FIXME: We shouldn't need to do this, the target should be immutable once
642- // created. This complexity should be lifted elsewhere.
643- Target->adjust (PP.getDiagnostics (), LangOpt, /* AuxTarget=*/ nullptr );
644-
645- // Initialize the preprocessor.
646- PP.Initialize (*Target);
647-
648- if (!Context)
649- return ;
650-
651- // Initialize the ASTContext
652- Context->InitBuiltinTypes (*Target);
653-
654- // Adjust printing policy based on language options.
655- Context->setPrintingPolicy (PrintingPolicy (LangOpt));
656-
657- // We didn't have access to the comment options when the ASTContext was
658- // constructed, so register them now.
659- Context->getCommentCommandTraits ().registerCommentOptions (
660- LangOpt.CommentOpts );
580+ unsigned NewCounter) override {
581+ Counter = NewCounter;
661582 }
662583};
663584
@@ -812,7 +733,7 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile(
812733 std::shared_ptr<DiagnosticOptions> DiagOpts,
813734 IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
814735 const FileSystemOptions &FileSystemOpts, const HeaderSearchOptions &HSOpts,
815- const LangOptions *LangOpts , bool OnlyLocalDecls,
736+ const LangOptions *ProvidedLangOpts , bool OnlyLocalDecls,
816737 CaptureDiagsKind CaptureDiagnostics, bool AllowASTWithCompilerErrors,
817738 bool UserFilesAreVolatile) {
818739 std::unique_ptr<ASTUnit> AST (new ASTUnit (true ));
@@ -826,66 +747,132 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile(
826747
827748 ConfigureDiags (Diags, *AST, CaptureDiagnostics);
828749
829- AST->LangOpts = LangOpts ? std::make_unique<LangOptions>(*LangOpts)
830- : std::make_unique<LangOptions>();
750+ std::unique_ptr<LangOptions> LocalLangOpts;
751+ const LangOptions &LangOpts = [&]() -> const LangOptions & {
752+ if (ProvidedLangOpts)
753+ return *ProvidedLangOpts;
754+ LocalLangOpts = std::make_unique<LangOptions>();
755+ return *LocalLangOpts;
756+ }();
757+
758+ AST->LangOpts = std::make_unique<LangOptions>(LangOpts);
831759 AST->OnlyLocalDecls = OnlyLocalDecls;
832760 AST->CaptureDiagnostics = CaptureDiagnostics;
833761 AST->DiagOpts = DiagOpts;
834762 AST->Diagnostics = Diags;
835- AST->FileMgr = llvm::makeIntrusiveRefCnt<FileManager>(FileSystemOpts, VFS);
836763 AST->UserFilesAreVolatile = UserFilesAreVolatile;
837- AST->SourceMgr = llvm::makeIntrusiveRefCnt<SourceManager>(
838- AST->getDiagnostics (), AST->getFileManager (), UserFilesAreVolatile);
839- AST->ModCache = createCrossProcessModuleCache ();
840764 AST->HSOpts = std::make_unique<HeaderSearchOptions>(HSOpts);
841765 AST->HSOpts ->ModuleFormat = std::string (PCHContainerRdr.getFormats ().front ());
842- AST->HeaderInfo .reset (new HeaderSearch (AST->getHeaderSearchOpts (),
843- AST->getSourceManager (),
844- AST->getDiagnostics (),
845- AST->getLangOpts (),
846- /* Target=*/ nullptr ));
847766 AST->PPOpts = std::make_shared<PreprocessorOptions>();
767+ AST->CodeGenOpts = std::make_unique<CodeGenOptions>();
768+ AST->TargetOpts = std::make_shared<TargetOptions>();
769+
770+ AST->ModCache = createCrossProcessModuleCache ();
771+
772+ // Gather info for preprocessor construction later on.
773+ std::string SpecificModuleCachePath;
774+ unsigned Counter = 0 ;
775+ // Using a temporary FileManager since the AST file might specify custom
776+ // HeaderSearchOptions::VFSOverlayFiles that affect the underlying VFS.
777+ FileManager TmpFileMgr (FileSystemOpts, VFS);
778+ ASTInfoCollector Collector (*AST->HSOpts , SpecificModuleCachePath,
779+ *AST->PPOpts , *AST->LangOpts , *AST->CodeGenOpts ,
780+ *AST->TargetOpts , Counter);
781+ if (ASTReader::readASTFileControlBlock (
782+ Filename, TmpFileMgr, *AST->ModCache , PCHContainerRdr,
783+ /* FindModuleFileExtensions=*/ true , Collector,
784+ /* ValidateDiagnosticOptions=*/ true , ASTReader::ARR_None)) {
785+ AST->getDiagnostics ().Report (diag::err_fe_unable_to_load_pch);
786+ return nullptr ;
787+ }
788+
789+ VFS = createVFSFromOverlayFiles (AST->HSOpts ->VFSOverlayFiles ,
790+ *AST->Diagnostics , std::move (VFS));
848791
849- // Gather Info for preprocessor construction later on.
792+ AST->FileMgr = llvm::makeIntrusiveRefCnt<FileManager>(FileSystemOpts, VFS);
793+
794+ AST->SourceMgr = llvm::makeIntrusiveRefCnt<SourceManager>(
795+ AST->getDiagnostics (), AST->getFileManager (), UserFilesAreVolatile);
850796
851- HeaderSearch &HeaderInfo = *AST->HeaderInfo ;
797+ AST->HSOpts ->PrebuiltModuleFiles = HSOpts.PrebuiltModuleFiles ;
798+ AST->HSOpts ->PrebuiltModulePaths = HSOpts.PrebuiltModulePaths ;
799+ AST->HeaderInfo = std::make_unique<HeaderSearch>(
800+ AST->getHeaderSearchOpts (), AST->getSourceManager (),
801+ AST->getDiagnostics (), AST->getLangOpts (),
802+ /* Target=*/ nullptr );
803+ AST->HeaderInfo ->setModuleCachePath (SpecificModuleCachePath);
852804
853805 AST->PP = std::make_shared<Preprocessor>(
854806 *AST->PPOpts , AST->getDiagnostics (), *AST->LangOpts ,
855- AST->getSourceManager (), HeaderInfo, AST->ModuleLoader ,
807+ AST->getSourceManager (), *AST-> HeaderInfo , AST->ModuleLoader ,
856808 /* IILookup=*/ nullptr ,
857809 /* OwnsHeaderSearch=*/ false );
858- Preprocessor &PP = *AST->PP ;
859810
860811 if (ToLoad >= LoadASTOnly)
861812 AST->Ctx = llvm::makeIntrusiveRefCnt<ASTContext>(
862- *AST->LangOpts , AST->getSourceManager (), PP. getIdentifierTable (),
863- PP. getSelectorTable (), PP. getBuiltinInfo (),
813+ *AST->LangOpts , AST->getSourceManager (), AST-> PP -> getIdentifierTable (),
814+ AST-> PP -> getSelectorTable (), AST-> PP -> getBuiltinInfo (),
864815 AST->getTranslationUnitKind ());
865816
866817 DisableValidationForModuleKind disableValid =
867818 DisableValidationForModuleKind::None;
868819 if (::getenv (" LIBCLANG_DISABLE_PCH_VALIDATION" ))
869820 disableValid = DisableValidationForModuleKind::All;
870821 AST->Reader = llvm::makeIntrusiveRefCnt<ASTReader>(
871- PP, *AST->ModCache , AST->Ctx .get (), PCHContainerRdr, *AST-> CodeGenOpts ,
872- ArrayRef<std::shared_ptr<ModuleFileExtension>>(),
822+ *AST-> PP , *AST->ModCache , AST->Ctx .get (), PCHContainerRdr,
823+ *AST-> CodeGenOpts , ArrayRef<std::shared_ptr<ModuleFileExtension>>(),
873824 /* isysroot=*/ " " ,
874825 /* DisableValidationKind=*/ disableValid, AllowASTWithCompilerErrors);
875826
876- unsigned Counter = 0 ;
877- AST->Reader ->setListener (std::make_unique<ASTInfoCollector>(
878- *AST->PP , AST->Ctx .get (), *AST->HSOpts , *AST->PPOpts , *AST->LangOpts ,
879- *AST->CodeGenOpts , AST->TargetOpts , AST->Target , Counter));
880-
881- // Attach the AST reader to the AST context as an external AST
882- // source, so that declarations will be deserialized from the
883- // AST file as needed.
827+ // Attach the AST reader to the AST context as an external AST source, so that
828+ // declarations will be deserialized from the AST file as needed.
884829 // We need the external source to be set up before we read the AST, because
885830 // eagerly-deserialized declarations may use it.
886831 if (AST->Ctx )
887832 AST->Ctx ->setExternalSource (AST->Reader );
888833
834+ AST->Target =
835+ TargetInfo::CreateTargetInfo (AST->PP ->getDiagnostics (), *AST->TargetOpts );
836+ // Inform the target of the language options.
837+ //
838+ // FIXME: We shouldn't need to do this, the target should be immutable once
839+ // created. This complexity should be lifted elsewhere.
840+ AST->Target ->adjust (AST->PP ->getDiagnostics (), *AST->LangOpts ,
841+ /* AuxTarget=*/ nullptr );
842+
843+ // Initialize the preprocessor.
844+ AST->PP ->Initialize (*AST->Target );
845+
846+ AST->PP ->setCounterValue (Counter);
847+
848+ if (AST->Ctx ) {
849+ // Initialize the ASTContext
850+ AST->Ctx ->InitBuiltinTypes (*AST->Target );
851+
852+ // Adjust printing policy based on language options.
853+ AST->Ctx ->setPrintingPolicy (PrintingPolicy (*AST->LangOpts ));
854+
855+ // We didn't have access to the comment options when the ASTContext was
856+ // constructed, so register them now.
857+ AST->Ctx ->getCommentCommandTraits ().registerCommentOptions (
858+ AST->LangOpts ->CommentOpts );
859+ }
860+
861+ // The temporary FileManager we used for ASTReader::readASTFileControlBlock()
862+ // might have already read stdin, and reading it again will fail. Let's
863+ // explicitly forward the buffer.
864+ if (Filename == " -" )
865+ if (auto FE = llvm::expectedToOptional (TmpFileMgr.getSTDIN ()))
866+ if (auto BufRef = TmpFileMgr.getBufferForFile (*FE)) {
867+ auto Buf = llvm::MemoryBuffer::getMemBufferCopy (
868+ (*BufRef)->getBuffer (), (*BufRef)->getBufferIdentifier ());
869+ AST->Reader ->getModuleManager ().addInMemoryBuffer (" -" , std::move (Buf));
870+ }
871+
872+ // Reinstate the provided options that are relevant for reading AST files.
873+ AST->HSOpts ->ForceCheckCXX20ModulesInputFiles =
874+ HSOpts.ForceCheckCXX20ModulesInputFiles ;
875+
889876 switch (AST->Reader ->ReadAST (Filename, serialization::MK_MainFile,
890877 SourceLocation (), ASTReader::ARR_None)) {
891878 case ASTReader::Success:
@@ -901,11 +888,18 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile(
901888 return nullptr ;
902889 }
903890
904- AST->OriginalSourceFile = std::string (AST->Reader ->getOriginalSourceFile ());
891+ // Now that we have successfully loaded the AST file, we can reinstate some
892+ // options that the clients expect us to preserve (but would trip AST file
893+ // validation, so we couldn't set them earlier).
894+ AST->HSOpts ->UserEntries = HSOpts.UserEntries ;
895+ AST->HSOpts ->SystemHeaderPrefixes = HSOpts.SystemHeaderPrefixes ;
896+ AST->HSOpts ->VFSOverlayFiles = HSOpts.VFSOverlayFiles ;
897+ AST->LangOpts ->PICLevel = LangOpts.PICLevel ;
898+ AST->LangOpts ->PIE = LangOpts.PIE ;
905899
906- PP. setCounterValue (Counter );
900+ AST-> OriginalSourceFile = std::string (AST-> Reader -> getOriginalSourceFile () );
907901
908- Module *M = HeaderInfo. lookupModule (AST->getLangOpts ().CurrentModule );
902+ Module *M = AST-> HeaderInfo -> lookupModule (AST->getLangOpts ().CurrentModule );
909903 if (M && AST->getLangOpts ().isCompilingModule () && M->isNamedModule ())
910904 AST->Ctx ->setCurrentNamedModule (M);
911905
@@ -915,13 +909,14 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile(
915909
916910 // Create a semantic analysis object and tell the AST reader about it.
917911 if (ToLoad >= LoadEverything) {
918- AST->TheSema . reset ( new Sema ( PP, *AST->Ctx , *AST->Consumer ) );
912+ AST->TheSema = std::make_unique< Sema>(*AST-> PP , *AST->Ctx , *AST->Consumer );
919913 AST->TheSema ->Initialize ();
920914 AST->Reader ->InitializeSema (*AST->TheSema );
921915 }
922916
923917 // Tell the diagnostic client that we have started a source file.
924- AST->getDiagnostics ().getClient ()->BeginSourceFile (PP.getLangOpts (), &PP);
918+ AST->getDiagnostics ().getClient ()->BeginSourceFile (AST->PP ->getLangOpts (),
919+ AST->PP .get ());
925920
926921 return AST;
927922}
0 commit comments