From: Chandler Carruth Date: Fri, 27 Mar 2015 01:48:11 +0000 (+0000) Subject: [Modules] When walking the lookup results in a namespace, sort them by X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4e5d822f120d151c93f75dd68213bd5bb7735c71;p=clang [Modules] When walking the lookup results in a namespace, sort them by declaration name so that we mark declarations for emission in a deterministic order (and in turn give them deterministic IDs). This is the last for loop or data structure I can find by inspection of the AST writer which doesn't use a deterministic order. Found by inspection, no test case. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@233348 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index f426846035..3632672e37 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -980,15 +980,29 @@ void ASTDeclWriter::VisitNamespaceDecl(NamespaceDecl *D) { NamespaceDecl *NS = D->getOriginalNamespace(); Writer.UpdatedDeclContexts.insert(NS); - // Make sure all visible decls are written. They will be recorded later. - if (StoredDeclsMap *Map = NS->buildLookup()) { - for (StoredDeclsMap::iterator D = Map->begin(), DEnd = Map->end(); - D != DEnd; ++D) { - DeclContext::lookup_result R = D->second.getLookupResult(); - for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; - ++I) - Writer.GetDeclRef(*I); - } + // Make sure all visible decls are written. They will be recorded later. We + // do this using a side data structure so we can sort the names into + // a deterministic order. + StoredDeclsMap *Map = NS->buildLookup(); + SmallVector, 16> + LookupResults; + LookupResults.reserve(Map->size()); + for (auto &Entry : *Map) + LookupResults.push_back( + std::make_pair(Entry.first, Entry.second.getLookupResult())); + + std::sort(LookupResults.begin(), LookupResults.end(), llvm::less_first()); + for (auto &NameAndResult : LookupResults) { + DeclarationName Name = NameAndResult.first; + (void)Name; + assert(Name.getNameKind() != DeclarationName::CXXConstructorName && + "Cannot have a constructor name in a namespace!"); + assert(Name.getNameKind() != DeclarationName::CXXConversionFunctionName && + "Cannot have a conversion function name in a namespace!"); + + DeclContext::lookup_result Result = NameAndResult.second; + for (NamedDecl *ND : Result) + Writer.GetDeclRef(ND); } }