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) {