diff options
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/Lex/PPMacroExpansion.cpp | 67 | 
1 files changed, 67 insertions, 0 deletions
diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp index 839cec0744f..b2d597713b9 100644 --- a/clang/lib/Lex/PPMacroExpansion.cpp +++ b/clang/lib/Lex/PPMacroExpansion.cpp @@ -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!");    }  | 

