aboutsummaryrefslogtreecommitdiff
path: root/lib/Serialization/ASTWriter.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2011-09-01 17:04:32 +0000
committerDouglas Gregor <dgregor@apple.com>2011-09-01 17:04:32 +0000
commit7143aab97c6e849a5a5005b7853b8c7d5af008ed (patch)
tree1d717dfe03b6e8ad673920a17b021fb3faf6912d /lib/Serialization/ASTWriter.cpp
parent8efcc0184a6dfe1ea799d3a6b9c1312ef1fac11d (diff)
Modules hide macro definitions by default, so that silly things like
include guards don't show up as macro definitions in every translation unit that imports a module. Macro definitions can, however, be exported with the intentionally-ugly #__export_macro__ directive. Implement this feature by not even bothering to serialize non-exported macros to a module, because clients of that module need not (should not) know that these macros even exist. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@138943 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Serialization/ASTWriter.cpp')
-rw-r--r--lib/Serialization/ASTWriter.cpp83
1 files changed, 51 insertions, 32 deletions
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index a57f3a1388..f2ff332de1 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -1667,7 +1667,7 @@ static int compareMacroDefinitions(const void *XPtr, const void *YPtr) {
/// \brief Writes the block containing the serialized form of the
/// preprocessor.
///
-void ASTWriter::WritePreprocessor(const Preprocessor &PP) {
+void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) {
RecordData Record;
// If the preprocessor __COUNTER__ value has been bumped, remember it.
@@ -1697,8 +1697,10 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP) {
for (Preprocessor::macro_iterator I = PP.macro_begin(Chain == 0),
E = PP.macro_end(Chain == 0);
I != E; ++I) {
- MacroDefinitionsSeen.insert(I->first);
- MacrosToEmit.push_back(std::make_pair(I->first, I->second));
+ if (!IsModule || I->second->isExported()) {
+ MacroDefinitionsSeen.insert(I->first);
+ MacrosToEmit.push_back(std::make_pair(I->first, I->second));
+ }
}
// Sort the set of macro definitions that need to be serialized by the
@@ -1730,14 +1732,15 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP) {
// chained PCH, by storing the offset into the original PCH rather than
// writing the macro definition a second time.
if (MI->isBuiltinMacro() ||
- (Chain && Name->isFromAST() && MI->isFromAST()))
+ (Chain && Name->isFromAST() && MI->isFromAST() &&
+ !MI->hasChangedAfterLoad()))
continue;
AddIdentifierRef(Name, Record);
MacroOffsets[Name] = Stream.GetCurrentBitNo();
Record.push_back(MI->getDefinitionLoc().getRawEncoding());
Record.push_back(MI->isUsed());
-
+ AddSourceLocation(MI->getExportLocation(), Record);
unsigned Code;
if (MI->isObjectLike()) {
Code = PP_MACRO_OBJECT_LIKE;
@@ -2293,38 +2296,52 @@ namespace {
class ASTIdentifierTableTrait {
ASTWriter &Writer;
Preprocessor &PP;
-
+ bool IsModule;
+
/// \brief Determines whether this is an "interesting" identifier
/// that needs a full IdentifierInfo structure written into the hash
/// table.
- static bool isInterestingIdentifier(const IdentifierInfo *II) {
- return II->isPoisoned() ||
- II->isExtensionToken() ||
- II->hasMacroDefinition() ||
- II->getObjCOrBuiltinID() ||
- II->getFETokenInfo<void>();
+ bool isInterestingIdentifier(IdentifierInfo *II, MacroInfo *&Macro) {
+ Macro = 0;
+
+ if (II->isPoisoned() ||
+ II->isExtensionToken() ||
+ II->getObjCOrBuiltinID() ||
+ II->getFETokenInfo<void>())
+ return true;
+
+ if (!II->hasMacroDefinition())
+ return false;
+
+ if (!IsModule)
+ return true;
+
+ if ((Macro = PP.getMacroInfo(II)))
+ return Macro->isExported();
+
+ return false;
}
public:
- typedef const IdentifierInfo* key_type;
+ typedef IdentifierInfo* key_type;
typedef key_type key_type_ref;
typedef IdentID data_type;
typedef data_type data_type_ref;
- ASTIdentifierTableTrait(ASTWriter &Writer, Preprocessor &PP)
- : Writer(Writer), PP(PP) { }
+ ASTIdentifierTableTrait(ASTWriter &Writer, Preprocessor &PP, bool IsModule)
+ : Writer(Writer), PP(PP), IsModule(IsModule) { }
static unsigned ComputeHash(const IdentifierInfo* II) {
return llvm::HashString(II->getName());
}
std::pair<unsigned,unsigned>
- EmitKeyDataLength(raw_ostream& Out, const IdentifierInfo* II,
- IdentID ID) {
+ EmitKeyDataLength(raw_ostream& Out, IdentifierInfo* II, IdentID ID) {
unsigned KeyLen = II->getLength() + 1;
unsigned DataLen = 4; // 4 bytes for the persistent ID << 1
- if (isInterestingIdentifier(II)) {
+ MacroInfo *Macro;
+ if (isInterestingIdentifier(II, Macro)) {
DataLen += 2; // 2 bytes for builtin ID, flags
if (II->hasMacroDefinition() &&
!PP.getMacroInfo(const_cast<IdentifierInfo *>(II))->isBuiltinMacro())
@@ -2350,18 +2367,19 @@ public:
Out.write(II->getNameStart(), KeyLen);
}
- void EmitData(raw_ostream& Out, const IdentifierInfo* II,
+ void EmitData(raw_ostream& Out, IdentifierInfo* II,
IdentID ID, unsigned) {
- if (!isInterestingIdentifier(II)) {
+ MacroInfo *Macro;
+ if (!isInterestingIdentifier(II, Macro)) {
clang::io::Emit32(Out, ID << 1);
return;
}
clang::io::Emit32(Out, (ID << 1) | 0x01);
uint32_t Bits = 0;
- bool hasMacroDefinition =
- II->hasMacroDefinition() &&
- !PP.getMacroInfo(const_cast<IdentifierInfo *>(II))->isBuiltinMacro();
+ bool hasMacroDefinition
+ = II->hasMacroDefinition() &&
+ (Macro || (Macro = PP.getMacroInfo(II))) && !Macro->isBuiltinMacro();
Bits = (uint32_t)II->getObjCOrBuiltinID();
Bits = (Bits << 1) | unsigned(hasMacroDefinition);
Bits = (Bits << 1) | unsigned(II->isExtensionToken());
@@ -2395,14 +2413,14 @@ public:
/// The identifier table consists of a blob containing string data
/// (the actual identifiers themselves) and a separate "offsets" index
/// that maps identifier IDs to locations within the blob.
-void ASTWriter::WriteIdentifierTable(Preprocessor &PP) {
+void ASTWriter::WriteIdentifierTable(Preprocessor &PP, bool IsModule) {
using namespace llvm;
// Create and write out the blob that contains the identifier
// strings.
{
OnDiskChainedHashTableGenerator<ASTIdentifierTableTrait> Generator;
- ASTIdentifierTableTrait Trait(*this, PP);
+ ASTIdentifierTableTrait Trait(*this, PP, IsModule);
// Look for any identifiers that were named while processing the
// headers, but are otherwise not needed. We add these to the hash
@@ -2422,14 +2440,15 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP) {
ID != IDEnd; ++ID) {
assert(ID->first && "NULL identifier in identifier table");
if (!Chain || !ID->first->isFromAST())
- Generator.insert(ID->first, ID->second, Trait);
+ Generator.insert(const_cast<IdentifierInfo *>(ID->first), ID->second,
+ Trait);
}
// Create the on-disk hash table in a buffer.
llvm::SmallString<4096> IdentifierTable;
uint32_t BucketOffset;
{
- ASTIdentifierTableTrait Trait(*this, PP);
+ ASTIdentifierTableTrait Trait(*this, PP, IsModule);
llvm::raw_svector_ostream Out(IdentifierTable);
// Make sure that no bucket is at offset 0
clang::io::Emit32(Out, 0);
@@ -2818,7 +2837,7 @@ ASTWriter::ASTWriter(llvm::BitstreamWriter &Stream)
void ASTWriter::WriteAST(Sema &SemaRef, MemorizeStatCalls *StatCalls,
const std::string &OutputFile,
- StringRef isysroot) {
+ bool IsModule, StringRef isysroot) {
// Emit the file header.
Stream.Emit((unsigned)'C', 8);
Stream.Emit((unsigned)'P', 8);
@@ -2828,7 +2847,7 @@ void ASTWriter::WriteAST(Sema &SemaRef, MemorizeStatCalls *StatCalls,
WriteBlockInfoBlock();
Context = &SemaRef.Context;
- WriteASTCore(SemaRef, StatCalls, isysroot, OutputFile);
+ WriteASTCore(SemaRef, StatCalls, isysroot, OutputFile, IsModule);
Context = 0;
}
@@ -2843,7 +2862,7 @@ static void AddLazyVectorDecls(ASTWriter &Writer, Vector &Vec,
void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls,
StringRef isysroot,
- const std::string &OutputFile) {
+ const std::string &OutputFile, bool IsModule) {
using namespace llvm;
ASTContext &Context = SemaRef.Context;
@@ -3095,11 +3114,11 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls,
}
Stream.ExitBlock();
- WritePreprocessor(PP);
+ WritePreprocessor(PP, IsModule);
WriteHeaderSearch(PP.getHeaderSearchInfo(), isysroot);
WriteSelectors(SemaRef);
WriteReferencedSelectorsPool(SemaRef);
- WriteIdentifierTable(PP);
+ WriteIdentifierTable(PP, IsModule);
WriteFPPragmaOptions(SemaRef.getFPOptions());
WriteOpenCLExtensions(SemaRef);