Browse Source

Fixed a bug in AnnotatedLine::startsWith when there are comments in the line.

Summary: When there are comments in the line, one token may be checked multiple times.

Reviewers: mprobst, djasper

Subscribers: ioeric, cfe-commits, klimek

Differential Revision: http://reviews.llvm.org/D19106

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@266803 91177308-0d34-0410-b5e6-96231b3b80d8
Eric Liu 9 years ago
parent
commit
a426f58b69
1 changed files with 13 additions and 4 deletions
  1. 13 4
      lib/Format/TokenAnnotator.h

+ 13 - 4
lib/Format/TokenAnnotator.h

@@ -83,7 +83,7 @@ public:
   /// \c true if this line starts with the given tokens in order, ignoring
   /// \c true if this line starts with the given tokens in order, ignoring
   /// comments.
   /// comments.
   template <typename... Ts> bool startsWith(Ts... Tokens) const {
   template <typename... Ts> bool startsWith(Ts... Tokens) const {
-    return startsWith(First, Tokens...);
+    return startsWithInternal(First, Tokens...);
   }
   }
 
 
   /// \c true if this line looks like a function definition instead of a
   /// \c true if this line looks like a function definition instead of a
@@ -124,15 +124,24 @@ private:
   void operator=(const AnnotatedLine &) = delete;
   void operator=(const AnnotatedLine &) = delete;
 
 
   template <typename A, typename... Ts>
   template <typename A, typename... Ts>
-  bool startsWith(FormatToken *Tok, A K1) const {
+  bool startsWithInternal(const FormatToken *Tok, A K1) const {
+    // Even though we skip comments in the outer `startWithInternal` function,
+    // this loop is still necessary if it is invoked by the public interface
+    // `startsWith`.
     while (Tok && Tok->is(tok::comment))
     while (Tok && Tok->is(tok::comment))
       Tok = Tok->Next;
       Tok = Tok->Next;
     return Tok && Tok->is(K1);
     return Tok && Tok->is(K1);
   }
   }
 
 
   template <typename A, typename... Ts>
   template <typename A, typename... Ts>
-  bool startsWith(FormatToken *Tok, A K1, Ts... Tokens) const {
-    return startsWith(Tok, K1) && startsWith(Tok->Next, Tokens...);
+  bool startsWithInternal(const FormatToken *Tok, A K1, Ts... Tokens) const {
+    // Skip comments before calling `startsWithInternal(Tok, K1)` so that  the
+    // second call to `startsWithInternal` takes the correct `Tok->Next`, which
+    // should be the next token of the token checked in the first call.
+    while (Tok && Tok->is(tok::comment))
+      Tok = Tok->Next;
+    return Tok && startsWithInternal(Tok, K1) &&
+           startsWithInternal(Tok->Next, Tokens...);
   }
   }
 };
 };