[nullability] Use `isSupportedPointer()` more widely.

Also:

- Rename to `isSupportedPointerType()` for consistency with
  `QualType::isPointerType()`.

- Make the function desugar. We'll want to desugar in most places we use this,
  and leaving the desugaring to the caller means the caller might forget.
  We do eventually want a version that doesn't desugar, so that we can decide
  whether we can rewrite a type or not, but that version should probably deal
  in `TypeLoc` instead of `QualType`.

- Add a corresponding AST matcher (called just `isSupportedPointer()` for
  consistency with `ast_matchers::isAnyPointer()`)

Use `isSupportedPointerType()` wherever we had been using `isPointerType()` or
`isAnyPointerType()`. (The latter was in widespread use but also includes
Objective-C pointers, which we don't currently actually support.)

PiperOrigin-RevId: 559377210
Change-Id: I69b44ce2ca78cf8e47a1061255ab797bfb68e374
diff --git a/nullability/BUILD b/nullability/BUILD
index ae4b293..0ee6158 100644
--- a/nullability/BUILD
+++ b/nullability/BUILD
@@ -26,6 +26,7 @@
         "//nullability/inference:__pkg__",
     ],
     deps = [
+        ":type_nullability",
         "@llvm-project//clang:ast",
         "@llvm-project//clang:ast_matchers",
     ],
diff --git a/nullability/inference/collect_evidence.cc b/nullability/inference/collect_evidence.cc
index 90a7a28..a4efd97 100644
--- a/nullability/inference/collect_evidence.cc
+++ b/nullability/inference/collect_evidence.cc
@@ -168,16 +168,12 @@
 
   // For each pointer parameter of the callee, ...
   for (; ParamI < CalleeDecl->param_size(); ++ParamI, ++ArgI) {
-    if (!CalleeDecl->getParamDecl(ParamI)
-             ->getType()
-             .getNonReferenceType()
-             ->isPointerType())
+    if (!isSupportedPointerType(
+            CalleeDecl->getParamDecl(ParamI)->getType().getNonReferenceType()))
       continue;
     // the corresponding argument should also be a pointer.
-    CHECK(CallExpr->getArg(ArgI)
-              ->getType()
-              .getNonReferenceType()
-              ->isPointerType());
+    CHECK(isSupportedPointerType(
+        CallExpr->getArg(ArgI)->getType().getNonReferenceType()));
 
     dataflow::PointerValue *PV =
         getPointerValueFromExpr(CallExpr->getArg(ArgI), Env);
@@ -222,7 +218,7 @@
   auto *ReturnStmt = dyn_cast_or_null<clang::ReturnStmt>(CFGStmt->getStmt());
   if (!ReturnStmt) return;
   auto *ReturnExpr = ReturnStmt->getRetValue();
-  if (!ReturnExpr || !ReturnExpr->getType()->isPointerType()) return;
+  if (!ReturnExpr || !isSupportedPointerType(ReturnExpr->getType())) return;
 
   NullabilityKind ReturnNullability =
       getNullability(ReturnExpr, Env,
@@ -254,7 +250,7 @@
 }
 
 std::optional<Evidence::Kind> evidenceKindFromDeclaredType(QualType T) {
-  if (!T.getNonReferenceType()->isPointerType()) return std::nullopt;
+  if (!isSupportedPointerType(T.getNonReferenceType())) return std::nullopt;
   auto Nullability = getNullabilityAnnotationsFromType(T);
   switch (Nullability.front().concrete()) {
     default:
@@ -289,7 +285,7 @@
   auto Parameters = Func->parameters();
   for (auto I = 0; I < Parameters.size(); ++I) {
     auto T = Parameters[I]->getType().getNonReferenceType();
-    if (T->isPointerType() && !evidenceKindFromDeclaredType(T)) {
+    if (isSupportedPointerType(T) && !evidenceKindFromDeclaredType(T)) {
       InferrableSlots.push_back(
           std::make_pair(Analysis.assignNullabilityVariable(
                              Parameters[I], AnalysisContext.arena()),
diff --git a/nullability/inference/inferrable.cc b/nullability/inference/inferrable.cc
index 2adb12a..e41c6e6 100644
--- a/nullability/inference/inferrable.cc
+++ b/nullability/inference/inferrable.cc
@@ -15,7 +15,7 @@
 namespace {
 
 bool isInferrable(QualType T) {
-  return isSupportedPointer(T.getNonReferenceType().getCanonicalType());
+  return isSupportedPointerType(T.getNonReferenceType());
 }
 
 }  // namespace
diff --git a/nullability/pointer_nullability_analysis.cc b/nullability/pointer_nullability_analysis.cc
index 846b90b..344df00 100644
--- a/nullability/pointer_nullability_analysis.cc
+++ b/nullability/pointer_nullability_analysis.cc
@@ -389,7 +389,7 @@
     }
   }
 
-  if (CallExpr->getType()->isAnyPointerType()) {
+  if (isSupportedPointerType(CallExpr->getType())) {
     // Create a pointer so that we can attach nullability to it and have the
     // nullability propagate with the pointer.
     auto *PointerVal = getPointerValueFromExpr(CallExpr, State.Env);
@@ -677,8 +677,8 @@
   computeNullability(ASE, State, [&]() {
     auto &BaseNullability = getNullabilityForChild(ASE->getBase(), State);
     QualType BaseType = ASE->getBase()->getType();
-    CHECK(BaseType->isAnyPointerType() || BaseType->isVectorType());
-    return BaseType->isAnyPointerType()
+    CHECK(isSupportedPointerType(BaseType) || BaseType->isVectorType());
+    return isSupportedPointerType(BaseType)
                ? ArrayRef(BaseNullability).slice(1).vec()
                : BaseNullability;
   });
@@ -747,7 +747,8 @@
   if (!S) return;
 
   auto *E = dyn_cast<Expr>(S->getStmt());
-  if (E == nullptr || !E->isPRValue() || !E->getType()->isPointerType()) return;
+  if (E == nullptr || !E->isPRValue() || !isSupportedPointerType(E->getType()))
+    return;
 
   if (Env.getValue(*E) == nullptr)
     // `createValue()` always produces a value for pointer types.
@@ -821,7 +822,7 @@
                                        const Environment &Env2,
                                        Value &MergedVal,
                                        Environment &MergedEnv) {
-  if (!Type->isAnyPointerType()) {
+  if (!isSupportedPointerType(Type)) {
     return false;
   }
 
diff --git a/nullability/pointer_nullability_diagnosis.cc b/nullability/pointer_nullability_diagnosis.cc
index 75d1a2b..b33fdf5 100644
--- a/nullability/pointer_nullability_diagnosis.cc
+++ b/nullability/pointer_nullability_diagnosis.cc
@@ -63,7 +63,7 @@
 SmallVector<PointerNullabilityDiagnostic> diagnoseTypeExprCompatibility(
     QualType DeclaredType, const Expr *E, const Environment &Env,
     ASTContext &Ctx) {
-  CHECK(DeclaredType->isAnyPointerType());
+  CHECK(isSupportedPointerType(DeclaredType));
   return getNullabilityKind(DeclaredType, Ctx) == NullabilityKind::NonNull
              ? diagnoseNonnullExpected(E, Env)
              : SmallVector<PointerNullabilityDiagnostic>{};
@@ -96,7 +96,7 @@
   SmallVector<PointerNullabilityDiagnostic> Diagnostics;
   for (unsigned int I = 0; I < Args.size(); ++I) {
     auto ParamType = ParamTypes[I].getNonReferenceType();
-    if (ParamType->isAnyPointerType())
+    if (isSupportedPointerType(ParamType))
       Diagnostics.append(
           diagnoseTypeExprCompatibility(ParamType, Args[I], Env, Ctx));
   }
@@ -260,12 +260,12 @@
   auto ReturnType = cast<FunctionDecl>(State.Env.getDeclCtx())->getReturnType();
 
   // TODO: Handle non-pointer return types.
-  if (!ReturnType->isPointerType()) {
+  if (!isSupportedPointerType(ReturnType)) {
     return {};
   }
 
   auto *ReturnExpr = RS->getRetValue();
-  CHECK(ReturnExpr->getType()->isPointerType());
+  CHECK(isSupportedPointerType(ReturnExpr->getType()));
 
   return diagnoseTypeExprCompatibility(ReturnType, ReturnExpr, State.Env,
                                        *Result.Context);
@@ -276,7 +276,7 @@
     const TransferStateForDiagnostics<PointerNullabilityLattice> &State) {
   CHECK(CI->isAnyMemberInitializer());
   auto MemberType = CI->getAnyMember()->getType();
-  if (!MemberType->isAnyPointerType()) return {};
+  if (!isSupportedPointerType(MemberType)) return {};
 
   auto *MemberInitExpr = CI->getInit();
   return diagnoseTypeExprCompatibility(MemberType, MemberInitExpr, State.Env,
diff --git a/nullability/pointer_nullability_matchers.cc b/nullability/pointer_nullability_matchers.cc
index dda8929..be9ca0f 100644
--- a/nullability/pointer_nullability_matchers.cc
+++ b/nullability/pointer_nullability_matchers.cc
@@ -26,7 +26,6 @@
 using ast_matchers::hasType;
 using ast_matchers::hasUnaryOperand;
 using ast_matchers::implicitCastExpr;
-using ast_matchers::isAnyPointer;
 using ast_matchers::isArrow;
 using ast_matchers::isMemberInitializer;
 using ast_matchers::memberExpr;
@@ -34,7 +33,7 @@
 using ast_matchers::unaryOperator;
 using ast_matchers::internal::Matcher;
 
-Matcher<Stmt> isPointerExpr() { return expr(hasType(isAnyPointer())); }
+Matcher<Stmt> isPointerExpr() { return expr(hasType(isSupportedPointer())); }
 Matcher<Stmt> isNullPointerLiteral() {
   return implicitCastExpr(anyOf(hasCastKind(CK_NullToPointer),
                                 hasCastKind(CK_NullToMemberPointer)));
@@ -51,13 +50,13 @@
   return implicitCastExpr(hasCastKind(CK_PointerToBoolean));
 }
 Matcher<Stmt> isMemberOfPointerType() {
-  return memberExpr(hasType(isAnyPointer()));
+  return memberExpr(hasType(isSupportedPointer()));
 }
 Matcher<Stmt> isPointerArrow() { return memberExpr(isArrow()); }
 Matcher<Stmt> isCXXThisExpr() { return cxxThisExpr(); }
 Matcher<Stmt> isCallExpr() { return callExpr(); }
 Matcher<Stmt> isPointerReturn() {
-  return returnStmt(hasReturnValue(hasType(isAnyPointer())));
+  return returnStmt(hasReturnValue(hasType(isSupportedPointer())));
 }
 Matcher<Stmt> isConstructExpr() { return cxxConstructExpr(); }
 Matcher<CXXCtorInitializer> isCtorMemberInitializer() {
diff --git a/nullability/pointer_nullability_matchers.h b/nullability/pointer_nullability_matchers.h
index 353bbe8..ea0ed26 100644
--- a/nullability/pointer_nullability_matchers.h
+++ b/nullability/pointer_nullability_matchers.h
@@ -5,12 +5,18 @@
 #ifndef CRUBIT_NULLABILITY_POINTER_NULLABILITY_MATCHERS_H_
 #define CRUBIT_NULLABILITY_POINTER_NULLABILITY_MATCHERS_H_
 
+#include "nullability/type_nullability.h"
 #include "clang/ASTMatchers/ASTMatchersInternal.h"
+#include "clang/ASTMatchers/ASTMatchersMacros.h"
 
 namespace clang {
 namespace tidy {
 namespace nullability {
 
+AST_MATCHER(QualType, isSupportedPointer) {
+  return isSupportedPointerType(Node);
+}
+
 ast_matchers::internal::Matcher<Stmt> isPointerExpr();
 ast_matchers::internal::Matcher<Stmt> isMemberOfPointerType();
 ast_matchers::internal::Matcher<Stmt> isPointerArrow();
diff --git a/nullability/type_nullability.cc b/nullability/type_nullability.cc
index 81c07fe..af998f3 100644
--- a/nullability/type_nullability.cc
+++ b/nullability/type_nullability.cc
@@ -28,7 +28,7 @@
 
 namespace clang::tidy::nullability {
 
-bool isSupportedPointer(QualType T) { return isa<PointerType>(T); }
+bool isSupportedPointerType(QualType T) { return T->isPointerType(); }
 
 PointerTypeNullability PointerTypeNullability::createSymbolic(
     dataflow::Arena &A) {
diff --git a/nullability/type_nullability.h b/nullability/type_nullability.h
index 1ba0bab..8605452 100644
--- a/nullability/type_nullability.h
+++ b/nullability/type_nullability.h
@@ -43,11 +43,12 @@
 namespace clang::tidy::nullability {
 
 /// Is this exactly a pointer type that we track outer nullability for?
+/// This unwraps sugar, i.e. it looks at the canonical type.
 /// Does not unwrap sugar, consider isSupportedPointer(T.getCanonicalType()).
 ///
-/// (For now, only regular PointerTypes, in future we should consider supporting
-/// pointer-to-member, ObjC pointers, etc).
-bool isSupportedPointer(QualType);
+/// (For now, only regular `PointerType`s, in future we should consider
+/// supporting pointer-to-member, ObjC pointers, `unique_ptr`, etc).
+bool isSupportedPointerType(QualType);
 
 /// Describes the nullability contract of a pointer "slot" within a type.
 ///
diff --git a/nullability/type_nullability_test.cc b/nullability/type_nullability_test.cc
index 33eb23a..e058bf3 100644
--- a/nullability/type_nullability_test.cc
+++ b/nullability/type_nullability_test.cc
@@ -19,7 +19,7 @@
 namespace {
 using testing::ElementsAre;
 
-TEST(TypeNullabilityTest, IsSupportedPointer) {
+TEST(TypeNullabilityTest, IsSupportedPointerType) {
   TestAST AST(R"cpp(
     using NotPointer = int;
     using Pointer = NotPointer*;
@@ -44,14 +44,14 @@
     EXPECT_TRUE(Lookup.isSingleResult());
     return Lookup.find_first<TypeAliasDecl>()->getUnderlyingType();
   };
-  EXPECT_FALSE(isSupportedPointer(Underlying("NotPointer")));
-  EXPECT_TRUE(isSupportedPointer(Underlying("Pointer")));
-  EXPECT_TRUE(isSupportedPointer(Underlying("FuncPointer")));
-  EXPECT_FALSE(isSupportedPointer(Underlying("SugaredPointer")));
-  EXPECT_FALSE(isSupportedPointer(Underlying("PointerDataMember")));
-  EXPECT_FALSE(isSupportedPointer(Underlying("PointerMemberFunction")));
-  EXPECT_FALSE(isSupportedPointer(Underlying("ObjCPointer")));
-  EXPECT_FALSE(isSupportedPointer(Underlying("ContainsPointers")));
+  EXPECT_FALSE(isSupportedPointerType(Underlying("NotPointer")));
+  EXPECT_TRUE(isSupportedPointerType(Underlying("Pointer")));
+  EXPECT_TRUE(isSupportedPointerType(Underlying("FuncPointer")));
+  EXPECT_TRUE(isSupportedPointerType(Underlying("SugaredPointer")));
+  EXPECT_FALSE(isSupportedPointerType(Underlying("PointerDataMember")));
+  EXPECT_FALSE(isSupportedPointerType(Underlying("PointerMemberFunction")));
+  EXPECT_FALSE(isSupportedPointerType(Underlying("ObjCPointer")));
+  EXPECT_FALSE(isSupportedPointerType(Underlying("ContainsPointers")));
 }
 
 class GetNullabilityAnnotationsFromTypeTest : public ::testing::Test {