@@ -155,8 +155,8 @@ class AnnotatingParser {
155155    if  (NonTemplateLess.count (CurrentToken->Previous ) > 0 )
156156      return  false ;
157157
158-     const  FormatToken  &Previous = *CurrentToken->Previous ; //  The '<'.
159-     if  ( Previous.Previous ) {
158+     if  ( const  auto  &Previous = *CurrentToken->Previous ; //  The '<'.
159+          Previous.Previous ) {
160160      if  (Previous.Previous ->Tok .isLiteral ())
161161        return  false ;
162162      if  (Previous.Previous ->is (tok::r_brace))
@@ -176,31 +176,38 @@ class AnnotatingParser {
176176    FormatToken *Left = CurrentToken->Previous ;
177177    Left->ParentBracket  = Contexts.back ().ContextKind ;
178178    ScopedContextCreator ContextCreator (*this , tok::less, 12 );
179- 
180179    Contexts.back ().IsExpression  = false ;
180+ 
181+     const  auto  *BeforeLess = Left->Previous ;
182+ 
181183    //  If there's a template keyword before the opening angle bracket, this is a
182184    //  template parameter, not an argument.
183-     if  (Left-> Previous  && Left-> Previous ->isNot (tok::kw_template))
185+     if  (BeforeLess  && BeforeLess ->isNot (tok::kw_template))
184186      Contexts.back ().ContextType  = Context::TemplateArgument;
185187
186188    if  (Style.Language  == FormatStyle::LK_Java &&
187189        CurrentToken->is (tok::question)) {
188190      next ();
189191    }
190192
191-     while  (CurrentToken) {
193+     for  (bool  SeenTernaryOperator = false ; CurrentToken;) {
194+       const  bool  InExpr = Contexts[Contexts.size () - 2 ].IsExpression ;
192195      if  (CurrentToken->is (tok::greater)) {
196+         const  auto  *Next = CurrentToken->Next ;
193197        //  Try to do a better job at looking for ">>" within the condition of
194198        //  a statement. Conservatively insert spaces between consecutive ">"
195199        //  tokens to prevent splitting right bitshift operators and potentially
196200        //  altering program semantics. This check is overly conservative and
197201        //  will prevent spaces from being inserted in select nested template
198202        //  parameter cases, but should not alter program semantics.
199-         if  (CurrentToken-> Next  && CurrentToken-> Next ->is (tok::greater) &&
203+         if  (Next && Next->is (tok::greater) &&
200204            Left->ParentBracket  != tok::less &&
201205            CurrentToken->getStartOfNonWhitespace () ==
202-                 CurrentToken->Next ->getStartOfNonWhitespace ().getLocWithOffset (
203-                     -1 )) {
206+                 Next->getStartOfNonWhitespace ().getLocWithOffset (-1 )) {
207+           return  false ;
208+         }
209+         if  (InExpr && SeenTernaryOperator &&
210+             (!Next || !Next->isOneOf (tok::l_paren, tok::l_brace))) {
204211          return  false ;
205212        }
206213        Left->MatchingParen  = CurrentToken;
@@ -211,14 +218,14 @@ class AnnotatingParser {
211218        //    msg: < item: data >
212219        //  In TT_TextProto, map<key, value> does not occur.
213220        if  (Style.Language  == FormatStyle::LK_TextProto ||
214-             (Style.Language  == FormatStyle::LK_Proto && Left-> Previous  &&
215-              Left-> Previous ->isOneOf (TT_SelectorName, TT_DictLiteral))) {
221+             (Style.Language  == FormatStyle::LK_Proto && BeforeLess  &&
222+              BeforeLess ->isOneOf (TT_SelectorName, TT_DictLiteral))) {
216223          CurrentToken->setType (TT_DictLiteral);
217224        } else  {
218225          CurrentToken->setType (TT_TemplateCloser);
219226          CurrentToken->Tok .setLength (1 );
220227        }
221-         if  (CurrentToken-> Next  && CurrentToken-> Next ->Tok .isLiteral ())
228+         if  (Next && Next->Tok .isLiteral ())
222229          return  false ;
223230        next ();
224231        return  true ;
@@ -230,18 +237,21 @@ class AnnotatingParser {
230237      }
231238      if  (CurrentToken->isOneOf (tok::r_paren, tok::r_square, tok::r_brace))
232239        return  false ;
240+       const  auto  &Prev = *CurrentToken->Previous ;
233241      //  If a && or || is found and interpreted as a binary operator, this set
234242      //  of angles is likely part of something like "a < b && c > d". If the
235243      //  angles are inside an expression, the ||/&& might also be a binary
236244      //  operator that was misinterpreted because we are parsing template
237245      //  parameters.
238246      //  FIXME: This is getting out of hand, write a decent parser.
239-       if  (CurrentToken-> Previous -> isOneOf (tok::pipepipe, tok::ampamp ) &&
240-           CurrentToken-> Previous -> is (TT_BinaryOperator) && 
241-           Contexts[Contexts. size () -  2 ]. IsExpression  && 
242-           !Line. startsWith (tok::kw_template)) { 
243-         return  false ;
247+       if  (InExpr && !Line. startsWith (tok::kw_template ) &&
248+           Prev. is (TT_BinaryOperator)) { 
249+         const   auto  Precedence = Prev. getPrecedence (); 
250+         if  (Precedence > prec::Conditional && Precedence < prec::Relational) 
251+            return  false ;
244252      }
253+       if  (Prev.is (TT_ConditionalExpr))
254+         SeenTernaryOperator = true ;
245255      updateParameterCount (Left, CurrentToken);
246256      if  (Style.Language  == FormatStyle::LK_Proto) {
247257        if  (FormatToken *Previous = CurrentToken->getPreviousNonComment ()) {
0 commit comments