Endless operator-> chain causing infinite loop
Rahul Jain
1989.rahuljain at gmail.com
Fri Nov 8 07:19:48 PST 2013
Thanks Richard!!
On Thu, Nov 7, 2013 at 1:18 AM, Richard Smith <richard at metafoo.co.uk> wrote:
> Committed with a few changes as r194161. Thanks!
>
>
> On Wed, Nov 6, 2013 at 9:20 AM, Rahul Jain <1989.rahuljain at gmail.com>wrote:
>
>> Ping.
>>
>>
>> On Tue, Oct 29, 2013 at 1:12 PM, Rahul Jain <1989.rahuljain at gmail.com>wrote:
>>
>>> Hi Richard,
>>>
>>> Thanks for you valuable inputs.
>>>
>>> I have reworked the patch barring just one particular change you
>>> suggested.
>>> Here is the patch.
>>>
>>> Index: lib/Frontend/CompilerInvocation.cpp
>>> ===================================================================
>>> --- lib/Frontend/CompilerInvocation.cpp (revision 193583)
>>>
>>> +++ lib/Frontend/CompilerInvocation.cpp (working copy)
>>> @@ -1313,6 +1313,8 @@
>>> Opts.MathErrno = !Opts.OpenCL && Args.hasArg(OPT_fmath_errno);
>>> Opts.InstantiationDepth =
>>> getLastArgIntValue(Args, OPT_ftemplate_depth, 256, Diags);
>>> + Opts.ArrowDepth =
>>> + getLastArgIntValue(Args, OPT_foperator_arrow_depth, 2048, Diags);
>>> Opts.ConstexprCallDepth =
>>> getLastArgIntValue(Args, OPT_fconstexpr_depth, 512, Diags);
>>> Opts.ConstexprStepLimit =
>>> Index: lib/Sema/SemaExprCXX.cpp
>>> ===================================================================
>>> --- lib/Sema/SemaExprCXX.cpp (revision 193583)
>>>
>>> +++ lib/Sema/SemaExprCXX.cpp (working copy)
>>> @@ -5189,7 +5189,17 @@
>>> SmallVector<SourceLocation, 8> Locations;
>>> CTypes.insert(Context.getCanonicalType(BaseType));
>>>
>>> + unsigned int ArrowInstantiationCount = 0;
>>> while (BaseType->isRecordType()) {
>>> + ArrowInstantiationCount++;
>>> + if (ArrowInstantiationCount >= getLangOpts().ArrowDepth) {
>>>
>>> + Diag(OpLoc, diag::err_arrow_instantiation_depth_exceeded)
>>> + << getLangOpts().ArrowDepth << Base->getSourceRange();
>>> + Diag(OpLoc, diag::note_arrow_instantiation_depth)
>>> + << getLangOpts().ArrowDepth;
>>> + return ExprError();
>>> + }
>>> +
>>> Result = BuildOverloadedArrowExpr(
>>> S, Base, OpLoc,
>>> // When in a template specialization and on the first loop
>>> iteration,
>>> Index: lib/Driver/Tools.cpp
>>> ===================================================================
>>> --- lib/Driver/Tools.cpp (revision 193583)
>>>
>>> +++ lib/Driver/Tools.cpp (working copy)
>>> @@ -2802,6 +2802,11 @@
>>> CmdArgs.push_back(A->getValue());
>>> }
>>>
>>> + if (Arg *A = Args.getLastArg(options::OPT_foperator_arrow_depth_EQ)) {
>>> + CmdArgs.push_back("-foperator-arrow-depth");
>>> + CmdArgs.push_back(A->getValue());
>>> + }
>>> +
>>> if (Arg *A = Args.getLastArg(options::OPT_fconstexpr_depth_EQ)) {
>>> CmdArgs.push_back("-fconstexpr-depth");
>>> CmdArgs.push_back(A->getValue());
>>> Index: include/clang/Basic/LangOptions.def
>>> ===================================================================
>>> --- include/clang/Basic/LangOptions.def (revision 193583)
>>>
>>> +++ include/clang/Basic/LangOptions.def (working copy)
>>> @@ -160,6 +160,8 @@
>>> ENUM_LANGOPT(SignedOverflowBehavior, SignedOverflowBehaviorTy, 2,
>>> SOB_Undefined,
>>> "signed integer overflow handling")
>>>
>>> +BENIGN_LANGOPT(ArrowDepth, 32, 2048,
>>> + "maximum number of operator->s to follow")
>>> BENIGN_LANGOPT(InstantiationDepth, 32, 256,
>>> "maximum template instantiation depth")
>>> BENIGN_LANGOPT(ConstexprCallDepth, 32, 512,
>>> Index: include/clang/Basic/DiagnosticSemaKinds.td
>>> ===================================================================
>>> --- include/clang/Basic/DiagnosticSemaKinds.td (revision 193583)
>>>
>>> +++ include/clang/Basic/DiagnosticSemaKinds.td (working copy)
>>> @@ -2569,6 +2569,11 @@
>>> // can handle that case properly.
>>> def note_ovl_candidate_non_deduced_mismatch_qualified : Note<
>>> "candidate template ignored: could not match %q0 against %q1">;
>>> +def err_arrow_instantiation_depth_exceeded : Error<
>>> + "arrow operator instantiation exceeded maximum depth of %0">;
>>> +def note_arrow_instantiation_depth : Note<
>>> + "use -foperator-arrow-depth=N to increase arrow operator
>>> instantiation "
>>> + "depth">;
>>>
>>> // Note that we don't treat templates differently for this diagnostic.
>>> def note_ovl_candidate_arity : Note<"candidate "
>>> Index: include/clang/Driver/Options.td
>>> ===================================================================
>>> --- include/clang/Driver/Options.td (revision 193583)
>>>
>>> +++ include/clang/Driver/Options.td (working copy)
>>> @@ -775,6 +775,8 @@
>>> def ftemplate_depth_ : Joined<["-"], "ftemplate-depth-">,
>>> Group<f_Group>;
>>> def ftemplate_backtrace_limit_EQ : Joined<["-"],
>>> "ftemplate-backtrace-limit=">,
>>> Group<f_Group>;
>>> +def foperator_arrow_depth_EQ : Joined<["-"], "foperator-arrow-depth=">,
>>> + Group<f_Group>;
>>> def ftest_coverage : Flag<["-"], "ftest-coverage">, Group<f_Group>;
>>> def fvectorize : Flag<["-"], "fvectorize">, Group<f_Group>,
>>> HelpText<"Enable the loop vectorization passes">;
>>> Index: include/clang/Driver/CC1Options.td
>>> ===================================================================
>>> --- include/clang/Driver/CC1Options.td (revision 193583)
>>>
>>> +++ include/clang/Driver/CC1Options.td (working copy)
>>> @@ -442,6 +442,8 @@
>>> HelpText<"Default type visibility">;
>>> def ftemplate_depth : Separate<["-"], "ftemplate-depth">,
>>> HelpText<"Maximum depth of recursive template instantiation">;
>>> +def foperator_arrow_depth : Separate<["-"], "foperator-arrow-depth">,
>>> + HelpText<"Maximum depth of arrow operator instantiation">;
>>> def fconstexpr_depth : Separate<["-"], "fconstexpr-depth">,
>>> HelpText<"Maximum depth of recursive constexpr function calls">;
>>> def fconstexpr_steps : Separate<["-"], "fconstexpr-steps">,
>>> Index: docs/UsersManual.rst
>>> ===================================================================
>>> --- docs/UsersManual.rst (revision 193583)
>>> +++ docs/UsersManual.rst (working copy)
>>> @@ -1292,6 +1292,11 @@
>>> Sets the limit for recursively nested template instantiations to N.
>>> The
>>> default is 1024.
>>>
>>> +.. option:: -foperator-arrow-depth=N
>>> +
>>> + Sets the limit for arrow operator instantiations to N. The
>>> + default is 2048.
>>> +
>>> .. _objc:
>>>
>>> Objective-C Language Features
>>>
>>>
>>>
>>> Here is the test case which I have worked out:
>>>
>>> // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s -DMAX=10
>>> -foperator-arrow-depth=10
>>> // RUN: %clang -std=c++11 -fsyntax-only -Xclang -verify %s -DMAX=10
>>> -foperator-arrow-depth=10
>>>
>>>
>>> template< int n >
>>> struct a {
>>> a< n+1 > operator->()
>>> {
>>> return a< n+1 >();
>>> }
>>> };
>>>
>>> int foo() {
>>> a<0>()->x; \
>>> // expected-error{{arrow operator instantiation exceeded maximum depth
>>> of 10}} \
>>> // expected-note {{use -foperator-arrow-depth=N to increase arrow
>>> operator instantiation depth}}
>>> }
>>>
>>> Please suggest improvements.
>>>
>>> A couple of things on which your inputs would be appreciated are:
>>>
>>> 1) ""Please don't use the word 'instantiation' here.""
>>>
>>>
>>> This comment was implied for note def name/error def name/note string
>>> being printed/error string being printed??
>>>
>>> Please suggest some alternatives for the same.
>>>
>>
> I've reworded this a little.
>
>
>> 2) "Have you considered including notes pointing at the sequence of
>>> operator-> functions we called, and the corresponding types? This might not
>>> be obvious."
>>>
>>> By this you mean backtrace right, similar to the option
>>> -ftemplate-backtrace-limit=N? If yes, I did think about it, but was
>>> concerned about the implementation difficulty. If necessary I will work it
>>> out.
>>>
>>
> I've added this. We now produce:
>
> <stdin>:1:81: error: use of 'operator->' on type 'Ptr<int>' would invoke a
> sequence of more than 256 'operator->' calls
> template<typename T> struct Ptr { Ptr<T*> operator->(); }; Ptr<int> p; int
> n = p->n;
>
> ~^
> <stdin>:1:43: note: 'operator->' declared here produces an object of type
> 'Ptr<int *>'
> template<typename T> struct Ptr { Ptr<T*> operator->(); }; Ptr<int> p; int
> n = p->n;
> ^
> <stdin>:1:43: note: 'operator->' declared here produces an object of type
> 'Ptr<int **>'
> <stdin>:1:43: note: 'operator->' declared here produces an object of type
> 'Ptr<int ***>'
> <stdin>:1:43: note: 'operator->' declared here produces an object of type
> 'Ptr<int ****>'
> <stdin>:1:43: note: (skipping 248 'operator->'s in backtrace)
> <stdin>:1:43: note: 'operator->' declared here produces an object of type
> 'Ptr<int
>
> *************************************************************************************************************************************************************************************************************************************************************>'
> <stdin>:1:43: note: 'operator->' declared here produces an object of type
> 'Ptr<int
>
> **************************************************************************************************************************************************************************************************************************************************************>'
> <stdin>:1:43: note: 'operator->' declared here produces an object of type
> 'Ptr<int
>
> ***************************************************************************************************************************************************************************************************************************************************************>'
> <stdin>:1:43: note: 'operator->' declared here produces an object of type
> 'Ptr<int
>
> ****************************************************************************************************************************************************************************************************************************************************************>'
> <stdin>:1:81: note: use -foperator-arrow-depth=N to increase 'operator->'
> limit
> template<typename T> struct Ptr { Ptr<T*> operator->(); }; Ptr<int> p; int
> n = p->n;
>
> ^
>
> I also reduced the depth limit to 256 to match the bracket limit
> (recursive AST visitors might otherwise hit stack overflows when analyzing
> a long operator-> chain).
>
>
>> Thanks,
>>> Rahul
>>>
>>>
>>>
>>>
>>>
>>> On Mon, Oct 28, 2013 at 11:55 PM, Richard Smith <richard at metafoo.co.uk>wrote:
>>>
>>>> On Sun, Oct 27, 2013 at 2:10 PM, Rahul Jain <1989.rahuljain at gmail.com>wrote:
>>>>
>>>>> Hi,
>>>>>
>>>>> Thanks a lot Arthur and Richard for your valuable comments. Feels
>>>>> great when a beginner is supported to such an extent.
>>>>>
>>>>> As per your comments I have reworked the patch. Here is the revised
>>>>> one. Please take a look for feedback.
>>>>>
>>>>> Index: lib/Frontend/CompilerInvocation.cpp
>>>>> ===================================================================
>>>>> --- lib/Frontend/CompilerInvocation.cpp (revision 193504)
>>>>> +++ lib/Frontend/CompilerInvocation.cpp (working copy)
>>>>> @@ -1313,6 +1313,8 @@
>>>>> Opts.MathErrno = !Opts.OpenCL && Args.hasArg(OPT_fmath_errno);
>>>>> Opts.InstantiationDepth =
>>>>> getLastArgIntValue(Args, OPT_ftemplate_depth, 256, Diags);
>>>>> + Opts.ArrowDepth =
>>>>> + getLastArgIntValue(Args, OPT_foperator_arrow_depth, 2048,
>>>>> Diags);
>>>>> Opts.ConstexprCallDepth =
>>>>> getLastArgIntValue(Args, OPT_fconstexpr_depth, 512, Diags);
>>>>> Opts.ConstexprStepLimit =
>>>>> Index: lib/Driver/Tools.cpp
>>>>> ===================================================================
>>>>> --- lib/Driver/Tools.cpp (revision 193504)
>>>>> +++ lib/Driver/Tools.cpp (working copy)
>>>>> @@ -2802,6 +2802,11 @@
>>>>> CmdArgs.push_back(A->getValue());
>>>>> }
>>>>>
>>>>> + if (Arg *A =
>>>>> Args.getLastArg(options::OPT_foperator_arrow_depth_EQ)) {
>>>>> + CmdArgs.push_back("-foperator-arrow-depth");
>>>>> + CmdArgs.push_back(A->getValue());
>>>>> + }
>>>>> +
>>>>> if (Arg *A = Args.getLastArg(options::OPT_fconstexpr_depth_EQ)) {
>>>>> CmdArgs.push_back("-fconstexpr-depth");
>>>>> CmdArgs.push_back(A->getValue());
>>>>> Index: lib/Sema/SemaExprCXX.cpp
>>>>> ===================================================================
>>>>> --- lib/Sema/SemaExprCXX.cpp (revision 193504)
>>>>> +++ lib/Sema/SemaExprCXX.cpp (working copy)
>>>>> @@ -5189,7 +5189,17 @@
>>>>> SmallVector<SourceLocation, 8> Locations;
>>>>> CTypes.insert(Context.getCanonicalType(BaseType));
>>>>>
>>>>> + unsigned int Arrow_instantiation_count = 0;
>>>>>
>>>>
>>>> This should be CamelCase, without underscores.
>>>>
>>>>
>>>>> while (BaseType->isRecordType()) {
>>>>> + Arrow_instantiation_count++;
>>>>> + if (Arrow_instantiation_count >= getLangOpts().ArrowDepth) {
>>>>> + Diag(OpLoc, diag::err_arrow_instantiation_depth_exceeded)
>>>>> + << getLangOpts().ArrowDepth << Base->getSourceRange();
>>>>> + Diag(OpLoc, diag::note_arrow_instantiation_depth)
>>>>> + << getLangOpts().ArrowDepth;
>>>>> + return ExprError();
>>>>>
>>>>
>>>> The body of this 'if' should be indented by two more spaces.
>>>>
>>>>
>>>>> + }
>>>>> +
>>>>> Result = BuildOverloadedArrowExpr(
>>>>> S, Base, OpLoc,
>>>>> // When in a template specialization and on the first loop
>>>>> iteration,
>>>>> Index: include/clang/Basic/LangOptions.def
>>>>> ===================================================================
>>>>> --- include/clang/Basic/LangOptions.def (revision 193504)
>>>>> +++ include/clang/Basic/LangOptions.def (working copy)
>>>>> @@ -160,6 +160,8 @@
>>>>> ENUM_LANGOPT(SignedOverflowBehavior, SignedOverflowBehaviorTy, 2,
>>>>> SOB_Undefined,
>>>>> "signed integer overflow handling")
>>>>>
>>>>> +BENIGN_LANGOPT(ArrowDepth, 32, 2048,
>>>>> + "maximum number of operator->s to follow")
>>>>> BENIGN_LANGOPT(InstantiationDepth, 32, 256,
>>>>> "maximum template instantiation depth")
>>>>> BENIGN_LANGOPT(ConstexprCallDepth, 32, 512,
>>>>> Index: include/clang/Basic/DiagnosticSemaKinds.td
>>>>> ===================================================================
>>>>> --- include/clang/Basic/DiagnosticSemaKinds.td (revision 193504)
>>>>> +++ include/clang/Basic/DiagnosticSemaKinds.td (working copy)
>>>>> @@ -2569,6 +2569,11 @@
>>>>> // can handle that case properly.
>>>>> def note_ovl_candidate_non_deduced_mismatch_qualified : Note<
>>>>> "candidate template ignored: could not match %q0 against %q1">;
>>>>> +def err_arrow_instantiation_depth_exceeded : Error<
>>>>> + "arrow operator instantiation exceeded maximum depth of %0">;
>>>>> +def note_arrow_instantiation_depth : Note<
>>>>> + "use -foperator-arrow-depth=N to increase arrow operator
>>>>> instantiation "
>>>>> + "depth">;
>>>>>
>>>>
>>>> Please don't use the word 'instantiation' here.
>>>>
>>>> Have you considered including notes pointing at the sequence of
>>>> operator-> functions we called, and the corresponding types? This might not
>>>> be obvious.
>>>>
>>>>
>>>>> // Note that we don't treat templates differently for this diagnostic.
>>>>> def note_ovl_candidate_arity : Note<"candidate "
>>>>> Index: include/clang/Driver/CC1Options.td
>>>>> ===================================================================
>>>>> --- include/clang/Driver/CC1Options.td (revision 193504)
>>>>> +++ include/clang/Driver/CC1Options.td (working copy)
>>>>> @@ -442,6 +442,8 @@
>>>>> HelpText<"Default type visibility">;
>>>>> def ftemplate_depth : Separate<["-"], "ftemplate-depth">,
>>>>> HelpText<"Maximum depth of recursive template instantiation">;
>>>>> +def foperator_arrow_depth : Separate<["-"], "foperator-arrow-depth">,
>>>>> + HelpText<"Maximum depth of arrow operator instantiation">;
>>>>> def fconstexpr_depth : Separate<["-"], "fconstexpr-depth">,
>>>>> HelpText<"Maximum depth of recursive constexpr function calls">;
>>>>> def fconstexpr_steps : Separate<["-"], "fconstexpr-steps">,
>>>>> Index: include/clang/Driver/Options.td
>>>>> ===================================================================
>>>>> --- include/clang/Driver/Options.td (revision 193504)
>>>>> +++ include/clang/Driver/Options.td (working copy)
>>>>> @@ -775,6 +775,8 @@
>>>>> def ftemplate_depth_ : Joined<["-"], "ftemplate-depth-">,
>>>>> Group<f_Group>;
>>>>> def ftemplate_backtrace_limit_EQ : Joined<["-"],
>>>>> "ftemplate-backtrace-limit=">,
>>>>> Group<f_Group>;
>>>>> +def foperator_arrow_depth_EQ : Joined<["-"],
>>>>> "foperator-arrow-depth=">,
>>>>> + Group<f_Group>;
>>>>> def ftest_coverage : Flag<["-"], "ftest-coverage">, Group<f_Group>;
>>>>> def fvectorize : Flag<["-"], "fvectorize">, Group<f_Group>,
>>>>> HelpText<"Enable the loop vectorization passes">;
>>>>>
>>>>>
>>>>> Attaching the gcc testsuite test case too for reference.
>>>>>
>>>>
>>>> Please don't mail code from GCC here.
>>>>
>>>> Instead, you'll need to craft a test case for our test suite. You can
>>>> take inspiration from
>>>>
>>>> test/SemaCXX/constexpr-depth.cpp
>>>> test/SemaTemplate/instantiation-depth.cpp
>>>>
>>>>
>>>>> How do I add the flag to the documentation?
>>>>>
>>>>
>>>> Modify docs/UsersManual.rst
>>>>
>>>> Thank you for working on this!
>>>>
>>>>
>>>>> Thanks,
>>>>> Rahul
>>>>>
>>>>>
>>>>> On Sat, Oct 26, 2013 at 12:14 AM, Richard Smith <richard at metafoo.co.uk
>>>>> > wrote:
>>>>>
>>>>>> On Fri, Oct 25, 2013 at 9:06 AM, Arthur O'Dwyer <
>>>>>> arthur.j.odwyer at gmail.com> wrote:
>>>>>>
>>>>>>> IMHO, it would be better to remove the command-line option, and just
>>>>>>> set the (hard-coded) limit to 2048 or something else of that general
>>>>>>> order of magnitude. I can't think of any valid use for deeply nested
>>>>>>> operator->s; it's not like recursive template instantiation, where
>>>>>>> you
>>>>>>> might want to use a higher limit to implement a useful behavior.
>>>>>>>
>>>>>>
>>>>>> The "usual" (albeit very rare) use is to get around the recursive
>>>>>> template instantiation depth limit.
>>>>>>
>>>>>>
>>>>>>> Therefore, setting the limit to something in the thousands ought to
>>>>>>> be
>>>>>>> good enough until someone legitimately runs into the limit; and in
>>>>>>> the
>>>>>>> meantime, we're not polluting the command-line docs with obscure and
>>>>>>> useless options.
>>>>>>>
>>>>>>
>>>>>> I don't see any problem with setting the default to a higher value,
>>>>>> like maybe 2048.
>>>>>>
>>>>>>
>>>>>>> Also FWIW, I do think a DR ought to be opened to make this an
>>>>>>> explicit
>>>>>>> implementation limit in the Standard... but I'm not volunteering. :)
>>>>>>>
>>>>>>> my $.02,
>>>>>>> –Arthur
>>>>>>>
>>>>>>>
>>>>>>> On Fri, Oct 25, 2013 at 7:45 AM, Rahul Jain <
>>>>>>> 1989.rahuljain at gmail.com> wrote:
>>>>>>> >
>>>>>>> > Hi,
>>>>>>> >
>>>>>>> > This is with reference to the below discussion thread:
>>>>>>> >
>>>>>>> >
>>>>>>> http://clang-developers.42468.n3.nabble.com/Endless-operator-gt-chain-causing-infinite-loop-td4035258.html
>>>>>>> >
>>>>>>> > I have tried to implement a command line argument to handle the
>>>>>>> issue.
>>>>>>> >
>>>>>>> > The patch for the same is below:
>>>>>>> >
>>>>>>> > Index: lib/Driver/Tools.cpp
>>>>>>> > ===================================================================
>>>>>>> > --- lib/Driver/Tools.cpp (revision 193400)
>>>>>>> > +++ lib/Driver/Tools.cpp (working copy)
>>>>>>> > @@ -2802,6 +2802,12 @@
>>>>>>> > CmdArgs.push_back(A->getValue());
>>>>>>> > }
>>>>>>> >
>>>>>>> > + if (Arg *A = Args.getLastArg(options::OPT_foperatorarrow_depth_,
>>>>>>> > +
>>>>>>> options::OPT_foperatorarrow_depth_EQ)) {
>>>>>>> > + CmdArgs.push_back("-foperatorarrow-depth");
>>>>>>>
>>>>>>
>>>>>> Please use foperator_arrow_depth and -foperator-arrow-depth.
>>>>>>
>>>>>>
>>>>>>> > + CmdArgs.push_back(A->getValue());
>>>>>>> > + }
>>>>>>> > +
>>>>>>> > if (Arg *A = Args.getLastArg(options::OPT_fconstexpr_depth_EQ))
>>>>>>> {
>>>>>>> > CmdArgs.push_back("-fconstexpr-depth");
>>>>>>> > CmdArgs.push_back(A->getValue());
>>>>>>> > Index: lib/Frontend/CompilerInvocation.cpp
>>>>>>> > ===================================================================
>>>>>>> > --- lib/Frontend/CompilerInvocation.cpp (revision 193400)
>>>>>>> > +++ lib/Frontend/CompilerInvocation.cpp (working copy)
>>>>>>> > @@ -1313,6 +1313,8 @@
>>>>>>> > Opts.MathErrno = !Opts.OpenCL && Args.hasArg(OPT_fmath_errno);
>>>>>>> > Opts.InstantiationDepth =
>>>>>>> > getLastArgIntValue(Args, OPT_ftemplate_depth, 256, Diags);
>>>>>>> > + Opts.ArrowDepth =
>>>>>>> > + getLastArgIntValue(Args, OPT_foperatorarrow_depth, 256,
>>>>>>> Diags);
>>>>>>> > Opts.ConstexprCallDepth =
>>>>>>> > getLastArgIntValue(Args, OPT_fconstexpr_depth, 512, Diags);
>>>>>>> > Opts.ConstexprStepLimit =
>>>>>>> > Index: lib/Sema/SemaExprCXX.cpp
>>>>>>> > ===================================================================
>>>>>>> > --- lib/Sema/SemaExprCXX.cpp (revision 193400)
>>>>>>> > +++ lib/Sema/SemaExprCXX.cpp (working copy)
>>>>>>> > @@ -5188,8 +5188,19 @@
>>>>>>> > llvm::SmallPtrSet<CanQualType,8> CTypes;
>>>>>>> > SmallVector<SourceLocation, 8> Locations;
>>>>>>> > CTypes.insert(Context.getCanonicalType(BaseType));
>>>>>>> > +
>>>>>>> > + static unsigned int arrow_instantiation_count = 0;
>>>>>>>
>>>>>>
>>>>>> This should not be static, and the name should follow the coding
>>>>>> convention:
>>>>>>
>>>>>>
>>>>>> http://llvm.org/docs/CodingStandards.html#name-types-functions-variables-and-enumerators-properly
>>>>>>
>>>>>> > + while (BaseType->isRecordType()) {
>>>>>>> > + arrow_instantiation_count++;
>>>>>>> > + if (arrow_instantiation_count >= getLangOpts().ArrowDepth) {
>>>>>>> > + Diag(OpLoc,diag::err_arrow_instantiation_depth_exceeded)
>>>>>>>
>>>>>>
>>>>>> Space after comma.
>>>>>>
>>>>>>
>>>>>>> > + << getLangOpts().ArrowDepth
>>>>>>> > + << Base->getSourceRange();
>>>>>>> > + Diag(OpLoc, diag::note_arrow_instantiation_depth)
>>>>>>> > + << getLangOpts().ArrowDepth;
>>>>>>> > + return ExprError();
>>>>>>>
>>>>>>
>>>>>> Indentation is strange here.
>>>>>>
>>>>>>
>>>>>>> > + }
>>>>>>> >
>>>>>>> > - while (BaseType->isRecordType()) {
>>>>>>> > Result = BuildOverloadedArrowExpr(
>>>>>>> > S, Base, OpLoc,
>>>>>>> > // When in a template specialization and on the first
>>>>>>> loop
>>>>>>> > iteration,
>>>>>>> > Index: include/clang/Basic/DiagnosticSemaKinds.td
>>>>>>> > ===================================================================
>>>>>>> > --- include/clang/Basic/DiagnosticSemaKinds.td (revision 193400)
>>>>>>> > +++ include/clang/Basic/DiagnosticSemaKinds.td (working copy)
>>>>>>> > @@ -2561,6 +2561,11 @@
>>>>>>> > // can handle that case properly.
>>>>>>> > def note_ovl_candidate_non_deduced_mismatch_qualified : Note<
>>>>>>> > "candidate template ignored: could not match %q0 against
>>>>>>> %q1">;
>>>>>>> > +def err_arrow_instantiation_depth_exceeded : Error<
>>>>>>> > + "arrow operator instantiation exceeded maximum depth of %0">,
>>>>>>> > + DefaultFatal, NoSFINAE;
>>>>>>>
>>>>>>
>>>>>> We don't need this to be fatal.
>>>>>>
>>>>>>
>>>>>>> > +def note_arrow_instantiation_depth : Note<
>>>>>>> > + "use -foperatorarrow-depth=N to increase arrow operator
>>>>>>> instantiation
>>>>>>> > depth">;
>>>>>>> >
>>>>>>> > // Note that we don't treat templates differently for this
>>>>>>> diagnostic.
>>>>>>> > def note_ovl_candidate_arity : Note<"candidate "
>>>>>>> > Index: include/clang/Basic/LangOptions.def
>>>>>>> > ===================================================================
>>>>>>> > --- include/clang/Basic/LangOptions.def (revision 193400)
>>>>>>> > +++ include/clang/Basic/LangOptions.def (working copy)
>>>>>>> > @@ -160,6 +160,8 @@
>>>>>>> > ENUM_LANGOPT(SignedOverflowBehavior, SignedOverflowBehaviorTy, 2,
>>>>>>> > SOB_Undefined,
>>>>>>> > "signed integer overflow handling")
>>>>>>> >
>>>>>>> > +BENIGN_LANGOPT(ArrowDepth, 32, 256,
>>>>>>> > + "maximum arrow instantiation depth")
>>>>>>>
>>>>>>
>>>>>> "instantiation" is not correct here. Maybe "maximum number of
>>>>>> operator->s to follow"?
>>>>>>
>>>>>>
>>>>>>> > BENIGN_LANGOPT(InstantiationDepth, 32, 256,
>>>>>>> > "maximum template instantiation depth")
>>>>>>> > BENIGN_LANGOPT(ConstexprCallDepth, 32, 512,
>>>>>>> > Index: include/clang/Driver/CC1Options.td
>>>>>>> > ===================================================================
>>>>>>> > --- include/clang/Driver/CC1Options.td (revision 193400)
>>>>>>> > +++ include/clang/Driver/CC1Options.td (working copy)
>>>>>>> > @@ -442,6 +442,8 @@
>>>>>>> > HelpText<"Default type visibility">;
>>>>>>> > def ftemplate_depth : Separate<["-"], "ftemplate-depth">,
>>>>>>> > HelpText<"Maximum depth of recursive template instantiation">;
>>>>>>> > +def foperatorarrow_depth : Separate<["-"],
>>>>>>> "foperatorarrow-depth">,
>>>>>>> > + HelpText<"Maximum depth of arrow operator instantiation">;
>>>>>>> > def fconstexpr_depth : Separate<["-"], "fconstexpr-depth">,
>>>>>>> > HelpText<"Maximum depth of recursive constexpr function calls">;
>>>>>>> > def fconstexpr_steps : Separate<["-"], "fconstexpr-steps">,
>>>>>>> > Index: include/clang/Driver/Options.td
>>>>>>> > ===================================================================
>>>>>>> > --- include/clang/Driver/Options.td (revision 193400)
>>>>>>> > +++ include/clang/Driver/Options.td (working copy)
>>>>>>> > @@ -775,6 +775,8 @@
>>>>>>> > def ftemplate_depth_ : Joined<["-"], "ftemplate-depth-">,
>>>>>>> Group<f_Group>;
>>>>>>> > def ftemplate_backtrace_limit_EQ : Joined<["-"],
>>>>>>> > "ftemplate-backtrace-limit=">,
>>>>>>> > Group<f_Group>;
>>>>>>> > +def foperatorarrow_depth_EQ : Joined<["-"],
>>>>>>> "foperatorarrow-depth=">,
>>>>>>> > Group<f_Group>;
>>>>>>> > +def foperatorarrow_depth_ : Joined<["-"],
>>>>>>> "foperatorarrow-depth-">,
>>>>>>> > Group<f_Group>;
>>>>>>>
>>>>>>
>>>>>> Please remove this variant. We only support the - form for
>>>>>> -ftemplate-depth for compatibility with an old g++ misstep.
>>>>>>
>>>>>>
>>>>>>> > def ftest_coverage : Flag<["-"], "ftest-coverage">,
>>>>>>> Group<f_Group>;
>>>>>>> > def fvectorize : Flag<["-"], "fvectorize">, Group<f_Group>,
>>>>>>> > HelpText<"Enable the loop vectorization passes">;
>>>>>>> >
>>>>>>> >
>>>>>>> >
>>>>>>> > Please if someone could help me by reviewing it and suggesting
>>>>>>> improvements?
>>>>>>>
>>>>>>
>>>>>> It looks basically right, other than the tweaks above. Thanks!
>>>>>>
>>>>>> Please also add this flag to the documentation.
>>>>>>
>>>>>
>>>>>
>>>>
>>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20131108/120ae562/attachment.html>
More information about the cfe-commits
mailing list