@@ -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