[nullability] Fix a null-pointer crash (ironically) on a null `TypeSourceInfo`.

This change adds a test that, without the fix, reproduces the crash.

PiperOrigin-RevId: 527502867
diff --git a/nullability_verification/pointer_nullability_analysis.cc b/nullability_verification/pointer_nullability_analysis.cc
index 8ec1323..e4a4729 100644
--- a/nullability_verification/pointer_nullability_analysis.cc
+++ b/nullability_verification/pointer_nullability_analysis.cc
@@ -174,10 +174,10 @@
                 dyn_cast<DeclRefExpr>(CE->getCallee()->IgnoreImpCasts());
             DRE != nullptr && ST->getReplacedParameter()->getDepth() == 0 &&
             DRE->hasExplicitTemplateArgs()) {
-          return getNullabilityAnnotationsFromType(
-              DRE->template_arguments()[ST->getIndex()]
-                  .getTypeSourceInfo()
-                  ->getType());
+          TypeSourceInfo* TSI =
+              DRE->template_arguments()[ST->getIndex()].getTypeSourceInfo();
+          if (TSI == nullptr) return std::nullopt;
+          return getNullabilityAnnotationsFromType(TSI->getType());
         }
         return std::nullopt;
       });
diff --git a/nullability_verification/test/function_calls.cc b/nullability_verification/test/function_calls.cc
index 44b918f..effa853 100644
--- a/nullability_verification/test/function_calls.cc
+++ b/nullability_verification/test/function_calls.cc
@@ -419,6 +419,22 @@
   )cc"));
 }
 
+TEST(PointerNullabilityTest,
+     CallFunctionTemplate_ReturnTypeHasNullTypeSourceInfo) {
+  // This test sets up a function call where we don't have a `TypeSourceInfo`
+  // for the template parameter. This is a regression test for a crash that we
+  // observed on real-world code.
+  EXPECT_TRUE(checkDiagnostics(R"cc(
+    template <class T>
+    struct A {
+      using Type = T;
+    };
+    template <int, class T>
+    typename A<T>::Type f(T);
+    void target() { f<0>(1); }
+  )cc"));
+}
+
 }  // namespace
 }  // namespace nullability
 }  // namespace tidy