[nullability] Handle class templates with default arguments

PiperOrigin-RevId: 543418334
diff --git a/nullability/test/templates.cc b/nullability/test/templates.cc
index 7890d42..8658626 100644
--- a/nullability/test/templates.cc
+++ b/nullability/test/templates.cc
@@ -1176,6 +1176,21 @@
   )cc"));
 }
 
+TEST(PointerNullabilityTest, ClassTemplateWithDefaultArgument) {
+  // Crash repro.
+  EXPECT_TRUE(checkDiagnostics(R"cc(
+    template <class T1, class T2 = T1>
+    struct S {
+     public:
+      void f(S<T2>);
+    };
+    void target() {
+      S<int* _Nullable> s;
+      s.f(s);
+    }
+  )cc"));
+}
+
 }  // namespace
 }  // namespace nullability
 }  // namespace tidy
diff --git a/nullability/type_nullability.cc b/nullability/type_nullability.cc
index 99df54b..caf312f 100644
--- a/nullability/type_nullability.cc
+++ b/nullability/type_nullability.cc
@@ -274,6 +274,16 @@
     ignoreUnexpectedNullability();
     Visit(CRD->getDeclContext());
     for (auto TA : TST->template_arguments()) Visit(TA);
+    // `TST->template_arguments()` doesn't contain any default arguments.
+    // Retrieve these (though in unsugared form) from the
+    // `ClassTemplateSpecializationDecl`.
+    // TODO(b/281474380): Can we fetch or compute default arguments in sugared
+    // form?
+    if (auto* CTSD = dyn_cast<ClassTemplateSpecializationDecl>(CRD)) {
+      for (unsigned i = TST->template_arguments().size();
+           i < CTSD->getTemplateArgs().size(); ++i)
+        Visit(CTSD->getTemplateArgs()[i]);
+    }
   }
 
   void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType* T) {
diff --git a/nullability/type_nullability_test.cc b/nullability/type_nullability_test.cc
index e8d760c..adf672d 100644
--- a/nullability/type_nullability_test.cc
+++ b/nullability/type_nullability_test.cc
@@ -357,6 +357,16 @@
               ElementsAre(NullabilityKind::Unspecified));
 }
 
+TEST_F(GetNullabilityAnnotationsFromTypeTest, ClassTemplateWithDefaultArg) {
+  Preamble = "template <typename T1, typename T2 = T1> class ClassTemplate {};";
+
+  // TODO(b/281474380): This should be [Nullable, Nullable], but we don't yet
+  // handle default arguments correctly.
+  EXPECT_THAT(
+      nullVec("ClassTemplate<int * _Nullable>"),
+      ElementsAre(NullabilityKind::Nullable, NullabilityKind::Unspecified));
+}
+
 TEST_F(GetNullabilityAnnotationsFromTypeTest, TemplateArgsBehindAlias) {
   Preamble = R"cpp(
     template <class X>