Skip to content

Commit 6879964

Browse files
committed
[ASTReader] Allow controlling separately whether validation should be disabled for a PCH vs a module file
This addresses an issue with how the PCH preable works, specifically: 1. When using a PCH/preamble the module hash changes and a different cache directory is used 2. When the preamble is used, PCH & PCM validation is disabled. Due to combination of #1 and #2, reparsing with preamble enabled can end up loading a stale module file before a header change and using it without updating it because validation is disabled and it doesn’t check that the header has changed and the module file is out-of-date. rdar://72611253 Differential Revision: https://reviews.llvm.org/D95159
1 parent 755a133 commit 6879964

File tree

17 files changed

+174
-39
lines changed

17 files changed

+174
-39
lines changed

clang/include/clang/Driver/Options.td

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5090,7 +5090,8 @@ def fhalf_no_semantic_interposition : Flag<["-"], "fhalf-no-semantic-interpositi
50905090
MarshallingInfoFlag<"LangOpts->HalfNoSemanticInterposition">;
50915091
def fno_validate_pch : Flag<["-"], "fno-validate-pch">,
50925092
HelpText<"Disable validation of precompiled headers">,
5093-
MarshallingInfoFlag<"PreprocessorOpts->DisablePCHValidation">;
5093+
MarshallingInfoFlag<"PreprocessorOpts->DisablePCHOrModuleValidation", "DisableValidationForModuleKind::None">,
5094+
Normalizer<"makeFlagToValueNormalizer(DisableValidationForModuleKind::All)">;
50945095
def fallow_pch_with_errors : Flag<["-"], "fallow-pch-with-compiler-errors">,
50955096
HelpText<"Accept a PCH file that was created with compiler errors">;
50965097
def fallow_pcm_with_errors : Flag<["-"], "fallow-pcm-with-compiler-errors">,

clang/include/clang/Frontend/CompilerInstance.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ class Preprocessor;
5050
class Sema;
5151
class SourceManager;
5252
class TargetInfo;
53+
enum class DisableValidationForModuleKind;
5354

5455
/// CompilerInstance - Helper class for managing a single instance of the Clang
5556
/// compiler.
@@ -673,16 +674,17 @@ class CompilerInstance : public ModuleLoader {
673674

674675
/// Create an external AST source to read a PCH file and attach it to the AST
675676
/// context.
676-
void createPCHExternalASTSource(StringRef Path, bool DisablePCHValidation,
677-
bool AllowPCHWithCompilerErrors,
678-
void *DeserializationListener,
679-
bool OwnDeserializationListener);
677+
void createPCHExternalASTSource(
678+
StringRef Path, DisableValidationForModuleKind DisableValidation,
679+
bool AllowPCHWithCompilerErrors, void *DeserializationListener,
680+
bool OwnDeserializationListener);
680681

681682
/// Create an external AST source to read a PCH file.
682683
///
683684
/// \return - The new object on success, or null on failure.
684685
static IntrusiveRefCntPtr<ASTReader> createPCHExternalASTSource(
685-
StringRef Path, StringRef Sysroot, bool DisablePCHValidation,
686+
StringRef Path, StringRef Sysroot,
687+
DisableValidationForModuleKind DisableValidation,
686688
bool AllowPCHWithCompilerErrors, Preprocessor &PP,
687689
InMemoryModuleCache &ModuleCache, ASTContext &Context,
688690
const PCHContainerReader &PCHContainerRdr,

clang/include/clang/Lex/PreprocessorOptions.h

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#ifndef LLVM_CLANG_LEX_PREPROCESSOROPTIONS_H_
1010
#define LLVM_CLANG_LEX_PREPROCESSOROPTIONS_H_
1111

12+
#include "clang/Basic/BitmaskEnum.h"
1213
#include "clang/Basic/LLVM.h"
1314
#include "clang/Lex/PreprocessorExcludedConditionalDirectiveSkipMapping.h"
1415
#include "llvm/ADT/StringRef.h"
@@ -40,6 +41,24 @@ enum ObjCXXARCStandardLibraryKind {
4041
ARCXX_libstdcxx
4142
};
4243

44+
/// Whether to disable the normal validation performed on precompiled
45+
/// headers and module files when they are loaded.
46+
enum class DisableValidationForModuleKind {
47+
/// Perform validation, don't disable it.
48+
None = 0,
49+
50+
/// Disable validation for a precompiled header and the modules it depends on.
51+
PCH = 0x1,
52+
53+
/// Disable validation for module files.
54+
Module = 0x2,
55+
56+
/// Disable validation for all kinds.
57+
All = PCH | Module,
58+
59+
LLVM_MARK_AS_BITMASK_ENUM(Module)
60+
};
61+
4362
/// PreprocessorOptions - This class is used for passing the various options
4463
/// used in preprocessor initialization to InitializePreprocessor().
4564
class PreprocessorOptions {
@@ -79,9 +98,10 @@ class PreprocessorOptions {
7998
/// Headers that will be converted to chained PCHs in memory.
8099
std::vector<std::string> ChainedIncludes;
81100

82-
/// When true, disables most of the normal validation performed on
83-
/// precompiled headers.
84-
bool DisablePCHValidation = false;
101+
/// Whether to disable most of the normal validation performed on
102+
/// precompiled headers and module files.
103+
DisableValidationForModuleKind DisablePCHOrModuleValidation =
104+
DisableValidationForModuleKind::None;
85105

86106
/// When true, a PCH with compiler errors will not be rejected.
87107
bool AllowPCHWithCompilerErrors = false;

clang/include/clang/Serialization/ASTReader.h

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "clang/Lex/ExternalPreprocessorSource.h"
2424
#include "clang/Lex/HeaderSearch.h"
2525
#include "clang/Lex/PreprocessingRecord.h"
26+
#include "clang/Lex/PreprocessorOptions.h"
2627
#include "clang/Sema/ExternalSemaSource.h"
2728
#include "clang/Sema/IdentifierResolver.h"
2829
#include "clang/Serialization/ASTBitCodes.h"
@@ -440,6 +441,9 @@ class ASTReader
440441
/// imported from. For non-module AST types it should be invalid.
441442
SourceLocation CurrentImportLoc;
442443

444+
/// The module kind that is currently deserializing.
445+
Optional<ModuleKind> CurrentDeserializingModuleKind;
446+
443447
/// The global module index, if loaded.
444448
std::unique_ptr<GlobalModuleIndex> GlobalIndex;
445449

@@ -923,8 +927,8 @@ class ASTReader
923927
std::string isysroot;
924928

925929
/// Whether to disable the normal validation performed on precompiled
926-
/// headers when they are loaded.
927-
bool DisableValidation;
930+
/// headers and module files when they are loaded.
931+
DisableValidationForModuleKind DisableValidationKind;
928932

929933
/// Whether to accept an AST file with compiler errors.
930934
bool AllowASTWithCompilerErrors;
@@ -1207,6 +1211,8 @@ class ASTReader
12071211

12081212
llvm::DenseMap<const Decl *, bool> DefinitionSource;
12091213

1214+
bool shouldDisableValidationForFile(const serialization::ModuleFile &M) const;
1215+
12101216
/// Reads a statement from the specified cursor.
12111217
Stmt *ReadStmtFromStream(ModuleFile &F);
12121218

@@ -1467,9 +1473,9 @@ class ASTReader
14671473
/// user. This is only used with relocatable PCH files. If non-NULL,
14681474
/// a relocatable PCH file will use the default path "/".
14691475
///
1470-
/// \param DisableValidation If true, the AST reader will suppress most
1476+
/// \param DisableValidationKind If set, the AST reader will suppress most
14711477
/// of its regular consistency checking, allowing the use of precompiled
1472-
/// headers that cannot be determined to be compatible.
1478+
/// headers and module files that cannot be determined to be compatible.
14731479
///
14741480
/// \param AllowASTWithCompilerErrors If true, the AST reader will accept an
14751481
/// AST file the was created out of an AST with compiler errors,
@@ -1490,7 +1496,9 @@ class ASTReader
14901496
ASTReader(Preprocessor &PP, InMemoryModuleCache &ModuleCache,
14911497
ASTContext *Context, const PCHContainerReader &PCHContainerRdr,
14921498
ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
1493-
StringRef isysroot = "", bool DisableValidation = false,
1499+
StringRef isysroot = "",
1500+
DisableValidationForModuleKind DisableValidationKind =
1501+
DisableValidationForModuleKind::None,
14941502
bool AllowASTWithCompilerErrors = false,
14951503
bool AllowConfigurationMismatch = false,
14961504
bool ValidateSystemInputs = false,

clang/lib/Frontend/ASTUnit.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -809,9 +809,10 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile(
809809
PP.getIdentifierTable(), PP.getSelectorTable(),
810810
PP.getBuiltinInfo());
811811

812-
bool disableValid = false;
812+
DisableValidationForModuleKind disableValid =
813+
DisableValidationForModuleKind::None;
813814
if (::getenv("LIBCLANG_DISABLE_PCH_VALIDATION"))
814-
disableValid = true;
815+
disableValid = DisableValidationForModuleKind::All;
815816
AST->Reader = new ASTReader(
816817
PP, *AST->ModuleCache, AST->Ctx.get(), PCHContainerRdr, {},
817818
/*isysroot=*/"",

clang/lib/Frontend/ChainedIncludesSource.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,10 @@ createASTReader(CompilerInstance &CI, StringRef pchFile,
8383
ASTDeserializationListener *deserialListener = nullptr) {
8484
Preprocessor &PP = CI.getPreprocessor();
8585
std::unique_ptr<ASTReader> Reader;
86-
Reader.reset(new ASTReader(PP, CI.getModuleCache(), &CI.getASTContext(),
87-
CI.getPCHContainerReader(),
88-
/*Extensions=*/{},
89-
/*isysroot=*/"", /*DisableValidation=*/true));
86+
Reader.reset(new ASTReader(
87+
PP, CI.getModuleCache(), &CI.getASTContext(), CI.getPCHContainerReader(),
88+
/*Extensions=*/{},
89+
/*isysroot=*/"", DisableValidationForModuleKind::PCH));
9090
for (unsigned ti = 0; ti < bufNames.size(); ++ti) {
9191
StringRef sr(bufNames[ti]);
9292
Reader->addInMemoryBuffer(sr, std::move(MemBufs[ti]));
@@ -129,7 +129,8 @@ IntrusiveRefCntPtr<ExternalSemaSource> clang::createChainedIncludesSource(
129129

130130
CInvok->getPreprocessorOpts().ChainedIncludes.clear();
131131
CInvok->getPreprocessorOpts().ImplicitPCHInclude.clear();
132-
CInvok->getPreprocessorOpts().DisablePCHValidation = true;
132+
CInvok->getPreprocessorOpts().DisablePCHOrModuleValidation =
133+
DisableValidationForModuleKind::PCH;
133134
CInvok->getPreprocessorOpts().Includes.clear();
134135
CInvok->getPreprocessorOpts().MacroIncludes.clear();
135136
CInvok->getPreprocessorOpts().Macros.clear();

clang/lib/Frontend/CompilerInstance.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -505,11 +505,12 @@ void CompilerInstance::createASTContext() {
505505
// ExternalASTSource
506506

507507
void CompilerInstance::createPCHExternalASTSource(
508-
StringRef Path, bool DisablePCHValidation, bool AllowPCHWithCompilerErrors,
509-
void *DeserializationListener, bool OwnDeserializationListener) {
508+
StringRef Path, DisableValidationForModuleKind DisableValidation,
509+
bool AllowPCHWithCompilerErrors, void *DeserializationListener,
510+
bool OwnDeserializationListener) {
510511
bool Preamble = getPreprocessorOpts().PrecompiledPreambleBytes.first != 0;
511512
TheASTReader = createPCHExternalASTSource(
512-
Path, getHeaderSearchOpts().Sysroot, DisablePCHValidation,
513+
Path, getHeaderSearchOpts().Sysroot, DisableValidation,
513514
AllowPCHWithCompilerErrors, getPreprocessor(), getModuleCache(),
514515
getASTContext(), getPCHContainerReader(),
515516
getFrontendOpts().ModuleFileExtensions, DependencyCollectors,
@@ -518,7 +519,8 @@ void CompilerInstance::createPCHExternalASTSource(
518519
}
519520

520521
IntrusiveRefCntPtr<ASTReader> CompilerInstance::createPCHExternalASTSource(
521-
StringRef Path, StringRef Sysroot, bool DisablePCHValidation,
522+
StringRef Path, StringRef Sysroot,
523+
DisableValidationForModuleKind DisableValidation,
522524
bool AllowPCHWithCompilerErrors, Preprocessor &PP,
523525
InMemoryModuleCache &ModuleCache, ASTContext &Context,
524526
const PCHContainerReader &PCHContainerRdr,
@@ -530,7 +532,7 @@ IntrusiveRefCntPtr<ASTReader> CompilerInstance::createPCHExternalASTSource(
530532

531533
IntrusiveRefCntPtr<ASTReader> Reader(new ASTReader(
532534
PP, ModuleCache, &Context, PCHContainerRdr, Extensions,
533-
Sysroot.empty() ? "" : Sysroot.data(), DisablePCHValidation,
535+
Sysroot.empty() ? "" : Sysroot.data(), DisableValidation,
534536
AllowPCHWithCompilerErrors, /*AllowConfigurationMismatch*/ false,
535537
HSOpts.ModulesValidateSystemHeaders, HSOpts.ValidateASTInputFilesContent,
536538
UseGlobalModuleIndex));
@@ -1532,7 +1534,8 @@ void CompilerInstance::createASTReader() {
15321534
TheASTReader = new ASTReader(
15331535
getPreprocessor(), getModuleCache(), &getASTContext(),
15341536
getPCHContainerReader(), getFrontendOpts().ModuleFileExtensions,
1535-
Sysroot.empty() ? "" : Sysroot.c_str(), PPOpts.DisablePCHValidation,
1537+
Sysroot.empty() ? "" : Sysroot.c_str(),
1538+
PPOpts.DisablePCHOrModuleValidation,
15361539
/*AllowASTWithCompilerErrors=*/FEOpts.AllowPCMWithCompilerErrors,
15371540
/*AllowConfigurationMismatch=*/false, HSOpts.ModulesValidateSystemHeaders,
15381541
HSOpts.ValidateASTInputFilesContent,

clang/lib/Frontend/FrontendAction.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -879,9 +879,9 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
879879
if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) {
880880
CI.createPCHExternalASTSource(
881881
CI.getPreprocessorOpts().ImplicitPCHInclude,
882-
CI.getPreprocessorOpts().DisablePCHValidation,
883-
CI.getPreprocessorOpts().AllowPCHWithCompilerErrors, DeserialListener,
884-
DeleteDeserialListener);
882+
CI.getPreprocessorOpts().DisablePCHOrModuleValidation,
883+
CI.getPreprocessorOpts().AllowPCHWithCompilerErrors,
884+
DeserialListener, DeleteDeserialListener);
885885
if (!CI.getASTContext().getExternalSource())
886886
goto failure;
887887
}

clang/lib/Frontend/FrontendActions.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ void VerifyPCHAction::ExecuteAction() {
344344
CI.getPreprocessor(), CI.getModuleCache(), &CI.getASTContext(),
345345
CI.getPCHContainerReader(), CI.getFrontendOpts().ModuleFileExtensions,
346346
Sysroot.empty() ? "" : Sysroot.c_str(),
347-
/*DisableValidation*/ false,
347+
DisableValidationForModuleKind::None,
348348
/*AllowASTWithCompilerErrors*/ false,
349349
/*AllowConfigurationMismatch*/ true,
350350
/*ValidateSystemInputs*/ true));

clang/lib/Frontend/PrecompiledPreamble.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -812,7 +812,8 @@ void PrecompiledPreamble::configurePreamble(
812812
PreprocessorOpts.PrecompiledPreambleBytes.first = Bounds.Size;
813813
PreprocessorOpts.PrecompiledPreambleBytes.second =
814814
Bounds.PreambleEndsAtStartOfLine;
815-
PreprocessorOpts.DisablePCHValidation = true;
815+
PreprocessorOpts.DisablePCHOrModuleValidation =
816+
DisableValidationForModuleKind::PCH;
816817

817818
setupPreambleStorage(Storage, PreprocessorOpts, VFS);
818819
}

0 commit comments

Comments
 (0)