[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:
Argyrios Kyrtzidis
2013-03-22 21:12:57 +00:00
parent 4f32da1ef5
commit eb663daeff
10 changed files with 608 additions and 344 deletions

View File

@@ -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

View File

@@ -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);

View File

@@ -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.

View File

@@ -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.

View File

@@ -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();

View File

@@ -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);

View File

@@ -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);

View File

@@ -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,

View File

@@ -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();

View File

@@ -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!");