forked from OSchip/llvm-project
[Modules] Extend -fmodule-name semantic for frameworks with private modules
Assume Foo.framework with two module maps and two modules Foo and Foo_Private. Framework authors need to skip building both Foo and Foo_Private when using -fmodule-name=Foo, since both are part of the framework and used interchangeably during compilation. rdar://problem/37500098 llvm-svn: 325305
This commit is contained in:
parent
ea33dee38c
commit
5bccc5270e
|
@ -115,6 +115,24 @@ static bool isReservedId(StringRef Text, const LangOptions &Lang) {
|
|||
return false;
|
||||
}
|
||||
|
||||
// The -fmodule-name option (represented here by \p CurrentModule) tells the
|
||||
// compiler to textually include headers in the specified module, meaning clang
|
||||
// won't build the specified module. This is useful in a number of situations,
|
||||
// for instance, when building a library that vends a module map, one might want
|
||||
// to avoid hitting intermediate build products containig the the module map or
|
||||
// avoid finding the system installed modulemap for that library.
|
||||
static bool isForModuleBuilding(Module *M, StringRef CurrentModule) {
|
||||
StringRef TopLevelName = M->getTopLevelModuleName();
|
||||
|
||||
// When building framework Foo, we wanna make sure that Foo *and* Foo_Private
|
||||
// are textually included and no modules are built for both.
|
||||
if (M->getTopLevelModule()->IsFramework &&
|
||||
!CurrentModule.endswith("_Private") && TopLevelName.endswith("_Private"))
|
||||
TopLevelName = TopLevelName.drop_back(8);
|
||||
|
||||
return TopLevelName == CurrentModule;
|
||||
}
|
||||
|
||||
static MacroDiag shouldWarnOnMacroDef(Preprocessor &PP, IdentifierInfo *II) {
|
||||
const LangOptions &Lang = PP.getLangOpts();
|
||||
StringRef Text = II->getName();
|
||||
|
@ -1856,8 +1874,8 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
|
|||
// there is one. Don't do so if precompiled module support is disabled or we
|
||||
// are processing this module textually (because we're building the module).
|
||||
if (ShouldEnter && File && SuggestedModule && getLangOpts().Modules &&
|
||||
SuggestedModule.getModule()->getTopLevelModuleName() !=
|
||||
getLangOpts().CurrentModule) {
|
||||
!isForModuleBuilding(SuggestedModule.getModule(),
|
||||
getLangOpts().CurrentModule)) {
|
||||
// If this include corresponds to a module but that module is
|
||||
// unavailable, diagnose the situation and bail out.
|
||||
// FIXME: Remove this; loadModule does the same check (but produces
|
||||
|
@ -2004,7 +2022,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
|
|||
// ShouldEnter is false because we are skipping the header. In that
|
||||
// case, We are not importing the specified module.
|
||||
if (SkipHeader && getLangOpts().CompilingPCH &&
|
||||
M->getTopLevelModuleName() == getLangOpts().CurrentModule)
|
||||
isForModuleBuilding(M, getLangOpts().CurrentModule))
|
||||
return;
|
||||
|
||||
makeModuleVisible(M, HashLoc);
|
||||
|
@ -2045,7 +2063,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
|
|||
// include headers in the specified module. We are not building the
|
||||
// specified module.
|
||||
if (getLangOpts().CompilingPCH &&
|
||||
M->getTopLevelModuleName() == getLangOpts().CurrentModule)
|
||||
isForModuleBuilding(M, getLangOpts().CurrentModule))
|
||||
return;
|
||||
|
||||
assert(!CurLexerSubmodule && "should not have marked this as a module yet");
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
// RUN: rm -rf %t
|
||||
// RUN: %clang_cc1 -verify -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -F %S/Inputs/implicit-private-canonical -fsyntax-only %s -Wprivate-module -fmodule-name=A -Rmodule-build
|
||||
|
||||
// Because of -fmodule-name=A, no module (A or A_Private) is supposed to be
|
||||
// built and -Rmodule-build should not produce any output.
|
||||
|
||||
// expected-no-diagnostics
|
||||
|
||||
#import <A/a.h>
|
||||
#import <A/aprivate.h>
|
||||
|
||||
int foo() { return APRIVATE; }
|
Loading…
Reference in New Issue