Skip to content

Commit ee97793

Browse files
committed
[modules] Add -fmodules-local-submodule-visibility flag.
This flag specifies that the normal visibility rules should be used even for local submodules (submodules of the currently-being-built module). Thus names will only be visible if a header / module that declares them has actually been included / imported, and not merely because a submodule that happened to be built earlier declared those names. This also removes the need to modularize bottom-up: textually-included headers will be included into every submodule that includes them, since their include guards will not leak between modules. So far, this only governs visibility of macros, not of declarations, so is not ready for real use yet. llvm-svn: 236350
1 parent f9b517c commit ee97793

File tree

11 files changed

+153
-74
lines changed

11 files changed

+153
-74
lines changed

clang/include/clang/Basic/LangOptions.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ COMPATIBLE_LANGOPT(ModulesStrictDeclUse, 1, 0, "require declaration of module us
130130
LANGOPT(ModulesErrorRecovery, 1, 1, "automatically import modules as needed when performing error recovery")
131131
BENIGN_LANGOPT(ModulesImplicitMaps, 1, 1, "use files called module.modulemap implicitly as module maps")
132132
BENIGN_LANGOPT(ImplicitModules, 1, 1, "build modules that are not specified via -fmodule-file")
133+
COMPATIBLE_LANGOPT(ModulesLocalVisibility, 1, 0, "local submodule visibility")
133134
COMPATIBLE_LANGOPT(Optimize , 1, 0, "__OPTIMIZE__ predefined macro")
134135
COMPATIBLE_LANGOPT(OptimizeSize , 1, 0, "__OPTIMIZE_SIZE__ predefined macro")
135136
LANGOPT(Static , 1, 0, "__STATIC__ predefined macro (as opposed to __DYNAMIC__)")

clang/include/clang/Basic/Module.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -480,14 +480,24 @@ class Module {
480480
class VisibleModuleSet {
481481
public:
482482
VisibleModuleSet() : Generation(0) {}
483+
VisibleModuleSet(VisibleModuleSet &&O)
484+
: ImportLocs(std::move(O.ImportLocs)), Generation(O.Generation ? 1 : 0) {
485+
O.ImportLocs.clear();
486+
++O.Generation;
487+
}
483488

489+
/// Move from another visible modules set. Guaranteed to leave the source
490+
/// empty and bump the generation on both.
484491
VisibleModuleSet &operator=(VisibleModuleSet &&O) {
485492
ImportLocs = std::move(O.ImportLocs);
493+
O.ImportLocs.clear();
494+
++O.Generation;
486495
++Generation;
487496
return *this;
488497
}
489498

490-
/// \brief Get the current visibility generation.
499+
/// \brief Get the current visibility generation. Incremented each time the
500+
/// set of visible modules changes in any way.
491501
unsigned getGeneration() const { return Generation; }
492502

493503
/// \brief Determine whether a module is visible.

clang/include/clang/Driver/CC1Options.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,10 @@ def fmodule_map_file_home_is_cwd : Flag<["-"], "fmodule-map-file-home-is-cwd">,
347347
def fmodule_feature : Separate<["-"], "fmodule-feature">,
348348
MetaVarName<"<feature>">,
349349
HelpText<"Enable <feature> in module map requires declarations">;
350+
def fmodules_local_submodule_visibility :
351+
Flag<["-"], "fmodules-local-submodule-visibility">,
352+
HelpText<"Enforce name visibility rules across submodules of the same "
353+
"top-level module.">;
350354

351355
let Group = Action_Group in {
352356

clang/include/clang/Lex/Preprocessor.h

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -466,12 +466,15 @@ class Preprocessor : public RefCountedBase<Preprocessor> {
466466
return Info->OverriddenMacros;
467467
return None;
468468
}
469-
void setOverriddenMacros(ArrayRef<ModuleMacro*> Overrides) {
469+
void setOverriddenMacros(Preprocessor &PP,
470+
ArrayRef<ModuleMacro *> Overrides) {
470471
auto *Info = State.dyn_cast<ModuleMacroInfo*>();
471472
if (!Info) {
472-
assert(Overrides.empty() &&
473-
"have overrides but never had module macro");
474-
return;
473+
if (Overrides.empty())
474+
return;
475+
Info = new (PP.getPreprocessorAllocator())
476+
ModuleMacroInfo(State.get<MacroDirective *>());
477+
State = Info;
475478
}
476479
Info->OverriddenMacros.clear();
477480
Info->OverriddenMacros.insert(Info->OverriddenMacros.end(),
@@ -498,16 +501,11 @@ class Preprocessor : public RefCountedBase<Preprocessor> {
498501
Module *M;
499502
/// The location at which the module was included.
500503
SourceLocation ImportLoc;
501-
502-
struct SavedMacroInfo {
503-
SavedMacroInfo() : Latest(nullptr) {}
504-
MacroDirective *Latest;
505-
llvm::TinyPtrVector<ModuleMacro*> Overridden;
506-
};
507504
/// The macros that were visible before we entered the module.
508-
llvm::DenseMap<const IdentifierInfo*, SavedMacroInfo> Macros;
505+
MacroMap Macros;
506+
/// The set of modules that was visible in the surrounding submodule.
507+
VisibleModuleSet VisibleModules;
509508

510-
// FIXME: VisibleModules?
511509
// FIXME: CounterValue?
512510
// FIXME: PragmaPushMacroInfo?
513511
};
@@ -662,6 +660,7 @@ class Preprocessor : public RefCountedBase<Preprocessor> {
662660
HeaderSearch &getHeaderSearchInfo() const { return HeaderInfo; }
663661

664662
IdentifierTable &getIdentifierTable() { return Identifiers; }
663+
const IdentifierTable &getIdentifierTable() const { return Identifiers; }
665664
SelectorTable &getSelectorTable() { return Selectors; }
666665
Builtin::Context &getBuiltinInfo() { return BuiltinInfo; }
667666
llvm::BumpPtrAllocator &getPreprocessorAllocator() { return BP; }

clang/lib/Frontend/CompilerInvocation.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1508,6 +1508,8 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
15081508
Opts.ModulesStrictDeclUse = Args.hasArg(OPT_fmodules_strict_decluse);
15091509
Opts.ModulesDeclUse =
15101510
Args.hasArg(OPT_fmodules_decluse) || Opts.ModulesStrictDeclUse;
1511+
Opts.ModulesLocalVisibility =
1512+
Args.hasArg(OPT_fmodules_local_submodule_visibility);
15111513
Opts.ModulesSearchAll = Opts.Modules &&
15121514
!Args.hasArg(OPT_fno_modules_search_all) &&
15131515
Args.hasArg(OPT_fmodules_search_all);

clang/lib/Lex/PPLexerChange.cpp

Lines changed: 52 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -612,16 +612,25 @@ void Preprocessor::HandleMicrosoftCommentPaste(Token &Tok) {
612612
void Preprocessor::EnterSubmodule(Module *M, SourceLocation ImportLoc) {
613613
// Save the current state for future imports.
614614
BuildingSubmoduleStack.push_back(BuildingSubmoduleInfo(M, ImportLoc));
615-
616615
auto &Info = BuildingSubmoduleStack.back();
617-
// Copy across our macros and start the submodule with the current state.
618-
// FIXME: We should start each submodule with just the predefined macros.
619-
for (auto &M : Macros) {
620-
BuildingSubmoduleInfo::SavedMacroInfo SMI;
621-
SMI.Latest = M.second.getLatest();
622-
auto O = M.second.getOverriddenMacros();
623-
SMI.Overridden.insert(SMI.Overridden.end(), O.begin(), O.end());
624-
Info.Macros.insert(std::make_pair(M.first, SMI));
616+
Info.Macros.swap(Macros);
617+
// Save our visible modules set. This is guaranteed to clear the set.
618+
if (getLangOpts().ModulesLocalVisibility)
619+
Info.VisibleModules = std::move(VisibleModules);
620+
621+
// Determine the set of starting macros for this submodule.
622+
// FIXME: If we re-enter a submodule, should we restore its MacroDirectives?
623+
auto &StartingMacros = (getLangOpts().ModulesLocalVisibility &&
624+
BuildingSubmoduleStack.size() > 1)
625+
? BuildingSubmoduleStack[0].Macros
626+
: Info.Macros;
627+
628+
// Restore to the starting state.
629+
// FIXME: Do this lazily, when each macro name is first referenced.
630+
for (auto &Macro : StartingMacros) {
631+
MacroState MS(Macro.second.getLatest());
632+
MS.setOverriddenMacros(*this, MS.getOverriddenMacros());
633+
Macros.insert(std::make_pair(Macro.first, std::move(MS)));
625634
}
626635
}
627636

@@ -631,19 +640,35 @@ void Preprocessor::LeaveSubmodule() {
631640
// Create ModuleMacros for any macros defined in this submodule.
632641
for (auto &Macro : Macros) {
633642
auto *II = const_cast<IdentifierInfo*>(Macro.first);
634-
auto SavedInfo = Info.Macros.lookup(II);
643+
auto &OuterInfo = Info.Macros[II];
644+
645+
// Find the starting point for the MacroDirective chain in this submodule.
646+
auto *OldMD = OuterInfo.getLatest();
647+
if (getLangOpts().ModulesLocalVisibility &&
648+
BuildingSubmoduleStack.size() > 1) {
649+
auto &PredefMacros = BuildingSubmoduleStack[0].Macros;
650+
auto PredefMacroIt = PredefMacros.find(Macro.first);
651+
if (PredefMacroIt == PredefMacros.end())
652+
OldMD = nullptr;
653+
else
654+
OldMD = PredefMacroIt->second.getLatest();
655+
}
635656

636657
// This module may have exported a new macro. If so, create a ModuleMacro
637658
// representing that fact.
638659
bool ExplicitlyPublic = false;
639-
for (auto *MD = Macro.second.getLatest(); MD != SavedInfo.Latest;
660+
for (auto *MD = Macro.second.getLatest(); MD != OldMD;
640661
MD = MD->getPrevious()) {
641662
assert(MD && "broken macro directive chain");
642663

643664
// Skip macros defined in other submodules we #included along the way.
644-
Module *Mod = getModuleContainingLocation(MD->getLocation());
645-
if (Mod != Info.M)
646-
continue;
665+
// There's no point doing this if we're tracking local submodule
666+
// visibiltiy, since there can be no such directives in our list.
667+
if (!getLangOpts().ModulesLocalVisibility) {
668+
Module *Mod = getModuleContainingLocation(MD->getLocation());
669+
if (Mod != Info.M)
670+
continue;
671+
}
647672

648673
if (auto *VisMD = dyn_cast<VisibilityMacroDirective>(MD)) {
649674
// The latest visibility directive for a name in a submodule affects
@@ -667,11 +692,21 @@ void Preprocessor::LeaveSubmodule() {
667692
}
668693
}
669694

670-
// Restore the macro's overrides list.
671-
Macro.second.setOverriddenMacros(SavedInfo.Overridden);
695+
// Maintain a single macro directive chain if we're not tracking
696+
// per-submodule macro visibility.
697+
if (!getLangOpts().ModulesLocalVisibility)
698+
OuterInfo.setLatest(Macro.second.getLatest());
672699
}
673700

674-
makeModuleVisible(Info.M, Info.ImportLoc);
701+
// Put back the old macros.
702+
std::swap(Info.Macros, Macros);
703+
704+
if (getLangOpts().ModulesLocalVisibility)
705+
VisibleModules = std::move(Info.VisibleModules);
706+
707+
// A nested #include makes the included submodule visible.
708+
if (BuildingSubmoduleStack.size() > 1)
709+
makeModuleVisible(Info.M, Info.ImportLoc);
675710

676711
BuildingSubmoduleStack.pop_back();
677712
}

clang/lib/Serialization/ASTWriter.cpp

Lines changed: 17 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2019,37 +2019,23 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) {
20192019
// Loop over all the macro directives that are live at the end of the file,
20202020
// emitting each to the PP section.
20212021

2022-
// Construct the list of macro directives that need to be serialized.
2023-
typedef std::pair<const IdentifierInfo *, MacroDirective *> MacroChain;
2024-
SmallVector<MacroChain, 2> MacroDirectives;
2025-
for (Preprocessor::macro_iterator
2026-
I = PP.macro_begin(/*IncludeExternalMacros=*/false),
2027-
E = PP.macro_end(/*IncludeExternalMacros=*/false);
2028-
I != E; ++I) {
2029-
MacroDirectives.push_back(std::make_pair(I->first, I->second.getLatest()));
2030-
}
2031-
2022+
// Construct the list of identifiers with macro directives that need to be
2023+
// serialized.
2024+
SmallVector<const IdentifierInfo *, 128> MacroIdentifiers;
2025+
for (auto &Id : PP.getIdentifierTable())
2026+
if (Id.second->hadMacroDefinition() &&
2027+
(!Id.second->isFromAST() ||
2028+
Id.second->hasChangedSinceDeserialization()))
2029+
MacroIdentifiers.push_back(Id.second);
20322030
// Sort the set of macro definitions that need to be serialized by the
20332031
// name of the macro, to provide a stable ordering.
2034-
int (*Cmp)(const MacroChain*, const MacroChain*) =
2035-
[](const MacroChain *A, const MacroChain *B) -> int {
2036-
return A->first->getName().compare(B->first->getName());
2037-
};
2038-
llvm::array_pod_sort(MacroDirectives.begin(), MacroDirectives.end(), Cmp);
2032+
std::sort(MacroIdentifiers.begin(), MacroIdentifiers.end(),
2033+
llvm::less_ptr<IdentifierInfo>());
20392034

20402035
// Emit the macro directives as a list and associate the offset with the
20412036
// identifier they belong to.
2042-
for (auto &Chain : MacroDirectives) {
2043-
const IdentifierInfo *Name = Chain.first;
2044-
MacroDirective *MD = Chain.second;
2045-
2046-
// If the macro or identifier need no updates, don't write the macro history
2047-
// for this one.
2048-
// FIXME: Chain the macro history instead of re-writing it.
2049-
if (MD && MD->isFromPCH() &&
2050-
Name->isFromAST() && !Name->hasChangedSinceDeserialization())
2051-
continue;
2052-
2037+
for (const IdentifierInfo *Name : MacroIdentifiers) {
2038+
MacroDirective *MD = PP.getLocalMacroDirectiveHistory(Name);
20532039
auto StartOffset = Stream.GetCurrentBitNo();
20542040

20552041
// Emit the macro directives in reverse source order.
@@ -2069,6 +2055,7 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) {
20692055
}
20702056

20712057
// Write out any exported module macros.
2058+
bool EmittedModuleMacros = false;
20722059
if (IsModule) {
20732060
auto Leafs = PP.getLeafModuleMacros(Name);
20742061
SmallVector<ModuleMacro*, 8> Worklist(Leafs.begin(), Leafs.end());
@@ -2079,7 +2066,7 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) {
20792066
// Emit a record indicating this submodule exports this macro.
20802067
ModuleMacroRecord.push_back(
20812068
getSubmoduleID(Macro->getOwningModule()));
2082-
ModuleMacroRecord.push_back(getMacroID(Macro->getMacroInfo()));
2069+
ModuleMacroRecord.push_back(getMacroRef(Macro->getMacroInfo(), Name));
20832070
for (auto *M : Macro->overrides())
20842071
ModuleMacroRecord.push_back(getSubmoduleID(M->getOwningModule()));
20852072

@@ -2090,10 +2077,12 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) {
20902077
for (auto *M : Macro->overrides())
20912078
if (++Visits[M] == M->getNumOverridingMacros())
20922079
Worklist.push_back(M);
2080+
2081+
EmittedModuleMacros = true;
20932082
}
20942083
}
20952084

2096-
if (Record.empty())
2085+
if (Record.empty() && !EmittedModuleMacros)
20972086
continue;
20982087

20992088
IdentMacroDirectivesOffsetMap[Name] = StartOffset;

clang/test/Modules/macro-ambiguity.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,27 @@
5757
// RUN: -fmodule-file=%t/c.pcm \
5858
// RUN: -fmodule-file=%t/d.pcm \
5959
// RUN: -Wambiguous-macro -verify macro-ambiguity.cpp
60+
//
61+
// RUN: %clang_cc1 -fmodules -x c++ -fmodules-cache-path=%t \
62+
// RUN: -v -fmodules-local-submodule-visibility \
63+
// RUN: -iquote Inputs/macro-ambiguity/a/quote \
64+
// RUN: -isystem Inputs/macro-ambiguity/a/system \
65+
// RUN: -iquote Inputs/macro-ambiguity/b/quote \
66+
// RUN: -isystem Inputs/macro-ambiguity/b/system \
67+
// RUN: -iquote Inputs/macro-ambiguity/c/quote \
68+
// RUN: -isystem Inputs/macro-ambiguity/c/system \
69+
// RUN: -iquote Inputs/macro-ambiguity/d/quote \
70+
// RUN: -isystem Inputs/macro-ambiguity/d/system \
71+
// RUN: -iquote Inputs/macro-ambiguity/e/quote \
72+
// RUN: -isystem Inputs/macro-ambiguity/e/system \
73+
// RUN: -fno-implicit-modules -fno-modules-implicit-maps \
74+
// RUN: -fmodule-map-file-home-is-cwd \
75+
// RUN: -fmodule-map-file=Inputs/macro-ambiguity/module.modulemap \
76+
// RUN: -fmodule-file=%t/a.pcm \
77+
// RUN: -fmodule-file=%t/b.pcm \
78+
// RUN: -fmodule-file=%t/c.pcm \
79+
// RUN: -fmodule-file=%t/d.pcm \
80+
// RUN: -Wambiguous-macro -verify macro-ambiguity.cpp
6081

6182
// Include the textual headers first to maximize the ways in which things can
6283
// become ambiguous.

clang/test/Modules/macro-reexport.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,15 @@
77
// RUN: %clang_cc1 -fsyntax-only -DD2 -I%S/Inputs/macro-reexport -fmodules %s -fmodules-cache-path=%t -verify
88
// RUN: %clang_cc1 -fsyntax-only -DF1 -I%S/Inputs/macro-reexport %s -fmodules-cache-path=%t -verify
99
// RUN: %clang_cc1 -fsyntax-only -DF1 -I%S/Inputs/macro-reexport -fmodules %s -fmodules-cache-path=%t -verify
10+
//
11+
// RUN: %clang_cc1 -fmodules-local-submodule-visibility -fsyntax-only -DC1 -I%S/Inputs/macro-reexport %s -fmodules-cache-path=%t -verify
12+
// RUN: %clang_cc1 -fmodules-local-submodule-visibility -fsyntax-only -DC1 -I%S/Inputs/macro-reexport -fmodules %s -fmodules-cache-path=%t -verify
13+
// RUN: %clang_cc1 -fmodules-local-submodule-visibility -fsyntax-only -DD1 -I%S/Inputs/macro-reexport %s -fmodules-cache-path=%t -verify
14+
// RUN: %clang_cc1 -fmodules-local-submodule-visibility -fsyntax-only -DD1 -I%S/Inputs/macro-reexport -fmodules %s -fmodules-cache-path=%t -verify
15+
// RUN: %clang_cc1 -fmodules-local-submodule-visibility -fsyntax-only -DD2 -I%S/Inputs/macro-reexport %s -fmodules-cache-path=%t -verify
16+
// RUN: %clang_cc1 -fmodules-local-submodule-visibility -fsyntax-only -DD2 -I%S/Inputs/macro-reexport -fmodules %s -fmodules-cache-path=%t -verify
17+
// RUN: %clang_cc1 -fmodules-local-submodule-visibility -fsyntax-only -DF1 -I%S/Inputs/macro-reexport %s -fmodules-cache-path=%t -verify
18+
// RUN: %clang_cc1 -fmodules-local-submodule-visibility -fsyntax-only -DF1 -I%S/Inputs/macro-reexport -fmodules %s -fmodules-cache-path=%t -verify
1019

1120
#if defined(F1)
1221
#include "f1.h"

clang/test/Modules/macros.c

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
// RUN: rm -rf %t
2-
// RUN: %clang_cc1 -fmodules -x objective-c -emit-module -fmodules-cache-path=%t -fmodule-name=macros_top %S/Inputs/module.map
3-
// RUN: %clang_cc1 -fmodules -x objective-c -emit-module -fmodules-cache-path=%t -fmodule-name=macros_left %S/Inputs/module.map
4-
// RUN: %clang_cc1 -fmodules -x objective-c -emit-module -fmodules-cache-path=%t -fmodule-name=macros_right %S/Inputs/module.map
5-
// RUN: %clang_cc1 -fmodules -x objective-c -emit-module -fmodules-cache-path=%t -fmodule-name=macros %S/Inputs/module.map
62
// RUN: %clang_cc1 -fmodules -x objective-c -verify -fmodules-cache-path=%t -I %S/Inputs %s
3+
// RUN: %clang_cc1 -fmodules -DLOCAL_VISIBILITY -fmodules-local-submodule-visibility -x objective-c -verify -fmodules-cache-path=%t -I %S/Inputs %s
74
// RUN: not %clang_cc1 -E -fmodules -x objective-c -fmodules-cache-path=%t -I %S/Inputs %s | FileCheck -check-prefix CHECK-PREPROCESSED %s
85
// FIXME: When we have a syntax for modules in C, use that.
96
// These notes come from headers in modules, and are bogus.
@@ -143,11 +140,20 @@ TOP_DEF_RIGHT_UNDEF *TDRUf() { return TDRUp; }
143140

144141
int TOP_DEF_RIGHT_UNDEF; // ok, no longer defined
145142

146-
// FIXME: When macros_right.undef is built, macros_top is visible because
147-
// the state from building macros_right leaks through, so macros_right.undef
148-
// undefines macros_top's macro.
149-
#ifdef TOP_RIGHT_UNDEF
150-
# error TOP_RIGHT_UNDEF should not be defined
143+
#ifdef LOCAL_VISIBILITY
144+
// TOP_RIGHT_UNDEF should not be undefined, because macros_right.undef does
145+
// not undefine macros_right's macro.
146+
# ifndef TOP_RIGHT_UNDEF
147+
# error TOP_RIGHT_UNDEF should still be defined
148+
# endif
149+
#else
150+
// When macros_right.undef is built and local submodule visibility is not
151+
// enabled, macros_top is visible because the state from building
152+
// macros_right leaks through, so macros_right.undef undefines macros_top's
153+
// macro.
154+
# ifdef TOP_RIGHT_UNDEF
155+
# error TOP_RIGHT_UNDEF should not be defined
156+
# endif
151157
#endif
152158

153159
@import macros_other;

clang/test/Modules/macros2.c

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
// RUN: rm -rf %t
2-
// RUN: %clang_cc1 -fmodules -x objective-c -emit-module -fmodules-cache-path=%t -fmodule-name=macros_top %S/Inputs/module.map
3-
// RUN: %clang_cc1 -fmodules -x objective-c -emit-module -fmodules-cache-path=%t -fmodule-name=macros_left %S/Inputs/module.map
4-
// RUN: %clang_cc1 -fmodules -x objective-c -emit-module -fmodules-cache-path=%t -fmodule-name=macros_right %S/Inputs/module.map
5-
// RUN: %clang_cc1 -fmodules -x objective-c -emit-module -fmodules-cache-path=%t -fmodule-name=macros %S/Inputs/module.map
62
// RUN: %clang_cc1 -fmodules -x objective-c -verify -fmodules-cache-path=%t -I %S/Inputs %s
3+
// RUN: %clang_cc1 -fmodules -fmodules-local-submodule-visibility -x objective-c -verify -fmodules-cache-path=%t -I %S/Inputs %s -DLOCAL_VISIBILITY
74

85
// This test checks some of the same things as macros.c, but imports modules in
96
// a different order.
@@ -49,9 +46,15 @@ void test() {
4946

5047
@import macros_right.undef;
5148

52-
// FIXME: See macros.c.
53-
#ifdef TOP_RIGHT_UNDEF
54-
# error TOP_RIGHT_UNDEF should not be defined
49+
// See macros.c.
50+
#ifdef LOCAL_VISIBILITY
51+
# ifndef TOP_RIGHT_UNDEF
52+
# error TOP_RIGHT_UNDEF should still be defined
53+
# endif
54+
#else
55+
# ifdef TOP_RIGHT_UNDEF
56+
# error TOP_RIGHT_UNDEF should not be defined
57+
# endif
5558
#endif
5659

5760
#ifndef TOP_OTHER_UNDEF1

0 commit comments

Comments
 (0)