Stop trying to walk partially lost TypeLocs for noreturn-ed aliases.

When a noreturn attribute is applied to a Typedef for a function pointer, the Type is unwrapped, modified to be noreturn, and then best-effort rewrapped, but type source information is lost in the case of Typedefs. Because the underlying type is now different, we can't simply rewrap in the same Typedef.

PiperOrigin-RevId: 667576397
Change-Id: If79df2c764337fe8e98d0b0188c305b3e112d353
diff --git a/bazel/llvm.bzl b/bazel/llvm.bzl
index 20c2674..b5d63b6 100644
--- a/bazel/llvm.bzl
+++ b/bazel/llvm.bzl
@@ -53,7 +53,7 @@
             executable = False,
         )
 
-LLVM_COMMIT_SHA = "7f7f4feaf07dd3bb4b22d0c25d34b6c99c753aa2"
+LLVM_COMMIT_SHA = "65281570afd7e35e01533b07c6c2937de410fc52"
 
 def llvm_loader_repository_dependencies():
     # This *declares* the dependency, but it won't actually be *downloaded* unless it's used.
diff --git a/nullability/inference/BUILD b/nullability/inference/BUILD
index 80175f8..e014961 100644
--- a/nullability/inference/BUILD
+++ b/nullability/inference/BUILD
@@ -162,7 +162,6 @@
         "//nullability:pragma",
         "//nullability:type_nullability",
         "@abseil-cpp//absl/log:check",
-        "@abseil-cpp//absl/strings:string_view",
         "@llvm-project//clang:ast",
         "@llvm-project//clang:ast_matchers",
         "@llvm-project//clang:basic",
diff --git a/nullability/inference/eligible_ranges_test.cc b/nullability/inference/eligible_ranges_test.cc
index 2f86963..eaea916 100644
--- a/nullability/inference/eligible_ranges_test.cc
+++ b/nullability/inference/eligible_ranges_test.cc
@@ -508,6 +508,21 @@
                                        SlotRange(-1, Input.range("three"))))));
 }
 
+TEST(EligibleRangesTest, NoreturnAliasLosesFunctionTypeSourceInfo) {
+  // This previously crashed because the noreturn attribute causes the
+  // TypedefType to be unwrapped and rewritten without the Typedef layer and
+  // the source information below that layer to be dropped.
+  auto Input = Annotations(R"(
+    typedef void (*Alias)(const char *, ...);
+
+    __attribute__((__noreturn__)) [[Alias]] target;
+  )");
+  EXPECT_THAT(
+      getVarRanges(Input.code()),
+      Optional(TypeLocRanges(
+          MainFileName, UnorderedElementsAre(SlotRange(0, Input.range(""))))));
+}
+
 TEST(EligibleRangesTest, TemplatedClassContext) {
   auto Input = Annotations(R"(
   template <typename T>
diff --git a/nullability/type_nullability.cc b/nullability/type_nullability.cc
index f883a26..6a55766 100644
--- a/nullability/type_nullability.cc
+++ b/nullability/type_nullability.cc
@@ -622,6 +622,13 @@
   void visitFunctionProtoType(absl::Nonnull<const FunctionProtoType *> FPT,
                               std::optional<FunctionProtoTypeLoc> L) {
     ignoreUnexpectedNullability();
+    if (FPT->getNoReturnAttr() && L && L->getNumParams() > 0 &&
+        L->getParam(0) == nullptr) {
+      // This FunctionProtoType was unwrapped and rewrapped to add a noreturn
+      // attribute, in a way that lost source information. We should not walk
+      // the TypeLoc.
+      L = std::nullopt;
+    }
     visit(FPT->getReturnType(),
           L ? std::optional<TypeLoc>(L->getReturnLoc()) : std::nullopt);
     if (L) {