Make the order of items coming from implicit template specializations deterministic

Currently we sort items in IR according to
1. Source location, and then
2. `Importer::GetDeclOrder()` <- this one ensures that implicit constructors/destructors come in a certain order

Implicit class template specialization decls and their methods have the same source location, which makes the following code snippet problematic:
```
template <typename T>
struct MyStruct {
  void Method(T t);
};

using Alias1 = MyStruct<int>;
using Alias2 = MyStruct<bool>;
```
The generated bindings will contain two structs for the implicit template specializations:
```
pub struct __CcTemplateInst8MyStructIiE {...}
pub struct __CcTemplateInst8MyStructIbE {...}
```
But the order in which they appear is nondeterministic. Same goes for the assertions we generate for these structs, as well as the respective functions in `rs_api_impl.cc`.

This cl addresses the issue by taking into account the mangled name of the class template specialization or function decls when determining the item order.

PiperOrigin-RevId: 456502619
diff --git a/rs_bindings_from_cc/importer.cc b/rs_bindings_from_cc/importer.cc
index f663bbe..107d6da 100644
--- a/rs_bindings_from_cc/importer.cc
+++ b/rs_bindings_from_cc/importer.cc
@@ -33,6 +33,7 @@
 #include "rs_bindings_from_cc/ir.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/Mangle.h"
 #include "clang/AST/RawCommentList.h"
@@ -227,7 +228,57 @@
   return 999;
 }
 
-class SourceLocationComparator {
+class Importer::SourceOrderKey {
+ public:
+  SourceOrderKey(clang::SourceRange source_range, int decl_order = 0,
+                 std::string name = "")
+      : source_range_(source_range), decl_order_(decl_order), name_(name) {}
+
+  SourceOrderKey(const SourceOrderKey&) = default;
+  SourceOrderKey& operator=(const SourceOrderKey&) = default;
+
+  bool isBefore(const SourceOrderKey& other,
+                const clang::SourceManager& sm) const {
+    if (!source_range_.isValid() || !other.source_range_.isValid()) {
+      if (source_range_.isValid() != other.source_range_.isValid())
+        return !source_range_.isValid() && other.source_range_.isValid();
+    } else {
+      if (source_range_.getBegin() != other.source_range_.getBegin()) {
+        return sm.isBeforeInTranslationUnit(source_range_.getBegin(),
+                                            other.source_range_.getBegin());
+      }
+      if (source_range_.getEnd() != other.source_range_.getEnd()) {
+        return sm.isBeforeInTranslationUnit(source_range_.getEnd(),
+                                            other.source_range_.getEnd());
+      }
+    }
+
+    if (decl_order_ < other.decl_order_) {
+      return true;
+    } else if (decl_order_ > other.decl_order_) {
+      return false;
+    }
+    return name_ < other.name_;
+  }
+
+ private:
+  clang::SourceRange source_range_;
+  int decl_order_;
+  std::string name_;
+};
+
+Importer::SourceOrderKey Importer::GetSourceOrderKey(
+    const clang::Decl* decl) const {
+  return SourceOrderKey(decl->getSourceRange(), GetDeclOrder(decl),
+                        GetNameForSourceOrder(decl));
+}
+
+Importer::SourceOrderKey Importer::GetSourceOrderKey(
+    const clang::RawComment* comment) const {
+  return SourceOrderKey(comment->getSourceRange());
+}
+
+class Importer::SourceLocationComparator {
  public:
   const bool operator()(const clang::SourceLocation& a,
                         const clang::SourceLocation& b) const {
@@ -246,34 +297,19 @@
     return this->operator()(a->getBeginLoc(), b->getBeginLoc());
   }
 
-  using OrderedItemId = std::tuple<clang::SourceRange, int, ItemId>;
-  using OrderedItem = std::tuple<clang::SourceRange, int, IR::Item>;
+  using OrderedItemId = std::pair<SourceOrderKey, ItemId>;
+  using OrderedItem = std::pair<SourceOrderKey, IR::Item>;
 
   template <typename OrderedItemOrId>
   bool operator()(const OrderedItemOrId& a, const OrderedItemOrId& b) const {
-    auto a_range = std::get<0>(a);
-    auto b_range = std::get<0>(b);
-    if (!a_range.isValid() || !b_range.isValid()) {
-      if (a_range.isValid() != b_range.isValid())
-        return !a_range.isValid() && b_range.isValid();
-    } else {
-      if (a_range.getBegin() != b_range.getBegin()) {
-        return sm.isBeforeInTranslationUnit(a_range.getBegin(),
-                                            b_range.getBegin());
-      }
-      if (a_range.getEnd() != b_range.getEnd()) {
-        return sm.isBeforeInTranslationUnit(a_range.getEnd(), b_range.getEnd());
-      }
-    }
-    auto a_decl_order = std::get<1>(a);
-    auto b_decl_order = std::get<1>(b);
-    return a_decl_order < b_decl_order;
+    auto a_source_order = a.first;
+    auto b_source_order = b.first;
+    return a_source_order.isBefore(b_source_order, sm);
   }
-
-  SourceLocationComparator(clang::SourceManager& sm) : sm(sm) {}
+  SourceLocationComparator(const clang::SourceManager& sm) : sm(sm) {}
 
  private:
-  clang::SourceManager& sm;
+  const clang::SourceManager& sm;
 };
 
 std::vector<ItemId> Importer::GetItemIdsInSourceOrder(
@@ -331,7 +367,7 @@
       // redecls, not just the canonical
       if (visited_item_ids.find(item_id) == visited_item_ids.end()) {
         visited_item_ids.insert(item_id);
-        items.push_back({decl->getSourceRange(), GetDeclOrder(decl), item_id});
+        items.push_back({GetSourceOrderKey(decl), item_id});
       }
     }
 
@@ -345,14 +381,14 @@
   }
 
   for (auto& [_, comment] : ordered_comments) {
-    items.push_back({comment->getSourceRange(), 0, GenerateItemId(comment)});
+    items.push_back({GetSourceOrderKey(comment), GenerateItemId(comment)});
   }
   llvm::sort(items, compare_locations);
 
   std::vector<ItemId> ordered_item_ids;
   ordered_item_ids.reserve(items.size());
   for (auto& ordered_item : items) {
-    ordered_item_ids.push_back(std::get<2>(ordered_item));
+    ordered_item_ids.push_back(ordered_item.second);
   }
   return ordered_item_ids;
 }
@@ -362,8 +398,7 @@
   std::vector<SourceLocationComparator::OrderedItemId> items;
   items.reserve(class_template_instantiations_for_current_target_.size());
   for (const auto* decl : class_template_instantiations_for_current_target_) {
-    items.push_back(
-        {decl->getSourceRange(), GetDeclOrder(decl), GenerateItemId(decl)});
+    items.push_back({GetSourceOrderKey(decl), GenerateItemId(decl)});
   }
 
   clang::SourceManager& sm = ctx_.getSourceManager();
@@ -373,7 +408,7 @@
   std::vector<ItemId> ordered_item_ids;
   ordered_item_ids.reserve(items.size());
   for (const auto& ordered_item : items) {
-    ordered_item_ids.push_back(std::get<2>(ordered_item));
+    ordered_item_ids.push_back(ordered_item.second);
   }
   return ordered_item_ids;
 }
@@ -400,7 +435,7 @@
 
   for (auto& comment : comments_) {
     ordered_items.push_back(
-        {comment->getSourceRange(), 0,
+        {GetSourceOrderKey(comment),
          Comment{.text = comment->getFormattedText(sm, sm.getDiagnostics()),
                  .id = GenerateItemId(comment)}});
   }
@@ -412,8 +447,7 @@
           !IsFromCurrentTarget(decl)) {
         continue;
       }
-      ordered_items.push_back(
-          {decl->getSourceRange(), GetDeclOrder(decl), *item});
+      ordered_items.push_back({GetSourceOrderKey(decl), *item});
     }
   }
 
@@ -421,7 +455,7 @@
 
   invocation_.ir_.items.reserve(ordered_items.size());
   for (auto& ordered_item : ordered_items) {
-    invocation_.ir_.items.push_back(std::get<2>(ordered_item));
+    invocation_.ir_.items.push_back(ordered_item.second);
   }
   invocation_.ir_.top_level_item_ids =
       GetItemIdsInSourceOrder(translation_unit_decl);
@@ -847,6 +881,21 @@
   return name;
 }
 
+std::string Importer::GetNameForSourceOrder(const clang::Decl* decl) const {
+  // Implicit class template specializations and their methods all have the
+  // same source location. In order to provide deterministic order of the
+  // respective items in generated source code, we additionally use the
+  // mangled names when sorting the items.
+  if (auto* class_template_specialization_decl =
+          clang::dyn_cast<clang::ClassTemplateSpecializationDecl>(decl)) {
+    return GetMangledName(class_template_specialization_decl);
+  } else if (auto* func_decl = clang::dyn_cast<clang::FunctionDecl>(decl)) {
+    return GetMangledName(func_decl);
+  } else {
+    return "";
+  }
+}
+
 std::optional<UnqualifiedIdentifier> Importer::GetTranslatedName(
     const clang::NamedDecl* named_decl) const {
   switch (named_decl->getDeclName().getNameKind()) {