diff --git a/libcextract/PrettyPrint.cpp b/libcextract/PrettyPrint.cpp index 20f4b1e..b69943b 100644 --- a/libcextract/PrettyPrint.cpp +++ b/libcextract/PrettyPrint.cpp @@ -390,6 +390,19 @@ SourceLocation PrettyPrint::Get_Expanded_Loc(Decl *decl) } } } + + /* In case this decl is a TypedefNameDecl, we also need to check for the + struct definition for extra attributes. See small/attr-10.c testscase + for an example where this happens. */ + if (TypedefNameDecl *typedecl = dyn_cast(decl)) { + if (TagDecl *tag = typedecl->getAnonDeclWithTypedefName()) { + SourceLocation tag_furthest = PrettyPrint::Get_Expanded_Loc(tag); + if (Is_Before(furthest, tag_furthest)) { + furthest = tag_furthest; + } + } + } + return furthest; } diff --git a/testsuite/small/attr-10.c b/testsuite/small/attr-10.c new file mode 100644 index 0000000..2073b75 --- /dev/null +++ b/testsuite/small/attr-10.c @@ -0,0 +1,29 @@ +/* { dg-options "-DCE_EXTRACT_FUNCTIONS=main -DCE_NO_EXTERNALIZATION" }*/ + +typedef unsigned short int sa_family_t; +typedef unsigned int __socklen_t; +typedef __socklen_t socklen_t; +typedef int ares_socket_t; +typedef socklen_t ares_socklen_t; + +struct sockaddr { + sa_family_t sa_family; + char sa_data[14]; +}; + +typedef union { + struct sockaddr *__restrict __sockaddr__; +} __SOCKADDR_ARG __attribute__((__transparent_union__)); + +extern int getsockname(int __fd, __SOCKADDR_ARG __addr, + socklen_t *__restrict __len) + __attribute__((__nothrow__)); + +int main(void) { + struct sockaddr *src_addr; + ares_socket_t sock; + ares_socklen_t len; + getsockname(sock, src_addr, &len); +} + +/* { dg-final { scan-tree-dump "__attribute__\(\(__transparent_union__\)\)" } } */