]> granicus.if.org Git - clang/commitdiff
Introduce builtin macros to determine whether we're building a
authorDouglas Gregor <dgregor@apple.com>
Tue, 25 Sep 2012 15:44:52 +0000 (15:44 +0000)
committerDouglas Gregor <dgregor@apple.com>
Tue, 25 Sep 2012 15:44:52 +0000 (15:44 +0000)
specific module (__building_module(modulename)) and to get the name of
the current module as an identifier (__MODULE__).

Used to help headers behave differently when they're being included as
part of building a module. Oh, the irony.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@164605 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticLexKinds.td
include/clang/Lex/Preprocessor.h
lib/Lex/PPMacroExpansion.cpp
test/Modules/Inputs/macros.h
test/Modules/macros.c

index b080360fad6974bd1c55264dfec99e01c9e554a9..fbdf56ce4aa5aada89bee02fb7936d40c97a57b8 100644 (file)
@@ -509,5 +509,7 @@ def warn_auto_module_import : Warning<
   "import of module '%1'">, InGroup<AutoImport>, DefaultIgnore;
 def warn_uncovered_module_header : Warning<
   "umbrella header does not include header '%0'">, InGroup<IncompleteUmbrella>;
-
+def err_expected_id_building_module : Error<
+  "expected a module name in '__building_module' expression">;
+  
 }
index 0ddf82e5dfeffd995cc05409d87904cf2e5a24ce..76d8fdb25924dc582e471fb29a9d13762e6ba802 100644 (file)
@@ -98,6 +98,8 @@ class Preprocessor : public RefCountedBase<Preprocessor> {
   IdentifierInfo *Ident__has_include;              // __has_include
   IdentifierInfo *Ident__has_include_next;         // __has_include_next
   IdentifierInfo *Ident__has_warning;              // __has_warning
+  IdentifierInfo *Ident__building_module;          // __building_module
+  IdentifierInfo *Ident__MODULE__;                 // __MODULE__
 
   SourceLocation DATELoc, TIMELoc;
   unsigned CounterValue;  // Next __COUNTER__ value.
index 839cec0744f48d81755db7a1ebf589d6340f6cb7..b2d597713b9afe8df355044374a96a81aecf92a9 100644 (file)
@@ -105,6 +105,20 @@ void Preprocessor::RegisterBuiltinMacros() {
   Ident__has_include_next = RegisterBuiltinMacro(*this, "__has_include_next");
   Ident__has_warning      = RegisterBuiltinMacro(*this, "__has_warning");
 
+  // Modules.
+  if (LangOpts.Modules) {
+    Ident__building_module  = RegisterBuiltinMacro(*this, "__building_module");
+
+    // __MODULE__
+    if (!LangOpts.CurrentModule.empty())
+      Ident__MODULE__ = RegisterBuiltinMacro(*this, "__MODULE__");
+    else
+      Ident__MODULE__ = 0;
+  } else {
+    Ident__building_module = 0;
+    Ident__MODULE__ = 0;
+  }
+  
   // Microsoft Extensions.
   if (LangOpts.MicrosoftExt) 
     Ident__pragma = RegisterBuiltinMacro(*this, "__pragma");
@@ -907,6 +921,47 @@ static bool EvaluateHasIncludeNext(Token &Tok,
   return EvaluateHasIncludeCommon(Tok, II, PP, Lookup);
 }
 
+/// \brief Process __building_module(identifier) expression.
+/// \returns true if we are building the named module, false otherwise.
+static bool EvaluateBuildingModule(Token &Tok,
+                                   IdentifierInfo *II, Preprocessor &PP) {
+  // Get '('.
+  PP.LexNonComment(Tok);
+
+  // Ensure we have a '('.
+  if (Tok.isNot(tok::l_paren)) {
+    PP.Diag(Tok.getLocation(), diag::err_pp_missing_lparen) << II->getName();
+    return false;
+  }
+
+  // Save '(' location for possible missing ')' message.
+  SourceLocation LParenLoc = Tok.getLocation();
+
+  // Get the module name.
+  PP.LexNonComment(Tok);
+
+  // Ensure that we have an identifier.
+  if (Tok.isNot(tok::identifier)) {
+    PP.Diag(Tok.getLocation(), diag::err_expected_id_building_module);
+    return false;
+  }
+
+  bool Result
+    = Tok.getIdentifierInfo()->getName() == PP.getLangOpts().CurrentModule;
+
+  // Get ')'.
+  PP.LexNonComment(Tok);
+
+  // Ensure we have a trailing ).
+  if (Tok.isNot(tok::r_paren)) {
+    PP.Diag(Tok.getLocation(), diag::err_pp_missing_rparen) << II->getName();
+    PP.Diag(LParenLoc, diag::note_matching) << "(";
+    return false;
+  }
+
+  return Result;
+}
+
 /// ExpandBuiltinMacro - If an identifier token is read that is to be expanded
 /// as a builtin macro, handle it and return the next token as 'Tok'.
 void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
@@ -1162,6 +1217,18 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
 
     OS << (int)Value;
     Tok.setKind(tok::numeric_constant);
+  } else if (II == Ident__building_module) {
+    // The argument to this builtin should be an identifier. The
+    // builtin evaluates to 1 when that identifier names the module we are
+    // currently building.
+    OS << (int)EvaluateBuildingModule(Tok, II, *this);
+    Tok.setKind(tok::numeric_constant);
+  } else if (II == Ident__MODULE__) {
+    // The current module as an identifier.
+    OS << getLangOpts().CurrentModule;
+    IdentifierInfo *ModuleII = getIdentifierInfo(getLangOpts().CurrentModule);
+    Tok.setIdentifierInfo(ModuleII);
+    Tok.setKind(ModuleII->getTokenID());
   } else {
     llvm_unreachable("Unknown identifier!");
   }
index 4f535563ad27db7aadde6f8f504712b446682834..27f43c0626ec31dda25eecf998538f6b7e0c8459 100644 (file)
@@ -8,3 +8,12 @@
 #__private_macro MODULE
 
 int (INTEGER);
+
+#if !__building_module(macros)
+#  error Can't include this header without building the 'macros' module.
+#endif
+
+#ifdef __MODULE__
+extern int __MODULE__;
+#endif
+
index 83e1c66a101717c59994c689a770d0329f8206dc..d93ce35a03a977497f0ecf7afeaecbc8d1234a3e 100644 (file)
@@ -27,4 +27,13 @@ DOUBLE *dp = &d;
 void f() {
   // CHECK-PREPROCESSED: int i = INTEGER;
   int i = INTEGER; // the value was exported, the macro was not.
+  i += macros; // expanded from __MODULE__ within the 'macros' module.
 }
+
+#ifdef __MODULE__
+# error Not building a module!
+#endif
+
+#if __building_module(macros)
+# error Not building a module
+#endif