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/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td
index 9b3a178..664d390 100644
--- a/include/clang/Basic/DiagnosticLexKinds.td
+++ b/include/clang/Basic/DiagnosticLexKinds.td
@@ -355,7 +355,7 @@
   "#line number greater than 32767 is incompatible with C++98">,
   InGroup<CXX98CompatPedantic>, DefaultIgnore;
 
-def err_pp_export_non_macro : Error<"no macro named %0 to export">;
+def err_pp_visibility_non_macro : Error<"no macro named %0">;
 
 def err_pp_arc_cf_code_audited_syntax : Error<"expected 'begin' or 'end'">;
 def err_pp_double_begin_of_arc_cf_code_audited : Error<
diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def
index 35a881c..cd0cd06 100644
--- a/include/clang/Basic/TokenKinds.def
+++ b/include/clang/Basic/TokenKinds.def
@@ -91,6 +91,7 @@
 
 // Clang extensions
 PPKEYWORD(__export_macro__)
+PPKEYWORD(__private_macro__)
 
 //===----------------------------------------------------------------------===//
 // Language keywords.
diff --git a/include/clang/Lex/MacroInfo.h b/include/clang/Lex/MacroInfo.h
index b381e0f..8775d39 100644
--- a/include/clang/Lex/MacroInfo.h
+++ b/include/clang/Lex/MacroInfo.h
@@ -39,10 +39,11 @@
   IdentifierInfo **ArgumentList;
   unsigned NumArguments;
 
-  /// \brief The location at which this macro was exported from its module.
+  /// \brief The location at which this macro was either explicitly exported
+  /// from its module or marked as private.
   ///
-  /// If invalid, this macro has not been explicitly exported.
-  SourceLocation ExportLocation;
+  /// If invalid, this macro has not been explicitly given any visibility.
+  SourceLocation VisibilityLocation;
   
   /// ReplacementTokens - This is the list of tokens that the macro is defined
   /// to.
@@ -97,6 +98,9 @@
   /// \brief Must warn if the macro is unused at the end of translation unit.
   bool IsWarnIfUnused : 1;
    
+  /// \brief Whether the macro has public (when described in a module).
+  bool IsPublic : 1;
+  
    ~MacroInfo() {
     assert(ArgumentList == 0 && "Didn't call destroy before dtor!");
   }
@@ -279,17 +283,18 @@
   }
 
   /// \brief Set the export location for this macro.
-  void setExportLocation(SourceLocation ExportLoc) {
-    ExportLocation = ExportLoc;
+  void setVisibility(bool Public, SourceLocation Loc) {
+    VisibilityLocation = Loc;
+    IsPublic = Public;
   }
 
-  /// \brief Determine whether this macro was explicitly exported from its
+  /// \brief Determine whether this macro is part of the public API of its
   /// module.
-  bool isExported() const { return ExportLocation.isValid(); }
+  bool isPublic() const { return IsPublic; }
   
-  /// \brief Determine the location where this macro was explicitly exported
-  /// from its module.
-  SourceLocation getExportLocation() { return ExportLocation; }
+  /// \brief Determine the location where this macro was explicitly made
+  /// public or private within its module.
+  SourceLocation getVisibilityLocation() { return VisibilityLocation; }
   
 private:
   unsigned getDefinitionLengthSlow(SourceManager &SM) const;
diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h
index 8b77433..50d6a2a 100644
--- a/include/clang/Lex/Preprocessor.h
+++ b/include/clang/Lex/Preprocessor.h
@@ -1183,6 +1183,7 @@
   void HandleUserDiagnosticDirective(Token &Tok, bool isWarning);
   void HandleIdentSCCSDirective(Token &Tok);
   void HandleMacroExportDirective(Token &Tok);
+  void HandleMacroPrivateDirective(Token &Tok);
   
   // File inclusion.
   void HandleIncludeDirective(SourceLocation HashLoc,
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;    
   }
diff --git a/test/Modules/Inputs/DependsOnModule.framework/Headers/DependsOnModule.h b/test/Modules/Inputs/DependsOnModule.framework/Headers/DependsOnModule.h
index fa40697..411e978 100644
--- a/test/Modules/Inputs/DependsOnModule.framework/Headers/DependsOnModule.h
+++ b/test/Modules/Inputs/DependsOnModule.framework/Headers/DependsOnModule.h
@@ -1,3 +1,5 @@
 #include <Module/Module.h>
 
 #define DEPENDS_ON_MODULE 1
+#__private_macro__ DEPENDS_ON_MODULE
+
diff --git a/test/Modules/Inputs/Module.framework/Headers/Module.h b/test/Modules/Inputs/Module.framework/Headers/Module.h
index 7c7ef6e..9bf6a27 100644
--- a/test/Modules/Inputs/Module.framework/Headers/Module.h
+++ b/test/Modules/Inputs/Module.framework/Headers/Module.h
@@ -1,3 +1,5 @@
+#ifndef MODULE_H
+#define MODULE_H
 const char *getModuleVersion(void);
 
 #ifdef FOO
@@ -10,3 +12,6 @@
 @end
 
 #define MODULE_H_MACRO 1
+#__private_macro__ MODULE_H_MACRO
+
+#endif // MODULE_H
diff --git a/test/Modules/macros.c b/test/Modules/macros.c
index 899c19b..e371237 100644
--- a/test/Modules/macros.c
+++ b/test/Modules/macros.c
@@ -8,7 +8,8 @@
 #define DOUBLE double
 
 #__export_macro__ INTEGER
-#__export_macro__ DOUBLE
+#__private_macro__ FLOAT
+#__private_macro__ MODULE
 
 int (INTEGER);
 
diff --git a/test/Modules/on-demand-build.m b/test/Modules/on-demand-build.m
index 649caa8..2c6a759 100644
--- a/test/Modules/on-demand-build.m
+++ b/test/Modules/on-demand-build.m
@@ -6,6 +6,8 @@
 __import_module__ Module;
 @interface OtherClass
 @end
+
+
 // in module: expected-note{{class method 'alloc' is assumed to return an instance of its receiver type ('Module *')}}
 void test_getModuleVersion() {
   const char *version = getModuleVersion();
@@ -14,4 +16,7 @@
   OtherClass *other = [Module alloc]; // expected-error{{init}}
 }
 
+#ifdef MODULE_H
+#  error MODULE_H should not be hidden
+#endif