mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-22 08:32:23 +00:00
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. llvm-svn: 138943
This commit is contained in:
parent
0274487d97
commit
4a69c2e6c5
@ -324,4 +324,6 @@ def err_pp_linemarker_invalid_pop : Error<
|
||||
def ext_pp_line_too_big : Extension<
|
||||
"C requires #line number to be less than %0, allowed as extension">;
|
||||
|
||||
def err_pp_export_non_macro : Error<"no macro named %0 to export">;
|
||||
|
||||
}
|
||||
|
@ -89,6 +89,9 @@ PPKEYWORD(sccs)
|
||||
PPKEYWORD(assert)
|
||||
PPKEYWORD(unassert)
|
||||
|
||||
// Clang extensions
|
||||
PPKEYWORD(__export_macro__)
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Language keywords.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -39,6 +39,11 @@ class MacroInfo {
|
||||
IdentifierInfo **ArgumentList;
|
||||
unsigned NumArguments;
|
||||
|
||||
/// \brief The location at which this macro was exported from its module.
|
||||
///
|
||||
/// If invalid, this macro has not been explicitly exported.
|
||||
SourceLocation ExportLocation;
|
||||
|
||||
/// ReplacementTokens - This is the list of tokens that the macro is defined
|
||||
/// to.
|
||||
SmallVector<Token, 8> ReplacementTokens;
|
||||
@ -68,6 +73,9 @@ class MacroInfo {
|
||||
/// IsFromAST - True if this macro was loaded from an AST file.
|
||||
bool IsFromAST : 1;
|
||||
|
||||
/// \brief Whether this macro changed after it was loaded from an AST file.
|
||||
bool ChangedAfterLoad : 1;
|
||||
|
||||
private:
|
||||
//===--------------------------------------------------------------------===//
|
||||
// State that changes as the macro is used.
|
||||
@ -209,6 +217,14 @@ public:
|
||||
/// setIsFromAST - Set whether this macro was loaded from an AST file.
|
||||
void setIsFromAST(bool FromAST = true) { IsFromAST = FromAST; }
|
||||
|
||||
/// \brief Determine whether this macro has changed since it was loaded from
|
||||
/// an AST file.
|
||||
bool hasChangedAfterLoad() const { return ChangedAfterLoad; }
|
||||
|
||||
/// \brief Note whether this macro has changed after it was loaded from an
|
||||
/// AST file.
|
||||
void setChangedAfterLoad(bool CAL = true) { ChangedAfterLoad = CAL; }
|
||||
|
||||
/// isUsed - Return false if this macro is defined in the main file and has
|
||||
/// not yet been used.
|
||||
bool isUsed() const { return IsUsed; }
|
||||
@ -262,6 +278,19 @@ public:
|
||||
IsDisabled = true;
|
||||
}
|
||||
|
||||
/// \brief Set the export location for this macro.
|
||||
void setExportLocation(SourceLocation ExportLoc) {
|
||||
ExportLocation = ExportLoc;
|
||||
}
|
||||
|
||||
/// \brief Determine whether this macro was explicitly exported from its
|
||||
/// module.
|
||||
bool isExported() const { return ExportLocation.isValid(); }
|
||||
|
||||
/// \brief Determine the location where this macro was explicitly exported
|
||||
/// from its module.
|
||||
SourceLocation getExportLocation() { return ExportLocation; }
|
||||
|
||||
private:
|
||||
unsigned getDefinitionLengthSlow(SourceManager &SM) const;
|
||||
};
|
||||
|
@ -1117,7 +1117,8 @@ private:
|
||||
void HandleDigitDirective(Token &Tok);
|
||||
void HandleUserDiagnosticDirective(Token &Tok, bool isWarning);
|
||||
void HandleIdentSCCSDirective(Token &Tok);
|
||||
|
||||
void HandleMacroExportDirective(Token &Tok);
|
||||
|
||||
// File inclusion.
|
||||
void HandleIncludeDirective(SourceLocation HashLoc,
|
||||
Token &Tok,
|
||||
|
@ -348,7 +348,7 @@ private:
|
||||
void WriteSourceManagerBlock(SourceManager &SourceMgr,
|
||||
const Preprocessor &PP,
|
||||
StringRef isysroot);
|
||||
void WritePreprocessor(const Preprocessor &PP);
|
||||
void WritePreprocessor(const Preprocessor &PP, bool IsModule);
|
||||
void WriteHeaderSearch(HeaderSearch &HS, StringRef isysroot);
|
||||
void WritePreprocessorDetail(PreprocessingRecord &PPRec);
|
||||
void WritePragmaDiagnosticMappings(const Diagnostic &Diag);
|
||||
@ -359,7 +359,7 @@ private:
|
||||
void WriteTypeDeclOffsets();
|
||||
void WriteSelectors(Sema &SemaRef);
|
||||
void WriteReferencedSelectorsPool(Sema &SemaRef);
|
||||
void WriteIdentifierTable(Preprocessor &PP);
|
||||
void WriteIdentifierTable(Preprocessor &PP, bool IsModule);
|
||||
void WriteAttributes(const AttrVec &Attrs, RecordDataImpl &Record);
|
||||
void WriteDeclUpdatesBlocks();
|
||||
void WriteDeclReplacementsBlock();
|
||||
@ -386,7 +386,8 @@ private:
|
||||
void WriteDecl(ASTContext &Context, Decl *D);
|
||||
|
||||
void WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls,
|
||||
StringRef isysroot, const std::string &OutputFile);
|
||||
StringRef isysroot, const std::string &OutputFile,
|
||||
bool IsModule);
|
||||
|
||||
public:
|
||||
/// \brief Create a new precompiled header writer that outputs to
|
||||
@ -407,11 +408,14 @@ public:
|
||||
/// \param StatCalls the object that cached all of the stat() calls made while
|
||||
/// searching for source files and headers.
|
||||
///
|
||||
/// \param isysroot if non-empty, write a relocatable PCH file whose headers
|
||||
/// \param IsModule Whether we're writing a module (otherwise, we're writing a
|
||||
/// precompiled header).
|
||||
///
|
||||
/// \param isysroot if non-empty, write a relocatable file whose headers
|
||||
/// are relative to the given system root.
|
||||
void WriteAST(Sema &SemaRef, MemorizeStatCalls *StatCalls,
|
||||
const std::string &OutputFile,
|
||||
StringRef isysroot);
|
||||
bool IsModule, StringRef isysroot);
|
||||
|
||||
/// \brief Emit a source location.
|
||||
void AddSourceLocation(SourceLocation Loc, RecordDataImpl &Record);
|
||||
@ -643,6 +647,7 @@ public:
|
||||
class PCHGenerator : public SemaConsumer {
|
||||
const Preprocessor &PP;
|
||||
std::string OutputFile;
|
||||
bool IsModule;
|
||||
std::string isysroot;
|
||||
raw_ostream *Out;
|
||||
Sema *SemaPtr;
|
||||
@ -657,6 +662,7 @@ protected:
|
||||
|
||||
public:
|
||||
PCHGenerator(const Preprocessor &PP, StringRef OutputFile,
|
||||
bool IsModule,
|
||||
StringRef isysroot, raw_ostream *Out);
|
||||
~PCHGenerator();
|
||||
virtual void InitializeSema(Sema &S) { SemaPtr = &S; }
|
||||
|
@ -217,6 +217,7 @@ tok::PPKeywordKind IdentifierInfo::getPPKeywordID() const {
|
||||
CASE(12, 'i', 'c', include_next);
|
||||
|
||||
CASE(16, '_', 'i', __include_macros);
|
||||
CASE(16, '_', 'e', __export_macro__);
|
||||
#undef CASE
|
||||
#undef HASH
|
||||
}
|
||||
|
@ -771,7 +771,7 @@ class PrecompilePreambleConsumer : public PCHGenerator,
|
||||
public:
|
||||
PrecompilePreambleConsumer(ASTUnit &Unit, const Preprocessor &PP,
|
||||
StringRef isysroot, raw_ostream *Out)
|
||||
: PCHGenerator(PP, "", isysroot, Out), Unit(Unit),
|
||||
: PCHGenerator(PP, "", /*IsModule=*/false, isysroot, Out), Unit(Unit),
|
||||
Hash(Unit.getCurrentTopLevelHashValue()) {
|
||||
Hash = 0;
|
||||
}
|
||||
@ -2324,7 +2324,8 @@ bool ASTUnit::serialize(raw_ostream &OS) {
|
||||
std::vector<unsigned char> Buffer;
|
||||
llvm::BitstreamWriter Stream(Buffer);
|
||||
ASTWriter Writer(Stream);
|
||||
Writer.WriteAST(getSema(), 0, std::string(), "");
|
||||
// FIXME: Handle modules
|
||||
Writer.WriteAST(getSema(), 0, std::string(), /*IsModule=*/false, "");
|
||||
|
||||
// Write the generated bitstream to "Out".
|
||||
if (!Buffer.empty())
|
||||
|
@ -83,7 +83,8 @@ ASTConsumer *GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI,
|
||||
|
||||
if (!CI.getFrontendOpts().RelocatablePCH)
|
||||
Sysroot.clear();
|
||||
return new PCHGenerator(CI.getPreprocessor(), OutputFile, Sysroot, OS);
|
||||
return new PCHGenerator(CI.getPreprocessor(), OutputFile, MakeModule,
|
||||
Sysroot, OS);
|
||||
}
|
||||
|
||||
bool GeneratePCHAction::ComputeASTConsumerArguments(CompilerInstance &CI,
|
||||
|
@ -21,6 +21,7 @@ MacroInfo::MacroInfo(SourceLocation DefLoc) : Location(DefLoc) {
|
||||
IsGNUVarargs = false;
|
||||
IsBuiltinMacro = false;
|
||||
IsFromAST = false;
|
||||
ChangedAfterLoad = false;
|
||||
IsDisabled = false;
|
||||
IsUsed = false;
|
||||
IsAllowRedefinitionsWithoutWarning = false;
|
||||
@ -40,6 +41,7 @@ MacroInfo::MacroInfo(const MacroInfo &MI, llvm::BumpPtrAllocator &PPAllocator) {
|
||||
IsGNUVarargs = MI.IsGNUVarargs;
|
||||
IsBuiltinMacro = MI.IsBuiltinMacro;
|
||||
IsFromAST = MI.IsFromAST;
|
||||
ChangedAfterLoad = MI.ChangedAfterLoad;
|
||||
IsDisabled = MI.IsDisabled;
|
||||
IsUsed = MI.IsUsed;
|
||||
IsAllowRedefinitionsWithoutWarning = MI.IsAllowRedefinitionsWithoutWarning;
|
||||
|
@ -652,6 +652,9 @@ TryAgain:
|
||||
case tok::pp_unassert:
|
||||
//isExtension = true; // FIXME: implement #unassert
|
||||
break;
|
||||
|
||||
case tok::pp___export_macro__:
|
||||
return HandleMacroExportDirective(Result);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -1000,6 +1003,37 @@ void Preprocessor::HandleIdentSCCSDirective(Token &Tok) {
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Handle a #__export_macro__ directive.
|
||||
void Preprocessor::HandleMacroExportDirective(Token &Tok) {
|
||||
Token MacroNameTok;
|
||||
ReadMacroName(MacroNameTok, 2);
|
||||
|
||||
// Error reading macro name? If so, diagnostic already issued.
|
||||
if (MacroNameTok.is(tok::eod))
|
||||
return;
|
||||
|
||||
// Check to see if this is the last token on the #__export_macro__ line.
|
||||
CheckEndOfDirective("__export_macro__");
|
||||
|
||||
// Okay, we finally have a valid identifier to undef.
|
||||
MacroInfo *MI = getMacroInfo(MacroNameTok.getIdentifierInfo());
|
||||
|
||||
// If the macro is not defined, this is an error.
|
||||
if (MI == 0) {
|
||||
Diag(MacroNameTok, diag::err_pp_export_non_macro)
|
||||
<< MacroNameTok.getIdentifierInfo();
|
||||
return;
|
||||
}
|
||||
|
||||
// Note that this macro has now been exported.
|
||||
MI->setExportLocation(MacroNameTok.getLocation());
|
||||
|
||||
// If this macro definition came from a PCH file, mark it
|
||||
// as having changed since serialization.
|
||||
if (MI->isFromAST())
|
||||
MI->setChangedAfterLoad();
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Preprocessor Include Directive Handling.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -1352,15 +1352,16 @@ void ASTReader::ReadMacroRecord(Module &F, uint64_t Offset) {
|
||||
MI->setIsFromAST();
|
||||
|
||||
unsigned NextIndex = 3;
|
||||
MI->setExportLocation(ReadSourceLocation(F, Record, NextIndex));
|
||||
|
||||
if (RecType == PP_MACRO_FUNCTION_LIKE) {
|
||||
// Decode function-like macro info.
|
||||
bool isC99VarArgs = Record[3];
|
||||
bool isGNUVarArgs = Record[4];
|
||||
bool isC99VarArgs = Record[NextIndex++];
|
||||
bool isGNUVarArgs = Record[NextIndex++];
|
||||
MacroArgs.clear();
|
||||
unsigned NumArgs = Record[5];
|
||||
NextIndex = 6 + NumArgs;
|
||||
unsigned NumArgs = Record[NextIndex++];
|
||||
for (unsigned i = 0; i != NumArgs; ++i)
|
||||
MacroArgs.push_back(getLocalIdentifier(F, Record[6+i]));
|
||||
MacroArgs.push_back(getLocalIdentifier(F, Record[NextIndex++]));
|
||||
|
||||
// Install function-like macro info.
|
||||
MI->setIsFunctionLike();
|
||||
|
@ -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);
|
||||
|
||||
|
@ -106,7 +106,7 @@ ChainedIncludesSource *ChainedIncludesSource::create(CompilerInstance &CI) {
|
||||
llvm::raw_svector_ostream OS(serialAST);
|
||||
llvm::OwningPtr<ASTConsumer> consumer;
|
||||
consumer.reset(new PCHGenerator(Clang->getPreprocessor(), "-",
|
||||
/*isysroot=*/"", &OS));
|
||||
/*IsModule=*/false, /*isysroot=*/"", &OS));
|
||||
Clang->getASTContext().setASTMutationListener(
|
||||
consumer->GetASTMutationListener());
|
||||
Clang->setASTConsumer(consumer.take());
|
||||
|
@ -28,9 +28,11 @@ using namespace clang;
|
||||
|
||||
PCHGenerator::PCHGenerator(const Preprocessor &PP,
|
||||
StringRef OutputFile,
|
||||
bool IsModule,
|
||||
StringRef isysroot,
|
||||
raw_ostream *OS)
|
||||
: PP(PP), OutputFile(OutputFile), isysroot(isysroot.str()), Out(OS),
|
||||
: PP(PP), OutputFile(OutputFile), IsModule(IsModule),
|
||||
isysroot(isysroot.str()), Out(OS),
|
||||
SemaPtr(0), StatCalls(0), Stream(Buffer), Writer(Stream) {
|
||||
// Install a stat() listener to keep track of all of the stat()
|
||||
// calls.
|
||||
@ -50,7 +52,7 @@ void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) {
|
||||
|
||||
// Emit the PCH file
|
||||
assert(SemaPtr && "No Sema?");
|
||||
Writer.WriteAST(*SemaPtr, StatCalls, OutputFile, isysroot);
|
||||
Writer.WriteAST(*SemaPtr, StatCalls, OutputFile, IsModule, isysroot);
|
||||
|
||||
// Write the generated bitstream to "Out".
|
||||
Out->write((char *)&Buffer.front(), Buffer.size());
|
||||
|
33
clang/test/Modules/macros.c
Normal file
33
clang/test/Modules/macros.c
Normal file
@ -0,0 +1,33 @@
|
||||
// RUN: %clang_cc1 -emit-module -o %t/macros.pcm -DMODULE %s
|
||||
// RUN: %clang_cc1 -verify -I %t %s
|
||||
|
||||
#if defined(MODULE)
|
||||
#define INTEGER(X) int
|
||||
#define FLOAT float
|
||||
#define DOUBLE double
|
||||
|
||||
#__export_macro__ INTEGER
|
||||
#__export_macro__ DOUBLE
|
||||
|
||||
#else
|
||||
|
||||
__import_module__ macros;
|
||||
|
||||
#ifndef INTEGER
|
||||
# error INTEGER macro should be visible
|
||||
#endif
|
||||
|
||||
#ifdef FLOAT
|
||||
# error FLOAT macro should not be visible
|
||||
#endif
|
||||
|
||||
#ifdef MODULE
|
||||
# error MODULE macro should not be visible
|
||||
#endif
|
||||
|
||||
double d;
|
||||
DOUBLE *dp = &d;
|
||||
|
||||
#__export_macro__ WIBBLE // expected-error{{no macro named 'WIBBLE' to export}}
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user