From c69e9ff9bdd12bf3a728e9ad3d333adfa56a03c8 Mon Sep 17 00:00:00 2001 From: Giuliano Belinassi Date: Tue, 20 Aug 2024 16:20:26 -0300 Subject: [PATCH] Fix Late Externalization when variable is declared as macro expansion In the case where a variable is declared as a consequence of a macro expansion, as an example: ``` #include "lateext-7.h" DEFINE_STATIC_KEY_FALSE(aaa); ``` What happens is that when trying to get the FileID of `aaa` it returns the FileID for the include file rather than the main file. Hence make sure it gets the expansion location rather than the spelling location. Signed-off-by: Giuliano Belinassi --- libcextract/LLVMMisc.cpp | 19 +++++++++++++++++++ libcextract/LLVMMisc.hh | 6 ++++++ libcextract/SymbolExternalizer.cpp | 6 ++++-- testsuite/lateext/lateext-7.c | 13 +++++++++++++ testsuite/lateext/lateext-7.h | 13 +++++++++++++ 5 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 testsuite/lateext/lateext-7.c create mode 100644 testsuite/lateext/lateext-7.h diff --git a/libcextract/LLVMMisc.cpp b/libcextract/LLVMMisc.cpp index 86a52f4..9fff9f7 100644 --- a/libcextract/LLVMMisc.cpp +++ b/libcextract/LLVMMisc.cpp @@ -121,6 +121,25 @@ Decl *Get_Bodyless_Or_Itself(Decl *decl) return bodyless ? bodyless : decl; } +DeclaratorDecl *Get_With_Body(DeclaratorDecl *decl) +{ + if (FunctionDecl *fdecl = dyn_cast(decl)) { + return fdecl->getDefinition(); + } + + if (VarDecl *vdecl = dyn_cast(decl)) { + return vdecl->getDefinition(); + } + + return nullptr; +} + +DeclaratorDecl *Get_With_Body_Or_Itself(DeclaratorDecl *decl) +{ + DeclaratorDecl *with_body = Get_With_Body(decl); + return with_body ? with_body : decl; +} + /* Get the TopLevel Decl that contains the location loc. */ Decl *Get_Toplevel_Decl_At_Location(ASTUnit *ast, const SourceLocation &loc) { diff --git a/libcextract/LLVMMisc.hh b/libcextract/LLVMMisc.hh index 11bfe60..584abec 100644 --- a/libcextract/LLVMMisc.hh +++ b/libcextract/LLVMMisc.hh @@ -77,6 +77,12 @@ FunctionDecl *Get_Bodyless_Or_Itself(FunctionDecl *decl); TagDecl *Get_Bodyless_Or_Itself(TagDecl *decl); Decl *Get_Bodyless_Or_Itself(Decl *decl); +/** Get version of declarator with body. */ +DeclaratorDecl *Get_With_Body(DeclaratorDecl *decl); + +/** Get version of declarator with body or itself. */ +DeclaratorDecl *Get_With_Body_Or_Itself(DeclaratorDecl *decl); + /* Get the TopLevel Decl that contains the location loc. */ Decl *Get_Toplevel_Decl_At_Location(ASTUnit *ast, const SourceLocation &loc); diff --git a/libcextract/SymbolExternalizer.cpp b/libcextract/SymbolExternalizer.cpp index 4740ded..e91dc0e 100644 --- a/libcextract/SymbolExternalizer.cpp +++ b/libcextract/SymbolExternalizer.cpp @@ -977,9 +977,11 @@ void SymbolExternalizer::Late_Externalize(void) SE.Insert_Text(sym->LateInsertLocation, outstr.str()); /* In case the symbol is in the main file already, we must delete it. */ - SourceLocation loc = sm.getExpansionLoc(sym->OldDecl->getBeginLoc()); + DeclaratorDecl *old_decl = Get_With_Body_Or_Itself(sym->OldDecl); + + SourceLocation loc = sm.getExpansionLoc(old_decl->getBeginLoc()); if (sm.getFileID(loc) == sm.getMainFileID()) { - SE.Remove_Text(sym->OldDecl->getSourceRange(), 1000); + SE.Remove_Text(old_decl->getSourceRange(), 1000); } } else { /* Fallback to the old method of rewriting the declaration. */ diff --git a/testsuite/lateext/lateext-7.c b/testsuite/lateext/lateext-7.c new file mode 100644 index 0000000..5217fcb --- /dev/null +++ b/testsuite/lateext/lateext-7.c @@ -0,0 +1,13 @@ +/* { dg-options "-DCE_EXTRACT_FUNCTIONS=f -DCE_LATE_EXTERNALIZE -DCE_EXPORT_SYMBOLS=aaa -DCE_KEEP_INCLUDES" }*/ + +#include "lateext-7.h" + +DEFINE_STATIC_KEY_FALSE(aaa); + +int f(void) +{ + return aaa.key; +} + +/* { dg-final { scan-tree-dump-not "DEFINE_STATIC_KEY_FALSE\(\*klpe_aaa\)" } } */ +/* { dg-final { scan-tree-dump "static struct AA \*klpe_aaa;" } } */ diff --git a/testsuite/lateext/lateext-7.h b/testsuite/lateext/lateext-7.h new file mode 100644 index 0000000..47d75a3 --- /dev/null +++ b/testsuite/lateext/lateext-7.h @@ -0,0 +1,13 @@ +struct AA { + int key; +}; + +int g(void); + +extern struct AA aaa; + +#define STATIC_KEY_FALSE_INIT (struct AA){ .key = 0, } + +#define DEFINE_STATIC_KEY_FALSE(name) \ + struct AA name = STATIC_KEY_FALSE_INIT +