910e62b5创建于 1月15日历史提交
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <tuple>

#include "third_party/do_not_rewrite/third_party_api.h"

int UnsafeIndex();  // Return out-of-bounds index.
bool Bool();        // Unknown boolean value.

// Expected rewrite:
// base::span<int> GetFirstPartyBuffer() {
int* GetFirstPartyBuffer() {
  return new int[10];
}

void test_cycle_isolated() {
  // An isolated cycle with no dependencies.
  //
  // As of today, it gets rewritten, because nothing prevents it from being
  // rewritten, and some of its dependents would like to be spanified.

  // Expected rewrite:
  // base::span<int> cycle_1;
  int* cycle_1;
  // Expected rewrite:
  // base::span<int> cycle_2;
  int* cycle_2;
  cycle_1 = cycle_2;
  cycle_2 = cycle_1;

  // Expected rewrite:
  // base::span<int> output;
  int* output;
  if (Bool()) {
    output = GetFirstPartyBuffer();
  } else {
    output = cycle_1;
  }
  std::ignore = output[UnsafeIndex()];
}

void test_cycle_depending_on_first_party_buffer() {
  // A cycle that can be rewritten, because it depends on something that can be
  // rewritten, and dependants would like to be spanified.

  // Expected rewrite:
  // base::span<int> cycle_1 = GetFirstPartyBuffer();
  int* cycle_1 = GetFirstPartyBuffer();
  // Expected rewrite:
  // base::span<int> cycle_2;
  int* cycle_2;
  cycle_1 = cycle_2;
  cycle_2 = cycle_1;

  // Expected rewrite:
  // base::span<int> output;
  int* output;
  if (Bool()) {
    output = GetFirstPartyBuffer();
  } else {
    output = cycle_1;
  }
  std::ignore = output[UnsafeIndex()];
}

void test_cycle_depending_on_third_party_buffer() {
  // A cycle that can't be rewritten, because it depends on something that can't
  // be rewritten.

  // The current implementation of the spanifier tool assumes that all third-
  // party functions tell the size someway. The implementation is below.
  // https://source.chromium.org/chromium/chromium/src/+/main:tools/clang/spanify/Spanifier.cpp;drc=f240549b481969cf1442aac67a9086bfd639787c;l=2190-2191
  //
  // This test case was originally introduced to test that a buffer returned by
  // a third-party function shouldn't be rewritten to base::span, but it's not
  // been the intended behavior. A bug caused that the buffer doesn't get
  // rewritten, but the bug was fixed in https://crrev.com/c/6348037.
  //
  // TODO: Revisit this point and determine whether buffers returned by third-
  // party functions must be spanified unconditionally or in a certain
  // condition.
  //
  // Expected rewrite:
  // base::span<int> cycle_1 = GetThirdPartyBuffer();
  int* cycle_1 = GetThirdPartyBuffer();
  // Expected rewrite:
  // base::span<int> cycle_2;
  int* cycle_2;
  cycle_1 = cycle_2;
  cycle_2 = cycle_1;

  // Expected rewrite:
  // base::span<int> output;
  int* output;
  if (Bool()) {
    output = GetFirstPartyBuffer();
  } else {
    output = cycle_1;
  }
  std::ignore = output[UnsafeIndex()];
}