summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorManuel Klimek <klimek@google.com>2014-03-27 11:17:36 +0000
committerManuel Klimek <klimek@google.com>2014-03-27 11:17:36 +0000
commitf81e5c0e50424f65ed60ba8de9578f6edc79dd5d (patch)
treeb17b8744fb3605eaed23a560563fe3f8e688df68
parent59a12198463bb13f1496205e496a2131462d3f88 (diff)
downloadbcm5719-llvm-f81e5c0e50424f65ed60ba8de9578f6edc79dd5d.tar.gz
bcm5719-llvm-f81e5c0e50424f65ed60ba8de9578f6edc79dd5d.zip
Fix bool expression special case.
Clang-format now correctly formats: some_type<a * b> v; template <bool a, bool b> typename enabled_if<a && b>::type f() {} llvm-svn: 204913
-rw-r--r--clang/lib/Format/TokenAnnotator.cpp21
-rw-r--r--clang/unittests/Format/FormatTest.cpp8
2 files changed, 25 insertions, 4 deletions
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index 19bc5a6a96b..ee68afe7dcc 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -44,6 +44,11 @@ private:
ScopedContextCreator ContextCreator(*this, tok::less, 10);
FormatToken *Left = CurrentToken->Previous;
Contexts.back().IsExpression = false;
+ // If there's a template keyword before the opening angle bracket, this is a
+ // template parameter, not an argument.
+ Contexts.back().InTemplateArgument =
+ Left->Previous != NULL && Left->Previous->Tok.isNot(tok::kw_template);
+
while (CurrentToken != NULL) {
if (CurrentToken->is(tok::greater)) {
Left->MatchingParen = CurrentToken;
@@ -615,7 +620,8 @@ private:
ColonIsForRangeExpr(false), ColonIsDictLiteral(false),
ColonIsObjCMethodExpr(false), FirstObjCSelectorName(NULL),
FirstStartOfName(NULL), IsExpression(IsExpression),
- CanBeExpression(true), InCtorInitializer(false), CaretFound(false) {}
+ CanBeExpression(true), InTemplateArgument(false),
+ InCtorInitializer(false), CaretFound(false) {}
tok::TokenKind ContextKind;
unsigned BindingStrength;
@@ -628,6 +634,7 @@ private:
FormatToken *FirstStartOfName;
bool IsExpression;
bool CanBeExpression;
+ bool InTemplateArgument;
bool InCtorInitializer;
bool CaretFound;
};
@@ -705,7 +712,8 @@ private:
} else if (Current.isOneOf(tok::star, tok::amp, tok::ampamp)) {
Current.Type =
determineStarAmpUsage(Current, Contexts.back().CanBeExpression &&
- Contexts.back().IsExpression);
+ Contexts.back().IsExpression,
+ Contexts.back().InTemplateArgument);
} else if (Current.isOneOf(tok::minus, tok::plus, tok::caret)) {
Current.Type = determinePlusMinusCaretUsage(Current);
if (Current.Type == TT_UnaryOperator) {
@@ -821,7 +829,8 @@ private:
}
/// \brief Return the type of the given token assuming it is * or &.
- TokenType determineStarAmpUsage(const FormatToken &Tok, bool IsExpression) {
+ TokenType determineStarAmpUsage(const FormatToken &Tok, bool IsExpression,
+ bool InTemplateArgument) {
const FormatToken *PrevToken = Tok.getPreviousNonComment();
if (PrevToken == NULL)
return TT_UnaryOperator;
@@ -851,7 +860,11 @@ private:
if (PrevToken->Tok.isLiteral() ||
PrevToken->isOneOf(tok::r_paren, tok::r_square) ||
- NextToken->Tok.isLiteral() || NextToken->isUnaryOperator())
+ NextToken->Tok.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.
+ (InTemplateArgument && NextToken->Tok.isAnyIdentifier()))
return TT_BinaryOperator;
// It is very unlikely that we are going to find a pointer or reference type
diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
index fa8ed3828d4..949167c8f56 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -4529,6 +4529,14 @@ TEST_F(FormatTest, UnderstandsUsesOfStarAndAmp) {
verifyFormat("delete *x;", PointerLeft);
verifyFormat("STATIC_ASSERT((a & b) == 0);");
verifyFormat("STATIC_ASSERT(0 == (a & b));");
+ verifyFormat("template <bool a, bool b> "
+ "typename t::if<x && y>::type f() {};");
+ verifyFormat("template <int *y> f() {};");
+ verifyFormat("vector<int *> v;");
+ verifyFormat("vector<int *const> v;");
+ verifyFormat("vector<int *const **const *> v;");
+ verifyFormat("vector<int *volatile> v;");
+ verifyFormat("vector<a * b> v;");
}
TEST_F(FormatTest, UnderstandsAttributes) {
OpenPOWER on IntegriCloud