forked from OSchip/llvm-project
[modules] Change module manager visitation order to be a bit more stable when
more modules are added: visit modules depth-first rather than breadth-first. The visitation is still (approximately) oldest-to-newest, and still guarantees that a module is visited before anything it imports, so modules that are imported by others sometimes need to jump to a later position in the visitation order when more modules are loaded, but independent module trees don't interfere with each other any more. llvm-svn: 242863
This commit is contained in:
parent
f8e102da6a
commit
a7c535b3c1
|
@ -316,28 +316,24 @@ ModuleManager::visit(bool (*Visitor)(ModuleFile &M, void *UserData),
|
||||||
SmallVector<ModuleFile *, 4> Queue;
|
SmallVector<ModuleFile *, 4> Queue;
|
||||||
Queue.reserve(N);
|
Queue.reserve(N);
|
||||||
llvm::SmallVector<unsigned, 4> UnusedIncomingEdges;
|
llvm::SmallVector<unsigned, 4> UnusedIncomingEdges;
|
||||||
UnusedIncomingEdges.reserve(size());
|
UnusedIncomingEdges.resize(size());
|
||||||
for (ModuleIterator M = begin(), MEnd = end(); M != MEnd; ++M) {
|
for (auto M = rbegin(), MEnd = rend(); M != MEnd; ++M) {
|
||||||
if (unsigned Size = (*M)->ImportedBy.size())
|
unsigned Size = (*M)->ImportedBy.size();
|
||||||
UnusedIncomingEdges.push_back(Size);
|
UnusedIncomingEdges[(*M)->Index] = Size;
|
||||||
else {
|
if (!Size)
|
||||||
UnusedIncomingEdges.push_back(0);
|
|
||||||
Queue.push_back(*M);
|
Queue.push_back(*M);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Traverse the graph, making sure to visit a module before visiting any
|
// Traverse the graph, making sure to visit a module before visiting any
|
||||||
// of its dependencies.
|
// of its dependencies.
|
||||||
unsigned QueueStart = 0;
|
while (!Queue.empty()) {
|
||||||
while (QueueStart < Queue.size()) {
|
ModuleFile *CurrentModule = Queue.pop_back_val();
|
||||||
ModuleFile *CurrentModule = Queue[QueueStart++];
|
|
||||||
VisitOrder.push_back(CurrentModule);
|
VisitOrder.push_back(CurrentModule);
|
||||||
|
|
||||||
// For any module that this module depends on, push it on the
|
// For any module that this module depends on, push it on the
|
||||||
// stack (if it hasn't already been marked as visited).
|
// stack (if it hasn't already been marked as visited).
|
||||||
for (llvm::SetVector<ModuleFile *>::iterator
|
for (auto M = CurrentModule->Imports.rbegin(),
|
||||||
M = CurrentModule->Imports.begin(),
|
MEnd = CurrentModule->Imports.rend();
|
||||||
MEnd = CurrentModule->Imports.end();
|
|
||||||
M != MEnd; ++M) {
|
M != MEnd; ++M) {
|
||||||
// Remove our current module as an impediment to visiting the
|
// Remove our current module as an impediment to visiting the
|
||||||
// module we depend on. If we were the last unvisited module
|
// module we depend on. If we were the last unvisited module
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
// RUN: rm -rf %t
|
// RUN: rm -rf %t
|
||||||
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -x objective-c -verify -fmodules-cache-path=%t -I %S/Inputs %s
|
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -x objective-c -verify -fmodules-cache-path=%t -I %S/Inputs %s
|
||||||
|
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -x objective-c -verify -fmodules-cache-path=%t -I %S/Inputs %s -DALT
|
||||||
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -x objective-c -verify -fmodules-cache-path=%t -I %S/Inputs %s -detailed-preprocessing-record
|
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -x objective-c -verify -fmodules-cache-path=%t -I %S/Inputs %s -detailed-preprocessing-record
|
||||||
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -DLOCAL_VISIBILITY -fmodules-local-submodule-visibility -x objective-c++ -verify -fmodules-cache-path=%t -I %S/Inputs %s
|
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -DLOCAL_VISIBILITY -fmodules-local-submodule-visibility -x objective-c++ -verify -fmodules-cache-path=%t -I %S/Inputs %s
|
||||||
// RUN: not %clang_cc1 -E -fmodules -fimplicit-module-maps -x objective-c -fmodules-cache-path=%t -I %S/Inputs %s | FileCheck -check-prefix CHECK-PREPROCESSED %s
|
// RUN: not %clang_cc1 -E -fmodules -fimplicit-module-maps -x objective-c -fmodules-cache-path=%t -I %S/Inputs %s | FileCheck -check-prefix CHECK-PREPROCESSED %s
|
||||||
|
@ -157,6 +158,10 @@ int TOP_DEF_RIGHT_UNDEF; // ok, no longer defined
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef ALT
|
||||||
|
int tmp = TOP_OTHER_REDEF1;
|
||||||
|
#endif
|
||||||
|
|
||||||
@import macros_other;
|
@import macros_other;
|
||||||
|
|
||||||
#ifndef TOP_OTHER_UNDEF1
|
#ifndef TOP_OTHER_UNDEF1
|
||||||
|
@ -166,13 +171,13 @@ int TOP_DEF_RIGHT_UNDEF; // ok, no longer defined
|
||||||
#ifndef TOP_OTHER_UNDEF2
|
#ifndef TOP_OTHER_UNDEF2
|
||||||
# error TOP_OTHER_UNDEF2 should still be defined
|
# error TOP_OTHER_UNDEF2 should still be defined
|
||||||
#endif
|
#endif
|
||||||
|
#pragma clang __debug macro TOP_OTHER_REDEF1
|
||||||
#ifndef TOP_OTHER_REDEF1
|
#ifndef TOP_OTHER_REDEF1
|
||||||
# error TOP_OTHER_REDEF1 should still be defined
|
# error TOP_OTHER_REDEF1 should still be defined
|
||||||
#endif
|
#endif
|
||||||
int n1 = TOP_OTHER_REDEF1; // expected-warning{{ambiguous expansion of macro 'TOP_OTHER_REDEF1'}}
|
int n1 = TOP_OTHER_REDEF1; // expected-warning{{ambiguous expansion of macro 'TOP_OTHER_REDEF1'}}
|
||||||
// expected-note@macros_top.h:19 {{expanding this definition}}
|
// expected-note@macros_other.h:4 {{expanding this definition}}
|
||||||
// expected-note@macros_other.h:4 {{other definition}}
|
// expected-note@macros_top.h:19 {{other definition}}
|
||||||
|
|
||||||
#ifndef TOP_OTHER_REDEF2
|
#ifndef TOP_OTHER_REDEF2
|
||||||
# error TOP_OTHER_REDEF2 should still be defined
|
# error TOP_OTHER_REDEF2 should still be defined
|
||||||
|
|
Loading…
Reference in New Issue