forked from OSchip/llvm-project
Introduce builtin macros to determine whether we're building a
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. llvm-svn: 164605
This commit is contained in:
parent
dcaf4a3a4b
commit
c83de30add
|
@ -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">;
|
||||
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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!");
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue