[cfe-dev] Endless operator-> chain causing infinite loop

Richard Smith richard at metafoo.co.uk
Wed Oct 23 13:49:46 PDT 2013


On Wed, Oct 23, 2013 at 11:56 AM, David Blaikie <dblaikie at gmail.com> wrote:

>
>
>
> On Wed, Oct 23, 2013 at 11:27 AM, Richard Smith <richard at metafoo.co.uk>wrote:
>
>> On Wed, Oct 23, 2013 at 6:06 AM, Rahul Jain <1989.rahuljain at gmail.com>wrote:
>>
>>> Hi Richard / Karen,
>>>
>>> Thanks for making things clearer.
>>> Now how do we go about handling this sort of behavior?
>>>
>>> Do we throw an error message just like g++ does? Wont it be better to
>>> print an error message instead of an infinite loop?
>>>
>>
>> We don't know the loop is infinite, but we should probably give up after
>> some number of iterations.
>>
>>
>>> Also if you could please elaborate a bit on how we can "limit the number
>>> of times we go around the loop looking for an overloaded operator->
>>> in Sema::
>>> ActOnStartCXXMemberReference" ?
>>>
>>
>> Add a counter to the "while (BaseType->isRecordType())" loop. Bail out
>> with a diagnostic if it hits the limit.
>>
>
> Pedantry, just for fun - should this be added to the implementation limits
> in the C++ standard?
>

The list of limits is not normative; an implementation can use whatever
limits it likes, so long as it documents them. And in some sense this is
already covered by "Nesting levels of parenthesized expressions within a
full-expression [256]." because the rewrite rule introduces nested
parentheses =)


>
> - David
>
>
>>
>>
>>>  Thanks,
>>> Rahul
>>>
>>>
>>>
>>>
>>> On Wed, Oct 23, 2013 at 3:30 AM, Karen Shaeffer <
>>> shaeffer at neuralscape.com> wrote:
>>>
>>>> On Tue, Oct 22, 2013 at 02:54:08PM -0700, Richard Smith wrote:
>>>> > On Tue, Oct 22, 2013 at 2:03 PM, Karen Shaeffer <
>>>> shaeffer at neuralscape.com>wrote:
>>>> >
>>>> > > On Tue, Oct 22, 2013 at 12:14:25PM -0700, Richard Smith wrote:
>>>> > > > On Tue, Oct 22, 2013 at 2:45 AM, Rahul Jain <
>>>> 1989.rahuljain at gmail.com
>>>> > > >wrote:
>>>> > > >
>>>> > > > >
>>>> > > > > Hi all,
>>>> > > > >
>>>> > > > > clang version 3.4 (192772)
>>>> > > > >
>>>> > > > > This is with respect to the following gcc testsuite TC:
>>>> > > > >
>>>> > > > > template< int n >
>>>> > > > > struct a {
>>>> > > > >     a< n+1 > operator->()
>>>> > > > >         {
>>>> > > > >         return a< n+1 >();
>>>> > > > >         }
>>>> > > > > };
>>>> > > > >
>>>> > > > > int main() {
>>>> > > > >     a<0>()->x;
>>>> > > > > }
>>>> > > > >
>>>> > > > >
>>>> > > > > This TC goes into an infinite loop when compiled. Ideally it
>>>> should
>>>> > > throw
>>>> > > > > the error
>>>> > > > > recursive template instantiation exceeded maximum depth of 256.
>>>> > > > >
>>>> > > >
>>>> > > > That's not the right behavior; there's no recursive template
>>>> > > instantiation
>>>> > > > here. Each operator-> is instantiated from within the context of
>>>> 'main',
>>>> > > > not from within some other instantiation.
>>>> > > >
>>>> > > > If we want to limit this, we should put a limit on the number of
>>>> times we
>>>> > > > go around the loop looking for an overloaded operator->
>>>> > > > in Sema::ActOnStartCXXMemberReference. However, I've seen people
>>>> use this
>>>> > > > in practice in template metaprogramming to get around the
>>>> recursive
>>>> > > > template instantiation depth, so this might break existing code.
>>>> > >
>>>> > > Hi Richard,
>>>> > >
>>>> > > Just checked, and g++-4.7.2 doesn't give a 'recusive template
>>>> > > instantiation' error.
>>>> > > The error is:
>>>> > >
>>>> > > error: template instantiation depth exceeds maximum of 900 (use
>>>> > > -ftemplate-depth= to increase the maximum) instantiating ‘a<(n + 1)>
>>>> > > a<n>::operator->() [with int n = 900]’
>>>> > >
>>>> >
>>>> > This is their recursive template instantiation error. I'm not sure
>>>> why they
>>>> > chose to diagnose this problem in that way; there is no recursive
>>>> > instantiation here. The loop is in [over.ref](13.5.6)p1:
>>>> >
>>>> > "An expression x->m is interpreted as (x.operator->())->m for a class
>>>> > object x of type T if T::operator->() exists and if the operator is
>>>> > selected as the best match function by the overload resolution
>>>> mechanism."
>>>> >
>>>> > This rule gets applied repeatedly, outside of any template
>>>> instantiation.
>>>> >
>>>> >
>>>> > > In the standard at [temp.inst]
>>>> > >
>>>> >
>>>> > > <14.7.1 note d>
>>>> > > There is an implementation-defined quantity that specifies the
>>>> limit on
>>>> > > the total depth
>>>> > > of recursive instantiations, which could involve more than one
>>>> template.
>>>> > > The result of an
>>>> > > infinite recursion in instantiation is undefined.
>>>> > >
>>>> >
>>>> > This is not what's happening in this case.
>>>>
>>>> Hi Richard,
>>>> I understand it is not what is happening. I just included the <14.7.2
>>>> note 15>
>>>> for clarity. I think the g++ error message is crystal clear. And the
>>>> practicality
>>>> of it is obvious.
>>>>
>>>> Thanks for your comments.
>>>>
>>>> enjoy,
>>>> Karen
>>>> --
>>>> Karen Shaeffer                 Be aware: If you see an obstacle in your
>>>> path,
>>>> Neuralscape Services           that obstacle is your path.        Zen
>>>> proverb
>>>>
>>>
>>>
>>
>> _______________________________________________
>> cfe-dev mailing list
>> cfe-dev at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20131023/36de8853/attachment.html>


More information about the cfe-dev mailing list