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