Index: include/clang/Serialization/ASTReader.h =================================================================== --- include/clang/Serialization/ASTReader.h +++ include/clang/Serialization/ASTReader.h @@ -284,6 +284,21 @@ void Error(const char *Msg); }; +/// \brief ASTReaderListenter implementation to set SuggestedPredefines of +/// ASTReader which is required to use a pch file. This is the replacement +/// of PCHValidator or SimplePCHValidator when using a pch file without +/// validating it. +class SimpleASTReaderListener : public ASTReaderListener { + Preprocessor &PP; + +public: + SimpleASTReaderListener(Preprocessor &PP) + : PP(PP) {} + + bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts, bool Complain, + std::string &SuggestedPredefines) override; +}; + namespace serialization { class ReadMethodPoolVisitor; Index: lib/Serialization/ASTReader.cpp =================================================================== --- lib/Serialization/ASTReader.cpp +++ lib/Serialization/ASTReader.cpp @@ -496,12 +496,16 @@ /// against the preprocessor options in an existing preprocessor. /// /// \param Diags If non-null, produce diagnostics for any mismatches incurred. +/// \param Validate If true, validate preprocessor options. If false, allow +/// macros defined by \p ExistingPPOpts to override those defined by +/// \p PPOpts in SuggestedPredefines. static bool checkPreprocessorOptions(const PreprocessorOptions &PPOpts, const PreprocessorOptions &ExistingPPOpts, DiagnosticsEngine *Diags, FileManager &FileMgr, std::string &SuggestedPredefines, - const LangOptions &LangOpts) { + const LangOptions &LangOpts, + bool Validate = true) { // Check macro definitions. MacroDefinitionsMap ASTFileMacros; collectMacroDefinitions(PPOpts, ASTFileMacros); @@ -517,7 +521,7 @@ // Check whether we know anything about this macro name or not. llvm::StringMap >::iterator Known = ASTFileMacros.find(MacroName); - if (Known == ASTFileMacros.end()) { + if (!Validate || Known == ASTFileMacros.end()) { // FIXME: Check whether this identifier was referenced anywhere in the // AST file. If so, we should reject the AST file. Unfortunately, this // information isn't in the control block. What shall we do about it? @@ -560,7 +564,7 @@ } // Check whether we're using predefines. - if (PPOpts.UsePredefines != ExistingPPOpts.UsePredefines) { + if (PPOpts.UsePredefines != ExistingPPOpts.UsePredefines && Validate) { if (Diags) { Diags->Report(diag::err_pch_undef) << ExistingPPOpts.UsePredefines; } @@ -569,7 +573,7 @@ // Detailed record is important since it is used for the module cache hash. if (LangOpts.Modules && - PPOpts.DetailedRecord != ExistingPPOpts.DetailedRecord) { + PPOpts.DetailedRecord != ExistingPPOpts.DetailedRecord && Validate) { if (Diags) { Diags->Report(diag::err_pch_pp_detailed_record) << PPOpts.DetailedRecord; } @@ -618,6 +622,19 @@ PP.getLangOpts()); } +bool SimpleASTReaderListener::ReadPreprocessorOptions( + const PreprocessorOptions &PPOpts, + bool Complain, + std::string &SuggestedPredefines) { + return checkPreprocessorOptions(PPOpts, + PP.getPreprocessorOpts(), + nullptr, + PP.getFileManager(), + SuggestedPredefines, + PP.getLangOpts(), + false); +} + /// Check the header search options deserialized from the control block /// against the header search options in an existing preprocessor. /// @@ -8710,7 +8727,10 @@ bool AllowConfigurationMismatch, bool ValidateSystemInputs, bool UseGlobalIndex, std::unique_ptr ReadTimer) - : Listener(new PCHValidator(PP, *this)), DeserializationListener(nullptr), + : Listener(DisableValidation ? + cast(new SimpleASTReaderListener(PP)) : + cast(new PCHValidator(PP, *this))), + DeserializationListener(nullptr), OwnsDeserializationListener(false), SourceMgr(PP.getSourceManager()), FileMgr(PP.getFileManager()), PCHContainerRdr(PCHContainerRdr), Diags(PP.getDiagnostics()), SemaObj(nullptr), PP(PP), Context(Context), Index: test/PCH/no-validate-pch.cl =================================================================== --- /dev/null +++ test/PCH/no-validate-pch.cl @@ -0,0 +1,39 @@ +// RUN: %clang_cc1 -emit-pch -D TWO=2 -D X=4 -o %t %s -triple spir-unknown-unknown +// RUN: %clang_cc1 -include-pch %t -D THREE=3 -D X=5 -O0 -U__OPTIMIZE__ -fno-validate-pch %s -triple spir-unknown-unknown 2>&1 | FileCheck %s +// RUN: not %clang_cc1 -include-pch %t -D THREE=3 -D X=5 -D VALIDATE -O0 -fsyntax-only %s -triple spir-unknown-unknown 2>&1 | FileCheck --check-prefix=CHECK-VAL %s + +#ifndef HEADER +#define HEADER +// Header. + +#define ONE 1 + +#else +// Using the header. + +// CHECK: warning: 'X' macro redefined +// CHECK: #define X 5 +// CHECK: note: previous definition is here +// CHECK: #define X 4 + +// CHECK-VAL: error: __OPTIMIZE__ predefined macro was enabled in PCH file but is currently disabled +// CHECK-VAL: error: definition of macro 'X' differs between the precompiled header ('4') and the command line ('5') + +void test(void) { + int a = ONE; + int b = TWO; + int c = THREE; + +#ifndef VALIDATE +#if X != 5 +#error Definition of X is not overridden! +#endif + +#ifdef __OPTIMIZE__ +#error Optimization is not off! +#endif +#endif + +} + +#endif