// Part of the Crubit project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include "lifetime_analysis/pointer_compatibility.h"

#include <cassert>

#include "lifetime_annotations/pointee_type.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Type.h"
#include "llvm/Support/ErrorHandling.h"

namespace clang {
namespace tidy {
namespace lifetimes {

// Returns whether `type` is an unsigned integer type or an enum with an
// underlying unsigned integer type.
// Note that, unlike this function, Type::isUnsignedIntegerType() considers
// `bool` to be an unsigned integer type.
static bool IsUnsignedIntegerOrEnumType(clang::QualType type) {
  type = type.getCanonicalType();
  return type->isUnsignedIntegerType() && !type->isBooleanType();
}

bool PointeesCompatible(clang::QualType pointee_type,
                        clang::QualType object_type,
                        clang::ASTContext& ast_context) {
  assert(!pointee_type.isNull());
  assert(!object_type.isNull());

  pointee_type = pointee_type.getCanonicalType();
  object_type = object_type.getCanonicalType();

  // `void *`, `char *`, `unsigned char *` and `std::byte *` are allowed to
  // point at anything.
  if (pointee_type->isVoidType() || pointee_type->isCharType() ||
      pointee_type->isStdByteType()) {
    return true;
  }

  // Anything is allowed to point at `void`. IOW, a function is allowed to cast
  // a void pointer back to any other type of pointer.
  if (object_type->isVoidType()) {
    return true;
  }

  // Records.
  if (pointee_type->isRecordType()) {
    const clang::CXXRecordDecl* pointee_record_decl =
        pointee_type->getAsCXXRecordDecl();
    const clang::CXXRecordDecl* object_record_decl =
        object_type->getAsCXXRecordDecl();
    // We leave the case where the records are the same to the hasSimilarType()
    // case below.
    if (pointee_record_decl && object_record_decl &&
        (object_record_decl->isDerivedFrom(pointee_record_decl) ||
         pointee_record_decl->isDerivedFrom(object_record_decl))) {
      return true;
    }
  }

  // A signed integer pointer may point to the unsigned variant of the integer
  // type and vice versa -- so arbitrarily canonicalize integer types to the
  // signed version.
  if (IsUnsignedIntegerOrEnumType(pointee_type)) {
    pointee_type = ast_context.getCorrespondingSignedType(pointee_type);
  }
  if (IsUnsignedIntegerOrEnumType(object_type)) {
    object_type = ast_context.getCorrespondingSignedType(object_type);
  }

  return ast_context.hasSimilarType(pointee_type, object_type);
}

bool MayPointTo(clang::QualType pointer_type, clang::QualType object_type,
                clang::ASTContext& ast_context) {
  assert(!pointer_type.isNull());
  assert(!object_type.isNull());

  pointer_type = pointer_type.getCanonicalType();
  object_type = object_type.getCanonicalType();

  clang::QualType pointee_type = PointeeType(pointer_type);

  if (pointee_type.isNull()) {
    llvm::report_fatal_error("pointee_type is null");
  }

  return PointeesCompatible(pointee_type, object_type, ast_context);
}

}  // namespace lifetimes
}  // namespace tidy
}  // namespace clang
