syntax = "proto2";

import "abi_dump.proto";

package abi_diff;

message TypeInfo {
  optional uint64 size = 1;
  optional uint32 alignment = 2;
}

message TypeInfoDiff {
  optional TypeInfo old_type_info  = 1;
  optional TypeInfo new_type_info  = 2;
}

message VTableLayoutDiff {
  optional abi_dump.VTableLayout old_vtable = 1;
  optional abi_dump.VTableLayout new_vtable = 2;
}

message RecordFieldDeclDiff {
  optional abi_dump.RecordFieldDecl old_field = 1;
  optional abi_dump.RecordFieldDecl new_field = 2;
}

message CXXBaseSpecifierDiff {
  repeated abi_dump.CXXBaseSpecifier old_bases = 1;
  repeated abi_dump.CXXBaseSpecifier new_bases = 2;
}

message RecordTypeDiff {
  optional string name = 1;
  optional string type_stack = 2;
  optional TypeInfoDiff type_info_diff = 3;
  repeated abi_dump.RecordFieldDecl fields_removed = 4;
  repeated abi_dump.RecordFieldDecl fields_added = 5;
  repeated RecordFieldDeclDiff fields_diff = 6;
  optional CXXBaseSpecifierDiff bases_diff = 7;
  optional VTableLayoutDiff vtable_layout_diff = 8;
}

message UnderlyingTypeDiff {
  optional string old_type  = 1;
  optional string new_type  = 2;
}

message EnumFieldDeclDiff {
  optional abi_dump.EnumFieldDecl old_field = 1;
  optional abi_dump.EnumFieldDecl new_field = 2;
}

message EnumTypeDiff {
  optional string type_stack = 1;
  optional string name = 2;
  repeated EnumFieldDeclDiff fields_diff = 3;
  optional UnderlyingTypeDiff underlying_type_diff = 4;
  repeated abi_dump.EnumFieldDecl fields_added = 5;
  repeated abi_dump.EnumFieldDecl fields_removed = 6;
}

message FunctionDeclDiff {
  // Template diffs are not required since in C++, they will show up in mangled
  // names and in C, templates are not supported.
  optional string type_stack = 1;
  optional string name = 2;
  optional abi_dump.FunctionDecl old = 3;
  optional abi_dump.FunctionDecl new = 4;
}

message GlobalVarDeclDiff {
  optional string type_stack = 1;
  optional string name = 2;
  optional abi_dump.GlobalVarDecl old = 3;  // Old global var
  optional abi_dump.GlobalVarDecl new = 4;  // New global var
}

message TranslationUnitDiff {
  // Library Name
  optional string lib_name = 1;
  optional string arch = 2;
  // Records.
  repeated RecordTypeDiff record_type_diffs = 3;
  repeated RecordTypeDiff unreferenced_record_type_diffs = 4;
  repeated abi_dump.RecordType unreferenced_record_types_removed = 5;
  repeated abi_dump.RecordType unreferenced_record_types_added = 6;

  // Enums
  repeated EnumTypeDiff enum_type_diffs = 7;
  repeated EnumTypeDiff enum_type_extension_diffs = 8;
  repeated EnumTypeDiff unreferenced_enum_type_diffs = 9;
  repeated EnumTypeDiff unreferenced_enum_type_extension_diffs = 10;
  repeated abi_dump.EnumType unreferenced_enum_types_removed = 11;
  repeated abi_dump.EnumType unreferenced_enum_types_added = 12;

  // Functions and Global variables.
  repeated FunctionDeclDiff function_diffs = 13;
  repeated GlobalVarDeclDiff global_var_diffs = 14;

  repeated abi_dump.FunctionDecl functions_removed = 15;
  repeated abi_dump.GlobalVarDecl global_vars_removed = 16;

  repeated abi_dump.FunctionDecl functions_added = 17;
  repeated abi_dump.GlobalVarDecl global_vars_added = 18;

  repeated abi_dump.ElfFunction added_elf_functions = 19;
  repeated abi_dump.ElfFunction removed_elf_functions = 20;

  repeated abi_dump.ElfObject added_elf_objects = 21;
  repeated abi_dump.ElfObject removed_elf_objects = 22;

  // Compatiblity Status
  optional CompatibilityStatus compatibility_status = 23;
}

// Not merged with TranslationUnitDiff to allow future extensions.
message ConciseDiffReportInformation {
  optional string lib_name = 1;
  optional string arch = 2;
  optional string diff_report_path = 3;
  optional CompatibilityStatus compatibility_status = 4;
}

message MergedTranslationUnitDiff {
  repeated ConciseDiffReportInformation diff_reports = 1;
}

enum CompatibilityStatus {
  COMPATIBLE = 0;
  EXTENSION = 1;
  INCOMPATIBLE = 4;
}
