Merge "Include anonymous enum in ABI dumps"

This commit is contained in:
Treehugger Robot
2020-02-01 04:54:27 +00:00
committed by Gerrit Code Review
13 changed files with 526 additions and 14 deletions

View File

@@ -20,6 +20,7 @@
#include <clang/AST/QualTypeNames.h>
#include <clang/Index/CodegenNameGenerator.h>
#include <regex>
#include <string>
#include <assert.h>
@@ -217,6 +218,51 @@ bool ABIWrapper::CreateExtendedType(clang::QualType qual_type,
return CreateBasicNamedAndTypedDecl(canonical_type, typep, "");
}
// A mangled anonymous enum name ends with $_<number> or Ut<number>_ where the
// number may be inconsistent between translation units. This function replaces
// the name with $ followed by the lexicographically smallest field name.
static std::string GetAnonymousEnumUniqueId(llvm::StringRef mangled_name,
const clang::EnumDecl *enum_decl) {
// Get the type name from the mangled name.
const std::string mangled_name_str = mangled_name;
std::smatch match_result;
std::string old_suffix;
std::string nested_name_suffix;
if (std::regex_search(mangled_name_str, match_result,
std::regex(R"((\$_\d+)(E?)$)"))) {
const std::ssub_match &old_name = match_result[1];
old_suffix = std::to_string(old_name.length()) + match_result[0].str();
nested_name_suffix = match_result[2].str();
if (!mangled_name.endswith(old_suffix)) {
llvm::errs() << "Unexpected length of anonymous enum type name: "
<< mangled_name << "\n";
::exit(1);
}
} else if (std::regex_search(mangled_name_str, match_result,
std::regex(R"(Ut\d*_(E?)$)"))) {
old_suffix = match_result[0].str();
nested_name_suffix = match_result[1].str();
} else {
llvm::errs() << "Cannot parse anonymous enum name: " << mangled_name
<< "\n";
::exit(1);
}
// Find the smallest enumerator name.
std::string smallest_enum_name;
for (auto enum_it : enum_decl->enumerators()) {
std::string enum_name = enum_it->getNameAsString();
if (smallest_enum_name.empty() || smallest_enum_name > enum_name) {
smallest_enum_name = enum_name;
}
}
smallest_enum_name = "$" + smallest_enum_name;
std::string new_suffix = std::to_string(smallest_enum_name.length()) +
smallest_enum_name + nested_name_suffix;
return mangled_name.drop_back(old_suffix.length()).str() + new_suffix;
}
std::string ABIWrapper::GetTypeUniqueId(clang::QualType qual_type) {
const clang::Type *canonical_type = qual_type.getCanonicalType().getTypePtr();
assert(canonical_type != nullptr);
@@ -224,6 +270,11 @@ std::string ABIWrapper::GetTypeUniqueId(clang::QualType qual_type) {
llvm::SmallString<256> uid;
llvm::raw_svector_ostream out(uid);
mangle_contextp_->mangleCXXRTTI(qual_type, out);
if (const clang::EnumDecl *enum_decl = GetAnonymousEnum(qual_type)) {
return GetAnonymousEnumUniqueId(uid.str(), enum_decl);
}
return uid.str();
}
@@ -548,10 +599,6 @@ bool RecordDeclWrapper::SetupRecordFields(repr::RecordTypeIR *recordp,
ast_contextp_->getASTRecordLayout(record_decl_);
while (field != record_decl_->field_end()) {
clang::QualType field_type = field->getType();
if (const clang::EnumDecl *enum_decl = GetAnonymousEnum(field_type)) {
// Handle anonymous enums.
field_type = enum_decl->getIntegerType();
}
if (!CreateBasicNamedAndTypedDecl(field_type, source_file)) {
llvm::errs() << "Creation of Type failed\n";
return false;

View File

@@ -61,8 +61,7 @@ bool HeaderASTVisitor::VisitRecordDecl(const clang::RecordDecl *decl) {
bool HeaderASTVisitor::VisitEnumDecl(const clang::EnumDecl *decl) {
if (!decl->isThisDeclarationADefinition() ||
decl->getTypeForDecl()->isDependentType() ||
!decl->hasNameForLinkage()) {
decl->getTypeForDecl()->isDependentType()) {
return true;
}
EnumDeclWrapper enum_decl_wrapper(

View File

@@ -100,13 +100,13 @@ record_types {
access: public_access
}
fields {
referenced_type: "_ZTIj"
referenced_type: "_ZTIN5Hello2$AE"
field_offset: 96
field_name: "enum_field"
access: public_access
}
fields {
referenced_type: "_ZTIj"
referenced_type: "_ZTIN5Hello2$CE"
field_offset: 128
field_name: "enum_field2"
access: public_access
@@ -446,6 +446,48 @@ enum_types {
}
access: public_access
}
enum_types {
type_info {
name: "Hello::(anonymous enum at /development/vndk/tools/header-checker/tests/input/example1.h:17:3)"
size: 4
alignment: 4
referenced_type: "_ZTIN5Hello2$AE"
source_file: "/development/vndk/tools/header-checker/tests/input/example1.h"
linker_set_key: "_ZTIN5Hello2$AE"
self_type: "_ZTIN5Hello2$AE"
}
underlying_type: "_ZTIj"
enum_fields {
enum_field_value: 0
name: "Hello::A"
}
enum_fields {
enum_field_value: 1
name: "Hello::B"
}
access: public_access
}
enum_types {
type_info {
name: "Hello::(anonymous enum at /development/vndk/tools/header-checker/tests/input/example1.h:18:3)"
size: 4
alignment: 4
referenced_type: "_ZTIN5Hello2$CE"
source_file: "/development/vndk/tools/header-checker/tests/input/example1.h"
linker_set_key: "_ZTIN5Hello2$CE"
self_type: "_ZTIN5Hello2$CE"
}
underlying_type: "_ZTIj"
enum_fields {
enum_field_value: 0
name: "Hello::C"
}
enum_fields {
enum_field_value: 1
name: "Hello::D"
}
access: public_access
}
enum_types {
type_info {
name: "test3::Kind"

View File

@@ -100,13 +100,13 @@ record_types {
access: public_access
}
fields {
referenced_type: "_ZTIj"
referenced_type: "_ZTIN5Hello2$AE"
field_offset: 96
field_name: "enum_field"
access: public_access
}
fields {
referenced_type: "_ZTIj"
referenced_type: "_ZTIN5Hello2$CE"
field_offset: 128
field_name: "enum_field2"
access: public_access
@@ -446,6 +446,48 @@ enum_types {
}
access: public_access
}
enum_types {
type_info {
name: "Hello::(anonymous enum at /development/vndk/tools/header-checker/tests/input/example1.h:17:3)"
size: 4
alignment: 4
referenced_type: "_ZTIN5Hello2$AE"
source_file: "/development/vndk/tools/header-checker/tests/input/example1.h"
linker_set_key: "_ZTIN5Hello2$AE"
self_type: "_ZTIN5Hello2$AE"
}
underlying_type: "_ZTIj"
enum_fields {
enum_field_value: 0
name: "Hello::A"
}
enum_fields {
enum_field_value: 1
name: "Hello::B"
}
access: public_access
}
enum_types {
type_info {
name: "Hello::(anonymous enum at /development/vndk/tools/header-checker/tests/input/example1.h:18:3)"
size: 4
alignment: 4
referenced_type: "_ZTIN5Hello2$CE"
source_file: "/development/vndk/tools/header-checker/tests/input/example1.h"
linker_set_key: "_ZTIN5Hello2$CE"
self_type: "_ZTIN5Hello2$CE"
}
underlying_type: "_ZTIj"
enum_fields {
enum_field_value: 0
name: "Hello::C"
}
enum_fields {
enum_field_value: 1
name: "Hello::D"
}
access: public_access
}
enum_types {
type_info {
name: "test3::Kind"

View File

@@ -0,0 +1,14 @@
enum : char {
A=1,
};
enum : char {
B=1,
};
struct {
enum {
B,
C,
} member;
} global_var;

View File

@@ -0,0 +1,4 @@
enum {
FIRST_ANONYMOUS_ENUM
};
#include <golden.h>

View File

@@ -0,0 +1,14 @@
enum : char {
B=1,
};
enum : char {
A=1,
};
struct {
enum {
B,
C,
} member;
} global_var;

View File

@@ -0,0 +1,14 @@
enum : char {
A=1,
};
enum : char {
B=1,
};
struct {
enum {
C=1,
B=0,
} member;
} global_var;

View File

@@ -596,6 +596,41 @@ TEST_MODULES = [
'-output-format', 'Json',
],
),
LsdumpModule(
name='libgolden_anonymous_enum',
arch='arm64',
srcs=['integration/cpp/anonymous_enum/include/golden.h'],
version_script='',
export_include_dirs=['integration/cpp/anonymous_enum/include'],
linker_flags=['-output-format', 'Json',],
),
LsdumpModule(
name='libswap_anonymous_enum',
arch='arm64',
srcs=['integration/cpp/anonymous_enum/include/swap_enum.h'],
version_script='',
export_include_dirs=['integration/cpp/anonymous_enum/include'],
linker_flags=['-output-format', 'Json'],
),
LsdumpModule(
name='libswap_anonymous_enum_field',
arch='arm64',
srcs=['integration/cpp/anonymous_enum/include/swap_enum_field.h'],
version_script='',
export_include_dirs=['integration/cpp/anonymous_enum/include'],
linker_flags=['-output-format', 'Json'],
),
LsdumpModule(
name='libanonymous_enum_odr',
arch='arm64',
srcs=[
'integration/cpp/anonymous_enum/include/golden.h',
'integration/cpp/anonymous_enum/include/include_golden.h',
],
version_script='',
export_include_dirs=['integration/cpp/anonymous_enum/include'],
linker_flags=['-output-format', 'Json'],
),
]
TEST_MODULES = {m.name: m for m in TEST_MODULES}

View File

@@ -0,0 +1,168 @@
{
"array_types" : [],
"builtin_types" :
[
{
"alignment" : 1,
"is_integral" : true,
"is_unsigned" : true,
"linker_set_key" : "_ZTIc",
"name" : "char",
"referenced_type" : "_ZTIc",
"self_type" : "_ZTIc",
"size" : 1
},
{
"alignment" : 4,
"is_integral" : true,
"is_unsigned" : true,
"linker_set_key" : "_ZTIj",
"name" : "unsigned int",
"referenced_type" : "_ZTIj",
"self_type" : "_ZTIj",
"size" : 4
}
],
"elf_functions" : [],
"elf_objects" : [],
"enum_types" :
[
{
"alignment" : 1,
"enum_fields" :
[
{
"enum_field_value" : 1,
"name" : "A"
}
],
"linker_set_key" : "_ZTI2$A",
"name" : "(anonymous enum at /development/vndk/tools/header-checker/tests/integration/cpp/anonymous_enum/include/golden.h:1:1)",
"referenced_type" : "_ZTI2$A",
"self_type" : "_ZTI2$A",
"size" : 1,
"source_file" : "/development/vndk/tools/header-checker/tests/integration/cpp/anonymous_enum/include/golden.h",
"underlying_type" : "_ZTIc"
},
{
"alignment" : 1,
"enum_fields" :
[
{
"enum_field_value" : 1,
"name" : "B"
}
],
"linker_set_key" : "_ZTI2$B",
"name" : "(anonymous enum at /development/vndk/tools/header-checker/tests/integration/cpp/anonymous_enum/include/golden.h:5:1)",
"referenced_type" : "_ZTI2$B",
"self_type" : "_ZTI2$B",
"size" : 1,
"source_file" : "/development/vndk/tools/header-checker/tests/integration/cpp/anonymous_enum/include/golden.h",
"underlying_type" : "_ZTIc"
},
{
"alignment" : 4,
"enum_fields" :
[
{
"enum_field_value" : 0,
"name" : "FIRST_ANONYMOUS_ENUM"
}
],
"linker_set_key" : "_ZTI21$FIRST_ANONYMOUS_ENUM",
"name" : "(anonymous enum at /development/vndk/tools/header-checker/tests/integration/cpp/anonymous_enum/include/include_golden.h:1:1)",
"referenced_type" : "_ZTI21$FIRST_ANONYMOUS_ENUM",
"self_type" : "_ZTI21$FIRST_ANONYMOUS_ENUM",
"size" : 4,
"source_file" : "/development/vndk/tools/header-checker/tests/integration/cpp/anonymous_enum/include/include_golden.h",
"underlying_type" : "_ZTIj"
},
{
"alignment" : 4,
"enum_fields" :
[
{
"enum_field_value" : 0,
"name" : "(anonymous struct)::B"
},
{
"enum_field_value" : 1,
"name" : "(anonymous struct)::C"
}
],
"linker_set_key" : "_ZTIN3$_22$BE",
"name" : "(anonymous struct at /development/vndk/tools/header-checker/tests/integration/cpp/anonymous_enum/include/golden.h:9:1)::(anonymous enum at /development/vndk/tools/header-checker/tests/integration/cpp/anonymous_enum/include/golden.h:10:3)",
"referenced_type" : "_ZTIN3$_22$BE",
"self_type" : "_ZTIN3$_22$BE",
"size" : 4,
"source_file" : "/development/vndk/tools/header-checker/tests/integration/cpp/anonymous_enum/include/golden.h",
"underlying_type" : "_ZTIj"
},
{
"alignment" : 4,
"enum_fields" :
[
{
"enum_field_value" : 0,
"name" : "(anonymous struct)::B"
},
{
"enum_field_value" : 1,
"name" : "(anonymous struct)::C"
}
],
"linker_set_key" : "_ZTIN3$_32$BE",
"name" : "(anonymous struct at /development/vndk/tools/header-checker/tests/integration/cpp/anonymous_enum/include/golden.h:9:1)::(anonymous enum at /development/vndk/tools/header-checker/tests/integration/cpp/anonymous_enum/include/golden.h:10:3)",
"referenced_type" : "_ZTIN3$_32$BE",
"self_type" : "_ZTIN3$_32$BE",
"size" : 4,
"source_file" : "/development/vndk/tools/header-checker/tests/integration/cpp/anonymous_enum/include/golden.h",
"underlying_type" : "_ZTIj"
}
],
"function_types" : [],
"functions" : [],
"global_vars" : [],
"lvalue_reference_types" : [],
"pointer_types" : [],
"qualified_types" : [],
"record_types" :
[
{
"alignment" : 4,
"fields" :
[
{
"field_name" : "member",
"referenced_type" : "_ZTIN3$_22$BE"
}
],
"is_anonymous" : true,
"linker_set_key" : "_ZTI3$_2",
"name" : "(anonymous struct at /development/vndk/tools/header-checker/tests/integration/cpp/anonymous_enum/include/golden.h:9:1)",
"referenced_type" : "_ZTI3$_2",
"self_type" : "_ZTI3$_2",
"size" : 4,
"source_file" : "/development/vndk/tools/header-checker/tests/integration/cpp/anonymous_enum/include/golden.h"
},
{
"alignment" : 4,
"fields" :
[
{
"field_name" : "member",
"referenced_type" : "_ZTIN3$_32$BE"
}
],
"is_anonymous" : true,
"linker_set_key" : "_ZTI3$_3",
"name" : "(anonymous struct at /development/vndk/tools/header-checker/tests/integration/cpp/anonymous_enum/include/golden.h:9:1)",
"referenced_type" : "_ZTI3$_3",
"self_type" : "_ZTI3$_3",
"size" : 4,
"source_file" : "/development/vndk/tools/header-checker/tests/integration/cpp/anonymous_enum/include/golden.h"
}
],
"rvalue_reference_types" : []
}

View File

@@ -0,0 +1,113 @@
{
"array_types" : [],
"builtin_types" :
[
{
"alignment" : 1,
"is_integral" : true,
"is_unsigned" : true,
"linker_set_key" : "_ZTIc",
"name" : "char",
"referenced_type" : "_ZTIc",
"self_type" : "_ZTIc",
"size" : 1
},
{
"alignment" : 4,
"is_integral" : true,
"is_unsigned" : true,
"linker_set_key" : "_ZTIj",
"name" : "unsigned int",
"referenced_type" : "_ZTIj",
"self_type" : "_ZTIj",
"size" : 4
}
],
"elf_functions" : [],
"elf_objects" : [],
"enum_types" :
[
{
"alignment" : 1,
"enum_fields" :
[
{
"enum_field_value" : 1,
"name" : "A"
}
],
"linker_set_key" : "_ZTI2$A",
"name" : "(anonymous enum at /development/vndk/tools/header-checker/tests/integration/cpp/anonymous_enum/include/golden.h:1:1)",
"referenced_type" : "_ZTI2$A",
"self_type" : "_ZTI2$A",
"size" : 1,
"source_file" : "/development/vndk/tools/header-checker/tests/integration/cpp/anonymous_enum/include/golden.h",
"underlying_type" : "_ZTIc"
},
{
"alignment" : 1,
"enum_fields" :
[
{
"enum_field_value" : 1,
"name" : "B"
}
],
"linker_set_key" : "_ZTI2$B",
"name" : "(anonymous enum at /development/vndk/tools/header-checker/tests/integration/cpp/anonymous_enum/include/golden.h:5:1)",
"referenced_type" : "_ZTI2$B",
"self_type" : "_ZTI2$B",
"size" : 1,
"source_file" : "/development/vndk/tools/header-checker/tests/integration/cpp/anonymous_enum/include/golden.h",
"underlying_type" : "_ZTIc"
},
{
"alignment" : 4,
"enum_fields" :
[
{
"enum_field_value" : 0,
"name" : "(anonymous struct)::B"
},
{
"enum_field_value" : 1,
"name" : "(anonymous struct)::C"
}
],
"linker_set_key" : "_ZTIN3$_22$BE",
"name" : "(anonymous struct at /development/vndk/tools/header-checker/tests/integration/cpp/anonymous_enum/include/golden.h:9:1)::(anonymous enum at /development/vndk/tools/header-checker/tests/integration/cpp/anonymous_enum/include/golden.h:10:3)",
"referenced_type" : "_ZTIN3$_22$BE",
"self_type" : "_ZTIN3$_22$BE",
"size" : 4,
"source_file" : "/development/vndk/tools/header-checker/tests/integration/cpp/anonymous_enum/include/golden.h",
"underlying_type" : "_ZTIj"
}
],
"function_types" : [],
"functions" : [],
"global_vars" : [],
"lvalue_reference_types" : [],
"pointer_types" : [],
"qualified_types" : [],
"record_types" :
[
{
"alignment" : 4,
"fields" :
[
{
"field_name" : "member",
"referenced_type" : "_ZTIN3$_22$BE"
}
],
"is_anonymous" : true,
"linker_set_key" : "_ZTI3$_2",
"name" : "(anonymous struct at /development/vndk/tools/header-checker/tests/integration/cpp/anonymous_enum/include/golden.h:9:1)",
"referenced_type" : "_ZTI3$_2",
"self_type" : "_ZTI3$_2",
"size" : 4,
"source_file" : "/development/vndk/tools/header-checker/tests/integration/cpp/anonymous_enum/include/golden.h"
}
],
"rvalue_reference_types" : []
}

View File

@@ -3,10 +3,10 @@
"builtin_types" :
[
{
"linker_set_key" : "void",
"linker_set_key" : "_ZTIv",
"name" : "void",
"referenced_type" : "type-1",
"self_type" : "type-1"
"referenced_type" : "_ZTIv",
"self_type" : "_ZTIv"
}
],
"elf_functions" :
@@ -24,7 +24,7 @@
{
"function_name" : "example",
"linker_set_key" : "example",
"return_type" : "type-1",
"return_type" : "_ZTIv",
"source_file" : "/development/vndk/tools/header-checker/tests/integration/weak_symbols/example.c"
}
],

View File

@@ -352,6 +352,26 @@ class HeaderCheckerTest(unittest.TestCase):
"libempty", "libempty", 0,
["-input-format-old", "Json", "-input-format-new", "Json"])
def test_golden_anonymous_enum(self):
self.prepare_and_absolute_diff_all_archs(
"libgolden_anonymous_enum", "libgolden_anonymous_enum")
def test_swap_anonymous_enum(self):
self.prepare_and_run_abi_diff_all_archs(
"libgolden_anonymous_enum", "libswap_anonymous_enum", 0,
["-input-format-old", "Json", "-input-format-new", "Json",
"-check-all-apis"])
def test_swap_anonymous_enum_field(self):
self.prepare_and_run_abi_diff_all_archs(
"libgolden_anonymous_enum", "libswap_anonymous_enum_field", 0,
["-input-format-old", "Json", "-input-format-new", "Json",
"-check-all-apis"])
def test_anonymous_enum_odr(self):
self.prepare_and_absolute_diff_all_archs(
"libanonymous_enum_odr", "libanonymous_enum_odr")
if __name__ == '__main__':
unittest.main()