Skip to content

Commit

Permalink
Fix redeclaration of RecordDecl in Records defined in array variables
Browse files Browse the repository at this point in the history
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.

Signed-off-by: Giuliano Belinassi <[email protected]>
  • Loading branch information
giulianobelinassi committed Mar 12, 2024
1 parent 8bd3545 commit 84a76ab
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 84a76ab

Please sign in to comment.