For modules, all macros that aren't include guards are implicitly
public. Add a __private_macro__ directive to hide a macro, similar to
the __module_private__ declaration specifier.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@142188 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Basic/IdentifierTable.cpp b/lib/Basic/IdentifierTable.cpp
index 38f09a08..78f8a7c 100644
--- a/lib/Basic/IdentifierTable.cpp
+++ b/lib/Basic/IdentifierTable.cpp
@@ -222,6 +222,8 @@
CASE(16, '_', 'i', __include_macros);
CASE(16, '_', 'e', __export_macro__);
+
+ CASE(17, '_', 'p', __private_macro__);
#undef CASE
#undef HASH
}
diff --git a/lib/Lex/MacroInfo.cpp b/lib/Lex/MacroInfo.cpp
index 5a7af56..3d0c9a1 100644
--- a/lib/Lex/MacroInfo.cpp
+++ b/lib/Lex/MacroInfo.cpp
@@ -27,7 +27,8 @@
IsAllowRedefinitionsWithoutWarning = false;
IsWarnIfUnused = false;
IsDefinitionLengthCached = false;
-
+ IsPublic = true;
+
ArgumentList = 0;
NumArguments = 0;
}
@@ -48,6 +49,8 @@
IsWarnIfUnused = MI.IsWarnIfUnused;
IsDefinitionLengthCached = MI.IsDefinitionLengthCached;
DefinitionLength = MI.DefinitionLength;
+ IsPublic = MI.IsPublic;
+
ArgumentList = 0;
NumArguments = 0;
setArgumentList(MI.ArgumentList, MI.NumArguments, PPAllocator);
diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp
index de50c75..9446d51 100644
--- a/lib/Lex/PPDirectives.cpp
+++ b/lib/Lex/PPDirectives.cpp
@@ -666,6 +666,8 @@
case tok::pp___export_macro__:
return HandleMacroExportDirective(Result);
+ case tok::pp___private_macro__:
+ return HandleMacroPrivateDirective(Result);
}
break;
}
@@ -1035,13 +1037,44 @@
// If the macro is not defined, this is an error.
if (MI == 0) {
- Diag(MacroNameTok, diag::err_pp_export_non_macro)
+ Diag(MacroNameTok, diag::err_pp_visibility_non_macro)
<< MacroNameTok.getIdentifierInfo();
return;
}
// Note that this macro has now been exported.
- MI->setExportLocation(MacroNameTok.getLocation());
+ MI->setVisibility(/*IsPublic=*/true, MacroNameTok.getLocation());
+
+ // If this macro definition came from a PCH file, mark it
+ // as having changed since serialization.
+ if (MI->isFromAST())
+ MI->setChangedAfterLoad();
+}
+
+/// \brief Handle a #__private_macro__ directive.
+void Preprocessor::HandleMacroPrivateDirective(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 #__private_macro__ line.
+ CheckEndOfDirective("__private_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_visibility_non_macro)
+ << MacroNameTok.getIdentifierInfo();
+ return;
+ }
+
+ // Note that this macro has now been marked private.
+ MI->setVisibility(/*IsPublic=*/false, MacroNameTok.getLocation());
// If this macro definition came from a PCH file, mark it
// as having changed since serialization.
diff --git a/lib/Lex/PPLexerChange.cpp b/lib/Lex/PPLexerChange.cpp
index 25a98ae..da6c8aa 100644
--- a/lib/Lex/PPLexerChange.cpp
+++ b/lib/Lex/PPLexerChange.cpp
@@ -16,6 +16,7 @@
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/MacroInfo.h"
#include "clang/Lex/LexDiagnostic.h"
+#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/Support/MemoryBuffer.h"
using namespace clang;
@@ -211,8 +212,28 @@
CurPPLexer->MIOpt.GetControllingMacroAtEndOfFile()) {
// Okay, this has a controlling macro, remember in HeaderFileInfo.
if (const FileEntry *FE =
- SourceMgr.getFileEntryForID(CurPPLexer->getFileID()))
+ SourceMgr.getFileEntryForID(CurPPLexer->getFileID())) {
HeaderInfo.SetFileControllingMacro(FE, ControllingMacro);
+
+ // Controlling macros are implicitly private.
+ if (MacroInfo *MI = getMacroInfo(
+ const_cast<IdentifierInfo *>(ControllingMacro))) {
+ if (MI->getVisibilityLocation().isInvalid()) {
+ // FIXME: HACK! Mark controlling macros from system headers as
+ // exported, along with our own Clang headers. This is a gross
+ // hack to deal with the fact that system headers are included in
+ // many places within module headers, but are not themselves
+ // modularized.
+ if ((StringRef(FE->getName()).find("lib/clang")
+ == StringRef::npos) &&
+ (StringRef(FE->getName()).find("usr/include")
+ == StringRef::npos) &&
+ (StringRef(FE->getName()).find("usr/local/include")
+ == StringRef::npos))
+ MI->setVisibility(false, SourceLocation());
+ }
+ }
+ }
}
}
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index 533b21c..4a9d8a5 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -468,34 +468,6 @@
}
if (TUKind == TU_Module) {
- // Mark any macros from system headers (in /usr/include) as exported, along
- // with our own Clang headers.
- // FIXME: This is a gross hack to deal with the fact that system headers
- // are #include'd in many places within module headers, but are not
- // themselves modularized. This doesn't actually work, but it lets us
- // focus on other issues for the moment.
- for (Preprocessor::macro_iterator M = PP.macro_begin(false),
- MEnd = PP.macro_end(false);
- M != MEnd; ++M) {
- if (M->second &&
- !M->second->isExported() &&
- !M->second->isBuiltinMacro()) {
- SourceLocation Loc = M->second->getDefinitionLoc();
- if (SourceMgr.isInSystemHeader(Loc)) {
- const FileEntry *File
- = SourceMgr.getFileEntryForID(SourceMgr.getFileID(Loc));
- if (File &&
- ((StringRef(File->getName()).find("lib/clang")
- != StringRef::npos) ||
- (StringRef(File->getName()).find("usr/include")
- != StringRef::npos) ||
- (StringRef(File->getName()).find("usr/local/include")
- != StringRef::npos)))
- M->second->setExportLocation(Loc);
- }
- }
- }
-
// Modules don't need any of the checking below.
TUScope = 0;
return;
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index fe1cc30..dc7829f 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -1283,8 +1283,9 @@
MI->setIsUsed(isUsed);
MI->setIsFromAST();
- unsigned NextIndex = 3;
- MI->setExportLocation(ReadSourceLocation(F, Record, NextIndex));
+ bool IsPublic = Record[3];
+ unsigned NextIndex = 4;
+ MI->setVisibility(IsPublic, ReadSourceLocation(F, Record, NextIndex));
if (RecType == PP_MACRO_FUNCTION_LIKE) {
// Decode function-like macro info.
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index b31262d..ba9a82b 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -1629,7 +1629,7 @@
for (Preprocessor::macro_iterator I = PP.macro_begin(Chain == 0),
E = PP.macro_end(Chain == 0);
I != E; ++I) {
- if (!IsModule || I->second->isExported()) {
+ if (!IsModule || I->second->isPublic()) {
MacroDefinitionsSeen.insert(I->first);
MacrosToEmit.push_back(std::make_pair(I->first, I->second));
}
@@ -1672,7 +1672,8 @@
MacroOffsets[Name] = Stream.GetCurrentBitNo();
Record.push_back(MI->getDefinitionLoc().getRawEncoding());
Record.push_back(MI->isUsed());
- AddSourceLocation(MI->getExportLocation(), Record);
+ Record.push_back(MI->isPublic());
+ AddSourceLocation(MI->getVisibilityLocation(), Record);
unsigned Code;
if (MI->isObjectLike()) {
Code = PP_MACRO_OBJECT_LIKE;
@@ -2210,7 +2211,7 @@
return false;
if (Macro || (Macro = PP.getMacroInfo(II)))
- return !Macro->isBuiltinMacro() && (!IsModule || Macro->isExported());
+ return !Macro->isBuiltinMacro() && (!IsModule || Macro->isPublic());
return false;
}