diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -653,11 +653,7 @@ // Check whether we know anything about this macro name or not. llvm::StringMap>::iterator Known = ASTFileMacros.find(MacroName); - 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? - + if (!Validate) { if (Existing.second) { SuggestedPredefines += "#undef "; SuggestedPredefines += MacroName.str(); @@ -671,6 +667,12 @@ } continue; } + if (Known == ASTFileMacros.end()) { + if (Diags) { + Diags->Report(diag::err_pch_macro_def_undef) << MacroName << true; + } + return true; + } // If the macro was defined in one but undef'd in the other, we have a // conflict. @@ -684,8 +686,10 @@ // If the macro was #undef'd in both, or if the macro bodies are identical, // it's fine. - if (Existing.second || Existing.first == Known->second.first) + if (Existing.second || Existing.first == Known->second.first) { + ASTFileMacros.erase(Known); continue; + } // The macro bodies differ; complain. if (Diags) { @@ -694,6 +698,12 @@ } return true; } + for (const auto &MacroName : ASTFileMacros.keys()) { + if (Diags) { + Diags->Report(diag::err_pch_macro_def_undef) << MacroName << false; + } + return true; + } // Check whether we're using predefines. if (PPOpts.UsePredefines != ExistingPPOpts.UsePredefines && Validate) { @@ -5171,7 +5181,7 @@ bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts, bool Complain, std::string &SuggestedPredefines) override { - return checkPreprocessorOptions(ExistingPPOpts, PPOpts, nullptr, FileMgr, + return checkPreprocessorOptions(PPOpts, ExistingPPOpts, nullptr, FileMgr, SuggestedPredefines, ExistingLangOpts); } }; diff --git a/clang/test/PCH/fuzzy-pch.c b/clang/test/PCH/fuzzy-pch.c --- a/clang/test/PCH/fuzzy-pch.c +++ b/clang/test/PCH/fuzzy-pch.c @@ -1,7 +1,9 @@ // Test with pch. // RUN: %clang_cc1 -emit-pch -DFOO -o %t %S/variables.h -// RUN: %clang_cc1 -DBAR=int -include-pch %t -fsyntax-only -pedantic %s -// RUN: %clang_cc1 -DFOO -DBAR=int -include-pch %t %s +// RUN: not %clang_cc1 -DBAR=int -include-pch %t -fsyntax-only -pedantic %s 2> %t.err +// RUN: FileCheck -check-prefix=CHECK-BAR %s < %t.err +// RUN: not %clang_cc1 -DFOO -DBAR=int -include-pch %t %s 2> %t.err +// RUN: FileCheck -check-prefix=CHECK-BAR %s < %t.err // RUN: not %clang_cc1 -DFOO=blah -DBAR=int -include-pch %t %s 2> %t.err // RUN: FileCheck -check-prefix=CHECK-FOO %s < %t.err // RUN: not %clang_cc1 -UFOO -include-pch %t %s 2> %t.err @@ -26,6 +28,7 @@ // CHECK-FOO: definition of macro 'FOO' differs between the precompiled header ('1') and the command line ('blah') // CHECK-NOFOO: macro 'FOO' was defined in the precompiled header but undef'd on the command line +// CHECK-BAR: macro 'BAR' was undef'd in the precompiled header but defined on the command line // CHECK-UNDEF: command line contains '-undef' but precompiled header was not built with it diff --git a/clang/test/PCH/pch-dir.c b/clang/test/PCH/pch-dir.c --- a/clang/test/PCH/pch-dir.c +++ b/clang/test/PCH/pch-dir.c @@ -6,7 +6,7 @@ // RUN: %clang -x c++-header -std=c++98 %S/pch-dir.h -o %t.h.gch/cpp.gch // RUN: %clang -include %t.h -DFOO=foo -fsyntax-only %s -Xclang -print-stats 2> %t.clog // RUN: FileCheck -check-prefix=CHECK-C %s < %t.clog -// RUN: %clang -include %t.h -DFOO=bar -DBAR=bar -fsyntax-only %s -Xclang -ast-print > %t.cbarlog +// RUN: %clang -include %t.h -DFOO=bar -fsyntax-only %s -Xclang -ast-print > %t.cbarlog // RUN: FileCheck -check-prefix=CHECK-CBAR %s < %t.cbarlog // RUN: %clang -x c++ -include %t.h -std=c++98 -fsyntax-only %s -Xclang -print-stats 2> %t.cpplog // RUN: FileCheck -check-prefix=CHECK-CPP %s < %t.cpplog @@ -14,6 +14,11 @@ // RUN: not %clang -x c++ -std=c++11 -include %t.h -fsyntax-only %s 2> %t.cpp11log // RUN: FileCheck -check-prefix=CHECK-NO-SUITABLE %s < %t.cpp11log +// RUN: not %clang -include %t.h -fsyntax-only %s 2> %t.missinglog2 +// RUN: FileCheck -check-prefix=CHECK-NO-SUITABLE %s < %t.missinglog2 +// RUN: not %clang -include %t.h -DFOO=foo -DBAR=bar -fsyntax-only %s 2> %t.missinglog2 +// RUN: FileCheck -check-prefix=CHECK-NO-SUITABLE %s < %t.missinglog2 + // Don't crash if the precompiled header file is missing. // RUN: not %clang_cc1 -include-pch %t.h.gch -DFOO=baz -fsyntax-only %s -print-stats 2> %t.missinglog // RUN: FileCheck -check-prefix=CHECK-NO-SUITABLE %s < %t.missinglog