Skip to content

Commit

Permalink
FunctionDepsFinder: Check for declarations inside another declaration
Browse files Browse the repository at this point in the history
Closes: #44

Signed-off-by: Marcos Paulo de Souza <[email protected]>
  • Loading branch information
marcosps authored and giulianobelinassi committed Jun 14, 2024
1 parent 2b0f58d commit 0925bdb
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 0 deletions.
28 changes: 28 additions & 0 deletions libcextract/FunctionDepsFinder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,34 @@ void FunctionDependencyFinder::Remove_Redundant_Decls(void) {
}
}
}

/*
* Check if there wasn't any symbol that is being defined in the same
* interval and remove it. Otherwise we might clash the types.
*
* One example of how this can happen is then we have something like
*
* typedef struct {
* ...
* } x, y;
*
* In the process of creating the closure we might reach the following
* situation:
*
* typdef struct {
* ...
* } x;
*
* typedef struct {
*
* } x, y;
*
* Which then breaks the one-definition-rule. In such cases, remove the
* previous declaration in the same code range, since the later will
* contain both definitions either way.
*/
if (Decl *range_decl = Closure.insideRangeOfDecl(decl))
Closure.Remove_Decl(range_decl);
}
}
/* Handle the case where an enum is declared as:
Expand Down
25 changes: 25 additions & 0 deletions libcextract/FunctionDepsFinder.hh
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,31 @@ class ClosureSet
Dependencies.insert(decl);
}

/*
* Check if the same Decl was already added into the closure but for a
* different typename.
*/
Decl *insideRangeOfDecl(Decl *decl)
{
SourceRange range = decl->getSourceRange();

/* FIXME: optimize this loop */
for (auto it = Dependencies.begin(); it != Dependencies.end(); ++it) {
if (TypedefDecl *cur_decl = dyn_cast<TypedefDecl>(*it)) {
SourceRange cur_range = cur_decl->getSourceRange();

// Avoid comparing to itself
if (cur_range == range)
continue;

if (PrettyPrint::Contains_From_LineCol(range, cur_range))
return cur_decl;
}
}

return nullptr;
}

inline std::unordered_set<Decl *> &Get_Set(void)
{
return Dependencies;
Expand Down
19 changes: 19 additions & 0 deletions testsuite/linux/typedef-1.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/* { dg-options "-DCE_EXTRACT_FUNCTIONS=f" } */

typedef struct {
int id;
int val;
} st1, st2;

int f(void)
{
st1 s1;
st2 s2;

s1.id = 10;
s2.val = 5;
}
/* { dg-final { scan-tree-dump "int f\(void\)" } } */
/* { dg-final { scan-tree-dump "} st1, st2;" } } */
/* { dg-final { scan-tree-dump-not "} st1;" } } */
/* { dg-final { scan-tree-dump-not "} st2;" } } */

0 comments on commit 0925bdb

Please sign in to comment.