diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td index 2c5dfcca09..4ed49a0ee4 100644 --- a/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/include/clang/Basic/DiagnosticFrontendKinds.td @@ -123,5 +123,7 @@ def warn_cmdline_missing_macro_defs : Warning< "macro definitions used to build the precompiled header are missing">; def note_using_macro_def_from_pch : Note< "using this macro definition from precompiled header">; - +def warn_macro_name_used_in_pch : Warning< + "definition of macro %0 conflicts with an identifier used in the " + "precompiled header">; } diff --git a/include/clang/Frontend/PCHReader.h b/include/clang/Frontend/PCHReader.h index 907ab7e0da..cd23cac84b 100644 --- a/include/clang/Frontend/PCHReader.h +++ b/include/clang/Frontend/PCHReader.h @@ -280,6 +280,16 @@ private: /// Objective-C protocols. llvm::SmallVector InterestingDecls; + /// \brief The file ID for the predefines buffer in the PCH file. + FileID PCHPredefinesBufferID; + + /// \brief Pointer to the beginning of the predefines buffer in the + /// PCH file. + const char *PCHPredefines; + + /// \brief Length of the predefines buffer in the PCH file. + unsigned PCHPredefinesLen; + /// \brief Suggested contents of the predefines buffer, after this /// PCH file has been processed. /// diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index f1d7e7a558..e7404f899b 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -507,9 +507,17 @@ bool PCHReader::CheckPredefinesBuffer(const char *PCHPredef, std::string MacroName = Extra.substr(StartOfMacroName, EndOfMacroName - StartOfMacroName); - // FIXME: Perform this check! - fprintf(stderr, "FIXME: check whether '%s' was used in the PCH file\n", - MacroName.c_str()); + // Check whether this name was used somewhere in the PCH file. If + // so, defining it as a macro could change behavior, so we reject + // the PCH file. + if (IdentifierInfo *II = get(MacroName.c_str(), + MacroName.c_str() + MacroName.size())) { + Diag(diag::warn_macro_name_used_in_pch) + << II; + Diag(diag::note_ignoring_pch) + << FileName; + return true; + } // Add this definition to the suggested predefines buffer. SuggestedPredefines += Extra; @@ -818,9 +826,11 @@ PCHReader::PCHReadResult PCHReader::ReadSLocEntryRecord(unsigned ID) { Name); FileID BufferID = SourceMgr.createFileIDForMemBuffer(Buffer, ID, Offset); - if (strcmp(Name, "") == 0 - && CheckPredefinesBuffer(BlobStart, BlobLen - 1, BufferID)) - return IgnorePCH; + if (strcmp(Name, "") == 0) { + PCHPredefinesBufferID = BufferID; + PCHPredefines = BlobStart; + PCHPredefinesLen = BlobLen - 1; + } break; } @@ -1287,7 +1297,12 @@ PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) { // Load the translation unit declaration if (Context) ReadDeclRecord(DeclOffsets[0], 0); - + + // Check the predefines buffer. + if (CheckPredefinesBuffer(PCHPredefines, PCHPredefinesLen, + PCHPredefinesBufferID)) + return IgnorePCH; + // Initialization of builtins and library builtins occurs before the // PCH file is read, so there may be some identifiers that were // loaded into the IdentifierTable before we intercepted the diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index e61cca554b..11f620279c 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -1378,11 +1378,21 @@ void PCHWriter::WriteIdentifierTable(Preprocessor &PP) { // Create and write out the blob that contains the identifier // strings. - IdentifierOffsets.resize(IdentifierIDs.size()); { OnDiskChainedHashTableGenerator Generator; + // Look for any identifiers that were named while processing the + // headers, but are otherwise not needed. We add these to the hash + // table to enable checking of the predefines buffer in the case + // where the user adds new macro definitions when building the PCH + // file. + for (IdentifierTable::iterator ID = PP.getIdentifierTable().begin(), + IDEnd = PP.getIdentifierTable().end(); + ID != IDEnd; ++ID) + getIdentifierRef(ID->second); + // Create the on-disk hash table representation. + IdentifierOffsets.resize(IdentifierIDs.size()); for (llvm::DenseMap::iterator ID = IdentifierIDs.begin(), IDEnd = IdentifierIDs.end(); ID != IDEnd; ++ID) { diff --git a/test/PCH/fuzzy-pch.c b/test/PCH/fuzzy-pch.c index ce4634d756..2ddcb8bb08 100644 --- a/test/PCH/fuzzy-pch.c +++ b/test/PCH/fuzzy-pch.c @@ -1,6 +1,8 @@ // Test with pch. // RUN: clang-cc -emit-pch -DFOO -o %t %S/variables.h && -// RUN: clang-cc -DBAR=int -include-pch %t -fsyntax-only -pedantic %s +// RUN: clang-cc -DBAR=int -include-pch %t -fsyntax-only -pedantic %s && +// RUN: clang-cc -DFOO -DBAR=int -include-pch %t -Werror %s && +// RUN: not clang-cc -DFOO -DBAR=int -DX=5 -include-pch %t -Werror %s BAR bar = 17;