This is an archive of the discontinued LLVM Phabricator instance.

[ASTImporter] Fix import of unnamed structs
ClosedPublic

Authored by martong on Jul 13 2018, 7:53 AM.

Details

Summary

D48773 simplified ASTImporter nicely, but it introduced a new error: Unnamed
structs are not imported correctly, if they appear in a recursive context.
This patch provides a fix for structural equivalency.

Diff Detail

Repository
rL LLVM

Event Timeline

martong created this revision.Jul 13 2018, 7:53 AM

Hi Gabor,
The change is OK but I have some questions regarding tests.

unittests/AST/ASTImporterTest.cpp
2495 ↗(On Diff #155386)

There is already a similar lambda definitions for getRecordDecl() in ObjectsWithUnnamedStructType test. Can we make it a function, like it is done for StructuralEquivalenceContext?

unittests/AST/StructuralEquivalenceTest.cpp
581 ↗(On Diff #155386)

Do we really want to test the equivalence of decl to itself, not to its imported version?

balazske added inline comments.Jul 16 2018, 12:06 AM
lib/AST/ASTStructuralEquivalence.cpp
913 ↗(On Diff #155386)

The problem was that value of isAnonymousStructOrUnion is not (or not yet) set correctly during the import? But getDeclName is always correct (if it is a false the record is anonymous struct)?

unittests/AST/StructuralEquivalenceTest.cpp
486 ↗(On Diff #155386)

RecordDecl *

578 ↗(On Diff #155386)

Is it possible at all that getRecordDecl returns nullptr? It uses cast (nor cast_or_null and not dyn_cast).

581 ↗(On Diff #155386)

I think this is correct: R0 should be equivalent with itself but not with R1.

martong updated this revision to Diff 155660.Jul 16 2018, 6:21 AM
martong marked 6 inline comments as done.

Address review comments

martong added inline comments.Jul 16 2018, 6:21 AM
lib/AST/ASTStructuralEquivalence.cpp
913 ↗(On Diff #155386)

There is a strange thing here: A struct without a name is not necessarily an anonymous struct!
For example the RecordDecl in struct { int i; float f; } obj; is not anonymous.
See the docs for RecordDecl::isAnonymousStructOrUnion:

/// Whether this is an anonymous struct or union. To be an anonymous
/// struct or union, it must have been declared without a name and
/// there must be no objects of this type declared, e.g.,
/// @code
///   union { int i; float f; };
/// @endcode
/// is an anonymous union but neither of the following are:
/// @code
///  union X { int i; float f; };
///  union { int i; float f; } obj;
/// @endcode
bool isAnonymousStructOrUnion() const { return AnonymousStructOrUnion; }

This might seem very perplexed, but this is aligned with the C++17 Standard:

12.3.1 Anonymous unions
para 3. A union for which objects, pointers, or references are declared is not an anonymous union.

Consequently, we should check whether the Decl has a name, isAnonymousStructOrUnion is misleading here.

unittests/AST/ASTImporterTest.cpp
2495 ↗(On Diff #155386)

OK, I added a new function template to handle both cases.

unittests/AST/StructuralEquivalenceTest.cpp
578 ↗(On Diff #155386)

Yes, good catch, changed it.

581 ↗(On Diff #155386)

I think it makes sense, because from the StructuralEquivalence's viewpoint there is no imported version, just two Decls/Types which may or may not have the same ASTContext.

martong updated this revision to Diff 155678.Jul 16 2018, 7:43 AM

RecordDecl* -> RecordDecl *

a_sidorin accepted this revision.Jul 16 2018, 3:51 PM

Thank you Gabor!

This revision is now accepted and ready to land.Jul 16 2018, 3:51 PM
balazske added inline comments.Jul 17 2018, 12:58 AM
unittests/AST/StructuralEquivalenceTest.cpp
615 ↗(On Diff #155678)

These asserts can be removed too.

martong updated this revision to Diff 155835.Jul 17 2018, 3:13 AM
martong marked an inline comment as done.

Remove unneeded assert

This revision was automatically updated to reflect the committed changes.