It depends whether this is Objective C or Objective C++.
In C++, we take advantage of the ODR, which allows us to assume that those
two 'struct Foo's are defining the same struct. We mostly make it look like
one of the declarations was never a definition (so that AST consumers don't
need to treat this as a special case), but in practice you can infer
whether the declaration was once a definition by checking whether its decl
context lexically contains any declarations (it just so happens that a
current or former definition will always contain at least an injected class
name decl, and a "pure" declaration will always be empty).
In C, there is no ODR, and the same struct name is permitted to have
different definitions in different translation units in the same program.
What we /should/ do is to keep decl chains for types from distinct modules
separate, and implement C's "compatible type" structural typing rules to
determine whether two 'Foo's can be used interchangeably. What we
/actually/ do is to form a single redeclaration chain containing all the
definitions, all of which think they are still "the" definition, and each
use of the type will pick a semi-arbitrary definition. This case is easy
for you: just ask the decl whether it's a complete definition (but I'm
guessing you're in Objective C++ mode since you said that checking
IsCompleteDefinition isn't working).