Check whether targets are valid before collecting evidence in more cases.

Also log more useful information about what invalid Target evidence is being emitted for.

PiperOrigin-RevId: 579311303
Change-Id: Id6ce4c5f34d1c5618cf54c3e645ddb9436fb7ec2
diff --git a/nullability/inference/collect_evidence.cc b/nullability/inference/collect_evidence.cc
index 9caf03c..6d1bd93 100644
--- a/nullability/inference/collect_evidence.cc
+++ b/nullability/inference/collect_evidence.cc
@@ -80,7 +80,10 @@
     void operator()(const Decl &Target, Slot S, Evidence::Kind Kind,
                     SourceLocation Loc) const {
       CHECK(isInferenceTarget(Target))
-          << "Evidence emitted for a Target which is not an inference target.";
+          << "Evidence emitted for a Target which is not an inference target: "
+          << (dyn_cast<NamedDecl>(&Target)
+                  ? dyn_cast<NamedDecl>(&Target)->getQualifiedNameAsString()
+                  : "not a named decl");
 
       Evidence E;
       E.set_slot(S);
@@ -257,6 +260,9 @@
       isa<clang::CXXMethodDecl>(CalleeDecl))
     ++ArgI;
 
+  bool CollectEvidenceForCallee = isInferenceTarget(CalleeDecl);
+  bool CollectEvidenceForCaller = isInferenceTarget(*Env.getCurrentFunc());
+
   // For each pointer parameter of the callee, ...
   for (; ParamI < CalleeDecl.param_size(); ++ParamI, ++ArgI) {
     const auto *ParamDecl = CalleeDecl.getParamDecl(ParamI);
@@ -271,33 +277,37 @@
 
     SourceLocation ArgLoc = Expr.getArg(ArgI)->getExprLoc();
 
-    auto ParamNullability = getNullabilityAnnotationsFromTypeAndOverrides(
-        ParamType, ParamDecl, Lattice);
+    if (CollectEvidenceForCaller) {
+      auto ParamNullability = getNullabilityAnnotationsFromTypeAndOverrides(
+          ParamType, ParamDecl, Lattice);
 
-    // Collect evidence from the binding of the argument to the parameter's
-    // nullability, if known.
-    collectEvidenceFromBindingToType(
-        ParamNullability, *PV, InferableCallerSlots, InferableSlotsConstraint,
-        Env, ArgLoc, Emit);
-
-    // Emit evidence of the parameter's nullability. First, calculate that
-    // nullability based on InferableSlots for the caller being assigned to
-    // Unknown or their previously-inferred value, to reflect the current
-    // annotations and not all possible annotations for them.
-    NullabilityKind ArgNullability =
-        getNullability(*PV, Env, &InferableSlotsConstraint);
-    Evidence::Kind ArgEvidenceKind;
-    switch (ArgNullability) {
-      case NullabilityKind::Nullable:
-        ArgEvidenceKind = Evidence::NULLABLE_ARGUMENT;
-        break;
-      case NullabilityKind::NonNull:
-        ArgEvidenceKind = Evidence::NONNULL_ARGUMENT;
-        break;
-      default:
-        ArgEvidenceKind = Evidence::UNKNOWN_ARGUMENT;
+      // Collect evidence from the binding of the argument to the parameter's
+      // nullability, if known.
+      collectEvidenceFromBindingToType(
+          ParamNullability, *PV, InferableCallerSlots, InferableSlotsConstraint,
+          Env, ArgLoc, Emit);
     }
-    Emit(CalleeDecl, paramSlot(ParamI), ArgEvidenceKind, ArgLoc);
+
+    if (CollectEvidenceForCallee) {
+      // Emit evidence of the parameter's nullability. First, calculate that
+      // nullability based on InferableSlots for the caller being assigned to
+      // Unknown or their previously-inferred value, to reflect the current
+      // annotations and not all possible annotations for them.
+      NullabilityKind ArgNullability =
+          getNullability(*PV, Env, &InferableSlotsConstraint);
+      Evidence::Kind ArgEvidenceKind;
+      switch (ArgNullability) {
+        case NullabilityKind::Nullable:
+          ArgEvidenceKind = Evidence::NULLABLE_ARGUMENT;
+          break;
+        case NullabilityKind::NonNull:
+          ArgEvidenceKind = Evidence::NONNULL_ARGUMENT;
+          break;
+        default:
+          ArgEvidenceKind = Evidence::UNKNOWN_ARGUMENT;
+      }
+      Emit(CalleeDecl, paramSlot(ParamI), ArgEvidenceKind, ArgLoc);
+    }
   }
 }
 
@@ -313,7 +323,7 @@
   if (!CallExpr || !CallExpr->getCalleeDecl()) return;
   auto *CalleeDecl =
       dyn_cast_or_null<clang::FunctionDecl>(CallExpr->getCalleeDecl());
-  if (!CalleeDecl || !isInferenceTarget(*CalleeDecl)) return;
+  if (!CalleeDecl) return;
 
   collectEvidenceFromArgsAndParams(*CalleeDecl, *CallExpr, InferableCallerSlots,
                                    InferableSlotsConstraint, Lattice, Env,
@@ -380,6 +390,7 @@
     llvm::function_ref<EvidenceEmitter> Emit) {
   auto CFGStmt = Element.getAs<clang::CFGStmt>();
   if (!CFGStmt) return;
+  if (!isInferenceTarget(*Env.getCurrentFunc())) return;
 
   // Initialization of new decl.
   if (auto *DeclStmt = dyn_cast_or_null<clang::DeclStmt>(CFGStmt->getStmt())) {
diff --git a/nullability/inference/collect_evidence_test.cc b/nullability/inference/collect_evidence_test.cc
index 4df90f8..bf2696a 100644
--- a/nullability/inference/collect_evidence_test.cc
+++ b/nullability/inference/collect_evidence_test.cc
@@ -585,9 +585,14 @@
 
 TEST(CollectEvidenceFromImplementationTest, NotInferenceTarget) {
   static constexpr llvm::StringRef Src = R"cc(
+    void isATarget(Nonnull<int*> a);
     template <typename T>
     T* target(T* p) {
       *p;
+      Nonnull<int*> a = p;
+      isATarget(p);
+      target<T>(nullptr);
+      target<int>(nullptr);
       return nullptr;
     }
 
@@ -611,7 +616,11 @@
                       usr_cache),
       usr_cache);
   if (Err) ADD_FAILURE() << toString(std::move(Err));
-  EXPECT_THAT(Results, IsEmpty());
+  // Doesn't collect any evidence for target from target's body, only collects
+  // some for isATarget.
+  EXPECT_THAT(Results, UnorderedElementsAre(
+                           evidence(paramSlot(0), Evidence::UNKNOWN_ARGUMENT,
+                                    functionNamed("isATarget"))));
 }
 
 TEST(CollectEvidenceFromImplementationTest, PropagatesPreviousInferences) {