Skip to content

Commit

Permalink
FunctionDepsFinder: Improve performance of duplicated typedef removal
Browse files Browse the repository at this point in the history
This change reduced the time to finishe running clang-extract from ~13
seconds to ~9 seconds in a specific use symbol being extracted.

Signed-off-by: Marcos Paulo de Souza <[email protected]>
  • Loading branch information
marcosps committed Jun 17, 2024
1 parent d48d476 commit 4f20de9
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 53 deletions.
81 changes: 53 additions & 28 deletions libcextract/FunctionDepsFinder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -623,34 +623,6 @@ 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 Expand Up @@ -725,6 +697,59 @@ void FunctionDependencyFinder::Remove_Redundant_Decls(void) {
}
}
}

// FIXME: use interval tree
ASTUnit::top_level_iterator it;
TypedefDecl *prev = nullptr;
for (it = AST->top_level_begin(); it != AST->top_level_end(); ++it) {
if (TypedefDecl *decl = dyn_cast<TypedefDecl>(*it)) {
if (!Closure.Is_Decl_Marked(decl))
continue;

// Set prev and exit, since we don't have anything to compare agains't
if (!prev) {
prev = decl;
continue;
}

/*
* 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 (PrettyPrint::Contains_From_LineCol(decl->getSourceRange(),
prev->getSourceRange())) {
/*
* If the prev and the current decl have the same start LoC, but
* different ending, remove the prev from the closure and set the
* new prev.
*/
Closure.Remove_Decl(prev);
}

prev = decl;
}
}
}

void FunctionDependencyFinder::Insert_Decls_From_Non_Expanded_Includes(void)
Expand Down
25 changes: 0 additions & 25 deletions libcextract/FunctionDepsFinder.hh
Original file line number Diff line number Diff line change
Expand Up @@ -43,31 +43,6 @@ 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

0 comments on commit 4f20de9

Please sign in to comment.