]> granicus.if.org Git - clang/commitdiff
Do not validate pch when -fno-validate-pch is set
authorYaxun Liu <Yaxun.Liu@amd.com>
Wed, 7 Sep 2016 18:40:20 +0000 (18:40 +0000)
committerYaxun Liu <Yaxun.Liu@amd.com>
Wed, 7 Sep 2016 18:40:20 +0000 (18:40 +0000)
There is a bug causing pch to be validated even though -fno-validate-pch is set. This patch fixes it.

ASTReader relies on ASTReaderListener to initialize SuggestedPredefines, which is required for compilations using PCH. Before this change, PCHValidator is the default ASTReaderListener. After this change, when -fno-validate-pch is set, PCHValidator is disabled, but we need a replacement ASTReaderListener to initialize SuggestedPredefines. Class SimpleASTReaderListener is implemented for this purpose.

This change only affects -fno-validate-pch. There is no functional change if -fno-validate-pch is not set.

If -fno-validate-pch is not set, conflicts in predefined macros between pch and current compiler instance causes error.

If -fno-validate-pch is set, predefine macros in current compiler override those in pch so that compilation can continue.

Differential Revision: https://reviews.llvm.org/D24054

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@280842 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Serialization/ASTReader.h
lib/Serialization/ASTReader.cpp
test/PCH/no-validate-pch.cl [new file with mode: 0644]

index 943765d212c3cf2baaae8a0e7a9b0586460754df..810e869442ae735ea5a1bf5744b08525c3c16b3c 100644 (file)
@@ -284,6 +284,21 @@ private:
   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 f8e4384c630231e19ea6f349bf143f16cf932ae9..bb39a436abec9c8eb04eae46f70079ddc63f34df 100644 (file)
@@ -496,12 +496,16 @@ collectMacroDefinitions(const PreprocessorOptions &PPOpts,
 /// 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 @@ static bool checkPreprocessorOptions(const PreprocessorOptions &PPOpts,
     // Check whether we know anything about this macro name or not.
     llvm::StringMap<std::pair<StringRef, bool /*IsUndef*/> >::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 @@ static bool checkPreprocessorOptions(const PreprocessorOptions &PPOpts,
   }
 
   // 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 @@ static bool checkPreprocessorOptions(const PreprocessorOptions &PPOpts,
 
   // 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 @@ bool PCHValidator::ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,
                                   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 @@ ASTReader::ASTReader(
   bool AllowConfigurationMismatch, bool ValidateSystemInputs,
   bool UseGlobalIndex,
   std::unique_ptr<llvm::Timer> ReadTimer)
-    : Listener(new PCHValidator(PP, *this)), DeserializationListener(nullptr),
+    : Listener(DisableValidation ?
+        cast<ASTReaderListener>(new SimpleASTReaderListener(PP)) :
+        cast<ASTReaderListener>(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),
diff --git a/test/PCH/no-validate-pch.cl b/test/PCH/no-validate-pch.cl
new file mode 100644 (file)
index 0000000..26c5fd5
--- /dev/null
@@ -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