Skip to content

Commit

Permalink
Merge pull request #4 from giulianobelinassi/fix_record_in_array_decl
Browse files Browse the repository at this point in the history
Fix redeclaration of RecordDecl in Records defined in array variables
  • Loading branch information
giulianobelinassi authored Apr 1, 2024
2 parents 56087bf + 84a76ab commit 3027853
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 1 deletion.
36 changes: 35 additions & 1 deletion libcextract/FunctionDepsFinder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -627,7 +627,41 @@ void FunctionDependencyFinder::Remove_Redundant_Decls(void) {
SourceRange range = decl->getSourceRange();

const clang::Type *type = ClangCompat::getTypePtr(decl->getType());
TagDecl *typedecl = type->getAsTagDecl();
/* There are some cases where a variable is declared as follows:
static const struct mount_opts
{
int token;
int mount_opts;
int flags;
} ext4_mount_opts[] = {
{1, 1, 1}
};
in this case, the `ext4_mount_opts` array is declared together with its
type, thus resulting in Clang splitting this into two decls in its AST:
struct mount_opts
{
int token;
int mount_opts;
int flags;
};
static const struct ext4_mount_opts[] = {
{1, 1, 1}
};
but since we try to get what the user wrote, it results in two declarations
of `struct mount_opts`, thus clang-extract fails because of a redeclaration
error. But since `ext4_mount_opts` is an array, geting its type returns
an array type, not the struct declaration itself, hence check for this
case as well. */
if (type->isArrayType() || type->isPointerType()) {
type = type->getBaseElementTypeUnsafe();
}

TagDecl *typedecl = type ? type->getAsTagDecl() : nullptr;
if (typedecl && Closure.Is_Decl_Marked(typedecl)) {
SourceRange type_range = typedecl->getSourceRange();

Expand Down
18 changes: 18 additions & 0 deletions testsuite/small/record-4.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/* { dg-options "-DCE_EXTRACT_FUNCTIONS=f -DCE_NO_EXTERNALIZATION" }*/

static const struct mount_opts
{
int token;
int mount_opts;
int flags;
} ext4_mount_opts[] = {
{1, 1, 1}
};

int f(void)
{
return ext4_mount_opts[0].token;
}

/* { dg-final { scan-tree-dump "static const struct mount_opts\n{\n *int token;\n *int mount_opts;\n *int flags;\n} ext4_mount_opts\[\] = {\n *{1, 1, 1}\n};" } } */
/* { dg-final { scan-tree-dump "return ext4_mount_opts\[0\]\.token;" } } */

0 comments on commit 3027853

Please sign in to comment.