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/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());
+          }
+        }
+      }
     }
   }