From 40aacf48726c5a7998e5c0ba2eeb7f1b8dc110be Mon Sep 17 00:00:00 2001 From: Daniel Jasper Date: Thu, 14 Mar 2013 13:45:21 +0000 Subject: [PATCH] Basic support for formatting asm() statments. llvm-svn: 177073 --- clang/lib/Format/Format.cpp | 4 ++-- clang/lib/Format/TokenAnnotator.cpp | 40 +++++++++++++++++++++-------------- clang/lib/Format/TokenAnnotator.h | 1 + clang/unittests/Format/FormatTest.cpp | 10 +++++++++ 4 files changed, 37 insertions(+), 18 deletions(-) diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index 63edc6e..ab895c7 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -553,8 +553,6 @@ private: State.Stack.back().LastSpace = State.Column; State.StartOfLineLevel = State.ParenLevel; - if (Current.is(tok::colon) && Current.Type != TT_ConditionalExpr) - State.Stack.back().Indent += 2; // Any break on this level means that the parent level has been broken // and we need to avoid bin packing there. @@ -1000,6 +998,8 @@ private: (State.NextToken->Parent->ClosesTemplateDeclaration && State.ParenLevel == 0))) return true; + if (State.NextToken->Type == TT_InlineASMColon) + return true; return false; } diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 93eeb7f..e878a96 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -92,14 +92,14 @@ public: IdentifierInfo &Ident_in) : SourceMgr(SourceMgr), Lex(Lex), Line(Line), CurrentToken(&Line.First), KeywordVirtualFound(false), Ident_in(Ident_in) { - Contexts.push_back(Context(1, /*IsExpression=*/ false)); + Contexts.push_back(Context(tok::unknown, 1, /*IsExpression=*/ false)); } private: bool parseAngle() { if (CurrentToken == NULL) return false; - ScopedContextCreator ContextCreator(*this, 10); + ScopedContextCreator ContextCreator(*this, tok::less, 10); AnnotatedToken *Left = CurrentToken->Parent; Contexts.back().IsExpression = false; while (CurrentToken != NULL) { @@ -124,7 +124,7 @@ private: bool parseParens(bool LookForDecls = false) { if (CurrentToken == NULL) return false; - ScopedContextCreator ContextCreator(*this, 1); + ScopedContextCreator ContextCreator(*this, tok::l_paren, 1); // FIXME: This is a bit of a hack. Do better. Contexts.back().ColonIsForRangeExpr = @@ -205,7 +205,7 @@ private: Parent->Type == TT_CastRParen || getBinOpPrecedence(Parent->FormatTok.Tok.getKind(), true, true) > prec::Unknown); - ScopedContextCreator ContextCreator(*this, 10); + ScopedContextCreator ContextCreator(*this, tok::l_square, 10); Contexts.back().IsExpression = true; bool StartsObjCArrayLiteral = Parent && Parent->is(tok::at); @@ -256,7 +256,7 @@ private: // Lines are fine to end with '{'. if (CurrentToken == NULL) return true; - ScopedContextCreator ContextCreator(*this, 1); + ScopedContextCreator ContextCreator(*this, tok::l_brace, 1); AnnotatedToken *Left = CurrentToken->Parent; while (CurrentToken != NULL) { if (CurrentToken->is(tok::r_brace)) { @@ -320,7 +320,7 @@ private: break; case tok::colon: // Colons from ?: are handled in parseConditional(). - if (Tok->Parent->is(tok::r_paren)) { + if (Tok->Parent->is(tok::r_paren) && Contexts.size() == 1) { Tok->Type = TT_CtorInitializerColon; } else if (Contexts.back().ColonIsObjCMethodExpr || Line.First.Type == TT_ObjCMethodSpecifier) { @@ -336,6 +336,8 @@ private: Tok->Type = TT_RangeBasedForLoopColon; } else if (Contexts.size() == 1) { Tok->Type = TT_InheritanceColon; + } else if (Contexts.back().ContextKind == tok::l_paren) { + Tok->Type = TT_InlineASMColon; } break; case tok::kw_if: @@ -531,12 +533,14 @@ private: /// \brief A struct to hold information valid in a specific context, e.g. /// a pair of parenthesis. struct Context { - Context(unsigned BindingStrength, bool IsExpression) - : BindingStrength(BindingStrength), LongestObjCSelectorName(0), - ColonIsForRangeExpr(false), ColonIsObjCMethodExpr(false), - FirstObjCSelectorName(NULL), IsExpression(IsExpression), - CanBeExpression(true) {} - + Context(tok::TokenKind ContextKind, unsigned BindingStrength, + bool IsExpression) + : ContextKind(ContextKind), BindingStrength(BindingStrength), + LongestObjCSelectorName(0), ColonIsForRangeExpr(false), + ColonIsObjCMethodExpr(false), FirstObjCSelectorName(NULL), + IsExpression(IsExpression), CanBeExpression(true) {} + + tok::TokenKind ContextKind; unsigned BindingStrength; unsigned LongestObjCSelectorName; bool ColonIsForRangeExpr; @@ -551,9 +555,12 @@ private: struct ScopedContextCreator { AnnotatingParser &P; - ScopedContextCreator(AnnotatingParser &P, unsigned Increase) : P(P) { - P.Contexts.push_back(Context(P.Contexts.back().BindingStrength + Increase, - P.Contexts.back().IsExpression)); + ScopedContextCreator(AnnotatingParser &P, tok::TokenKind ContextKind, + unsigned Increase) + : P(P) { + P.Contexts.push_back( + Context(ContextKind, P.Contexts.back().BindingStrength + Increase, + P.Contexts.back().IsExpression)); } ~ScopedContextCreator() { P.Contexts.pop_back(); } @@ -755,7 +762,8 @@ public: if (Current) { if (Current->Type == TT_ConditionalExpr) CurrentPrecedence = 1 + (int) prec::Conditional; - else if (Current->is(tok::semi)) + else if (Current->is(tok::semi) || Current->Type == TT_InlineASMColon || + Current->Type == TT_CtorInitializerColon) CurrentPrecedence = 1; else if (Current->Type == TT_BinaryOperator || Current->is(tok::comma)) CurrentPrecedence = 1 + (int) getPrecedence(*Current); diff --git a/clang/lib/Format/TokenAnnotator.h b/clang/lib/Format/TokenAnnotator.h index 2b93836..9296844 100644 --- a/clang/lib/Format/TokenAnnotator.h +++ b/clang/lib/Format/TokenAnnotator.h @@ -34,6 +34,7 @@ enum TokenType { TT_ConditionalExpr, TT_CtorInitializerColon, TT_ImplicitStringLiteral, + TT_InlineASMColon, TT_InheritanceColon, TT_LineComment, TT_ObjCArrayLiteral, diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 86b98b3..af580dd 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -776,6 +776,16 @@ TEST_F(FormatTest, FormatsNamespaces) { TEST_F(FormatTest, FormatsExternC) { verifyFormat("extern \"C\" {\nint a;"); } +TEST_F(FormatTest, FormatsInlineASM) { + verifyFormat("asm(\"xyz\" : \"=a\"(a), \"=d\"(b) : \"a\"(data));"); + verifyFormat( + "asm(\"movq\\t%%rbx, %%rsi\\n\\t\"\n" + " \"cpuid\\n\\t\"\n" + " \"xchgq\\t%%rbx, %%rsi\\n\\t\"\n" + " : \"=a\" (*rEAX), \"=S\" (*rEBX), \"=c\" (*rECX), \"=d\" (*rEDX)\n" + " : \"a\"(value));"); +} + TEST_F(FormatTest, FormatTryCatch) { // FIXME: Handle try-catch explicitly in the UnwrappedLineParser, then we'll // also not create single-line-blocks. -- 2.7.4