Internal change
PiperOrigin-RevId: 544547431
Change-Id: Id843abf8cfaa065ec58c020c44c39b81074f4c66
diff --git a/nullability/pointer_nullability_analysis.cc b/nullability/pointer_nullability_analysis.cc
index b950422..e0dbb6c 100644
--- a/nullability/pointer_nullability_analysis.cc
+++ b/nullability/pointer_nullability_analysis.cc
@@ -148,11 +148,17 @@
unsigned ArgIndex = ST->getIndex();
auto TemplateArgs = Specialization->getTemplateArgs().asArray();
+ // TODO: If the type was substituted from a pack template argument,
+ // we must find the slice that pertains to this particular type.
+ // For now, just give up on resugaring this type.
+ if (ST->getPackIndex().has_value()) return std::nullopt;
+
unsigned PointerCount =
countPointersInType(Specialization->getDeclContext());
for (auto TA : TemplateArgs.take_front(ArgIndex)) {
PointerCount += countPointersInType(TA);
}
+
unsigned SliceSize = countPointersInType(TemplateArgs[ArgIndex]);
return ArrayRef(BaseNullabilityAnnotations)
.slice(PointerCount, SliceSize)
diff --git a/nullability/test/templates.cc b/nullability/test/templates.cc
index 37fa7b8..53bc052 100644
--- a/nullability/test/templates.cc
+++ b/nullability/test/templates.cc
@@ -1208,5 +1208,20 @@
)cc"));
}
+TEST(PointerNullabilityTest, CallMethodTakingParameterPack) {
+ EXPECT_TRUE(checkDiagnostics(R"cc(
+ template <class... Ts>
+ struct S {
+ S<Ts...> Foo(Ts...);
+ };
+ void target(int* _Nonnull p1, char* _Nullable p2) {
+ S<int* _Nonnull, char* _Nullable> s;
+ // TODO: Should be [NK_nonnull, NK_nullable], but we don't treat parameter
+ // packs correctly yet.
+ __assert_nullability<NK_unspecified, NK_unspecified>(s.Foo(p1, p2));
+ }
+ )cc"));
+}
+
} // namespace
} // namespace clang::tidy::nullability