.comp AllocationType {
  //----------------------------------------------------------------------------
  // "Input"/declared rules
  //
  // https://souffle-lang.github.io/components#input-rules
  //----------------------------------------------------------------------------

  .decl alloc_subregion_type(?region: AllocSubregion, ?type: Type) inline
  .decl backpropagated_allocation_type(?alloc: Allocation, ?type: Type) inline
  .decl sig_allocation_type(?alloc: Allocation, ?type: Type) inline
  .decl is_init_by_ctor(?type: ClassType, ?ctor: FunctionDecl, ?inFunction: Function, ?alloc: Allocation) inline
  .decl heap_allocation_by_alloc_exc(?insn: Instruction, ?heapAlloc: HeapAllocation) inline

  //----------------------------------------------------------------------------
  // "Output"/defined rules
  //----------------------------------------------------------------------------

  .decl allocation_type(?alloc:Allocation, ?type:Type)

  allocation_type(?alloc, ?type) :-
    static_allocation_type(?alloc, ?type).

  allocation_type(?alloc, ?type) :-
    alloc_subregion_type(?alloc, ?type).

  allocation_type(?alloc, ?type) :-
    backpropagated_allocation_type(?alloc, ?type).

  allocation_type(?alloc, ?type) :-
    sig_allocation_type(?alloc, ?type).

  //----------------------------------------------------------------------------
  // C++
  //----------------------------------------------------------------------------

  // The actual type of the object must match its size, and the relevant
  // constructor must be in the same func that allocates it.
  allocation_type(?heapAlloc, ?type) :-
    !inlined_constructors(),
    instr_func(?allocInsn, ?inFunction),
    heap_allocation_by_new(?allocInsn, ?heapAlloc),
    allocation_size(?heapAlloc, ?size),
    type_has_size(?type, ?size),
    is_init_by_ctor(?type, _, ?inFunction, ?heapAlloc).

  allocation_type(?excObj, ?type) :-
    !inlined_constructors(),
    instr_func(?allocInsn, ?inFunction),
    heap_allocation_by_alloc_exc(?allocInsn, ?excObj),
    allocation_size(?excObj, ?size),
    type_has_size(?type, ?size),
    is_init_by_ctor(?type, _, ?inFunction, ?excObj).
}
