This is an archive of the discontinued LLVM Phabricator instance.

[clang][ASTImporter] Generic attribute import handling (first step).
ClosedPublic

Authored by balazske on Sep 10 2021, 9:04 AM.

Details

Summary

Import of Attr objects was incomplete in ASTImporter.
This change introduces support for a generic way of importing an attribute.
For an usage example import of the attribute AssertCapability is
added to ASTImporter.
Updating the old attribute import code and adding new attributes or extending
the generic functions (if needed) is future work.

Diff Detail

Event Timeline

balazske created this revision.Sep 10 2021, 9:04 AM
balazske requested review of this revision.Sep 10 2021, 9:04 AM
Herald added a project: Restricted Project. · View Herald TranscriptSep 10 2021, 9:04 AM
Herald added a subscriber: cfe-commits. · View Herald Transcript

Thanks, nice work! I like the direction, however, I'd like to ask comments from @teemperor .

clang/lib/AST/ASTImporter.cpp
656–671

What's the reason of moving this hunk?

8468–8469

Why can't we use importChecked here?

8480–8481

Could you please remove this comment?

8569–8570

Could we hide these arguments?
I mean we probably need a higher abstraction, something like

Expected<Attr *> ToAttrOrErr = AI.createImportedAttr(From);

should be sufficient, isn't it. We do want to import all arguments of all kind of attributes, don't we?

shafik added inline comments.Sep 13 2021, 9:48 AM
clang/lib/AST/ASTImporter.cpp
711

Looks like left over unused code?

8443

@martong the ASTImporter file is quite large as it is and I think it makes sense to have AttrImporter but perhaps it would help long-term maintainability to split it out into its own source file? What do you think?

martong added inline comments.Sep 13 2021, 11:44 AM
clang/lib/AST/ASTImporter.cpp
8443

Yes, good idea, I agree. Although, I wouldn't insist to do that in this patch, a following patch is okay for me.

After all, it would make sense to split ASTNodeImporter into it's own implementation file. Or, even better, we could put Visit*Type, Visit*Decl and Visit*Stmt into separate files. Other than that, the ASTImporterTest.cpp test file compiles painfully slow, so that is among my TODOs for a while to split that up as well.

balazske added inline comments.Sep 14 2021, 2:44 AM
clang/lib/AST/ASTImporter.cpp
656–671

This is moved into the public section. Other such functions are public already.

8468–8469

For Identifier* no error is possible and importChecked does not work (could be added to have uniform code).

8569–8570

It should be possible to pass every kind of needed arguments (after it is imported) to the constructor of the newly created Attr object. The problem is solved here by the AttrArgImporter that imports the object and can store it in a temporary value until it is passed to the constructor. The temporary value is important if an array is imported. To import the array the size must be passed to the array importer before, and the size must be passed to the constructor of the Attr too, therefore it exists 2 times in the code. An AttrArgImporter can provide only one value to the constructor of the new Attr object. (Probably other solution is possible with std::tuple and std::apply but not sure if it is better.)

martong added a subscriber: steakhal.

@steakhal, could you please take a look?

I like the adapter layer idea. However, I agree with @martong that it should be more 'abstract' ~ terse.
It's remarkable how compact the test is. Good job.

clang/lib/AST/ASTImporter.cpp
8412–8413

What about the rest of the special member functions like assignment operators?

All the rest of the code mentions this template parameter using the AT name. Could you please consolidate this? It would make it more readable.

8420

So, the value() sometimes returns const ref, and other times it returns a mutable raw pointer...

I suspect, attribute constructors expect simple reference arguments and pointers for lists. And this is why it behaves like this. Am I right about this?

8434

Please fix this.

8455–8457

The name AT suggests to me that you expect the template type parameter to be a subtype of class Attr. However, I suspect it's not always the case.
For example in case of the OwnershipAttr the args() returns a sequence of ParamIdx* objects. So, in that sense, the AT name is not properly justified.

Restricting template parameter types makes the code cleaner, so I would suggest introducing a metafunction, that you could use in a static_assert that you could use to check this requirement as the first instruction in the function.

template <typename T>
constexpr static bool AttrOrParamIdx = std::is_base_of<Attr, T>::value || std::is_same_v<T, ParamIdx>;

static_assert(AttrOrParamIdx<T>);
8461

I think you should be consistently using typename or class. I'm generally in favor of using typename though.

8462

So, this accepts universal references, shouldn't we std::forward when we consume them?
If not, why do you use && ?

8468–8469

Why don't you initialize the variables directly? Same for the other variables. This way they could be const as well.

8569–8570

What about having two implementations. One for any T that has args() and one for anything else and using SFINAE choosing the right one.
In this context, we should have the appropriate dynamic type, so by using template type deduction on From could achieve this dispatch.

Internally it could do the AI.importArrayArg(From->args(), From->args_size()).value() for the args() case.
WDYT?

clang/unittests/AST/ASTImporterTest.cpp
6414

Should we dump to the stderr?

6442–6443

<3 More!

6467–6468

An iterator range is just a pair of iterators, am I right?
We could still pass them by value.

6549–6551

You could probably use the regular "void test(int A1, int A2) __attribute__((assert_capability(A1, A2)));" string literal. It would still fit in the line and would consume only a single line.

balazske updated this revision to Diff 373525.Sep 20 2021, 2:22 AM
balazske marked 9 inline comments as done.

Fixed review issues.
Added code comments.

clang/lib/AST/ASTImporter.cpp
8420

The data returned by value is the one that is passed to the attribute constructor. It is in exact the same form, and for arrays this is a simple pointer to the array data. The array in the attribute has a size parameter too, this can be passed separately from this object.

One such "importer" is created for every attribute argument even if it is of an array type. For the array size no such object has to be created, only for the array data.

8455–8457

In this case AT is the element type of the array attribute argument, mostly Expr * but can be any other. The AT should mean "Argument Type". Now is is renamed to T because it is the only parameter, and every other place T is used too. I think it is not needed to make a static assert for every possible attribute argument type. The class can be still used incorrectly and theoretically attribute argument can be of any type, so the assert adds not much value.

8461

Here the first parameter is really a class, the second not.

8569–8570

Probably we can have a specialization for exactly the case when the attribute has one parameter called "Args" that is of an array type. We need to check at how many attributes this is the case, probably it is only used at the thread safety part (relatively) many times.

clang/unittests/AST/ASTImporterTest.cpp
6467–6468

Probably enough to pass by value but this should be not worse than that.

balazske added inline comments.Sep 20 2021, 2:30 AM
clang/unittests/AST/ASTImporterTest.cpp
6414

It would be good to have a "sink stream" that just discards the input. In this case it is not needed to allocate memory buffer, the text output of the dump is not used. ASTImporterTest has already many unneeded output.

steakhal accepted this revision.Sep 20 2021, 2:58 AM

I think I'm convinced.
Thanks.

clang/unittests/AST/ASTImporterTest.cpp
6414

llvm::nulls() returns such a stream.

This revision is now accepted and ready to land.Sep 20 2021, 2:58 AM
martong accepted this revision.Sep 21 2021, 2:24 AM

Look good! Thanks!

balazske updated this revision to Diff 373922.Sep 21 2021, 7:26 AM

Dump to 'llvm::nulls()'.

steakhal accepted this revision.Sep 21 2021, 7:48 AM
This revision was landed with ongoing or failed builds.Sep 22 2021, 1:00 AM
This revision was automatically updated to reflect the committed changes.