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.
Import of Attr objects was incomplete in ASTImporter.
Thanks, nice work! I like the direction, however, I'd like to ask comments from @teemperor .
What's the reason of moving this hunk?
Why can't we use importChecked here?
Could you please remove this comment?
Could we hide these arguments?
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?
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.
This is moved into the public section. Other such functions are public already.
For Identifier* no error is possible and importChecked does not work (could be added to have uniform code).
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.)
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.
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.
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?
Please fix this.
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.
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>);
I think you should be consistently using typename or class. I'm generally in favor of using typename though.
So, this accepts universal references, shouldn't we std::forward when we consume them?
Why don't you initialize the variables directly? Same for the other variables. This way they could be const as well.
What about having two implementations. One for any T that has args() and one for anything else and using SFINAE choosing the right one.
Internally it could do the AI.importArrayArg(From->args(), From->args_size()).value() for the args() case.
Should we dump to the stderr?
An iterator range is just a pair of iterators, am I right?
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.
Fixed review issues.
Added code comments.
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.
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.
Here the first parameter is really a class, the second not.
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.
Probably enough to pass by value but this should be not worse than that.
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.