diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-09-01 17:04:32 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-09-01 17:04:32 +0000 |
commit | 7143aab97c6e849a5a5005b7853b8c7d5af008ed (patch) | |
tree | 1d717dfe03b6e8ad673920a17b021fb3faf6912d | |
parent | 8efcc0184a6dfe1ea799d3a6b9c1312ef1fac11d (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
-rw-r--r-- | include/clang/Basic/DiagnosticLexKinds.td | 2 | ||||
-rw-r--r-- | include/clang/Basic/TokenKinds.def | 3 | ||||
-rw-r--r-- | include/clang/Lex/MacroInfo.h | 29 | ||||
-rw-r--r-- | include/clang/Lex/Preprocessor.h | 3 | ||||
-rw-r--r-- | include/clang/Serialization/ASTWriter.h | 16 | ||||
-rw-r--r-- | lib/Basic/IdentifierTable.cpp | 1 | ||||
-rw-r--r-- | lib/Frontend/ASTUnit.cpp | 5 | ||||
-rw-r--r-- | lib/Frontend/FrontendActions.cpp | 3 | ||||
-rw-r--r-- | lib/Lex/MacroInfo.cpp | 2 | ||||
-rw-r--r-- | lib/Lex/PPDirectives.cpp | 34 | ||||
-rw-r--r-- | lib/Serialization/ASTReader.cpp | 11 | ||||
-rw-r--r-- | lib/Serialization/ASTWriter.cpp | 83 | ||||
-rw-r--r-- | lib/Serialization/ChainedIncludesSource.cpp | 2 | ||||
-rw-r--r-- | lib/Serialization/GeneratePCH.cpp | 6 | ||||
-rw-r--r-- | test/Modules/macros.c | 33 |
15 files changed, 184 insertions, 49 deletions
diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td index 275e8a1e28..481adc43a4 100644 --- a/include/clang/Basic/DiagnosticLexKinds.td +++ b/include/clang/Basic/DiagnosticLexKinds.td @@ -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">; + } diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def index b5752fe688..5d68a22ffc 100644 --- a/include/clang/Basic/TokenKinds.def +++ b/include/clang/Basic/TokenKinds.def @@ -89,6 +89,9 @@ PPKEYWORD(sccs) PPKEYWORD(assert) PPKEYWORD(unassert) +// Clang extensions +PPKEYWORD(__export_macro__) + //===----------------------------------------------------------------------===// // Language keywords. //===----------------------------------------------------------------------===// diff --git a/include/clang/Lex/MacroInfo.h b/include/clang/Lex/MacroInfo.h index 822a3764b9..b381e0f25f 100644 --- a/include/clang/Lex/MacroInfo.h +++ b/include/clang/Lex/MacroInfo.h @@ -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; }; diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index f2f3f73b9b..2871c8f080 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -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, diff --git a/include/clang/Serialization/ASTWriter.h b/include/clang/Serialization/ASTWriter.h index cb71415d34..d872ce260b 100644 --- a/include/clang/Serialization/ASTWriter.h +++ b/include/clang/Serialization/ASTWriter.h @@ -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; } diff --git a/lib/Basic/IdentifierTable.cpp b/lib/Basic/IdentifierTable.cpp index 792b0c9c61..0103318405 100644 --- a/lib/Basic/IdentifierTable.cpp +++ b/lib/Basic/IdentifierTable.cpp @@ -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 } diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp index cc96d486b1..eee5b1a7cc 100644 --- a/lib/Frontend/ASTUnit.cpp +++ b/lib/Frontend/ASTUnit.cpp @@ -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()) diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp index e05d5767ea..c80802e353 100644 --- a/lib/Frontend/FrontendActions.cpp +++ b/lib/Frontend/FrontendActions.cpp @@ -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, diff --git a/lib/Lex/MacroInfo.cpp b/lib/Lex/MacroInfo.cpp index 9e682ce306..5a7af56398 100644 --- a/lib/Lex/MacroInfo.cpp +++ b/lib/Lex/MacroInfo.cpp @@ -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; diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp index 99383e4791..c8fcc3e37d 100644 --- a/lib/Lex/PPDirectives.cpp +++ b/lib/Lex/PPDirectives.cpp @@ -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. //===----------------------------------------------------------------------===// diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index bc022f5721..10b01d8c9f 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -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(); 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); diff --git a/lib/Serialization/ChainedIncludesSource.cpp b/lib/Serialization/ChainedIncludesSource.cpp index 56dc07f4cb..e354054fb1 100644 --- a/lib/Serialization/ChainedIncludesSource.cpp +++ b/lib/Serialization/ChainedIncludesSource.cpp @@ -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()); diff --git a/lib/Serialization/GeneratePCH.cpp b/lib/Serialization/GeneratePCH.cpp index 358954ed19..25fac8b7a8 100644 --- a/lib/Serialization/GeneratePCH.cpp +++ b/lib/Serialization/GeneratePCH.cpp @@ -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()); diff --git a/test/Modules/macros.c b/test/Modules/macros.c new file mode 100644 index 0000000000..691e8ec0ec --- /dev/null +++ b/test/Modules/macros.c @@ -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 |