Internal change
PiperOrigin-RevId: 544335572
Change-Id: I28e98c4973519b8c0da29e5f8bc51078cffb52ce
diff --git a/nullability/pointer_nullability_analysis.cc b/nullability/pointer_nullability_analysis.cc
index 3964d1c..b950422 100644
--- a/nullability/pointer_nullability_analysis.cc
+++ b/nullability/pointer_nullability_analysis.cc
@@ -15,6 +15,7 @@
#include "nullability/type_nullability.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTDumper.h"
+#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
#include "clang/AST/OperationKinds.h"
#include "clang/AST/Stmt.h"
@@ -137,6 +138,12 @@
// (e.g. PointerNullabilityTest.MemberFunctionTemplateOfTemplateStruct)
if (!Specialization || Specialization != ST->getAssociatedDecl())
return std::nullopt;
+ // TODO: The code below does not deal correctly with partial
+ // specializations. We should eventually handle these, but for now, just
+ // bail out.
+ if (isa<ClassTemplatePartialSpecializationDecl>(
+ ST->getReplacedParameter()->getDeclContext()))
+ return std::nullopt;
unsigned ArgIndex = ST->getIndex();
auto TemplateArgs = Specialization->getTemplateArgs().asArray();
diff --git a/nullability/test/templates.cc b/nullability/test/templates.cc
index 00357f5..37fa7b8 100644
--- a/nullability/test/templates.cc
+++ b/nullability/test/templates.cc
@@ -1189,5 +1189,24 @@
)cc"));
}
+TEST(PointerNullabilityTest, MethodOnPartialSpecialization) {
+ EXPECT_TRUE(checkDiagnostics(R"cc(
+ template <class T>
+ struct S {};
+ template <class T1, class T2>
+ struct pair {};
+ template <class T1, class T2>
+ struct S<pair<T1, T2>> {
+ T1 Foo(T1, T2);
+ };
+ void target(int* _Nonnull p1, char* _Nullable p2) {
+ S<pair<int* _Nonnull, char* _Nullable>> s;
+ // TODO: Should be NK_nonnull, but we don't treat partial specializations
+ // correctly yet.
+ __assert_nullability<NK_unspecified>(s.Foo(p1, p2));
+ }
+ )cc"));
+}
+
} // namespace
} // namespace clang::tidy::nullability