diff options
26 files changed, 474 insertions, 89 deletions
diff --git a/clang/include/clang/AST/ASTConsumer.h b/clang/include/clang/AST/ASTConsumer.h index 8418b5a45af..a183eb059c8 100644 --- a/clang/include/clang/AST/ASTConsumer.h +++ b/clang/include/clang/AST/ASTConsumer.h @@ -19,6 +19,7 @@ namespace clang { class CXXRecordDecl; class DeclGroupRef; class HandleTagDeclDefinition; + class PPMutationListener; class ASTMutationListener; class ASTDeserializationListener; // layering violation because void* is ugly class SemaConsumer; // layering violation required for safe SemaConsumer @@ -111,6 +112,11 @@ public: /// it was actually used. virtual void HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) {} + /// \brief If the consumer is interested in preprocessor entities getting + /// modified after their initial creation, it should return a pointer to + /// a PPMutationListener here. + virtual PPMutationListener *GetPPMutationListener() { return 0; } + /// \brief If the consumer is interested in entities getting modified after /// their initial creation, it should return a pointer to /// an ASTMutationListener here. diff --git a/clang/include/clang/AST/ASTMutationListener.h b/clang/include/clang/AST/ASTMutationListener.h index cb038a0a582..56d15260a58 100644 --- a/clang/include/clang/AST/ASTMutationListener.h +++ b/clang/include/clang/AST/ASTMutationListener.h @@ -13,6 +13,8 @@ #ifndef LLVM_CLANG_AST_ASTMUTATIONLISTENER_H #define LLVM_CLANG_AST_ASTMUTATIONLISTENER_H +#include "clang/Basic/SourceLocation.h" + namespace clang { class Decl; class DeclContext; diff --git a/clang/include/clang/Lex/PPMutationListener.h b/clang/include/clang/Lex/PPMutationListener.h new file mode 100644 index 00000000000..5319c66fa27 --- /dev/null +++ b/clang/include/clang/Lex/PPMutationListener.h @@ -0,0 +1,43 @@ +//===--- PPMutationListener.h - Preprocessor Mutation Interface -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the PPMutationListener interface. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_LEX_PPTMUTATIONLISTENER_H +#define LLVM_CLANG_LEX_PPTMUTATIONLISTENER_H + +#include "clang/Basic/SourceLocation.h" + +namespace clang { + +class MacroInfo; + +/// \brief A record that describes an update to a macro that was +/// originally loaded to an AST file and has been modified within the +/// current translation unit. +struct MacroUpdate { + /// \brief The source location at which this macro was #undef'd. + SourceLocation UndefLoc; +}; + +/// \brief An abstract interface that should be implemented by +/// listeners that want to be notified when a preprocessor entity gets +/// modified after its initial creation. +class PPMutationListener { +public: + virtual ~PPMutationListener(); + + /// \brief A macro has been #undef'd. + virtual void UndefinedMacro(MacroInfo *MI) { } +}; + +} // end namespace clang + +#endif diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h index 03ff02798ba..12b99af6e0c 100644 --- a/clang/include/clang/Lex/Preprocessor.h +++ b/clang/include/clang/Lex/Preprocessor.h @@ -18,6 +18,7 @@ #include "clang/Lex/Lexer.h" #include "clang/Lex/PTHLexer.h" #include "clang/Lex/PPCallbacks.h" +#include "clang/Lex/PPMutationListener.h" #include "clang/Lex/TokenLexer.h" #include "clang/Lex/PTHManager.h" #include "clang/Basic/Builtins.h" @@ -288,6 +289,11 @@ class Preprocessor : public RefCountedBase<Preprocessor> { /// encountered (e.g. a file is \#included, etc). PPCallbacks *Callbacks; + /// \brief Listener whose actions are invoked when an entity in the + /// preprocessor (e.g., a macro) that was loaded from an AST file is + /// later mutated. + PPMutationListener *Listener; + struct MacroExpandsInfo { Token Tok; MacroInfo *MI; @@ -480,6 +486,19 @@ public: Callbacks = C; } + /// \brief Attach an preprocessor mutation listener to the preprocessor. + /// + /// The preprocessor mutation listener provides the ability to track + /// modifications to the preprocessor entities committed after they were + /// initially created. + void setPPMutationListener(PPMutationListener *Listener) { + this->Listener = Listener; + } + + /// \brief Retrieve a pointer to the preprocessor mutation listener + /// associated with this preprocessor, if any. + PPMutationListener *getPPMutationListener() const { return Listener; } + /// \brief Given an identifier, return the MacroInfo it is \#defined to /// or null if it isn't \#define'd. MacroInfo *getMacroInfo(IdentifierInfo *II) const { @@ -1339,6 +1358,8 @@ private: // Macro handling. void HandleDefineDirective(Token &Tok); void HandleUndefDirective(Token &Tok); + void UndefineMacro(IdentifierInfo *II, MacroInfo *MI, + SourceLocation UndefLoc); // Conditional Inclusion. void HandleIfdefDirective(Token &Tok, bool isIfndef, diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index 57d896ee411..a0c62bb296c 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -126,7 +126,13 @@ namespace clang { /// \brief The number of predefined identifier IDs. const unsigned int NUM_PREDEF_IDENT_IDS = 1; + + /// \brief An ID number that refers to a macro in an AST file. + typedef uint32_t MacroID; + /// \brief The number of predefined macro IDs. + const unsigned int NUM_PREDEF_MACRO_IDS = 1; + /// \brief An ID number that refers to an ObjC selector in an AST file. typedef uint32_t SelectorID; @@ -472,7 +478,18 @@ namespace clang { /// /// This array can only be interpreted properly using the Objective-C /// categories map. - OBJC_CATEGORIES = 54 + OBJC_CATEGORIES = 54, + + /// \brief Record code for the table of offsets of each macro ID. + /// + /// The offset table contains offsets into the blob stored in + /// the preprocessor block. Each offset points to the corresponding + /// macro definition. + MACRO_OFFSET = 55, + + /// \brief Record of updates for a macro that was modified after + /// being deserialized. + MACRO_UPDATES = 56 }; /// \brief Record types used within a source manager block. diff --git a/clang/include/clang/Serialization/ASTDeserializationListener.h b/clang/include/clang/Serialization/ASTDeserializationListener.h index ab0d313a5c8..f24e39d8e1b 100644 --- a/clang/include/clang/Serialization/ASTDeserializationListener.h +++ b/clang/include/clang/Serialization/ASTDeserializationListener.h @@ -23,6 +23,7 @@ class Decl; class ASTReader; class QualType; class MacroDefinition; +class MacroInfo; class Module; class ASTDeserializationListener { @@ -37,6 +38,8 @@ public: /// \brief An identifier was deserialized from the AST file. virtual void IdentifierRead(serialization::IdentID ID, IdentifierInfo *II) { } + /// \brief A macro was read from the AST file. + virtual void MacroRead(serialization::MacroID ID, MacroInfo *MI) { } /// \brief A type was deserialized from the AST file. The ID here has the /// qualifier bits already removed, and T is guaranteed to be locally /// unqualified. diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index 5875a5052bb..a5fb396a501 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -24,6 +24,7 @@ #include "clang/AST/TemplateBase.h" #include "clang/Lex/ExternalPreprocessorSource.h" #include "clang/Lex/HeaderSearch.h" +#include "clang/Lex/PPMutationListener.h" #include "clang/Lex/PreprocessingRecord.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/FileManager.h" @@ -368,11 +369,33 @@ private: typedef ContinuousRangeMap<serialization::IdentID, ModuleFile *, 4> GlobalIdentifierMapType; - /// \brief Mapping from global identifer IDs to the module in which the + /// \brief Mapping from global identifier IDs to the module in which the /// identifier resides along with the offset that should be added to the /// global identifier ID to produce a local ID. GlobalIdentifierMapType GlobalIdentifierMap; + /// \brief A vector containing macros that have already been + /// loaded. + /// + /// If the pointer at index I is non-NULL, then it refers to the + /// MacroInfo for the identifier with ID=I+1 that has already + /// been loaded. + std::vector<MacroInfo *> MacrosLoaded; + + typedef ContinuousRangeMap<serialization::MacroID, ModuleFile *, 4> + GlobalMacroMapType; + + /// \brief Mapping from global macro IDs to the module in which the + /// macro resides along with the offset that should be added to the + /// global macro ID to produce a local ID. + GlobalMacroMapType GlobalMacroMap; + + typedef llvm::DenseMap<serialization::MacroID, MacroUpdate> MacroUpdatesMap; + + /// \brief Mapping from (global) macro IDs to the set of updates to be + /// performed to the corresponding macro. + MacroUpdatesMap MacroUpdates; + /// \brief A vector containing submodules that have already been loaded. /// /// This vector is indexed by the Submodule ID (-1). NULL submodule entries @@ -441,9 +464,8 @@ private: llvm::DenseMap<Selector, unsigned> SelectorGeneration; /// \brief Mapping from identifiers that represent macros whose definitions - /// have not yet been deserialized to the global offset where the macro - /// record resides. - llvm::DenseMap<IdentifierInfo *, uint64_t> UnreadMacroRecordOffsets; + /// have not yet been deserialized to the global ID of the macro. + llvm::DenseMap<IdentifierInfo *, serialization::MacroID> UnreadMacroIDs; typedef ContinuousRangeMap<unsigned, ModuleFile *, 4> GlobalPreprocessedEntityMapType; @@ -1065,6 +1087,11 @@ public: return static_cast<unsigned>(IdentifiersLoaded.size()); } + /// \brief Returns the number of macros found in the chain. + unsigned getTotalNumMacros() const { + return static_cast<unsigned>(MacrosLoaded.size()); + } + /// \brief Returns the number of types found in the chain. unsigned getTotalNumTypes() const { return static_cast<unsigned>(TypesLoaded.size()); @@ -1366,6 +1393,13 @@ public: serialization::IdentifierID getGlobalIdentifierID(ModuleFile &M, unsigned LocalID); + /// \brief Retrieve the macro with the given ID. + MacroInfo *getMacro(serialization::MacroID ID); + + /// \brief Retrieve the global macro ID corresponding to the given local + /// ID within the given module file. + serialization::MacroID getGlobalMacroID(ModuleFile &M, unsigned LocalID); + /// \brief Read the source location entry with index ID. virtual bool ReadSLocEntry(int ID); @@ -1521,14 +1555,11 @@ public: /// /// \param II The name of the macro. /// - /// \param F The module file from which the macro definition was deserialized. - /// - /// \param Offset The offset into the module file at which the macro - /// definition is located. + /// \param ID The global macro ID. /// /// \param Visible Whether the macro should be made visible. - void setIdentifierIsMacro(IdentifierInfo *II, ModuleFile &F, - uint64_t Offset, bool Visible); + void setIdentifierIsMacro(IdentifierInfo *II, serialization::MacroID ID, + bool Visible); /// \brief Read the set of macros defined by this external macro source. virtual void ReadDefinedMacros(); @@ -1541,11 +1572,11 @@ public: /// \brief Note that this identifier is up-to-date. void markIdentifierUpToDate(IdentifierInfo *II); - + /// \brief Read the macro definition corresponding to this iterator /// into the unread macro record offsets table. void LoadMacroDefinition( - llvm::DenseMap<IdentifierInfo *, uint64_t>::iterator Pos); + llvm::DenseMap<IdentifierInfo *,serialization::MacroID>::iterator Pos); /// \brief Load all external visible decls in the given DeclContext. void completeVisibleDeclsMap(const DeclContext *DC); diff --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h index d95b249a28b..db5b8ca99e2 100644 --- a/clang/include/clang/Serialization/ASTWriter.h +++ b/clang/include/clang/Serialization/ASTWriter.h @@ -18,6 +18,7 @@ #include "clang/AST/DeclarationName.h" #include "clang/AST/TemplateBase.h" #include "clang/AST/ASTMutationListener.h" +#include "clang/Lex/PPMutationListener.h" #include "clang/Serialization/ASTBitCodes.h" #include "clang/Serialization/ASTDeserializationListener.h" #include "clang/Sema/SemaConsumer.h" @@ -25,6 +26,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/MapVector.h" #include "llvm/ADT/SetVector.h" #include "llvm/Bitcode/BitstreamWriter.h" #include <map> @@ -51,6 +53,7 @@ class MemorizeStatCalls; class OpaqueValueExpr; class OpenCLOptions; class ASTReader; +class MacroInfo; class Module; class PreprocessedEntity; class PreprocessingRecord; @@ -70,6 +73,7 @@ namespace SrcMgr { class SLocEntry; } /// data structures. This bitstream can be de-serialized via an /// instance of the ASTReader class. class ASTWriter : public ASTDeserializationListener, + public PPMutationListener, public ASTMutationListener { public: typedef SmallVector<uint64_t, 64> RecordData; @@ -214,6 +218,15 @@ private: /// IdentifierInfo. llvm::DenseMap<const IdentifierInfo *, serialization::IdentID> IdentifierIDs; + /// \brief The first ID number we can use for our own macros. + serialization::MacroID FirstMacroID; + + /// \brief The identifier ID that will be assigned to the next new identifier. + serialization::MacroID NextMacroID; + + /// \brief Map that provides the ID numbers of each macro. + llvm::DenseMap<MacroInfo *, serialization::MacroID> MacroIDs; + /// @name FlushStmt Caches /// @{ @@ -249,17 +262,14 @@ private: /// table, indexed by the Selector ID (-1). std::vector<uint32_t> SelectorOffsets; - /// \brief Offsets of each of the macro identifiers into the - /// bitstream. - /// - /// For each identifier that is associated with a macro, this map - /// provides the offset into the bitstream where that macro is - /// defined. - llvm::DenseMap<const IdentifierInfo *, uint64_t> MacroOffsets; - /// \brief The set of identifiers that had macro definitions at some point. std::vector<const IdentifierInfo *> DeserializedMacroNames; + typedef llvm::MapVector<MacroInfo *, MacroUpdate> MacroUpdatesMap; + + /// \brief Updates to macro definitions that were loaded from an AST file. + MacroUpdatesMap MacroUpdates; + /// \brief Mapping from macro definitions (as they occur in the preprocessing /// record) to the macro IDs. llvm::DenseMap<const MacroDefinition *, serialization::PreprocessedEntityID> @@ -427,6 +437,7 @@ private: void WriteIdentifierTable(Preprocessor &PP, IdentifierResolver &IdResolver, bool IsModule); void WriteAttributes(ArrayRef<const Attr*> Attrs, RecordDataImpl &Record); + void WriteMacroUpdates(); void ResolveDeclUpdatesBlocks(); void WriteDeclUpdatesBlocks(); void WriteDeclReplacementsBlock(); @@ -500,6 +511,9 @@ public: /// \brief Emit a reference to an identifier. void AddIdentifierRef(const IdentifierInfo *II, RecordDataImpl &Record); + /// \brief Emit a reference to a macro. + void addMacroRef(MacroInfo *MI, RecordDataImpl &Record); + /// \brief Emit a Selector (which is a smart pointer reference). void AddSelectorRef(Selector, RecordDataImpl &Record); @@ -517,15 +531,8 @@ public: /// \brief Get the unique number used to refer to the given identifier. serialization::IdentID getIdentifierRef(const IdentifierInfo *II); - /// \brief Retrieve the offset of the macro definition for the given - /// identifier. - /// - /// The identifier must refer to a macro. - uint64_t getMacroOffset(const IdentifierInfo *II) { - assert(MacroOffsets.find(II) != MacroOffsets.end() && - "Identifier does not name a macro"); - return MacroOffsets[II]; - } + /// \brief Get the unique number used to refer to the given macro. + serialization::MacroID getMacroRef(MacroInfo *MI); /// \brief Emit a reference to a type. void AddTypeRef(QualType T, RecordDataImpl &Record); @@ -688,13 +695,17 @@ public: // ASTDeserializationListener implementation void ReaderInitialized(ASTReader *Reader); void IdentifierRead(serialization::IdentID ID, IdentifierInfo *II); + void MacroRead(serialization::MacroID ID, MacroInfo *MI); void TypeRead(serialization::TypeIdx Idx, QualType T); void SelectorRead(serialization::SelectorID ID, Selector Sel); void MacroDefinitionRead(serialization::PreprocessedEntityID ID, MacroDefinition *MD); void MacroVisible(IdentifierInfo *II); void ModuleRead(serialization::SubmoduleID ID, Module *Mod); - + + // PPMutationListener implementation. + virtual void UndefinedMacro(MacroInfo *MI); + // ASTMutationListener implementation. virtual void CompletedTagDefinition(const TagDecl *D); virtual void AddedVisibleDecl(const DeclContext *DC, const Decl *D); @@ -737,6 +748,7 @@ public: ~PCHGenerator(); virtual void InitializeSema(Sema &S) { SemaPtr = &S; } virtual void HandleTranslationUnit(ASTContext &Ctx); + virtual PPMutationListener *GetPPMutationListener(); virtual ASTMutationListener *GetASTMutationListener(); virtual ASTDeserializationListener *GetASTDeserializationListener(); }; diff --git a/clang/include/clang/Serialization/Module.h b/clang/include/clang/Serialization/Module.h index 87a0e40e9e9..ecf0ae13494 100644 --- a/clang/include/clang/Serialization/Module.h +++ b/clang/include/clang/Serialization/Module.h @@ -173,6 +173,22 @@ public: /// all of the macro definitions. llvm::BitstreamCursor MacroCursor; + /// \brief The number of macros in this AST file. + unsigned LocalNumMacros; + + /// \brief Offsets of macros in the preprocessor block. + /// + /// This array is indexed by the macro ID (-1), and provides + /// the offset into the preprocessor block where macro definitions are + /// stored. + const uint32_t *MacroOffsets; + + /// \brief Base macro ID for macros local to this module. + serialization::MacroID BaseMacroID; + + /// \brief Remapping table for macro IDs in this module. + ContinuousRangeMap<uint32_t, int, 2> MacroRemap; + /// \brief The offset of the start of the set of defined macros. uint64_t MacroStartOffset; diff --git a/clang/lib/Frontend/ChainedIncludesSource.cpp b/clang/lib/Frontend/ChainedIncludesSource.cpp index dbb06bd23cd..5f7ff74bc6f 100644 --- a/clang/lib/Frontend/ChainedIncludesSource.cpp +++ b/clang/lib/Frontend/ChainedIncludesSource.cpp @@ -108,6 +108,8 @@ ChainedIncludesSource *ChainedIncludesSource::create(CompilerInstance &CI) { OwningPtr<ASTConsumer> consumer; consumer.reset(new PCHGenerator(Clang->getPreprocessor(), "-", 0, /*isysroot=*/"", &OS)); + Clang->getPreprocessor().setPPMutationListener( + consumer->GetPPMutationListener()); Clang->getASTContext().setASTMutationListener( consumer->GetASTMutationListener()); Clang->setASTConsumer(consumer.take()); diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index bf46e549b5d..24f38d428b0 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -946,6 +946,8 @@ Module *CompilerInstance::loadModule(SourceLocation ImportLoc, getASTConsumer().GetASTDeserializationListener()); getASTContext().setASTMutationListener( getASTConsumer().GetASTMutationListener()); + getPreprocessor().setPPMutationListener( + getASTConsumer().GetPPMutationListener()); } OwningPtr<ExternalASTSource> Source; Source.reset(ModuleManager); diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp index a4321e720ed..ca8511247a3 100644 --- a/clang/lib/Frontend/FrontendAction.cpp +++ b/clang/lib/Frontend/FrontendAction.cpp @@ -247,7 +247,9 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, goto failure; CI.getASTContext().setASTMutationListener(Consumer->GetASTMutationListener()); - + CI.getPreprocessor().setPPMutationListener( + Consumer->GetPPMutationListener()); + if (!CI.getPreprocessorOpts().ChainedIncludes.empty()) { // Convert headers to PCH and chain them. OwningPtr<ExternalASTSource> source; diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp index 23cbef63edf..9314517ed3a 100644 --- a/clang/lib/Lex/PPDirectives.cpp +++ b/clang/lib/Lex/PPDirectives.cpp @@ -1944,8 +1944,20 @@ void Preprocessor::HandleUndefDirective(Token &UndefTok) { if (MI->isWarnIfUnused()) WarnUnusedMacroLocs.erase(MI->getDefinitionLoc()); - MI->setUndefLoc(MacroNameTok.getLocation()); - clearMacroInfo(MacroNameTok.getIdentifierInfo()); + UndefineMacro(MacroNameTok.getIdentifierInfo(), MI, + MacroNameTok.getLocation()); +} + +void Preprocessor::UndefineMacro(IdentifierInfo *II, MacroInfo *MI, + SourceLocation UndefLoc) { + MI->setUndefLoc(UndefLoc); + if (MI->isFromAST()) { + MI->setChangedAfterLoad(); + if (Listener) + Listener->UndefinedMacro(MI); + } + + clearMacroInfo(II); } diff --git a/clang/lib/Lex/Pragma.cpp b/clang/lib/Lex/Pragma.cpp index b5bc9583f6c..1f9c811f55c 100644 --- a/clang/lib/Lex/Pragma.cpp +++ b/clang/lib/Lex/Pragma.cpp @@ -737,7 +737,7 @@ void Preprocessor::HandlePragmaPopMacro(Token &PopMacroTok) { if (MacroInfo *CurrentMI = getMacroInfo(IdentInfo)) { if (CurrentMI->isWarnIfUnused()) WarnUnusedMacroLocs.erase(CurrentMI->getDefinitionLoc()); - CurrentMI->setUndefLoc(MessageLoc); + UndefineMacro(IdentInfo, CurrentMI, MessageLoc); } // Get the MacroInfo we want to reinstall. diff --git a/clang/lib/Lex/Preprocessor.cpp b/clang/lib/Lex/Preprocessor.cpp index a0fc265b6b3..d9f206901d2 100644 --- a/clang/lib/Lex/Preprocessor.cpp +++ b/clang/lib/Lex/Preprocessor.cpp @@ -49,6 +49,8 @@ using namespace clang; //===----------------------------------------------------------------------===// ExternalPreprocessorSource::~ExternalPreprocessorSource() { } +PPMutationListener::~PPMutationListener() { } + Preprocessor::Preprocessor(DiagnosticsEngine &diags, LangOptions &opts, const TargetInfo *target, SourceManager &SM, HeaderSearch &Headers, ModuleLoader &TheModuleLoader, @@ -62,8 +64,8 @@ Preprocessor::Preprocessor(DiagnosticsEngine &diags, LangOptions &opts, IncrementalProcessing(IncrProcessing), CodeComplete(0), CodeCompletionFile(0), CodeCompletionOffset(0), CodeCompletionReached(0), SkipMainFilePreamble(0, true), CurPPLexer(0), - CurDirLookup(0), CurLexerKind(CLK_Lexer), Callbacks(0), MacroArgCache(0), - Record(0), MIChainHead(0), MICache(0) + CurDirLookup(0), CurLexerKind(CLK_Lexer), Callbacks(0), Listener(0), + MacroArgCache(0), Record(0), MIChainHead(0), MICache(0) { OwnsHeaderSearch = OwnsHeaders; diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index b7266ebbba5..cdb9646758c 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -573,7 +573,7 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k, // definition. if (hadMacroDefinition) { // FIXME: Check for conflicts? - uint32_t Offset = ReadUnalignedLE32(d); + uint32_t LocalID = ReadUnalignedLE32(d); unsigned LocalSubmoduleID = ReadUnalignedLE32(d); // Determine whether this macro definition should be visible now, or @@ -594,7 +594,8 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k, } } - Reader.setIdentifierIsMacro(II, F, Offset, Visible && hasMacroDefinition); + Reader.setIdentifierIsMacro(II, Reader.getGlobalMacroID(F, LocalID), + Visible && hasMacroDefinition); DataLen -= 8; } @@ -1314,10 +1315,19 @@ void ASTReader::ReadMacroRecord(ModuleFile &F, uint64_t Offset) { return; } - unsigned NextIndex = 1; + unsigned GlobalID = getGlobalMacroID(F, Record[1]); + + // If this macro has already been loaded, don't do so again. + if (MacrosLoaded[GlobalID - NUM_PREDEF_MACRO_IDS]) + return; + + unsigned NextIndex = 2; SourceLocation Loc = ReadSourceLocation(F, Record, NextIndex); MacroInfo *MI = PP.AllocateMacroInfo(Loc); + // Record this macro. + MacrosLoaded[GlobalID - NUM_PREDEF_MACRO_IDS] = MI; + SourceLocation UndefLoc = ReadSourceLocation(F, Record, NextIndex); if (UndefLoc.isValid()) MI->setUndefLoc(UndefLoc); @@ -1345,6 +1355,20 @@ void ASTReader::ReadMacroRecord(ModuleFile &F, uint64_t Offset) { PP.getPreprocessorAllocator()); } + if (DeserializationListener) + DeserializationListener->MacroRead(GlobalID, MI); + + // If an update record marked this as undefined, do so now. + MacroUpdatesMap::iterator Update = MacroUpdates.find(GlobalID); + if (Update != MacroUpdates.end()) { + if (MI->getUndefLoc().isInvalid()) { + MI->setUndefLoc(Update->second.UndefLoc); + if (PPMutationListener *Listener = PP.getPPMutationListener()) + Listener->UndefinedMacro(MI); + } + MacroUpdates.erase(Update); + } + // Finally, install the macro. PP.setMacroInfo(II, MI, /*LoadedFromAST=*/true); @@ -1455,17 +1479,18 @@ HeaderFileInfoTrait::ReadData(const internal_key_type, const unsigned char *d, return HFI; } -void ASTReader::setIdentifierIsMacro(IdentifierInfo *II, ModuleFile &F, - uint64_t LocalOffset, bool Visible) { +void ASTReader::setIdentifierIsMacro(IdentifierInfo *II, MacroID ID, + bool Visible) { if (Visible) { // Note that this identifier has a macro definition. II->setHasMacroDefinition(true); } else { II->setHadMacroDefinition(true); } - - // Adjust the offset to a global offset. - UnreadMacroRecordOffsets[II] = F.GlobalBitOffset + LocalOffset; + + // FIXME: This could end up overwriting a previously recording macro + // definition here, which is not cool at all. + UnreadMacroIDs[II] = ID; } void ASTReader::ReadDefinedMacros() { @@ -1522,23 +1547,21 @@ void ASTReader::ReadDefinedMacros() { } // Drain the unread macro-record offsets map. - while (!UnreadMacroRecordOffsets.empty()) - LoadMacroDefinition(UnreadMacroRecordOffsets.begin()); + while (!UnreadMacroIDs.empty()) + LoadMacroDefinition(UnreadMacroIDs.begin()); } void ASTReader::LoadMacroDefinition( - llvm::DenseMap<IdentifierInfo *, uint64_t>::iterator Pos) { - assert(Pos != UnreadMacroRecordOffsets.end() && "Unknown macro definition"); - uint64_t Offset = Pos->second; - UnreadMacroRecordOffsets.erase(Pos); - - RecordLocation Loc = getLocalBitOffset(Offset); - ReadMacroRecord(*Loc.F, Loc.Offset); + llvm::DenseMap<IdentifierInfo *, MacroID>::iterator Pos) { + assert(Pos != UnreadMacroIDs.end() && "Unknown macro definition"); + uint64_t GlobalID = Pos->second; + UnreadMacroIDs.erase(Pos); + getMacro(GlobalID); } void ASTReader::LoadMacroDefinition(IdentifierInfo *II) { - llvm::DenseMap<IdentifierInfo *, uint64_t>::iterator Pos - = UnreadMacroRecordOffsets.find(II); + llvm::DenseMap<IdentifierInfo *, MacroID>::iterator Pos + = UnreadMacroIDs.find(II); LoadMacroDefinition(Pos); } @@ -1959,7 +1982,7 @@ ASTReader::ReadASTBlock(ModuleFile &F) { } break; } - + case EXTERNAL_DEFINITIONS: for (unsigned I = 0, N = Record.size(); I != N; ++I) ExternalDefinitions.push_back(getGlobalDeclID(F, Record[I])); @@ -2109,7 +2132,9 @@ ASTReader::ReadASTBlock(ModuleFile &F) { ContinuousRangeMap<uint32_t, int, 2>::Builder SLocRemap(F.SLocRemap); ContinuousRangeMap<uint32_t, int, 2>::Builder IdentifierRemap(F.IdentifierRemap); - ContinuousRangeMap<uint32_t, int, 2>::Builder + ContinuousRangeMap<uint32_t, int, 2>::Builder + MacroRemap(F.MacroRemap); + ContinuousRangeMap<uint32_t, int, 2>::Builder PreprocessedEntityRemap(F.PreprocessedEntityRemap); ContinuousRangeMap<uint32_t, int, 2>::Builder SubmoduleRemap(F.SubmoduleRemap); @@ -2130,6 +2155,7 @@ ASTReader::ReadASTBlock(ModuleFile &F) { uint32_t SLocOffset = io::ReadUnalignedLE32(Data); uint32_t IdentifierIDOffset = io::ReadUnalignedLE32(Data); + uint32_t MacroIDOffset = io::ReadUnalignedLE32(Data); uint32_t PreprocessedEntityIDOffset = io::ReadUnalignedLE32(Data); uint32_t SubmoduleIDOffset = io::ReadUnalignedLE32(Data); uint32_t SelectorIDOffset = io::ReadUnalignedLE32(Data); @@ -2142,6 +2168,8 @@ ASTReader::ReadASTBlock(ModuleFile &F) { IdentifierRemap.insert( std::make_pair(IdentifierIDOffset, OM->BaseIdentifierID - IdentifierIDOffset)); + MacroRemap.insert(std::make_pair(MacroIDOffset, + OM->BaseMacroID - MacroIDOffset)); PreprocessedEntityRemap.insert( std::make_pair(PreprocessedEntityIDOffset, OM->BasePreprocessedEntityID - PreprocessedEntityIDOffset)); @@ -2458,6 +2486,41 @@ ASTReader::ReadASTBlock(ModuleFile &F) { } break; } + + case MACRO_OFFSET: { + if (F.LocalNumMacros != 0) { + Error("duplicate MACRO_OFFSET record in AST file"); + return Failure; + } + F.MacroOffsets = (const uint32_t *)BlobStart; + F.LocalNumMacros = Record[0]; + unsigned LocalBaseMacroID = Record[1]; + F.BaseMacroID = getTotalNumMacros(); + + if (F.LocalNumMacros > 0) { + // Introduce the global -> local mapping for macros within this module. + GlobalMacroMap.insert(std::make_pair(getTotalNumMacros() + 1, &F)); + + // Introduce the local -> global mapping for macros within this module. + F.MacroRemap.insertOrReplace( + std::make_pair(LocalBaseMacroID, + F.BaseMacroID - LocalBaseMacroID)); + + MacrosLoaded.resize(MacrosLoaded.size() + F.LocalNumMacros); + } + break; + } + + case MACRO_UPDATES: { + for (unsigned I = 0, N = Record.size(); I != N; /* in loop */) { + MacroID ID = getGlobalMacroID(F, Record[I++]); + if (I == N) + break; + + MacroUpdates[ID].UndefLoc = ReadSourceLocation(F, Record, I); + } + break; + } } } Error("premature end of bitstream in AST file"); @@ -5195,6 +5258,10 @@ void ASTReader::PrintStats() { = IdentifiersLoaded.size() - std::count(IdentifiersLoaded.begin(), IdentifiersLoaded.end(), (IdentifierInfo *)0); + unsigned NumMacrosLoaded + = MacrosLoaded.size() - std::count(MacrosLoaded.begin(), + MacrosLoaded.end(), + (MacroInfo *)0); unsigned NumSelectorsLoaded = SelectorsLoaded.size() - std::count(SelectorsLoaded.begin(), SelectorsLoaded.end(), @@ -5218,6 +5285,10 @@ void ASTReader::PrintStats() { std::fprintf(stderr, " %u/%u identifiers read (%f%%)\n", NumIdentifiersLoaded, (unsigned)IdentifiersLoaded.size(), ((float)NumIdentifiersLoaded/IdentifiersLoaded.size() * 100)); + if (!MacrosLoaded.empty()) + std::fprintf(stderr, " %u/%u macros read (%f%%)\n", + NumMacrosLoaded, (unsigned)MacrosLoaded.size(), + ((float)NumMacrosLoaded/MacrosLoaded.size() * 100)); if (!SelectorsLoaded.empty()) std::fprintf(stderr, " %u/%u selectors read (%f%%)\n", NumSelectorsLoaded, (unsigned)SelectorsLoaded.size(), @@ -5276,6 +5347,7 @@ void ASTReader::dump() { dumpModuleIDMap("Global type map", GlobalTypeMap); dumpModuleIDMap("Global declaration map", GlobalDeclMap); dumpModuleIDMap("Global identifier map", GlobalIdentifierMap); + dumpModuleIDMap("Global macro map", GlobalMacroMap); dumpModuleIDMap("Global submodule map", GlobalSubmoduleMap); dumpModuleIDMap("Global selector map", GlobalSelectorMap); dumpModuleIDMap("Global preprocessed entity map", @@ -5746,6 +5818,39 @@ IdentifierID ASTReader::getGlobalIdentifierID(ModuleFile &M, unsigned LocalID) { return LocalID + I->second; } +MacroInfo *ASTReader::getMacro(MacroID ID) { + if (ID == 0) + return 0; + + if (MacrosLoaded.empty()) { + Error("no macro table in AST file"); + return 0; + } + + ID -= NUM_PREDEF_MACRO_IDS; + if (!MacrosLoaded[ID]) { + GlobalMacroMapType::iterator I + = GlobalMacroMap.find(ID + NUM_PREDEF_MACRO_IDS); + assert(I != GlobalMacroMap.end() && "Corrupted global macro map"); + ModuleFile *M = I->second; + unsigned Index = ID - M->BaseMacroID; + ReadMacroRecord(*M, M->MacroOffsets[Index]); + } + + return MacrosLoaded[ID]; +} + +MacroID ASTReader::getGlobalMacroID(ModuleFile &M, unsigned LocalID) { + if (LocalID < NUM_PREDEF_MACRO_IDS) + return LocalID; + + ContinuousRangeMap<uint32_t, int, 2>::iterator I + = M.MacroRemap.find(LocalID - NUM_PREDEF_MACRO_IDS); + assert(I != M.MacroRemap.end() && "Invalid index into macro index remap"); + + return LocalID + I->second; +} + bool ASTReader::ReadSLocEntry(int ID) { return ReadSLocEntryRecord(ID) != Success; } @@ -5758,7 +5863,7 @@ ASTReader::getGlobalSubmoduleID(ModuleFile &M, unsigned LocalID) { ContinuousRangeMap<uint32_t, int, 2>::iterator I = M.SubmoduleRemap.find(LocalID - NUM_PREDEF_SUBMODULE_IDS); assert(I != M.SubmoduleRemap.end() - && "Invalid index into identifier index remap"); + && "Invalid index into submodule index remap"); return LocalID + I->second; } @@ -5823,7 +5928,7 @@ ASTReader::getGlobalSelectorID(ModuleFile &M, unsigned LocalID) const { ContinuousRangeMap<uint32_t, int, 2>::iterator I = M.SelectorRemap.find(LocalID - NUM_PREDEF_SELECTOR_IDS); assert(I != M.SelectorRemap.end() - && "Invalid index into identifier index remap"); + && "Invalid index into selector index remap"); return LocalID + I->second; } diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 19a236fde2f..76eb1a1a8a1 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -820,6 +820,8 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(MERGED_DECLARATIONS); RECORD(LOCAL_REDECLARATIONS); RECORD(OBJC_CATEGORIES); + RECORD(MACRO_OFFSET); + RECORD(MACRO_UPDATES); // SourceManager Block. BLOCK(SOURCE_MANAGER_BLOCK); @@ -1702,37 +1704,46 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) { PP.getMacroInfoHistory(Name))); } + /// \brief Offsets of each of the macros into the bitstream, indexed by + /// the local macro ID + /// + /// For each identifier that is associated with a macro, this map + /// provides the offset into the bitstream where that macro is + /// defined. + std::vector<uint32_t> MacroOffsets; + for (unsigned I = 0, N = MacrosToEmit.size(); I != N; ++I) { const IdentifierInfo *Name = MacrosToEmit[I].first; - MacroInfo *MI = MacrosToEmit[I].second; - // History of macro definitions for this identifier in chronological order. - SmallVector<MacroInfo*, 8> MacroHistory; - while (MI) { - MacroHistory.push_back(MI); - MI = MI->getPreviousDefinition(); - } + for (MacroInfo *MI = MacrosToEmit[I].second; MI; + MI = MI->getPreviousDefinition()) { + MacroID ID = getMacroRef(MI); + if (!ID) + continue; + + // Skip macros from a AST file if we're chaining. + if (Chain && MI->isFromAST() && !MI->hasChangedAfterLoad()) + continue; - while (!MacroHistory.empty()) { - MI = MacroHistory.pop_back_val(); - - // Don't emit builtin macros like __LINE__ to the AST file unless they - // have been redefined by the header (in which case they are not - // isBuiltinMacro). - // Also skip macros from a AST file if we're chaining. - - // FIXME: There is a (probably minor) optimization we could do here, if - // the macro comes from the original PCH but the identifier comes from a - // chained PCH, by storing the offset into the original PCH rather than - // writing the macro definition a second time. - if (MI->isBuiltinMacro() || - (Chain && - Name->isFromAST() && !Name->hasChangedSinceDeserialization() && - MI->isFromAST() && !MI->hasChangedAfterLoad())) + if (ID < FirstMacroID) { + // This will have been dealt with via an update record. + assert(MacroUpdates.count(MI) > 0 && "Missing macro update"); continue; + } + + // Record the local offset of this macro. + unsigned Index = ID - FirstMacroID; + if (Index == MacroOffsets.size()) + MacroOffsets.push_back(Stream.GetCurrentBitNo()); + else { + if (Index > MacroOffsets.size()) + MacroOffsets.resize(Index + 1); + + MacroOffsets[Index] = Stream.GetCurrentBitNo(); + } AddIdentifierRef(Name, Record); - MacroOffsets[Name] = Stream.GetCurrentBitNo(); + addMacroRef(MI, Record); AddSourceLocation(MI->getDefinitionLoc(), Record); AddSourceLocation(MI->getUndefLoc(), Record); Record.push_back(MI->isUsed()); @@ -1785,6 +1796,22 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) { } } Stream.ExitBlock(); + + // Write the offsets table for macro IDs. + using namespace llvm; + BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); + Abbrev->Add(BitCodeAbbrevOp(MACRO_OFFSET)); + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of macros + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // first ID + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); + + unsigned MacroOffsetAbbrev = Stream.EmitAbbrev(Abbrev); + Record.clear(); + Record.push_back(MACRO_OFFSET); + Record.push_back(MacroOffsets.size()); + Record.push_back(FirstMacroID - NUM_PREDEF_MACRO_IDS); + Stream.EmitRecordWithBlob(MacroOffsetAbbrev, Record, + data(MacroOffsets)); } void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec) { @@ -2608,7 +2635,7 @@ public: clang::io::Emit16(Out, Bits); if (HadMacroDefinition) { - clang::io::Emit32(Out, Writer.getMacroOffset(II)); + clang::io::Emit32(Out, Writer.getMacroRef(Macro)); clang::io::Emit32(Out, Writer.inferSubmoduleIDFromLocation(Macro->getDefinitionLoc())); } @@ -3182,7 +3209,8 @@ ASTWriter::ASTWriter(llvm::BitstreamWriter &Stream) ASTHasCompilerErrors(false), FirstDeclID(NUM_PREDEF_DECL_IDS), NextDeclID(FirstDeclID), FirstTypeID(NUM_PREDEF_TYPE_IDS), NextTypeID(FirstTypeID), - FirstIdentID(NUM_PREDEF_IDENT_IDS), NextIdentID(FirstIdentID), + FirstIdentID(NUM_PREDEF_IDENT_IDS), NextIdentID(FirstIdentID), + FirstMacroID(NUM_PREDEF_MACRO_IDS), NextMacroID(FirstMacroID), FirstSubmoduleID(NUM_PREDEF_SUBMODULE_IDS), NextSubmoduleID(FirstSubmoduleID), FirstSelectorID(NUM_PREDEF_SELECTOR_IDS), NextSelectorID(FirstSelectorID), @@ -3517,6 +3545,7 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, Out.write(FileName.data(), FileName.size()); io::Emit32(Out, (*M)->SLocEntryBaseOffset); io::Emit32(Out, (*M)->BaseIdentifierID); + io::Emit32(Out, (*M)->BaseMacroID); io::Emit32(Out, (*M)->BasePreprocessedEntityID); io::Emit32(Out, (*M)->BaseSubmoduleID); io::Emit32(Out, (*M)->BaseSelectorID); @@ -3630,7 +3659,8 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, Stream.EmitRecord(IMPORTED_MODULES, ImportedModules); } } - + + WriteMacroUpdates(); WriteDeclUpdatesBlocks(); WriteDeclReplacementsBlock(); WriteMergedDecls(); @@ -3647,6 +3677,20 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, Stream.ExitBlock(); } +void ASTWriter::WriteMacroUpdates() { + if (MacroUpdates.empty()) + return; + + RecordData Record; + for (MacroUpdatesMap::iterator I = MacroUpdates.begin(), + E = MacroUpdates.end(); + I != E; ++I) { + addMacroRef(I->first, Record); + AddSourceLocation(I->second.UndefLoc, Record); + } + Stream.EmitRecord(MACRO_UPDATES, Record); +} + /// \brief Go through the declaration update blocks and resolve declaration /// pointers into declaration IDs. void ASTWriter::ResolveDeclUpdatesBlocks() { @@ -3742,6 +3786,10 @@ void ASTWriter::AddIdentifierRef(const IdentifierInfo *II, RecordDataImpl &Recor Record.push_back(getIdentifierRef(II)); } +void ASTWriter::addMacroRef(MacroInfo *MI, RecordDataImpl &Record) { + Record.push_back(getMacroRef(MI)); +} + IdentID ASTWriter::getIdentifierRef(const IdentifierInfo *II) { if (II == 0) return 0; @@ -3752,6 +3800,19 @@ IdentID ASTWriter::getIdentifierRef(const IdentifierInfo *II) { return ID; } +MacroID ASTWriter::getMacroRef(MacroInfo *MI) { + // Don't emit builtin macros like __LINE__ to the AST file unless they + // have been redefined by the header (in which case they are not + // isBuiltinMacro). + if (MI == 0 || MI->isBuiltinMacro()) + return 0; + + MacroID &ID = MacroIDs[MI]; + if (ID == 0) + ID = NextMacroID++; + return ID; +} + void ASTWriter::AddSelectorRef(const Selector SelRef, RecordDataImpl &Record) { Record.push_back(getSelectorRef(SelRef)); } @@ -4464,6 +4525,7 @@ void ASTWriter::ReaderInitialized(ASTReader *Reader) { assert(FirstDeclID == NextDeclID && FirstTypeID == NextTypeID && FirstIdentID == NextIdentID && + FirstMacroID == NextMacroID && FirstSubmoduleID == NextSubmoduleID && FirstSelectorID == NextSelectorID && "Setting chain after writing has started."); @@ -4473,11 +4535,13 @@ void ASTWriter::ReaderInitialized(ASTReader *Reader) { FirstDeclID = NUM_PREDEF_DECL_IDS + Chain->getTotalNumDecls(); FirstTypeID = NUM_PREDEF_TYPE_IDS + Chain->getTotalNumTypes(); FirstIdentID = NUM_PREDEF_IDENT_IDS + Chain->getTotalNumIdentifiers(); + FirstMacroID = NUM_PREDEF_MACRO_IDS + Chain->getTotalNumMacros(); FirstSubmoduleID = NUM_PREDEF_SUBMODULE_IDS + Chain->getTotalNumSubmodules(); FirstSelectorID = NUM_PREDEF_SELECTOR_IDS + Chain->getTotalNumSelectors(); NextDeclID = FirstDeclID; NextTypeID = FirstTypeID; NextIdentID = FirstIdentID; + NextMacroID = FirstMacroID; NextSelectorID = FirstSelectorID; NextSubmoduleID = FirstSubmoduleID; } @@ -4488,6 +4552,10 @@ void ASTWriter::IdentifierRead(IdentID ID, IdentifierInfo *II) { DeserializedMacroNames.push_back(II); } +void ASTWriter::MacroRead(serialization::MacroID ID, MacroInfo *MI) { + MacroIDs[MI] = ID; +} + void ASTWriter::TypeRead(TypeIdx Idx, QualType T) { // Always take the highest-numbered type index. This copes with an interesting // case for chained AST writing where we schedule writing the type and then, @@ -4518,6 +4586,10 @@ void ASTWriter::ModuleRead(serialization::SubmoduleID ID, Module *Mod) { SubmoduleIDs[Mod] = ID; } +void ASTWriter::UndefinedMacro(MacroInfo *MI) { + MacroUpdates[MI].UndefLoc = MI->getUndefLoc(); +} + void ASTWriter::CompletedTagDefinition(const TagDecl *D) { assert(D->isCompleteDefinition()); assert(!WritingAST && "Already writing the AST!"); @@ -4531,6 +4603,7 @@ void ASTWriter::CompletedTagDefinition(const TagDecl *D) { } } } + void ASTWriter::AddedVisibleDecl(const DeclContext *DC, const Decl *D) { assert(!WritingAST && "Already writing the AST!"); diff --git a/clang/lib/Serialization/GeneratePCH.cpp b/clang/lib/Serialization/GeneratePCH.cpp index 02aed103f1b..c2b353a9644 100644 --- a/clang/lib/Serialization/GeneratePCH.cpp +++ b/clang/lib/Serialization/GeneratePCH.cpp @@ -60,6 +60,10 @@ void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) { Buffer.clear(); } +PPMutationListener *PCHGenerator::GetPPMutationListener() { + return &Writer; +} + ASTMutationListener *PCHGenerator::GetASTMutationListener() { return &Writer; } diff --git a/clang/lib/Serialization/Module.cpp b/clang/lib/Serialization/Module.cpp index a5f709153c7..b6204f9478e 100644 --- a/clang/lib/Serialization/Module.cpp +++ b/clang/lib/Serialization/Module.cpp @@ -25,9 +25,11 @@ ModuleFile::ModuleFile(ModuleKind Kind, unsigned Generation) Generation(Generation), SizeInBits(0), LocalNumSLocEntries(0), SLocEntryBaseID(0), SLocEntryBaseOffset(0), SLocEntryOffsets(0), - SLocFileOffsets(0), LocalNumIdentifiers(0), + SLocFileOffsets(0), LocalNumIdentifiers(0), IdentifierOffsets(0), BaseIdentifierID(0), IdentifierTableData(0), - IdentifierLookupTable(0), BasePreprocessedEntityID(0), + IdentifierLookupTable(0), + LocalNumMacros(0), MacroOffsets(0), + BasePreprocessedEntityID(0), PreprocessedEntityOffsets(0), NumPreprocessedEntities(0), LocalNumHeaderFileInfos(0), HeaderFileInfoTableData(0), HeaderFileInfoTable(0), @@ -91,6 +93,10 @@ void ModuleFile::dump() { << " Number of identifiers: " << LocalNumIdentifiers << '\n'; dumpLocalRemap("Identifier ID local -> global map", IdentifierRemap); + llvm::errs() << " Base macro ID: " << BaseMacroID << '\n' + << " Number of macros: " << LocalNumMacros << '\n'; + dumpLocalRemap("Macro ID local -> global map", MacroRemap); + llvm::errs() << " Base submodule ID: " << BaseSubmoduleID << '\n' << " Number of submodules: " << LocalNumSubmodules << '\n'; dumpLocalRemap("Submodule ID local -> global map", SubmoduleRemap); diff --git a/clang/test/Modules/Inputs/macros_left.h b/clang/test/Modules/Inputs/macros_left.h new file mode 100644 index 00000000000..dfe56052bfc --- /dev/null +++ b/clang/test/Modules/Inputs/macros_left.h @@ -0,0 +1,5 @@ +#include "macros_top.h" +#define LEFT unsigned long + +#undef TOP_LEFT_UNDEF + diff --git a/clang/test/Modules/Inputs/macros_other.h b/clang/test/Modules/Inputs/macros_other.h new file mode 100644 index 00000000000..ea686bfc558 --- /dev/null +++ b/clang/test/Modules/Inputs/macros_other.h @@ -0,0 +1 @@ +#define OTHER_INTEGER int diff --git a/clang/test/Modules/Inputs/macros_right.h b/clang/test/Modules/Inputs/macros_right.h new file mode 100644 index 00000000000..3351e9796c4 --- /dev/null +++ b/clang/test/Modules/Inputs/macros_right.h @@ -0,0 +1,6 @@ +#include "macros_top.h" +#define RIGHT unsigned short + +#undef TOP_RIGHT_REDEF +#define TOP_RIGHT_REDEF float + diff --git a/clang/test/Modules/Inputs/macros_top.h b/clang/test/Modules/Inputs/macros_top.h new file mode 100644 index 00000000000..1a21848f6c5 --- /dev/null +++ b/clang/test/Modules/Inputs/macros_top.h @@ -0,0 +1,5 @@ +#define TOP unsigned int + +#define TOP_LEFT_UNDEF 1 + +#define TOP_RIGHT_REDEF int diff --git a/clang/test/PCH/Inputs/chain-macro-override1.h b/clang/test/PCH/Inputs/chain-macro-override1.h index d956396f916..7532d7ef58d 100644 --- a/clang/test/PCH/Inputs/chain-macro-override1.h +++ b/clang/test/PCH/Inputs/chain-macro-override1.h @@ -3,3 +3,7 @@ void g(); #define g() f() #define h() f() #define x x +#define h2() f() + +#define h3() +#undef h3 diff --git a/clang/test/PCH/Inputs/chain-macro-override2.h b/clang/test/PCH/Inputs/chain-macro-override2.h index e4bff77294f..1e0e3b96715 100644 --- a/clang/test/PCH/Inputs/chain-macro-override2.h +++ b/clang/test/PCH/Inputs/chain-macro-override2.h @@ -3,3 +3,6 @@ #undef h #define h() g() int x; +#undef h2 + +int h3(); diff --git a/clang/test/PCH/chain-macro-override.c b/clang/test/PCH/chain-macro-override.c index 2713e7084a9..24a7b3edf64 100644 --- a/clang/test/PCH/chain-macro-override.c +++ b/clang/test/PCH/chain-macro-override.c @@ -10,5 +10,7 @@ int foo() { f(); g(); h(); + h2(); // expected-warning{{implicit declaration of function 'h2' is invalid in C99}} + h3(); return x; } |