[cfe-dev] Working with ConceptClang: Binding input arguments to functions.

Larisse Voufo lvoufo at cs.indiana.edu
Mon Apr 25 18:57:59 PDT 2011


Issue resolved.

It turns out that my mistake was in the way I was (1) copying the
implementation of associated functions over from concept definitions to
their concept maps, and then (2) instantiating that concept map's
implementation.
Basically, after substituting the types on the associated function, since
the instantiation was treating the function itself as its own "pattern", I
should have been substituting the types on the function's body as well
somehow...
But this did not look like a very trivial move...

On the other hand, it was much easier to (1) keep records of the original
implementations of those associated functions, before type substitution, and
then (2) to treat those original implementations as the "patterns" needed
during instantiation...

Anyway, I hope this makes sense somehow. But I did make these changes, and
everything works perfectly! :)

Thanks for the help!

-- Larisse.



On Fri, Apr 22, 2011 at 12:57 PM, Larisse Voufo <lvoufo at cs.indiana.edu>wrote:

>
>
> On Fri, Apr 22, 2011 at 12:38 PM, Douglas Gregor <dgregor at apple.com>wrote:
>
>>
>> On Apr 22, 2011, at 9:27 AM, Larisse Voufo wrote:
>>
>>
>>
>> On Fri, Apr 22, 2011 at 11:51 AM, Douglas Gregor <dgregor at apple.com>wrote:
>>
>>>
>>> On Apr 22, 2011, at 2:05 AM, Larisse Voufo wrote:
>>>
>>> Here's a basic example I've been trying to get to work:
>>>
>>> explicit concept A<typename T> {
>>>     typename AType;
>>>
>>>     AType h(AType a) {
>>>         return a;
>>>     }
>>>
>>>     AType f(AType a) {
>>>         AType b;
>>>         return b;
>>>     }
>>> }
>>>
>>> concept_map A<int> {
>>>     typedef char AType;
>>> }
>>>
>>> template<typename T>
>>> requires (A<T>)
>>> void func(T a, AType b) {
>>>     AType x = h(b);         // <-- Instantiation DOES NOT WORK
>>>     AType y = f(b);          // <-- Instantiation WORKS
>>> }
>>>
>>> int main(int argc, char **argv)
>>> {
>>>     func<int>(10, 'a');      // Fails with declaration for 'x', for
>>> passes with declaration of 'y'.
>>> }
>>>
>>>
>>> It appears that during the instantiation of *func<int>()*, the value for
>>> input parameter '*b*' for '*func()*'
>>> can be looked up no problem. However, that of '*a*' for associated
>>> function '*h()*' cannot.
>>> Instead, a call to *clang::LocalInstantiationScope::getInstantiationOf()
>>> * fails at runtime on the assertion:
>>>
>>> *(D->isInvalidDecl() && "declaration was not instantiated in this
>>> scope!")*.
>>>
>>> I have been tracing through the procedures for building, transforming,
>>> and rebuilding Call Expressions -- as well as instantiating functions,
>>> noting each
>>> execution of *clang::LocalInstantiationScope::getInstantiationOf()* and
>>> *clang::LocalInstantiationScope::InstantiatedLocal()*...
>>>
>>> Still, I can't see what needs to be done differently for calls to *h()*from calls to
>>> *func<int>()*. Hence...
>>>
>>> Question:
>>> When/how exactly are input arguments bound to functions?
>>>
>>>
>>> That's a runtime issue. All the front-end does is enforce the calling
>>> convention on both sides of the call.
>>>
>>
>> And how does it do that? Exactly, when is *func<int>*'s '*b*' supposed to
>> meet *h*'s '*a*'?
>> Just as... When do the *main*'s *10* and '*a*' meet *func<int>*'s '*a*'
>> and '*b*' ?
>>
>>
>> At run time, the caller puts the call arguments into registers and on the
>> stack, and executes a call instruction. The Clang front-end never does this;
>> optimization passes may do it at the IR level.
>>
>>
>>> Why would the current procedure fail to bind the value of '*b*' from the
>>> context of *func<int>* to the
>>> parameter '*a*' of *h* ?
>>>
>>>
>>> They are in completely different contexts. func<int>'s b is completely
>>> disjoint from h's a. And, in fact, they might not be the same thing, since
>>> passing 'b' as an argument to h() implies the creation of a temporary.
>>>
>>> The only way I could see this issue coming up is if you're doing some
>>> kind of inlining of A<AType>::h into func<int> as part of instantiation. If
>>> so, I recommend against doing that: inlining will be handled by later
>>> optimization passes, and tangling the func<int> instantiation with the
>>> A<AType>::h instantiation is going to cause more problems in the front end
>>> than it solves.
>>>
>>
>> Hmm... How would the call be handled if *h* was a global function -- a
>> specialization of some template, not associated with any concept?
>>
>>
>> Exactly the same here.
>>
>> I am not trying to achieve any inlining here, I just want to pass in the
>> arguments as I would any inner function call (though thanks for the tip)...
>>
>>
>> You don't need to do any argument passing. Let Clang do that for you. All
>> you need to do is trigger the right instantiation.
>>
>
> I believe I'm doing exactly what should be done with any function call,
> i.e. rebuilding the call expressions et al. -- after hijacking the callee
> pointer so it points to the appropriate concept's associated function
> implementation.
> Apparently, in the way that I'm currently using Clang, it is not doing a
> very good job at taking care of things for me, and I am not sure which
> "parameters" I may have overlooked.
>
> I notice that the transformation of a call expression (via
> TreeTransform<>::
> TransformCallExpr)  transforms both the callee and the arguments. I am
> doing just that after redefining the callee...
> Somehow, this looses the temporaries instantiation that happens for normal
> function calls...
> Note that when I run examples where h is global, it works... But when I put
> h in a concept, it doesn't.
> The local instantiation scope for the instantiation of h somehow can pick
> up any local variable, but not it's parameters...
> and this only happens in cases where h is in a concept context.
>
> Is there something that ActOnCallExpr does that is dependent on the calling
> context that I am overlooking?
> I'm really not sure how to diagnose this issue anymore... :-/
>
> A quick hack that i could do, is explicitly inject an instantiation of
> function parameters after/while transforming the call expression. But I'm
> not sure (don't think) this is a good idea, as -- like you said -- Clang
> should automatically take care of this for me.
>
> What do you think? I'll keep thinking about this, but thanks for your help
> already.
>
>
>
>>
>> - Doug
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20110425/2aa3138d/attachment.html>


More information about the cfe-dev mailing list