Skip to content

Commit cd62a5c

Browse files
Fix corner case where struct attributes are declared from #include
The `struct link_map` definition of glibc includes an header which must be expanded for correct output. This is an corner-case which was already acknowledged for enums, hence expand and refactor the logic to TagDecls. Signed-off-by: Giuliano Belinassi <gbelinassi@suse.de>
1 parent 8fa99e9 commit cd62a5c

File tree

10 files changed

+62
-24
lines changed

10 files changed

+62
-24
lines changed

libcextract/ArgvParser.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ static const char *UnsupportedGCCArgs[] = {
5858
"-Wno-stringop-truncation",
5959
"-Werror=designated-init",
6060
"-Wimplicit-fallthrough=",
61+
"-Wendif-labels",
62+
"-Wmissing-selector-name",
6163
};
6264

6365
ArgvParser::ArgvParser(int argc, char **argv)

libcextract/PrettyPrint.cpp

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,13 @@
2020
#include "LLVMMisc.hh"
2121

2222
#include <clang/AST/Attr.h>
23+
#include <llvm/Support/Regex.h>
2324

2425
/** Public methods. */
2526

2627
#define Out (*Out)
2728

28-
void PrettyPrint::Print_Decl(Decl *decl)
29+
void PrettyPrint::Print_Decl(Decl *decl, bool keep_includes)
2930
{
3031
/* When handling C code, we need to check if given declaration is a function
3132
with body. If yes, we can simply print the declaration, but otherwise
@@ -38,22 +39,22 @@ void PrettyPrint::Print_Decl(Decl *decl)
3839
if (f && f->hasBody() && f->isThisDeclarationADefinition()) {
3940
Print_Decl_Raw(f);
4041
Out << "\n\n";
41-
} else if (e) {
42-
decl->print(Out, PPolicy);
43-
Out << ";\n\n";
4442
} else if (!e && t && t->getName() == "") {
4543
/* If the RecordType doesn't have a name, then don't print it. Except when
4644
it is an empty named enum declaration, which in this case we must print
4745
because it contains declared constants. */
4846
} else {
49-
/* Structs and prototypes */
47+
/* Structs, enums, and prototypes */
5048

51-
/** Check if we can get a partial declaration of `decl` rather than a full
52-
declaration. */
53-
bool full_def_removed = false;
54-
if (t && t->isCompleteDefinitionRequired() == false) {
55-
/* We don't need the full defintion. Hide the body for Print_Decl_Raw. */
56-
t->setCompleteDefinition(false);
49+
/** Check if the output string has an include directive. In that case, if we
50+
don't want to keep the includes, we must print the ast dump rather than
51+
the source text to get rid of the #include directive.
52+
FIXME: regexes are slow. */
53+
static llvm::Regex regex("# *include *(<|\")");
54+
55+
/* FIXME: Why isCompleteDefinitionRequired does not work for EnumDecls? */
56+
if (t && ((!e && t->isCompleteDefinitionRequired() == false)
57+
|| (!keep_includes && regex.match(Get_Source_Text(t->getSourceRange()))))) {
5758

5859
/* FIXME: The Print_Decl_Raw class will attempt to write this declaration
5960
as the user wrote, that means WITH a body. To avoid this, we set
@@ -63,7 +64,15 @@ void PrettyPrint::Print_Decl(Decl *decl)
6364
correct way of doing this would be update the source location to
6465
the correct range. */
6566
t->setLocStart(t->getEndLoc());
67+
}
6668

69+
/** Check if we can get a partial declaration of `decl` rather than a full
70+
declaration. */
71+
bool full_def_removed = false;
72+
/* FIXME: Why isCompleteDefinitionRequired does not work for EnumDecls? */
73+
if (t && !e && t->isCompleteDefinitionRequired() == false) {
74+
/* We don't need the full defintion. Hide the body for Print_Decl_Raw. */
75+
t->setCompleteDefinition(false);
6776
full_def_removed = true;
6877
}
6978

@@ -613,7 +622,7 @@ void RecursivePrint::Print_Decl(Decl *decl)
613622
PrettyPrint::Print_RawComment(sm, comment);
614623
}
615624
}
616-
PrettyPrint::Print_Decl(decl);
625+
PrettyPrint::Print_Decl(decl, KeepIncludes);
617626
}
618627
}
619628

@@ -656,13 +665,7 @@ void RecursivePrint::Print(void)
656665
decl = (*ASTIterator).AsDecl;
657666
Print_Decl(decl);
658667
++ASTIterator;
659-
660-
/* Skip to the end of the Declaration. */
661-
if (!dyn_cast<EnumDecl>(decl)) {
662-
/* EnumDecls are handled somewhat differently: we dump the AST, not
663-
what the user wrote. */
664-
ASTIterator.Skip_Until(decl->getEndLoc());
665-
}
668+
ASTIterator.Skip_Until(decl->getEndLoc());
666669
break;
667670

668671
case TopLevelASTIterator::ReturnType::TYPE_PREPROCESSED_ENTITY:

libcextract/PrettyPrint.hh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class PrettyPrint
3838
{
3939
public:
4040
/** Print a Decl node into ostream `Out`. */
41-
static void Print_Decl(Decl *decl);
41+
static void Print_Decl(Decl *decl, bool keep_includes = false);
4242

4343
/** Print Decl node as is, without any kind of processing. */
4444
static void Print_Decl_Raw(Decl *decl);

testsuite/small/enum-11.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/* { dg-options "-DCE_EXTRACT_FUNCTIONS=f -DCE_NO_EXTERNALIZATION" }*/
2+
3+
enum consts {
4+
CST0 = 0,
5+
CST1,
6+
#include "enums.h"
7+
};
8+
9+
enum consts f(void)
10+
{
11+
return CST2;
12+
}
13+
14+
/* { dg-final { scan-tree-dump "CST2," } } */

testsuite/small/enum-6.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,4 @@ int f()
1616

1717
/* { dg-final { scan-tree-dump "ANOTHER_CONST = 1 << CONST0" } } */
1818
/* { dg-final { scan-tree-dump "return ANOTHER_CONST;" } } */
19-
/* { dg-final { scan-tree-dump "enum *{\n *CONST0" } } */
19+
/* { dg-final { scan-tree-dump "enum\n? *{\n? *CONST0" } } */

testsuite/small/enum-8.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,6 @@ int f() {
3232
}
3333

3434
/* { dg-final { scan-tree-dump "TRACE_EVENT_FL_TRACEPOINT_BIT," } } */
35-
/* { dg-final { scan-tree-dump "TRACE_EVENT_FL_TRACEPOINT *= \(1 << TRACE_EVENT_FL_TRACEPOINT_BIT\)," } } */
35+
/* { dg-final { scan-tree-dump "TRACE_EVENT_FL_TRACEPOINT( |\t)*= \(1 << TRACE_EVENT_FL_TRACEPOINT_BIT\)," } } */
3636
/* { dg-final { scan-tree-dump "#define MACRO TRACE_EVENT_FL_TRACEPOINT" } } */
3737
/* { dg-final { scan-tree-dump "return 1 \+ MACRO;" } } */

testsuite/small/enums.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
CST2,
2+
CST3,

testsuite/small/fields.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
int field2;
2+
int field3;

testsuite/small/record-12.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/* { dg-options "-DCE_EXTRACT_FUNCTIONS=f -DCE_NO_EXTERNALIZATION" }*/
2+
3+
struct record {
4+
int field1;
5+
# include "fields.h"
6+
int field4;
7+
};
8+
9+
int f(struct record *r)
10+
{
11+
return r->field2;
12+
}
13+
14+
/* { dg-final { scan-tree-dump "struct record {" } } */
15+
/* { dg-final { scan-tree-dump "int field2;" } } */

testsuite/small/typedef-6.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ int f(struct A *a) {
2121
return a->y;
2222
}
2323

24-
/* { dg-final { scan-tree-dump "enum CONSTANT {\n *CONST1,\n *CONST2\n};" } } */
25-
/* { dg-final { scan-tree-dump "enum CONSTANT2 {\n *AAAA,\n *BBBB\n};" } } */
24+
/* { dg-final { scan-tree-dump "enum CONSTANT {\n *CONST1,\n *CONST2,?\n};" } } */
25+
/* { dg-final { scan-tree-dump "enum CONSTANT2 {\n *AAAA,\n *BBBB,?\n};" } } */
2626
/* { dg-final { scan-tree-dump "typedef int \(\*GEN_SESSION_CB\)\(enum CONSTANT \*, enum CONSTANT2 \*\);" } } */
2727
/* { dg-final { scan-tree-dump "struct A {\n *GEN_SESSION_CB a;\n *int y;\n};" } } */
2828
/* { dg-final { scan-tree-dump "int f" } } */

0 commit comments

Comments
 (0)