]> granicus.if.org Git - clang/commitdiff
Improve handling of bool expressions in template arguments.
authorManuel Klimek <klimek@google.com>
Thu, 27 Mar 2014 19:00:52 +0000 (19:00 +0000)
committerManuel Klimek <klimek@google.com>
Thu, 27 Mar 2014 19:00:52 +0000 (19:00 +0000)
Now correctly formats:
  foo<true && false>();

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@204950 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Format/FormatToken.h
lib/Format/TokenAnnotator.cpp
unittests/Format/FormatTest.cpp

index 42d4a8dc249a213e086a0b839e253f61660fcd56..b7262f396d5082faf7cd990311e4e7a1e6f1274e 100644 (file)
@@ -282,6 +282,10 @@ struct FormatToken {
            (!ColonRequired || (Next && Next->is(tok::colon)));
   }
 
+  bool isLiteral() const {
+    return Tok.isLiteral() || isOneOf(tok::kw_true, tok::kw_false);
+  }
+
   /// \brief Determine whether the token is a simple-type-specifier.
   bool isSimpleTypeSpecifier() const;
 
index ee68afe7dcc745873ac70395f882bba5e2edc4dc..c3312cc66bdc1ba76b0e51d6e65b655a9cb518ef 100644 (file)
@@ -67,7 +67,11 @@ private:
       // parameters.
       // FIXME: This is getting out of hand, write a decent parser.
       if (CurrentToken->Previous->isOneOf(tok::pipepipe, tok::ampamp) &&
-          (CurrentToken->Previous->Type == TT_BinaryOperator ||
+          ((CurrentToken->Previous->Type == TT_BinaryOperator &&
+            // Toplevel bool expressions do not make lots of sense;
+            // If we're on the top level, it contains only the base context and
+            // the context for the current opening angle bracket.
+            Contexts.size() > 2) ||
            Contexts[Contexts.size() - 2].IsExpression) &&
           Line.First->isNot(tok::kw_template))
         return false;
@@ -858,9 +862,9 @@ private:
         PrevToken->MatchingParen->Previous->is(tok::kw_typeof))
       return TT_PointerOrReference;
 
-    if (PrevToken->Tok.isLiteral() ||
+    if (PrevToken->isLiteral() ||
         PrevToken->isOneOf(tok::r_paren, tok::r_square) ||
-        NextToken->Tok.isLiteral() || NextToken->isUnaryOperator() ||
+        NextToken->isLiteral() || NextToken->isUnaryOperator() ||
         // If we know we're in a template argument, there are no named
         // declarations. Thus, having an identifier on the right-hand side
         // indicates a binary operator.
index b5a70760a418785bc5876237cb490ab520f626c8..3d1e5a5d8e27cf0317f02135698b275f373deaaa 100644 (file)
@@ -4537,6 +4537,12 @@ TEST_F(FormatTest, UnderstandsUsesOfStarAndAmp) {
   verifyFormat("vector<int *const **const *> v;");
   verifyFormat("vector<int *volatile> v;");
   verifyFormat("vector<a * b> v;");
+  verifyFormat("foo<b && false>();");
+  verifyFormat("foo<b & 1>();");
+
+  // FIXME: We cannot handle this case yet; we might be able to figure out that
+  // foo<x> d > v; doesn't make sense.
+  verifyFormat("foo<a < b && c> d > v;");
 }
 
 TEST_F(FormatTest, UnderstandsAttributes) {