Skip to content

Commit

Permalink
Extend parent RecordDecl analysis for EnumDecls
Browse files Browse the repository at this point in the history
If the current declaration is a EnumDecl and it is inside a nested
struct we also fall in the case we need to output the parent RecordDecl
as well.

Signed-off-by: Giuliano Belinassi <[email protected]>
  • Loading branch information
giulianobelinassi committed Jul 20, 2024
1 parent 57e013e commit cebcb26
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 18 deletions.
42 changes: 24 additions & 18 deletions libcextract/Closure.hh
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,25 @@ class DeclClosureVisitor : public RecursiveASTVisitor<DeclClosureVisitor>
return VISITOR_CONTINUE;
}

bool ParentRecordDeclHelper(TagDecl *decl)
{
/* In case this references a struct/union defined inside a struct (nested
struct), then we also need to analyze the parent struct. */
RecordDecl *parent = dyn_cast<RecordDecl>(decl->getLexicalDeclContext());
if (parent) {
/* If the parent struct is flagged as not needing a complete definition
then we need to set it to true, else the nested struct won't be
output as of only a partial definition of the parent struct is
output. */
parent->setCompleteDefinitionRequired(true);

/* Analyze parent struct. */
TRY_TO(TraverseDecl(parent));
}

return VISITOR_CONTINUE;
}

bool VisitRecordDecl(RecordDecl *decl)
{
/* If this is a C++ record decl, then analyze it as such. */
Expand All @@ -253,24 +272,11 @@ class DeclClosureVisitor : public RecursiveASTVisitor<DeclClosureVisitor>
typedef struct { int a; } A; */
return VisitTypedefNameDecl(typedecl);
} else {
/* In case this references a struct/union defined inside a struct (nested
struct), then we also need to analyze the parent struct. */
RecordDecl *parent = dyn_cast<RecordDecl>(decl->getLexicalDeclContext());
if (parent) {
/* If the parent struct is flagged as not needing a complete definition
then we need to set it to true, else the nested struct won't be
output as of only a partial definition of the parent struct is
output. */
parent->setCompleteDefinitionRequired(true);

/* Analyze parent struct. */
TRY_TO(TraverseDecl(parent));
}

Closure.Add_Decl_And_Prevs(decl);
}

TRY_TO(ParentRecordDeclHelper(decl));
Closure.Add_Decl_And_Prevs(decl);

return VISITOR_CONTINUE;
}

Expand All @@ -287,10 +293,10 @@ class DeclClosureVisitor : public RecursiveASTVisitor<DeclClosureVisitor>
typedef enum { CONSTANT = 1 } A; */
return VisitTypedefNameDecl(typedecl);
} else {
Closure.Add_Decl_And_Prevs(decl);
}

TRY_TO(ParentRecordDeclHelper(decl));
Closure.Add_Decl_And_Prevs(decl);
return VISITOR_CONTINUE;
}

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

extern int strncasecmp (const char *__s1, const char *__s2, unsigned long __n)
__attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2)));

extern unsigned long strlen (const char *__s)
__attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1)));

struct config {
enum sched_prio {
SCHED_ERR = -1,
SCHED_HIGH,
SCHED_DEFAULT,
SCHED_LOW
} prio;
unsigned int verbose;
};

/** clang-extract: from source.c:1511:1 */
enum sched_prio f(const char *str)
{
if (strncasecmp("high", str, strlen(str)) == 0)
return SCHED_HIGH;
else if (strncasecmp("default", str, strlen(str)) == 0)
return SCHED_DEFAULT;
else if (strncasecmp("low", str, strlen(str)) == 0)
return SCHED_LOW;
else
return SCHED_ERR;
}

/* { dg-final { scan-tree-dump "struct config *{" } } */
/* { dg-final { scan-tree-dump " *enum sched_prio *{" } } */

0 comments on commit cebcb26

Please sign in to comment.