[cfe-dev] [ASTImporter][CrossTU] inconsistent enumerators
Rafael·Stahl via cfe-dev
cfe-dev at lists.llvm.org
Mon Nov 13 03:16:54 PST 2017
Deal all
While using the static analyzer with cross translation unit support (
https://reviews.llvm.org/D30691 ), I stumbled upon an issue that is most
likely related to the ASTImporter.
I'm using a custom checker, but this should be reproduced by just
running the scan-build tool.
A simple reproducing example:
main.c:
---------------------------------------
void foo();
void moo();
int main()
{
foo();
moo();
}
---------------------------------------
foo.c:
---------------------------------------
#include "thing.h"
void foo()
{
(void)THING_VALUE;
}
void conflict(thing_t type)
{
}
---------------------------------------
moo.c:
---------------------------------------
#include "thing.h"
void moo()
{
conflict(THING_VALUE);
}
---------------------------------------
thing.h:
---------------------------------------
typedef enum {
THING_VALUE
} thing_t;
void conflict(thing_t type);
---------------------------------------
Notes on particularities of this example:
- main.c needs to NOT include the header
- main() needs to call the functions in this order
- foo() needs to reference the enumerator
- the enum needs to be typedef'd
If any of the above points do not apply, the issue does not appear.
The issue:
---------------------------------------
In file included from moo.c:1:
thing.h:1:9: warning: type 'thing_t' has incompatible
definitions in different translation units [-Wodr]
typedef enum {
^
thing.h:2:5: note: enumerator 'THING_VALUE' with value 0 here
THING_VALUE
^
thing.h:1:9: note: no corresponding enumerator here
foo.c:8:6: error: external function 'conflict' declared
with incompatible types in different translation units ('void
(thing_t)' vs. 'void (thing_t)')
void conflict(thing_t type)
^
thing.h:5:6: note: declared here with type
'void (thing_t)'
void conflict(thing_t type);
^
---------------------------------------
After importing conflict(thing_t) the ASTImporter compared the imported
one with the original by structural equivalence. This reveals that in
the imported enum the enumerators are missing, causing the above error.
In my real code, not this example, I was unable to dump the imported
EnumDecl, because it eventually calls
SourceManager::isBeforeInTranslationUnit with two SourceLocations from
different files. Not sure if this is related.
I have tried adding:
for (const auto Enumerator : D->enumerators())
D2->addDecl(Importer.Import(Enumerator));
before completing the definition in ASTNodeImporter::VisitEnumDecl(),
but that results in:
exe: tools/clang/lib/AST/DeclBase.cpp:1374: void
clang::DeclContext::addHiddenDecl(clang::Decl*): Assertion
`!D->getNextDeclInContext() && D != LastDecl && "Decl already inserted
into a DeclContext"' failed.
I'm not familiar enough with the ASTImporter to help myself further
here. Does anyone know what could be the issue?
Best regards
Rafael Stahl
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 5449 bytes
Desc: S/MIME Cryptographic Signature
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20171113/4b2352e8/attachment.bin>
More information about the cfe-dev
mailing list