mirror of
https://github.com/intel/llvm.git
synced 2026-01-27 06:06:34 +08:00
[PCH/Modules] De/Serialize MacroInfos separately than MacroDirectives.
-Serialize the macro directives history into its own section -Get rid of the macro updates section -When de/serializing an identifier from a module, associate only one macro per submodule that defined+exported it. llvm-svn: 177761
This commit is contained in:
@@ -332,7 +332,10 @@ class MacroDirective {
|
||||
/// If invalid, this macro has not been explicitly given any visibility.
|
||||
SourceLocation VisibilityLocation;
|
||||
|
||||
/// \brief True if this macro was loaded from an AST file.
|
||||
/// \brief True if the macro directive was loaded from a PCH file.
|
||||
bool IsFromPCH : 1;
|
||||
|
||||
/// \brief True if this macro was imported from a module.
|
||||
bool IsImported : 1;
|
||||
|
||||
/// \brief Whether the macro has public (when described in a module).
|
||||
@@ -354,14 +357,14 @@ class MacroDirective {
|
||||
public:
|
||||
explicit MacroDirective(MacroInfo *MI)
|
||||
: Info(MI), Previous(0), Loc(MI->getDefinitionLoc()),
|
||||
IsImported(false), IsPublic(true), IsHidden(false), IsAmbiguous(false),
|
||||
ChangedAfterLoad(false) {
|
||||
IsFromPCH(false), IsImported(false), IsPublic(true), IsHidden(false),
|
||||
IsAmbiguous(false), ChangedAfterLoad(false) {
|
||||
assert(MI && "MacroInfo is null");
|
||||
}
|
||||
|
||||
MacroDirective(MacroInfo *MI, SourceLocation Loc, bool isImported)
|
||||
: Info(MI), Previous(0), Loc(Loc),
|
||||
IsImported(isImported), IsPublic(true), IsHidden(false),
|
||||
IsFromPCH(false), IsImported(isImported), IsPublic(true), IsHidden(false),
|
||||
IsAmbiguous(false), ChangedAfterLoad(false) {
|
||||
assert(MI && "MacroInfo is null");
|
||||
}
|
||||
@@ -412,7 +415,12 @@ public:
|
||||
/// public or private within its module.
|
||||
SourceLocation getVisibilityLocation() const { return VisibilityLocation; }
|
||||
|
||||
/// \brief True if this macro was loaded from an AST file.
|
||||
/// \brief Return true if the macro directive was loaded from a PCH file.
|
||||
bool isFromPCH() const { return IsFromPCH; }
|
||||
|
||||
void setIsFromPCH() { IsFromPCH = true; }
|
||||
|
||||
/// \brief True if this macro was imported from a module.
|
||||
bool isImported() const { return IsImported; }
|
||||
|
||||
/// \brief Determine whether this macro is currently defined (and has not
|
||||
|
||||
@@ -560,11 +560,18 @@ public:
|
||||
MacroDirective *getMacroDirectiveHistory(const IdentifierInfo *II) const;
|
||||
|
||||
/// \brief Specify a macro for this identifier.
|
||||
void setMacroDirective(IdentifierInfo *II, MacroDirective *MD);
|
||||
MacroDirective *setMacroDirective(IdentifierInfo *II, MacroInfo *MI,
|
||||
SourceLocation Loc, bool isImported);
|
||||
SourceLocation Loc, bool isImported) {
|
||||
MacroDirective *MD = AllocateMacroDirective(MI, Loc, isImported);
|
||||
setMacroDirective(II, MD);
|
||||
return MD;
|
||||
}
|
||||
MacroDirective *setMacroDirective(IdentifierInfo *II, MacroInfo *MI) {
|
||||
return setMacroDirective(II, MI, MI->getDefinitionLoc(), false);
|
||||
}
|
||||
/// \brief Set a MacroDirective that was loaded from a PCH file.
|
||||
void setLoadedMacroDirective(IdentifierInfo *II, MacroDirective *MD);
|
||||
/// \brief Add a MacroInfo that was loaded from an AST file.
|
||||
void addLoadedMacroInfo(IdentifierInfo *II, MacroDirective *MD,
|
||||
MacroDirective *Hint = 0);
|
||||
|
||||
@@ -129,7 +129,14 @@ namespace clang {
|
||||
|
||||
/// \brief An ID number that refers to a macro in an AST file.
|
||||
typedef uint32_t MacroID;
|
||||
|
||||
|
||||
/// \brief A global ID number that refers to a macro in an AST file.
|
||||
typedef uint32_t GlobalMacroID;
|
||||
|
||||
/// \brief A local to a module ID number that refers to a macro in an
|
||||
/// AST file.
|
||||
typedef uint32_t LocalMacroID;
|
||||
|
||||
/// \brief The number of predefined macro IDs.
|
||||
const unsigned int NUM_PREDEF_MACRO_IDS = 1;
|
||||
|
||||
@@ -522,9 +529,9 @@ namespace clang {
|
||||
/// macro definition.
|
||||
MACRO_OFFSET = 47,
|
||||
|
||||
/// \brief Record of updates for a macro that was modified after
|
||||
/// being deserialized.
|
||||
MACRO_UPDATES = 48,
|
||||
/// \brief Mapping table from the identifier ID to the offset of the
|
||||
/// macro directive history for the identifier.
|
||||
MACRO_TABLE = 48,
|
||||
|
||||
/// \brief Record code for undefined but used functions and variables that
|
||||
/// need a definition in this TU.
|
||||
@@ -565,7 +572,10 @@ namespace clang {
|
||||
|
||||
/// \brief Describes one token.
|
||||
/// [PP_TOKEN, SLoc, Length, IdentInfoID, Kind, Flags]
|
||||
PP_TOKEN = 3
|
||||
PP_TOKEN = 3,
|
||||
|
||||
/// \brief The macro directives history for a particular identifier.
|
||||
PP_MACRO_DIRECTIVE_HISTORY = 4
|
||||
};
|
||||
|
||||
/// \brief Record types used within a preprocessor detail block.
|
||||
|
||||
@@ -23,7 +23,7 @@ class Decl;
|
||||
class ASTReader;
|
||||
class QualType;
|
||||
class MacroDefinition;
|
||||
class MacroDirective;
|
||||
class MacroInfo;
|
||||
class Module;
|
||||
|
||||
class ASTDeserializationListener {
|
||||
@@ -39,7 +39,7 @@ public:
|
||||
virtual void IdentifierRead(serialization::IdentID ID,
|
||||
IdentifierInfo *II) { }
|
||||
/// \brief A macro was read from the AST file.
|
||||
virtual void MacroRead(serialization::MacroID ID, MacroDirective *MD) { }
|
||||
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.
|
||||
|
||||
@@ -430,7 +430,7 @@ private:
|
||||
/// 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<MacroDirective *> MacrosLoaded;
|
||||
std::vector<MacroInfo *> MacrosLoaded;
|
||||
|
||||
typedef ContinuousRangeMap<serialization::MacroID, ModuleFile *, 4>
|
||||
GlobalMacroMapType;
|
||||
@@ -564,8 +564,35 @@ private:
|
||||
/// global method pool for this selector.
|
||||
llvm::DenseMap<Selector, unsigned> SelectorGeneration;
|
||||
|
||||
typedef llvm::MapVector<IdentifierInfo *,
|
||||
SmallVector<serialization::MacroID, 2> >
|
||||
struct PendingMacroInfo {
|
||||
ModuleFile *M;
|
||||
|
||||
struct ModuleMacroDataTy {
|
||||
serialization::GlobalMacroID GMacID;
|
||||
unsigned ImportLoc;
|
||||
};
|
||||
struct PCHMacroDataTy {
|
||||
uint64_t MacroDirectivesOffset;
|
||||
};
|
||||
|
||||
union {
|
||||
ModuleMacroDataTy ModuleMacroData;
|
||||
PCHMacroDataTy PCHMacroData;
|
||||
};
|
||||
|
||||
PendingMacroInfo(ModuleFile *M,
|
||||
serialization::GlobalMacroID GMacID,
|
||||
SourceLocation ImportLoc) : M(M) {
|
||||
ModuleMacroData.GMacID = GMacID;
|
||||
ModuleMacroData.ImportLoc = ImportLoc.getRawEncoding();
|
||||
}
|
||||
|
||||
PendingMacroInfo(ModuleFile *M, uint64_t MacroDirectivesOffset) : M(M) {
|
||||
PCHMacroData.MacroDirectivesOffset = MacroDirectivesOffset;
|
||||
}
|
||||
};
|
||||
|
||||
typedef llvm::MapVector<IdentifierInfo *, SmallVector<PendingMacroInfo, 2> >
|
||||
PendingMacroIDsMap;
|
||||
|
||||
/// \brief Mapping from identifiers that have a macro history to the global
|
||||
@@ -1619,8 +1646,15 @@ public:
|
||||
serialization::IdentifierID getGlobalIdentifierID(ModuleFile &M,
|
||||
unsigned LocalID);
|
||||
|
||||
void resolvePendingMacro(IdentifierInfo *II, const PendingMacroInfo &PMInfo);
|
||||
|
||||
void installPCHMacroDirectives(IdentifierInfo *II,
|
||||
ModuleFile &M, uint64_t Offset);
|
||||
|
||||
void installImportedMacro(IdentifierInfo *II, MacroDirective *MD);
|
||||
|
||||
/// \brief Retrieve the macro with the given ID.
|
||||
MacroDirective *getMacro(serialization::MacroID ID, MacroDirective *Hint = 0);
|
||||
MacroInfo *getMacro(serialization::MacroID ID);
|
||||
|
||||
/// \brief Retrieve the global macro ID corresponding to the given local
|
||||
/// ID within the given module file.
|
||||
@@ -1779,20 +1813,32 @@ public:
|
||||
Expr *ReadSubExpr();
|
||||
|
||||
/// \brief Reads the macro record located at the given offset.
|
||||
void ReadMacroRecord(ModuleFile &F, uint64_t Offset, MacroDirective *Hint = 0);
|
||||
MacroInfo *ReadMacroRecord(ModuleFile &F, uint64_t Offset);
|
||||
|
||||
/// \brief Determine the global preprocessed entity ID that corresponds to
|
||||
/// the given local ID within the given module.
|
||||
serialization::PreprocessedEntityID
|
||||
getGlobalPreprocessedEntityID(ModuleFile &M, unsigned LocalID) const;
|
||||
|
||||
/// \brief Note that the identifier has a macro history.
|
||||
/// \brief Add a macro to resolve imported from a module.
|
||||
///
|
||||
/// \param II The name of the macro.
|
||||
/// \param M The module file.
|
||||
/// \param GMacID The global macro ID that is associated with this identifier.
|
||||
/// \param ImportLoc The location where the module is imported.
|
||||
void addPendingMacroFromModule(IdentifierInfo *II,
|
||||
ModuleFile *M,
|
||||
serialization::GlobalMacroID GMacID,
|
||||
SourceLocation ImportLoc);
|
||||
|
||||
/// \brief Add a macro to deserialize its macro directive history from a PCH.
|
||||
///
|
||||
/// \param IDs The global macro IDs that are associated with this identifier.
|
||||
void setIdentifierIsMacro(IdentifierInfo *II,
|
||||
ArrayRef<serialization::MacroID> IDs);
|
||||
/// \param II The name of the macro.
|
||||
/// \param M The module file.
|
||||
/// \param MacroDirectivesOffset Offset of the serialized macro directive
|
||||
/// history.
|
||||
void addPendingMacroFromPCH(IdentifierInfo *II,
|
||||
ModuleFile *M, uint64_t MacroDirectivesOffset);
|
||||
|
||||
/// \brief Read the set of macros defined by this external macro source.
|
||||
virtual void ReadDefinedMacros();
|
||||
|
||||
@@ -51,10 +51,11 @@ class HeaderSearch;
|
||||
class HeaderSearchOptions;
|
||||
class IdentifierResolver;
|
||||
class MacroDefinition;
|
||||
class MacroDirective;
|
||||
class MacroInfo;
|
||||
class OpaqueValueExpr;
|
||||
class OpenCLOptions;
|
||||
class ASTReader;
|
||||
class MacroDirective;
|
||||
class Module;
|
||||
class PreprocessedEntity;
|
||||
class PreprocessingRecord;
|
||||
@@ -231,7 +232,17 @@ private:
|
||||
serialization::MacroID NextMacroID;
|
||||
|
||||
/// \brief Map that provides the ID numbers of each macro.
|
||||
llvm::DenseMap<MacroDirective *, serialization::MacroID> MacroIDs;
|
||||
llvm::DenseMap<MacroInfo *, serialization::MacroID> MacroIDs;
|
||||
|
||||
struct MacroInfoToEmitData {
|
||||
const IdentifierInfo *Name;
|
||||
MacroInfo *MI;
|
||||
serialization::MacroID ID;
|
||||
};
|
||||
/// \brief The macro infos to emit.
|
||||
std::vector<MacroInfoToEmitData> MacroInfosToEmit;
|
||||
|
||||
llvm::DenseMap<const IdentifierInfo *, uint64_t> IdentMacroDirectivesOffsetMap;
|
||||
|
||||
/// @name FlushStmt Caches
|
||||
/// @{
|
||||
@@ -268,11 +279,6 @@ private:
|
||||
/// table, indexed by the Selector ID (-1).
|
||||
std::vector<uint32_t> SelectorOffsets;
|
||||
|
||||
typedef llvm::MapVector<MacroDirective *, 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>
|
||||
@@ -441,7 +447,6 @@ 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();
|
||||
@@ -512,9 +517,6 @@ public:
|
||||
/// \brief Emit a reference to an identifier.
|
||||
void AddIdentifierRef(const IdentifierInfo *II, RecordDataImpl &Record);
|
||||
|
||||
/// \brief Emit a reference to a macro.
|
||||
void addMacroRef(MacroDirective *MI, RecordDataImpl &Record);
|
||||
|
||||
/// \brief Emit a Selector (which is a smart pointer reference).
|
||||
void AddSelectorRef(Selector, RecordDataImpl &Record);
|
||||
|
||||
@@ -533,7 +535,12 @@ public:
|
||||
serialization::IdentID getIdentifierRef(const IdentifierInfo *II);
|
||||
|
||||
/// \brief Get the unique number used to refer to the given macro.
|
||||
serialization::MacroID getMacroRef(MacroDirective *MI);
|
||||
serialization::MacroID getMacroRef(MacroInfo *MI, const IdentifierInfo *Name);
|
||||
|
||||
/// \brief Determine the ID of an already-emitted macro.
|
||||
serialization::MacroID getMacroID(MacroInfo *MI);
|
||||
|
||||
uint64_t getMacroDirectivesOffset(const IdentifierInfo *Name);
|
||||
|
||||
/// \brief Emit a reference to a type.
|
||||
void AddTypeRef(QualType T, RecordDataImpl &Record);
|
||||
@@ -700,16 +707,13 @@ public:
|
||||
// ASTDeserializationListener implementation
|
||||
void ReaderInitialized(ASTReader *Reader);
|
||||
void IdentifierRead(serialization::IdentID ID, IdentifierInfo *II);
|
||||
void MacroRead(serialization::MacroID ID, MacroDirective *MI);
|
||||
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 ModuleRead(serialization::SubmoduleID ID, Module *Mod);
|
||||
|
||||
// PPMutationListener implementation.
|
||||
virtual void UndefinedMacro(MacroDirective *MD);
|
||||
|
||||
// ASTMutationListener implementation.
|
||||
virtual void CompletedTagDefinition(const TagDecl *D);
|
||||
virtual void AddedVisibleDecl(const DeclContext *DC, const Decl *D);
|
||||
|
||||
@@ -1119,23 +1119,26 @@ void Preprocessor::HandleMacroPublicDirective(Token &Tok) {
|
||||
// Check to see if this is the last token on the #__public_macro line.
|
||||
CheckEndOfDirective("__public_macro");
|
||||
|
||||
IdentifierInfo *II = MacroNameTok.getIdentifierInfo();
|
||||
// Okay, we finally have a valid identifier to undef.
|
||||
MacroDirective *MD = getMacroDirective(MacroNameTok.getIdentifierInfo());
|
||||
MacroDirective *MD = getMacroDirective(II);
|
||||
|
||||
// If the macro is not defined, this is an error.
|
||||
if (MD == 0) {
|
||||
Diag(MacroNameTok, diag::err_pp_visibility_non_macro)
|
||||
<< MacroNameTok.getIdentifierInfo();
|
||||
Diag(MacroNameTok, diag::err_pp_visibility_non_macro) << II;
|
||||
return;
|
||||
}
|
||||
|
||||
// Note that this macro has now been exported.
|
||||
MD->setVisibility(/*IsPublic=*/true, MacroNameTok.getLocation());
|
||||
|
||||
// If this macro definition came from a PCH file, mark it
|
||||
// as having changed since serialization.
|
||||
if (MD->isImported())
|
||||
// If this macro directive came from a PCH file, mark it as having changed
|
||||
// since serialization.
|
||||
if (MD->isFromPCH()) {
|
||||
MD->setChangedAfterLoad();
|
||||
assert(II->isFromAST());
|
||||
II->setChangedSinceDeserialization();
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Handle a #private directive.
|
||||
@@ -1150,23 +1153,26 @@ void Preprocessor::HandleMacroPrivateDirective(Token &Tok) {
|
||||
// Check to see if this is the last token on the #__private_macro line.
|
||||
CheckEndOfDirective("__private_macro");
|
||||
|
||||
IdentifierInfo *II = MacroNameTok.getIdentifierInfo();
|
||||
// Okay, we finally have a valid identifier to undef.
|
||||
MacroDirective *MD = getMacroDirective(MacroNameTok.getIdentifierInfo());
|
||||
MacroDirective *MD = getMacroDirective(II);
|
||||
|
||||
// If the macro is not defined, this is an error.
|
||||
if (MD == 0) {
|
||||
Diag(MacroNameTok, diag::err_pp_visibility_non_macro)
|
||||
<< MacroNameTok.getIdentifierInfo();
|
||||
Diag(MacroNameTok, diag::err_pp_visibility_non_macro) << II;
|
||||
return;
|
||||
}
|
||||
|
||||
// Note that this macro has now been marked private.
|
||||
MD->setVisibility(/*IsPublic=*/false, MacroNameTok.getLocation());
|
||||
|
||||
// If this macro definition came from a PCH file, mark it
|
||||
// as having changed since serialization.
|
||||
if (MD->isImported())
|
||||
// If this macro directive came from a PCH file, mark it as having changed
|
||||
// since serialization.
|
||||
if (MD->isFromPCH()) {
|
||||
MD->setChangedAfterLoad();
|
||||
assert(II->isFromAST());
|
||||
II->setChangedSinceDeserialization();
|
||||
}
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
@@ -2011,7 +2017,7 @@ void Preprocessor::HandleUndefDirective(Token &UndefTok) {
|
||||
void Preprocessor::UndefineMacro(IdentifierInfo *II, MacroDirective *MD,
|
||||
SourceLocation UndefLoc) {
|
||||
MD->setUndefLoc(UndefLoc);
|
||||
if (MD->isImported()) {
|
||||
if (MD->isFromPCH()) {
|
||||
MD->setChangedAfterLoad();
|
||||
if (Listener)
|
||||
Listener->UndefinedMacro(MD);
|
||||
|
||||
@@ -42,20 +42,28 @@ Preprocessor::getMacroDirectiveHistory(const IdentifierInfo *II) const {
|
||||
}
|
||||
|
||||
/// \brief Specify a macro for this identifier.
|
||||
MacroDirective *
|
||||
Preprocessor::setMacroDirective(IdentifierInfo *II, MacroInfo *MI,
|
||||
SourceLocation Loc, bool isImported) {
|
||||
assert(MI && "MacroInfo should be non-zero!");
|
||||
void Preprocessor::setMacroDirective(IdentifierInfo *II, MacroDirective *MD) {
|
||||
assert(MD && "MacroDirective should be non-zero!");
|
||||
|
||||
MacroDirective *MD = AllocateMacroDirective(MI, Loc, isImported);
|
||||
MacroDirective *&StoredMD = Macros[II];
|
||||
MD->setPrevious(StoredMD);
|
||||
StoredMD = MD;
|
||||
II->setHasMacroDefinition(true);
|
||||
if (II->isFromAST())
|
||||
II->setChangedSinceDeserialization();
|
||||
}
|
||||
|
||||
return MD;
|
||||
void Preprocessor::setLoadedMacroDirective(IdentifierInfo *II,
|
||||
MacroDirective *MD) {
|
||||
assert(II && MD);
|
||||
MacroDirective *&StoredMD = Macros[II];
|
||||
assert(!StoredMD &&
|
||||
"the macro history was modified before initializing it from a pch");
|
||||
StoredMD = MD;
|
||||
// Setup the identifier as having associated macro history.
|
||||
II->setHasMacroDefinition(true);
|
||||
if (!MD->isDefined())
|
||||
II->setHasMacroDefinition(false);
|
||||
}
|
||||
|
||||
void Preprocessor::addLoadedMacroInfo(IdentifierInfo *II, MacroDirective *MD,
|
||||
|
||||
@@ -516,6 +516,8 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k,
|
||||
Bits >>= 1;
|
||||
bool ExtensionToken = Bits & 0x01;
|
||||
Bits >>= 1;
|
||||
bool hasSubmoduleMacros = Bits & 0x01;
|
||||
Bits >>= 1;
|
||||
bool hadMacroDefinition = Bits & 0x01;
|
||||
Bits >>= 1;
|
||||
|
||||
@@ -554,13 +556,26 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k,
|
||||
// If this identifier is a macro, deserialize the macro
|
||||
// definition.
|
||||
if (hadMacroDefinition) {
|
||||
SmallVector<MacroID, 4> MacroIDs;
|
||||
while (uint32_t LocalID = ReadUnalignedLE32(d)) {
|
||||
MacroIDs.push_back(Reader.getGlobalMacroID(F, LocalID));
|
||||
uint32_t MacroDirectivesOffset = ReadUnalignedLE32(d);
|
||||
DataLen -= 4;
|
||||
SmallVector<uint32_t, 8> LocalMacroIDs;
|
||||
if (hasSubmoduleMacros) {
|
||||
while (uint32_t LocalMacroID = ReadUnalignedLE32(d)) {
|
||||
DataLen -= 4;
|
||||
LocalMacroIDs.push_back(LocalMacroID);
|
||||
}
|
||||
DataLen -= 4;
|
||||
}
|
||||
DataLen -= 4;
|
||||
Reader.setIdentifierIsMacro(II, MacroIDs);
|
||||
|
||||
if (F.Kind == MK_Module) {
|
||||
for (SmallVectorImpl<uint32_t>::iterator
|
||||
I = LocalMacroIDs.begin(), E = LocalMacroIDs.end(); I != E; ++I) {
|
||||
MacroID MacID = Reader.getGlobalMacroID(F, *I);
|
||||
Reader.addPendingMacroFromModule(II, &F, MacID, F.DirectImportLoc);
|
||||
}
|
||||
} else {
|
||||
Reader.addPendingMacroFromPCH(II, &F, MacroDirectivesOffset);
|
||||
}
|
||||
}
|
||||
|
||||
Reader.SetIdentifierInfo(ID, II);
|
||||
@@ -1073,8 +1088,7 @@ bool ASTReader::ReadBlockAbbrevs(BitstreamCursor &Cursor, unsigned BlockID) {
|
||||
}
|
||||
}
|
||||
|
||||
void ASTReader::ReadMacroRecord(ModuleFile &F, uint64_t Offset,
|
||||
MacroDirective *Hint) {
|
||||
MacroInfo *ASTReader::ReadMacroRecord(ModuleFile &F, uint64_t Offset) {
|
||||
BitstreamCursor &Stream = F.MacroCursor;
|
||||
|
||||
// Keep track of where we are in the stream, then jump back there
|
||||
@@ -1086,24 +1100,6 @@ void ASTReader::ReadMacroRecord(ModuleFile &F, uint64_t Offset,
|
||||
SmallVector<IdentifierInfo*, 16> MacroArgs;
|
||||
MacroInfo *Macro = 0;
|
||||
|
||||
// RAII object to add the loaded macro information once we're done
|
||||
// adding tokens.
|
||||
struct AddLoadedMacroInfoRAII {
|
||||
Preprocessor &PP;
|
||||
MacroDirective *Hint;
|
||||
MacroDirective *MD;
|
||||
IdentifierInfo *II;
|
||||
|
||||
AddLoadedMacroInfoRAII(Preprocessor &PP, MacroDirective *Hint)
|
||||
: PP(PP), Hint(Hint), MD(), II() { }
|
||||
~AddLoadedMacroInfoRAII( ) {
|
||||
if (MD) {
|
||||
// Finally, install the macro.
|
||||
PP.addLoadedMacroInfo(II, MD, Hint);
|
||||
}
|
||||
}
|
||||
} AddLoadedMacroInfo(PP, Hint);
|
||||
|
||||
while (true) {
|
||||
// Advance to the next record, but if we get to the end of the block, don't
|
||||
// pop it (removing all the abbreviations from the cursor) since we want to
|
||||
@@ -1115,9 +1111,9 @@ void ASTReader::ReadMacroRecord(ModuleFile &F, uint64_t Offset,
|
||||
case llvm::BitstreamEntry::SubBlock: // Handled for us already.
|
||||
case llvm::BitstreamEntry::Error:
|
||||
Error("malformed block record in AST file");
|
||||
return;
|
||||
return Macro;
|
||||
case llvm::BitstreamEntry::EndBlock:
|
||||
return;
|
||||
return Macro;
|
||||
case llvm::BitstreamEntry::Record:
|
||||
// The interesting case.
|
||||
break;
|
||||
@@ -1128,47 +1124,24 @@ void ASTReader::ReadMacroRecord(ModuleFile &F, uint64_t Offset,
|
||||
PreprocessorRecordTypes RecType =
|
||||
(PreprocessorRecordTypes)Stream.readRecord(Entry.ID, Record);
|
||||
switch (RecType) {
|
||||
case PP_MACRO_DIRECTIVE_HISTORY:
|
||||
return Macro;
|
||||
|
||||
case PP_MACRO_OBJECT_LIKE:
|
||||
case PP_MACRO_FUNCTION_LIKE: {
|
||||
// If we already have a macro, that means that we've hit the end
|
||||
// of the definition of the macro we were looking for. We're
|
||||
// done.
|
||||
if (Macro)
|
||||
return;
|
||||
return Macro;
|
||||
|
||||
IdentifierInfo *II = getLocalIdentifier(F, Record[0]);
|
||||
if (II == 0) {
|
||||
Error("macro must have a name in AST file");
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
SubmoduleID GlobalSubmoduleID = getGlobalSubmoduleID(F, Record[2]);
|
||||
unsigned NextIndex = 3;
|
||||
unsigned NextIndex = 1; // Skip identifier ID.
|
||||
SubmoduleID SubModID = getGlobalSubmoduleID(F, Record[NextIndex++]);
|
||||
SourceLocation Loc = ReadSourceLocation(F, Record, NextIndex);
|
||||
MacroInfo *MI = PP.AllocateDeserializedMacroInfo(Loc, GlobalSubmoduleID);
|
||||
// FIXME: Location should be import location in case of module.
|
||||
MacroDirective *MD = PP.AllocateMacroDirective(MI, Loc,
|
||||
/*isImported=*/true);
|
||||
MacroInfo *MI = PP.AllocateDeserializedMacroInfo(Loc, SubModID);
|
||||
MI->setDefinitionEndLoc(ReadSourceLocation(F, Record, NextIndex));
|
||||
|
||||
// Record this macro.
|
||||
MacrosLoaded[GlobalID - NUM_PREDEF_MACRO_IDS] = MD;
|
||||
|
||||
SourceLocation UndefLoc = ReadSourceLocation(F, Record, NextIndex);
|
||||
if (UndefLoc.isValid())
|
||||
MD->setUndefLoc(UndefLoc);
|
||||
|
||||
MI->setIsUsed(Record[NextIndex++]);
|
||||
|
||||
bool IsPublic = Record[NextIndex++];
|
||||
MD->setVisibility(IsPublic, ReadSourceLocation(F, Record, NextIndex));
|
||||
|
||||
if (RecType == PP_MACRO_FUNCTION_LIKE) {
|
||||
// Decode function-like macro info.
|
||||
bool isC99VarArgs = Record[NextIndex++];
|
||||
@@ -1188,61 +1161,6 @@ void ASTReader::ReadMacroRecord(ModuleFile &F, uint64_t Offset,
|
||||
PP.getPreprocessorAllocator());
|
||||
}
|
||||
|
||||
if (DeserializationListener)
|
||||
DeserializationListener->MacroRead(GlobalID, MD);
|
||||
|
||||
// If an update record marked this as undefined, do so now.
|
||||
// FIXME: Only if the submodule this update came from is visible?
|
||||
MacroUpdatesMap::iterator Update = MacroUpdates.find(GlobalID);
|
||||
if (Update != MacroUpdates.end()) {
|
||||
if (MD->getUndefLoc().isInvalid()) {
|
||||
for (unsigned I = 0, N = Update->second.size(); I != N; ++I) {
|
||||
bool Hidden = false;
|
||||
if (unsigned SubmoduleID = Update->second[I].first) {
|
||||
if (Module *Owner = getSubmodule(SubmoduleID)) {
|
||||
if (Owner->NameVisibility == Module::Hidden) {
|
||||
// Note that this #undef is hidden.
|
||||
Hidden = true;
|
||||
|
||||
// Record this hiding for later.
|
||||
HiddenNamesMap[Owner].push_back(
|
||||
HiddenName(II, MD, Update->second[I].second.UndefLoc));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!Hidden) {
|
||||
MD->setUndefLoc(Update->second[I].second.UndefLoc);
|
||||
if (PPMutationListener *Listener = PP.getPPMutationListener())
|
||||
Listener->UndefinedMacro(MD);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
MacroUpdates.erase(Update);
|
||||
}
|
||||
|
||||
// Determine whether this macro definition is visible.
|
||||
bool Hidden = !MD->isPublic();
|
||||
if (!Hidden && GlobalSubmoduleID) {
|
||||
if (Module *Owner = getSubmodule(GlobalSubmoduleID)) {
|
||||
if (Owner->NameVisibility == Module::Hidden) {
|
||||
// The owning module is not visible, and this macro definition
|
||||
// should not be, either.
|
||||
Hidden = true;
|
||||
|
||||
// Note that this macro definition was hidden because its owning
|
||||
// module is not yet visible.
|
||||
HiddenNamesMap[Owner].push_back(HiddenName(II, MD));
|
||||
}
|
||||
}
|
||||
}
|
||||
MD->setHidden(Hidden);
|
||||
|
||||
// Make sure we install the macro once we're done.
|
||||
AddLoadedMacroInfo.MD = MD;
|
||||
AddLoadedMacroInfo.II = II;
|
||||
|
||||
// Remember that we saw this macro last so that we add the tokens that
|
||||
// form its body to it.
|
||||
Macro = MI;
|
||||
@@ -1381,10 +1299,19 @@ HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d,
|
||||
return HFI;
|
||||
}
|
||||
|
||||
void ASTReader::setIdentifierIsMacro(IdentifierInfo *II, ArrayRef<MacroID> IDs){
|
||||
II->setHadMacroDefinition(true);
|
||||
void ASTReader::addPendingMacroFromModule(IdentifierInfo *II,
|
||||
ModuleFile *M,
|
||||
GlobalMacroID GMacID,
|
||||
SourceLocation ImportLoc) {
|
||||
assert(NumCurrentElementsDeserializing > 0 &&"Missing deserialization guard");
|
||||
PendingMacroIDs[II].append(IDs.begin(), IDs.end());
|
||||
PendingMacroIDs[II].push_back(PendingMacroInfo(M, GMacID, ImportLoc));
|
||||
}
|
||||
|
||||
void ASTReader::addPendingMacroFromPCH(IdentifierInfo *II,
|
||||
ModuleFile *M,
|
||||
uint64_t MacroDirectivesOffset) {
|
||||
assert(NumCurrentElementsDeserializing > 0 &&"Missing deserialization guard");
|
||||
PendingMacroIDs[II].push_back(PendingMacroInfo(M, MacroDirectivesOffset));
|
||||
}
|
||||
|
||||
void ASTReader::ReadDefinedMacros() {
|
||||
@@ -1526,6 +1453,119 @@ void ASTReader::markIdentifierUpToDate(IdentifierInfo *II) {
|
||||
IdentifierGeneration[II] = CurrentGeneration;
|
||||
}
|
||||
|
||||
void ASTReader::resolvePendingMacro(IdentifierInfo *II,
|
||||
const PendingMacroInfo &PMInfo) {
|
||||
assert(II);
|
||||
|
||||
if (PMInfo.M->Kind != MK_Module) {
|
||||
installPCHMacroDirectives(II, *PMInfo.M,
|
||||
PMInfo.PCHMacroData.MacroDirectivesOffset);
|
||||
return;
|
||||
}
|
||||
|
||||
// Module Macro.
|
||||
|
||||
GlobalMacroID GMacID = PMInfo.ModuleMacroData.GMacID;
|
||||
SourceLocation ImportLoc =
|
||||
SourceLocation::getFromRawEncoding(PMInfo.ModuleMacroData.ImportLoc);
|
||||
|
||||
assert(GMacID);
|
||||
// If this macro has already been loaded, don't do so again.
|
||||
if (MacrosLoaded[GMacID - NUM_PREDEF_MACRO_IDS])
|
||||
return;
|
||||
|
||||
MacroInfo *MI = getMacro(GMacID);
|
||||
SubmoduleID SubModID = MI->getOwningModuleID();
|
||||
MacroDirective *MD = PP.AllocateMacroDirective(MI, ImportLoc,
|
||||
/*isImported=*/true);
|
||||
|
||||
// Determine whether this macro definition is visible.
|
||||
bool Hidden = false;
|
||||
if (SubModID) {
|
||||
if (Module *Owner = getSubmodule(SubModID)) {
|
||||
if (Owner->NameVisibility == Module::Hidden) {
|
||||
// The owning module is not visible, and this macro definition
|
||||
// should not be, either.
|
||||
Hidden = true;
|
||||
|
||||
// Note that this macro definition was hidden because its owning
|
||||
// module is not yet visible.
|
||||
HiddenNamesMap[Owner].push_back(HiddenName(II, MD));
|
||||
}
|
||||
}
|
||||
}
|
||||
MD->setHidden(Hidden);
|
||||
|
||||
if (!Hidden)
|
||||
installImportedMacro(II, MD);
|
||||
}
|
||||
|
||||
void ASTReader::installPCHMacroDirectives(IdentifierInfo *II,
|
||||
ModuleFile &M, uint64_t Offset) {
|
||||
assert(M.Kind != MK_Module);
|
||||
|
||||
BitstreamCursor &Cursor = M.MacroCursor;
|
||||
SavedStreamPosition SavedPosition(Cursor);
|
||||
Cursor.JumpToBit(Offset);
|
||||
|
||||
llvm::BitstreamEntry Entry =
|
||||
Cursor.advance(BitstreamCursor::AF_DontPopBlockAtEnd);
|
||||
if (Entry.Kind != llvm::BitstreamEntry::Record) {
|
||||
Error("malformed block record in AST file");
|
||||
return;
|
||||
}
|
||||
|
||||
RecordData Record;
|
||||
PreprocessorRecordTypes RecType =
|
||||
(PreprocessorRecordTypes)Cursor.readRecord(Entry.ID, Record);
|
||||
if (RecType != PP_MACRO_DIRECTIVE_HISTORY) {
|
||||
Error("malformed block record in AST file");
|
||||
return;
|
||||
}
|
||||
|
||||
// Deserialize the macro directives history in reverse source-order.
|
||||
MacroDirective *Latest = 0, *Earliest = 0;
|
||||
unsigned Idx = 0, N = Record.size();
|
||||
while (Idx < N) {
|
||||
GlobalMacroID GMacID = getGlobalMacroID(M, Record[Idx++]);
|
||||
MacroInfo *MI = getMacro(GMacID);
|
||||
SourceLocation Loc = ReadSourceLocation(M, Record, Idx);
|
||||
SourceLocation UndefLoc = ReadSourceLocation(M, Record, Idx);
|
||||
SourceLocation VisibilityLoc = ReadSourceLocation(M, Record, Idx);
|
||||
bool isImported = Record[Idx++];
|
||||
bool isPublic = Record[Idx++];
|
||||
bool isAmbiguous = Record[Idx++];
|
||||
|
||||
MacroDirective *MD = PP.AllocateMacroDirective(MI, Loc, isImported);
|
||||
if (UndefLoc.isValid())
|
||||
MD->setUndefLoc(UndefLoc);
|
||||
if (VisibilityLoc.isValid())
|
||||
MD->setVisibility(isPublic, VisibilityLoc);
|
||||
MD->setAmbiguous(isAmbiguous);
|
||||
MD->setIsFromPCH();
|
||||
|
||||
if (!Latest)
|
||||
Latest = MD;
|
||||
if (Earliest)
|
||||
Earliest->setPrevious(MD);
|
||||
Earliest = MD;
|
||||
}
|
||||
|
||||
PP.setLoadedMacroDirective(II, Latest);
|
||||
}
|
||||
|
||||
void ASTReader::installImportedMacro(IdentifierInfo *II, MacroDirective *MD) {
|
||||
assert(II && MD);
|
||||
|
||||
MacroDirective *Prev = PP.getMacroDirective(II);
|
||||
if (Prev && !Prev->getInfo()->isIdenticalTo(*MD->getInfo(), PP)) {
|
||||
Prev->setAmbiguous(true);
|
||||
MD->setAmbiguous(true);
|
||||
}
|
||||
|
||||
PP.setMacroDirective(II, MD);
|
||||
}
|
||||
|
||||
InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
|
||||
// If this ID is bogus, just return an empty input file.
|
||||
if (ID == 0 || ID > F.InputFilesLoaded.size())
|
||||
@@ -2629,18 +2669,8 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) {
|
||||
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;
|
||||
|
||||
SourceLocation UndefLoc = ReadSourceLocation(F, Record, I);
|
||||
SubmoduleID SubmoduleID = getGlobalSubmoduleID(F, Record[I++]);;
|
||||
MacroUpdate Update;
|
||||
Update.UndefLoc = UndefLoc;
|
||||
MacroUpdates[ID].push_back(std::make_pair(SubmoduleID, Update));
|
||||
}
|
||||
case MACRO_TABLE: {
|
||||
// FIXME: Not used yet.
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -2695,7 +2725,7 @@ void ASTReader::makeNamesVisible(const HiddenNames &Names) {
|
||||
std::pair<IdentifierInfo *, MacroDirective *> Macro = Names[I].getMacro();
|
||||
Macro.second->setHidden(!Macro.second->isPublic());
|
||||
if (Macro.second->isDefined()) {
|
||||
PP.makeLoadedMacroInfoVisible(Macro.first, Macro.second);
|
||||
installImportedMacro(Macro.first, Macro.second);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -5789,7 +5819,7 @@ void ASTReader::PrintStats() {
|
||||
unsigned NumMacrosLoaded
|
||||
= MacrosLoaded.size() - std::count(MacrosLoaded.begin(),
|
||||
MacrosLoaded.end(),
|
||||
(MacroDirective *)0);
|
||||
(MacroInfo *)0);
|
||||
unsigned NumSelectorsLoaded
|
||||
= SelectorsLoaded.size() - std::count(SelectorsLoaded.begin(),
|
||||
SelectorsLoaded.end(),
|
||||
@@ -6398,7 +6428,7 @@ IdentifierID ASTReader::getGlobalIdentifierID(ModuleFile &M, unsigned LocalID) {
|
||||
return LocalID + I->second;
|
||||
}
|
||||
|
||||
MacroDirective *ASTReader::getMacro(MacroID ID, MacroDirective *Hint) {
|
||||
MacroInfo *ASTReader::getMacro(MacroID ID) {
|
||||
if (ID == 0)
|
||||
return 0;
|
||||
|
||||
@@ -6414,7 +6444,11 @@ MacroDirective *ASTReader::getMacro(MacroID ID, MacroDirective *Hint) {
|
||||
assert(I != GlobalMacroMap.end() && "Corrupted global macro map");
|
||||
ModuleFile *M = I->second;
|
||||
unsigned Index = ID - M->BaseMacroID;
|
||||
ReadMacroRecord(*M, M->MacroOffsets[Index], Hint);
|
||||
MacrosLoaded[ID] = ReadMacroRecord(*M, M->MacroOffsets[Index]);
|
||||
|
||||
if (DeserializationListener)
|
||||
DeserializationListener->MacroRead(ID + NUM_PREDEF_MACRO_IDS,
|
||||
MacrosLoaded[ID]);
|
||||
}
|
||||
|
||||
return MacrosLoaded[ID];
|
||||
@@ -7128,12 +7162,22 @@ void ASTReader::finishPendingActions() {
|
||||
|
||||
// Load any pending macro definitions.
|
||||
for (unsigned I = 0; I != PendingMacroIDs.size(); ++I) {
|
||||
// FIXME: std::move here
|
||||
SmallVector<MacroID, 2> GlobalIDs = PendingMacroIDs.begin()[I].second;
|
||||
MacroDirective *Hint = 0;
|
||||
IdentifierInfo *II = PendingMacroIDs.begin()[I].first;
|
||||
SmallVector<PendingMacroInfo, 2> GlobalIDs;
|
||||
GlobalIDs.swap(PendingMacroIDs.begin()[I].second);
|
||||
// Initialize the macro history from chained-PCHs ahead of module imports.
|
||||
for (unsigned IDIdx = 0, NumIDs = GlobalIDs.size(); IDIdx != NumIDs;
|
||||
++IDIdx) {
|
||||
Hint = getMacro(GlobalIDs[IDIdx], Hint);
|
||||
const PendingMacroInfo &Info = GlobalIDs[IDIdx];
|
||||
if (Info.M->Kind != MK_Module)
|
||||
resolvePendingMacro(II, Info);
|
||||
}
|
||||
// Handle module imports.
|
||||
for (unsigned IDIdx = 0, NumIDs = GlobalIDs.size(); IDIdx != NumIDs;
|
||||
++IDIdx) {
|
||||
const PendingMacroInfo &Info = GlobalIDs[IDIdx];
|
||||
if (Info.M->Kind == MK_Module)
|
||||
resolvePendingMacro(II, Info);
|
||||
}
|
||||
}
|
||||
PendingMacroIDs.clear();
|
||||
|
||||
@@ -835,7 +835,7 @@ void ASTWriter::WriteBlockInfoBlock() {
|
||||
RECORD(LOCAL_REDECLARATIONS);
|
||||
RECORD(OBJC_CATEGORIES);
|
||||
RECORD(MACRO_OFFSET);
|
||||
RECORD(MACRO_UPDATES);
|
||||
RECORD(MACRO_TABLE);
|
||||
|
||||
// SourceManager Block.
|
||||
BLOCK(SOURCE_MANAGER_BLOCK);
|
||||
@@ -1787,11 +1787,47 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
|
||||
// Preprocessor Serialization
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
static int compareMacroDefinitions(const void *XPtr, const void *YPtr) {
|
||||
const std::pair<const IdentifierInfo *, MacroInfo *> &X =
|
||||
*(const std::pair<const IdentifierInfo *, MacroInfo *>*)XPtr;
|
||||
const std::pair<const IdentifierInfo *, MacroInfo *> &Y =
|
||||
*(const std::pair<const IdentifierInfo *, MacroInfo *>*)YPtr;
|
||||
namespace {
|
||||
class ASTMacroTableTrait {
|
||||
public:
|
||||
typedef IdentID key_type;
|
||||
typedef key_type key_type_ref;
|
||||
|
||||
struct Data {
|
||||
uint32_t MacroDirectivesOffset;
|
||||
};
|
||||
|
||||
typedef Data data_type;
|
||||
typedef const data_type &data_type_ref;
|
||||
|
||||
static unsigned ComputeHash(IdentID IdID) {
|
||||
return llvm::hash_value(IdID);
|
||||
}
|
||||
|
||||
std::pair<unsigned,unsigned>
|
||||
static EmitKeyDataLength(raw_ostream& Out,
|
||||
key_type_ref Key, data_type_ref Data) {
|
||||
unsigned KeyLen = 4; // IdentID.
|
||||
unsigned DataLen = 4; // MacroDirectivesOffset.
|
||||
return std::make_pair(KeyLen, DataLen);
|
||||
}
|
||||
|
||||
static void EmitKey(raw_ostream& Out, key_type_ref Key, unsigned KeyLen) {
|
||||
clang::io::Emit32(Out, Key);
|
||||
}
|
||||
|
||||
static void EmitData(raw_ostream& Out, key_type_ref Key, data_type_ref Data,
|
||||
unsigned) {
|
||||
clang::io::Emit32(Out, Data.MacroDirectivesOffset);
|
||||
}
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
static int compareMacroDirectives(const void *XPtr, const void *YPtr) {
|
||||
const std::pair<const IdentifierInfo *, MacroDirective *> &X =
|
||||
*(const std::pair<const IdentifierInfo *, MacroDirective *>*)XPtr;
|
||||
const std::pair<const IdentifierInfo *, MacroDirective *> &Y =
|
||||
*(const std::pair<const IdentifierInfo *, MacroDirective *>*)YPtr;
|
||||
return X.first->getName().compare(Y.first->getName());
|
||||
}
|
||||
|
||||
@@ -1837,24 +1873,68 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) {
|
||||
fprintf(stderr, "warning: precompiled header used __DATE__ or __TIME__.\n");
|
||||
|
||||
|
||||
// Loop over all the macro definitions that are live at the end of the file,
|
||||
// Loop over all the macro directives that are live at the end of the file,
|
||||
// emitting each to the PP section.
|
||||
|
||||
// Construct the list of macro definitions that need to be serialized.
|
||||
// Construct the list of macro directives that need to be serialized.
|
||||
SmallVector<std::pair<const IdentifierInfo *, MacroDirective *>, 2>
|
||||
MacrosToEmit;
|
||||
for (Preprocessor::macro_iterator I = PP.macro_begin(Chain == 0),
|
||||
E = PP.macro_end(Chain == 0);
|
||||
MacroDirectives;
|
||||
for (Preprocessor::macro_iterator
|
||||
I = PP.macro_begin(/*IncludeExternalMacros=*/false),
|
||||
E = PP.macro_end(/*IncludeExternalMacros=*/false);
|
||||
I != E; ++I) {
|
||||
if (!IsModule || I->second->isPublic()) {
|
||||
MacrosToEmit.push_back(std::make_pair(I->first, I->second));
|
||||
}
|
||||
MacroDirectives.push_back(std::make_pair(I->first, I->second));
|
||||
}
|
||||
|
||||
// Sort the set of macro definitions that need to be serialized by the
|
||||
// name of the macro, to provide a stable ordering.
|
||||
llvm::array_pod_sort(MacrosToEmit.begin(), MacrosToEmit.end(),
|
||||
&compareMacroDefinitions);
|
||||
llvm::array_pod_sort(MacroDirectives.begin(), MacroDirectives.end(),
|
||||
&compareMacroDirectives);
|
||||
|
||||
OnDiskChainedHashTableGenerator<ASTMacroTableTrait> Generator;
|
||||
|
||||
// Emit the macro directives as a list and associate the offset with the
|
||||
// identifier they belong to.
|
||||
for (unsigned I = 0, N = MacroDirectives.size(); I != N; ++I) {
|
||||
const IdentifierInfo *Name = MacroDirectives[I].first;
|
||||
uint64_t MacroDirectiveOffset = Stream.GetCurrentBitNo();
|
||||
MacroDirective *MD = MacroDirectives[I].second;
|
||||
|
||||
// If the macro or identifier need no updates, don't write the macro history
|
||||
// for this one.
|
||||
if (MD->isFromPCH() && !MD->hasChangedAfterLoad() &&
|
||||
Name->isFromAST() && !Name->hasChangedSinceDeserialization())
|
||||
continue;
|
||||
|
||||
// Emit the macro directives in reverse source order.
|
||||
for (; MD; MD = MD->getPrevious()) {
|
||||
if (shouldIgnoreMacro(MD, IsModule, PP))
|
||||
continue;
|
||||
MacroID InfoID = getMacroRef(MD->getInfo(), Name);
|
||||
if (InfoID == 0)
|
||||
continue;
|
||||
|
||||
Record.push_back(InfoID);
|
||||
AddSourceLocation(MD->getLocation(), Record);
|
||||
AddSourceLocation(MD->getUndefLoc(), Record);
|
||||
AddSourceLocation(MD->getVisibilityLocation(), Record);
|
||||
Record.push_back(MD->isImported());
|
||||
Record.push_back(MD->isPublic());
|
||||
Record.push_back(MD->isAmbiguous());
|
||||
}
|
||||
if (Record.empty())
|
||||
continue;
|
||||
|
||||
Stream.EmitRecord(PP_MACRO_DIRECTIVE_HISTORY, Record);
|
||||
Record.clear();
|
||||
|
||||
IdentMacroDirectivesOffsetMap[Name] = MacroDirectiveOffset;
|
||||
|
||||
IdentID NameID = getIdentifierRef(Name);
|
||||
ASTMacroTableTrait::Data data;
|
||||
data.MacroDirectivesOffset = MacroDirectiveOffset;
|
||||
Generator.insert(NameID, data);
|
||||
}
|
||||
|
||||
/// \brief Offsets of each of the macros into the bitstream, indexed by
|
||||
/// the local macro ID
|
||||
@@ -1864,101 +1944,107 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) {
|
||||
/// defined.
|
||||
std::vector<uint32_t> MacroOffsets;
|
||||
|
||||
for (unsigned I = 0, N = MacrosToEmit.size(); I != N; ++I) {
|
||||
const IdentifierInfo *Name = MacrosToEmit[I].first;
|
||||
for (unsigned I = 0, N = MacroInfosToEmit.size(); I != N; ++I) {
|
||||
const IdentifierInfo *Name = MacroInfosToEmit[I].Name;
|
||||
MacroInfo *MI = MacroInfosToEmit[I].MI;
|
||||
MacroID ID = MacroInfosToEmit[I].ID;
|
||||
|
||||
for (MacroDirective *MD = MacrosToEmit[I].second; MD;
|
||||
MD = MD->getPrevious()) {
|
||||
if (shouldIgnoreMacro(MD, IsModule, PP))
|
||||
continue;
|
||||
|
||||
MacroID ID = getMacroRef(MD);
|
||||
if (!ID)
|
||||
continue;
|
||||
|
||||
// Skip macros from a AST file if we're chaining.
|
||||
if (Chain && MD->isImported() && !MD->hasChangedAfterLoad())
|
||||
continue;
|
||||
|
||||
if (ID < FirstMacroID) {
|
||||
// This will have been dealt with via an update record.
|
||||
assert(MacroUpdates.count(MD) > 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);
|
||||
addMacroRef(MD, Record);
|
||||
const MacroInfo *MI = MD->getInfo();
|
||||
Record.push_back(inferSubmoduleIDFromLocation(MI->getDefinitionLoc()));
|
||||
AddSourceLocation(MI->getDefinitionLoc(), Record);
|
||||
AddSourceLocation(MI->getDefinitionEndLoc(), Record);
|
||||
AddSourceLocation(MD->getUndefLoc(), Record);
|
||||
Record.push_back(MI->isUsed());
|
||||
Record.push_back(MD->isPublic());
|
||||
AddSourceLocation(MD->getVisibilityLocation(), Record);
|
||||
unsigned Code;
|
||||
if (MI->isObjectLike()) {
|
||||
Code = PP_MACRO_OBJECT_LIKE;
|
||||
} else {
|
||||
Code = PP_MACRO_FUNCTION_LIKE;
|
||||
|
||||
Record.push_back(MI->isC99Varargs());
|
||||
Record.push_back(MI->isGNUVarargs());
|
||||
Record.push_back(MI->hasCommaPasting());
|
||||
Record.push_back(MI->getNumArgs());
|
||||
for (MacroInfo::arg_iterator I = MI->arg_begin(), E = MI->arg_end();
|
||||
I != E; ++I)
|
||||
AddIdentifierRef(*I, Record);
|
||||
}
|
||||
|
||||
// If we have a detailed preprocessing record, record the macro definition
|
||||
// ID that corresponds to this macro.
|
||||
if (PPRec)
|
||||
Record.push_back(MacroDefinitions[PPRec->findMacroDefinition(MI)]);
|
||||
|
||||
Stream.EmitRecord(Code, Record);
|
||||
Record.clear();
|
||||
|
||||
// Emit the tokens array.
|
||||
for (unsigned TokNo = 0, e = MI->getNumTokens(); TokNo != e; ++TokNo) {
|
||||
// Note that we know that the preprocessor does not have any annotation
|
||||
// tokens in it because they are created by the parser, and thus can't
|
||||
// be in a macro definition.
|
||||
const Token &Tok = MI->getReplacementToken(TokNo);
|
||||
|
||||
Record.push_back(Tok.getLocation().getRawEncoding());
|
||||
Record.push_back(Tok.getLength());
|
||||
|
||||
// FIXME: When reading literal tokens, reconstruct the literal pointer
|
||||
// if it is needed.
|
||||
AddIdentifierRef(Tok.getIdentifierInfo(), Record);
|
||||
// FIXME: Should translate token kind to a stable encoding.
|
||||
Record.push_back(Tok.getKind());
|
||||
// FIXME: Should translate token flags to a stable encoding.
|
||||
Record.push_back(Tok.getFlags());
|
||||
|
||||
Stream.EmitRecord(PP_TOKEN, Record);
|
||||
Record.clear();
|
||||
}
|
||||
++NumMacros;
|
||||
if (ID < FirstMacroID) {
|
||||
assert(0 && "Loaded MacroInfo entered MacroInfosToEmit ?");
|
||||
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);
|
||||
Record.push_back(inferSubmoduleIDFromLocation(MI->getDefinitionLoc()));
|
||||
AddSourceLocation(MI->getDefinitionLoc(), Record);
|
||||
AddSourceLocation(MI->getDefinitionEndLoc(), Record);
|
||||
Record.push_back(MI->isUsed());
|
||||
unsigned Code;
|
||||
if (MI->isObjectLike()) {
|
||||
Code = PP_MACRO_OBJECT_LIKE;
|
||||
} else {
|
||||
Code = PP_MACRO_FUNCTION_LIKE;
|
||||
|
||||
Record.push_back(MI->isC99Varargs());
|
||||
Record.push_back(MI->isGNUVarargs());
|
||||
Record.push_back(MI->hasCommaPasting());
|
||||
Record.push_back(MI->getNumArgs());
|
||||
for (MacroInfo::arg_iterator I = MI->arg_begin(), E = MI->arg_end();
|
||||
I != E; ++I)
|
||||
AddIdentifierRef(*I, Record);
|
||||
}
|
||||
|
||||
// If we have a detailed preprocessing record, record the macro definition
|
||||
// ID that corresponds to this macro.
|
||||
if (PPRec)
|
||||
Record.push_back(MacroDefinitions[PPRec->findMacroDefinition(MI)]);
|
||||
|
||||
Stream.EmitRecord(Code, Record);
|
||||
Record.clear();
|
||||
|
||||
// Emit the tokens array.
|
||||
for (unsigned TokNo = 0, e = MI->getNumTokens(); TokNo != e; ++TokNo) {
|
||||
// Note that we know that the preprocessor does not have any annotation
|
||||
// tokens in it because they are created by the parser, and thus can't
|
||||
// be in a macro definition.
|
||||
const Token &Tok = MI->getReplacementToken(TokNo);
|
||||
|
||||
Record.push_back(Tok.getLocation().getRawEncoding());
|
||||
Record.push_back(Tok.getLength());
|
||||
|
||||
// FIXME: When reading literal tokens, reconstruct the literal pointer
|
||||
// if it is needed.
|
||||
AddIdentifierRef(Tok.getIdentifierInfo(), Record);
|
||||
// FIXME: Should translate token kind to a stable encoding.
|
||||
Record.push_back(Tok.getKind());
|
||||
// FIXME: Should translate token flags to a stable encoding.
|
||||
Record.push_back(Tok.getFlags());
|
||||
|
||||
Stream.EmitRecord(PP_TOKEN, Record);
|
||||
Record.clear();
|
||||
}
|
||||
++NumMacros;
|
||||
}
|
||||
|
||||
Stream.ExitBlock();
|
||||
|
||||
// Create the on-disk hash table in a buffer.
|
||||
SmallString<4096> MacroTable;
|
||||
uint32_t BucketOffset;
|
||||
{
|
||||
llvm::raw_svector_ostream Out(MacroTable);
|
||||
// Make sure that no bucket is at offset 0
|
||||
clang::io::Emit32(Out, 0);
|
||||
BucketOffset = Generator.Emit(Out);
|
||||
}
|
||||
|
||||
// Write the macro table
|
||||
using namespace llvm;
|
||||
BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
|
||||
Abbrev->Add(BitCodeAbbrevOp(MACRO_TABLE));
|
||||
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
|
||||
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
|
||||
unsigned MacroTableAbbrev = Stream.EmitAbbrev(Abbrev);
|
||||
|
||||
Record.push_back(MACRO_TABLE);
|
||||
Record.push_back(BucketOffset);
|
||||
Stream.EmitRecordWithBlob(MacroTableAbbrev, Record, MacroTable.str());
|
||||
Record.clear();
|
||||
|
||||
// Write the offsets table for macro IDs.
|
||||
using namespace llvm;
|
||||
BitCodeAbbrev *Abbrev = new 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
|
||||
@@ -2801,13 +2887,61 @@ class ASTIdentifierTableTrait {
|
||||
if (!II->hadMacroDefinition())
|
||||
return false;
|
||||
|
||||
if (Macro || (Macro = PP.getMacroDirectiveHistory(II)))
|
||||
return !shouldIgnoreMacro(Macro, IsModule, PP) &&
|
||||
(!IsModule || Macro->isPublic());
|
||||
if (Macro || (Macro = PP.getMacroDirectiveHistory(II))) {
|
||||
if (!IsModule)
|
||||
return !shouldIgnoreMacro(Macro, IsModule, PP);
|
||||
SubmoduleID ModID;
|
||||
if (getFirstPublicSubmoduleMacro(Macro, ModID))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
MacroDirective *getFirstPublicSubmoduleMacro(MacroDirective *MD,
|
||||
SubmoduleID &ModID) {
|
||||
if (shouldIgnoreMacro(MD, IsModule, PP))
|
||||
return 0;
|
||||
ModID = getSubmoduleID(MD);
|
||||
if (ModID == 0)
|
||||
return 0;
|
||||
if (MD->isDefined() && MD->isPublic())
|
||||
return MD;
|
||||
return getNextPublicSubmoduleMacro(MD, ModID);
|
||||
}
|
||||
|
||||
MacroDirective *getNextPublicSubmoduleMacro(MacroDirective *MD,
|
||||
SubmoduleID &ModID) {
|
||||
while (MD) {
|
||||
MD = getNextSubmoduleMacro(MD, ModID);
|
||||
if (MD && MD->isDefined() && MD->isPublic())
|
||||
return MD;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
MacroDirective *getNextSubmoduleMacro(MacroDirective *CurrMD,
|
||||
SubmoduleID &CurrModID) {
|
||||
SubmoduleID OrigID = CurrModID;
|
||||
while ((CurrMD = CurrMD->getPrevious())) {
|
||||
if (shouldIgnoreMacro(CurrMD, IsModule, PP))
|
||||
return 0;
|
||||
CurrModID = getSubmoduleID(CurrMD);
|
||||
if (CurrModID == 0)
|
||||
return 0;
|
||||
if (CurrModID != OrigID)
|
||||
return CurrMD;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
SubmoduleID getSubmoduleID(MacroDirective *MD) {
|
||||
MacroInfo *MI = MD->getInfo();
|
||||
if (unsigned ID = MI->getOwningModuleID())
|
||||
return ID;
|
||||
return Writer.inferSubmoduleIDFromLocation(MI->getDefinitionLoc());
|
||||
}
|
||||
|
||||
public:
|
||||
typedef IdentifierInfo* key_type;
|
||||
typedef key_type key_type_ref;
|
||||
@@ -2832,14 +2966,15 @@ public:
|
||||
DataLen += 2; // 2 bytes for builtin ID
|
||||
DataLen += 2; // 2 bytes for flags
|
||||
if (hadMacroDefinition(II, Macro)) {
|
||||
for (MacroDirective *M = Macro; M; M = M->getPrevious()) {
|
||||
if (shouldIgnoreMacro(M, IsModule, PP))
|
||||
continue;
|
||||
if (Writer.getMacroRef(M) != 0)
|
||||
DataLen += 4;
|
||||
DataLen += 4; // MacroDirectives offset.
|
||||
if (IsModule) {
|
||||
SubmoduleID ModID;
|
||||
for (MacroDirective *MD = getFirstPublicSubmoduleMacro(Macro, ModID);
|
||||
MD; MD = getNextPublicSubmoduleMacro(MD, ModID)) {
|
||||
DataLen += 4; // MacroInfo ID.
|
||||
}
|
||||
DataLen += 4;
|
||||
}
|
||||
|
||||
DataLen += 4;
|
||||
}
|
||||
|
||||
for (IdentifierResolver::iterator D = IdResolver.begin(II),
|
||||
@@ -2878,6 +3013,7 @@ public:
|
||||
Bits = 0;
|
||||
bool HadMacroDefinition = hadMacroDefinition(II, Macro);
|
||||
Bits = (Bits << 1) | unsigned(HadMacroDefinition);
|
||||
Bits = (Bits << 1) | unsigned(IsModule);
|
||||
Bits = (Bits << 1) | unsigned(II->isExtensionToken());
|
||||
Bits = (Bits << 1) | unsigned(II->isPoisoned());
|
||||
Bits = (Bits << 1) | unsigned(II->hasRevertedTokenIDToIdentifier());
|
||||
@@ -2885,15 +3021,18 @@ public:
|
||||
clang::io::Emit16(Out, Bits);
|
||||
|
||||
if (HadMacroDefinition) {
|
||||
// Write all of the macro IDs associated with this identifier.
|
||||
for (MacroDirective *M = Macro; M; M = M->getPrevious()) {
|
||||
if (shouldIgnoreMacro(M, IsModule, PP))
|
||||
continue;
|
||||
if (MacroID ID = Writer.getMacroRef(M))
|
||||
clang::io::Emit32(Out, ID);
|
||||
clang::io::Emit32(Out, Writer.getMacroDirectivesOffset(II));
|
||||
if (IsModule) {
|
||||
// Write the IDs of macros coming from different submodules.
|
||||
SubmoduleID ModID;
|
||||
for (MacroDirective *MD = getFirstPublicSubmoduleMacro(Macro, ModID);
|
||||
MD; MD = getNextPublicSubmoduleMacro(MD, ModID)) {
|
||||
MacroID InfoID = Writer.getMacroID(MD->getInfo());
|
||||
assert(InfoID);
|
||||
clang::io::Emit32(Out, InfoID);
|
||||
}
|
||||
clang::io::Emit32(Out, 0);
|
||||
}
|
||||
|
||||
clang::io::Emit32(Out, 0);
|
||||
}
|
||||
|
||||
// Emit the declaration IDs in reverse order, because the
|
||||
@@ -3968,7 +4107,6 @@ void ASTWriter::WriteASTCore(Sema &SemaRef,
|
||||
}
|
||||
}
|
||||
|
||||
WriteMacroUpdates();
|
||||
WriteDeclUpdatesBlocks();
|
||||
WriteDeclReplacementsBlock();
|
||||
WriteRedeclarations();
|
||||
@@ -3985,21 +4123,6 @@ void ASTWriter::WriteASTCore(Sema &SemaRef,
|
||||
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);
|
||||
Record.push_back(inferSubmoduleIDFromLocation(I->second.UndefLoc));
|
||||
}
|
||||
Stream.EmitRecord(MACRO_UPDATES, Record);
|
||||
}
|
||||
|
||||
/// \brief Go through the declaration update blocks and resolve declaration
|
||||
/// pointers into declaration IDs.
|
||||
void ASTWriter::ResolveDeclUpdatesBlocks() {
|
||||
@@ -4095,10 +4218,6 @@ void ASTWriter::AddIdentifierRef(const IdentifierInfo *II, RecordDataImpl &Recor
|
||||
Record.push_back(getIdentifierRef(II));
|
||||
}
|
||||
|
||||
void ASTWriter::addMacroRef(MacroDirective *MD, RecordDataImpl &Record) {
|
||||
Record.push_back(getMacroRef(MD));
|
||||
}
|
||||
|
||||
IdentID ASTWriter::getIdentifierRef(const IdentifierInfo *II) {
|
||||
if (II == 0)
|
||||
return 0;
|
||||
@@ -4109,19 +4228,35 @@ IdentID ASTWriter::getIdentifierRef(const IdentifierInfo *II) {
|
||||
return ID;
|
||||
}
|
||||
|
||||
MacroID ASTWriter::getMacroRef(MacroDirective *MD) {
|
||||
MacroID ASTWriter::getMacroRef(MacroInfo *MI, const IdentifierInfo *Name) {
|
||||
// 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 (MD == 0 || MD->getInfo()->isBuiltinMacro())
|
||||
if (MI == 0 || MI->isBuiltinMacro())
|
||||
return 0;
|
||||
|
||||
MacroID &ID = MacroIDs[MD];
|
||||
if (ID == 0)
|
||||
MacroID &ID = MacroIDs[MI];
|
||||
if (ID == 0) {
|
||||
ID = NextMacroID++;
|
||||
MacroInfoToEmitData Info = { Name, MI, ID };
|
||||
MacroInfosToEmit.push_back(Info);
|
||||
}
|
||||
return ID;
|
||||
}
|
||||
|
||||
MacroID ASTWriter::getMacroID(MacroInfo *MI) {
|
||||
if (MI == 0 || MI->isBuiltinMacro())
|
||||
return 0;
|
||||
|
||||
assert(MacroIDs.find(MI) != MacroIDs.end() && "Macro not emitted!");
|
||||
return MacroIDs[MI];
|
||||
}
|
||||
|
||||
uint64_t ASTWriter::getMacroDirectivesOffset(const IdentifierInfo *Name) {
|
||||
assert(IdentMacroDirectivesOffsetMap[Name] && "not set!");
|
||||
return IdentMacroDirectivesOffsetMap[Name];
|
||||
}
|
||||
|
||||
void ASTWriter::AddSelectorRef(const Selector SelRef, RecordDataImpl &Record) {
|
||||
Record.push_back(getSelectorRef(SelRef));
|
||||
}
|
||||
@@ -4861,9 +4996,9 @@ void ASTWriter::IdentifierRead(IdentID ID, IdentifierInfo *II) {
|
||||
StoredID = ID;
|
||||
}
|
||||
|
||||
void ASTWriter::MacroRead(serialization::MacroID ID, MacroDirective *MD) {
|
||||
void ASTWriter::MacroRead(serialization::MacroID ID, MacroInfo *MI) {
|
||||
// Always keep the highest ID. See \p TypeRead() for more information.
|
||||
MacroID &StoredID = MacroIDs[MD];
|
||||
MacroID &StoredID = MacroIDs[MI];
|
||||
if (ID > StoredID)
|
||||
StoredID = ID;
|
||||
}
|
||||
@@ -4897,10 +5032,6 @@ void ASTWriter::ModuleRead(serialization::SubmoduleID ID, Module *Mod) {
|
||||
SubmoduleIDs[Mod] = ID;
|
||||
}
|
||||
|
||||
void ASTWriter::UndefinedMacro(MacroDirective *MD) {
|
||||
MacroUpdates[MD].UndefLoc = MD->getUndefLoc();
|
||||
}
|
||||
|
||||
void ASTWriter::CompletedTagDefinition(const TagDecl *D) {
|
||||
assert(D->isCompleteDefinition());
|
||||
assert(!WritingAST && "Already writing the AST!");
|
||||
|
||||
Reference in New Issue
Block a user