summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKim Gräsman <kim.grasman@gmail.com>2022-07-09 23:29:39 +0200
committerKim Gräsman <kim.grasman@gmail.com>2022-07-24 22:02:19 +0200
commitd2d4d15d8dcfebc388b07618ba3a9471223fc9d3 (patch)
treee79b271c21ddb578e9146f6b7535312cf9a2ebef
parent0f7a7aba8c949f97b579a4643367e9b9ffddf7c2 (diff)
Allow forward-declaration of elaborated types in type decls
This covers the common C pattern of declaring a typedef for a struct before the struct itself, e.g. typedef struct foo foo_t; struct foo { int value; foo_t *next; }; Fixes issue #1065.
-rw-r--r--iwyu.cc5
-rw-r--r--tests/c/elaborated_struct.c8
2 files changed, 13 insertions, 0 deletions
diff --git a/iwyu.cc b/iwyu.cc
index e3849cf..0147718 100644
--- a/iwyu.cc
+++ b/iwyu.cc
@@ -170,6 +170,7 @@ using clang::Decl;
using clang::DeclContext;
using clang::DeclRefExpr;
using clang::DeducedTemplateSpecializationType;
+using clang::ElaboratedType;
using clang::EnumConstantDecl;
using clang::EnumDecl;
using clang::EnumType;
@@ -2610,6 +2611,10 @@ class IwyuBaseAstVisitor : public BaseAstVisitor<Derived> {
}
parent_type = GetTypeOf(decl);
+ } else if (ast_node->IsA<ElaboratedType>()) {
+ // If it's not a ValueDecl, it must be a type decl. Elaborated types in
+ // type decls are forward-declarable.
+ return true;
}
}
diff --git a/tests/c/elaborated_struct.c b/tests/c/elaborated_struct.c
index 941ad69..5ef008c 100644
--- a/tests/c/elaborated_struct.c
+++ b/tests/c/elaborated_struct.c
@@ -28,6 +28,14 @@ int UseStruct(struct Struct* s);
struct ForwardDeclared;
void UseForwardDeclared(struct ForwardDeclared*);
+// If a forward-declaration is seen before an actual struct declaration in the
+// same file, no diagnostic is expected (see issue #1065).
+typedef struct local_struct local_struct_t;
+struct local_struct {
+ int x;
+ local_struct_t* next;
+};
+
/**** IWYU_SUMMARY
tests/c/elaborated_struct.c should add these lines: