]> granicus.if.org Git - clang/commitdiff
[Modules] When walking the lookup results in a namespace, sort them by
authorChandler Carruth <chandlerc@gmail.com>
Fri, 27 Mar 2015 01:48:11 +0000 (01:48 +0000)
committerChandler Carruth <chandlerc@gmail.com>
Fri, 27 Mar 2015 01:48:11 +0000 (01:48 +0000)
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

lib/Serialization/ASTWriterDecl.cpp

index f4268460350d9f91141b62d4b077013db7ae59f3..3632672e37bd78d4e93cc3d51ffd215b94bebdc8 100644 (file)
@@ -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<std::pair<DeclarationName, DeclContext::lookup_result>, 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);
     }
   }