r228148 - clang-format: Add support for SEH __try / __except / __finally blocks.

Nico Weber nicolasweber at gmx.de
Wed Feb 4 07:26:27 PST 2015


Author: nico
Date: Wed Feb  4 09:26:27 2015
New Revision: 228148

URL: http://llvm.org/viewvc/llvm-project?rev=228148&view=rev
Log:
clang-format: Add support for SEH __try / __except / __finally blocks.

This lets clang-format format

    __try {
    } __except(0) {
    }

and

    __try {
    } __finally {
    }

correctly. __try and __finally are keywords if `LangOpts.MicrosoftExt` is set,
so this turns this on.  This also enables a few other keywords, but it
shouldn't overly perturb regular clang-format operation.  __except is a
context-sensitive keyword, so `AdditionalKeywords` needs to be passed around to
a few more places.

Fixes PR22321.

Modified:
    cfe/trunk/lib/Format/Format.cpp
    cfe/trunk/lib/Format/FormatToken.h
    cfe/trunk/lib/Format/TokenAnnotator.cpp
    cfe/trunk/lib/Format/UnwrappedLineFormatter.cpp
    cfe/trunk/lib/Format/UnwrappedLineFormatter.h
    cfe/trunk/lib/Format/UnwrappedLineParser.cpp
    cfe/trunk/unittests/Format/FormatTest.cpp

Modified: cfe/trunk/lib/Format/Format.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/Format.cpp?rev=228148&r1=228147&r2=228148&view=diff
==============================================================================
--- cfe/trunk/lib/Format/Format.cpp (original)
+++ cfe/trunk/lib/Format/Format.cpp Wed Feb  4 09:26:27 2015
@@ -1123,7 +1123,8 @@ public:
     ContinuationIndenter Indenter(Style, Tokens.getKeywords(), SourceMgr,
                                   Whitespaces, Encoding,
                                   BinPackInconclusiveFunctions);
-    UnwrappedLineFormatter Formatter(&Indenter, &Whitespaces, Style);
+    UnwrappedLineFormatter Formatter(&Indenter, &Whitespaces, Style,
+                                     Tokens.getKeywords());
     Formatter.format(AnnotatedLines, /*DryRun=*/false);
     return Whitespaces.generateReplacements();
   }
@@ -1399,6 +1400,7 @@ LangOptions getFormattingLangOpts(const
   LangOpts.Bool = 1;
   LangOpts.ObjC1 = 1;
   LangOpts.ObjC2 = 1;
+  LangOpts.MicrosoftExt = 1; // To get kw___try, kw___finally.
   return LangOpts;
 }
 

Modified: cfe/trunk/lib/Format/FormatToken.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/FormatToken.h?rev=228148&r1=228147&r2=228148&view=diff
==============================================================================
--- cfe/trunk/lib/Format/FormatToken.h (original)
+++ cfe/trunk/lib/Format/FormatToken.h Wed Feb  4 09:26:27 2015
@@ -555,6 +555,7 @@ struct AdditionalKeywords {
     kw_package = &IdentTable.get("package");
     kw_synchronized = &IdentTable.get("synchronized");
     kw_throws = &IdentTable.get("throws");
+    kw___except = &IdentTable.get("__except");
 
     kw_option = &IdentTable.get("option");
     kw_optional = &IdentTable.get("optional");
@@ -563,12 +564,13 @@ struct AdditionalKeywords {
     kw_returns = &IdentTable.get("returns");
   }
 
-  // ObjC context sensitive keywords.
+  // Context sensitive keywords.
   IdentifierInfo *kw_in;
   IdentifierInfo *kw_CF_ENUM;
   IdentifierInfo *kw_CF_OPTIONS;
   IdentifierInfo *kw_NS_ENUM;
   IdentifierInfo *kw_NS_OPTIONS;
+  IdentifierInfo *kw___except;
 
   // JavaScript keywords.
   IdentifierInfo *kw_finally;

Modified: cfe/trunk/lib/Format/TokenAnnotator.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.cpp?rev=228148&r1=228147&r2=228148&view=diff
==============================================================================
--- cfe/trunk/lib/Format/TokenAnnotator.cpp (original)
+++ cfe/trunk/lib/Format/TokenAnnotator.cpp Wed Feb  4 09:26:27 2015
@@ -1701,8 +1701,8 @@ bool TokenAnnotator::spaceRequiredBetwee
            (Style.SpaceBeforeParens != FormatStyle::SBPO_Never &&
             (Left.isOneOf(tok::kw_if, tok::kw_for, tok::kw_while,
                           tok::kw_switch, tok::kw_case) ||
-             (Left.isOneOf(tok::kw_try, tok::kw_catch, tok::kw_new,
-                           tok::kw_delete) &&
+             (Left.isOneOf(tok::kw_try, Keywords.kw___except, tok::kw_catch,
+                           tok::kw_new, tok::kw_delete) &&
               (!Left.Previous || Left.Previous->isNot(tok::period))) ||
              Left.IsForEachMacro)) ||
            (Style.SpaceBeforeParens == FormatStyle::SBPO_Always &&

Modified: cfe/trunk/lib/Format/UnwrappedLineFormatter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/UnwrappedLineFormatter.cpp?rev=228148&r1=228147&r2=228148&view=diff
==============================================================================
--- cfe/trunk/lib/Format/UnwrappedLineFormatter.cpp (original)
+++ cfe/trunk/lib/Format/UnwrappedLineFormatter.cpp Wed Feb  4 09:26:27 2015
@@ -27,7 +27,8 @@ bool startsExternCBlock(const AnnotatedL
 
 class LineJoiner {
 public:
-  LineJoiner(const FormatStyle &Style) : Style(Style) {}
+  LineJoiner(const FormatStyle &Style, const AdditionalKeywords &Keywords)
+      : Style(Style), Keywords(Keywords) {}
 
   /// \brief Calculates how many lines can be merged into 1 starting at \p I.
   unsigned
@@ -200,7 +201,9 @@ private:
     if (Line.First->isOneOf(tok::kw_else, tok::kw_case))
       return 0;
     if (Line.First->isOneOf(tok::kw_if, tok::kw_while, tok::kw_do, tok::kw_try,
-                            tok::kw_catch, tok::kw_for, tok::r_brace)) {
+                            tok::kw___try, tok::kw_catch, tok::kw___finally,
+                            tok::kw_for, tok::r_brace) ||
+        Line.First->is(Keywords.kw___except)) {
       if (!Style.AllowShortBlocksOnASingleLine)
         return 0;
       if (!Style.AllowShortIfStatementsOnASingleLine &&
@@ -211,7 +214,11 @@ private:
         return 0;
       // FIXME: Consider an option to allow short exception handling clauses on
       // a single line.
-      if (Line.First->isOneOf(tok::kw_try, tok::kw_catch))
+      // FIXME: This isn't covered by tests.
+      // FIXME: For catch, __except, __finally the first token on the line
+      // is '}', so this isn't correct here.
+      if (Line.First->isOneOf(tok::kw_try, tok::kw___try, tok::kw_catch,
+                              Keywords.kw___except, tok::kw___finally))
         return 0;
     }
 
@@ -286,6 +293,7 @@ private:
   }
 
   const FormatStyle &Style;
+  const AdditionalKeywords &Keywords;
 };
 
 class NoColumnLimitFormatter {
@@ -324,7 +332,7 @@ unsigned
 UnwrappedLineFormatter::format(const SmallVectorImpl<AnnotatedLine *> &Lines,
                                bool DryRun, int AdditionalIndent,
                                bool FixBadIndentation) {
-  LineJoiner Joiner(Style);
+  LineJoiner Joiner(Style, Keywords);
 
   // Try to look up already computed penalty in DryRun-mode.
   std::pair<const SmallVectorImpl<AnnotatedLine *> *, unsigned> CacheKey(

Modified: cfe/trunk/lib/Format/UnwrappedLineFormatter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/UnwrappedLineFormatter.h?rev=228148&r1=228147&r2=228148&view=diff
==============================================================================
--- cfe/trunk/lib/Format/UnwrappedLineFormatter.h (original)
+++ cfe/trunk/lib/Format/UnwrappedLineFormatter.h Wed Feb  4 09:26:27 2015
@@ -32,8 +32,10 @@ class UnwrappedLineFormatter {
 public:
   UnwrappedLineFormatter(ContinuationIndenter *Indenter,
                          WhitespaceManager *Whitespaces,
-                         const FormatStyle &Style)
-      : Indenter(Indenter), Whitespaces(Whitespaces), Style(Style) {}
+                         const FormatStyle &Style,
+                         const AdditionalKeywords &Keywords)
+      : Indenter(Indenter), Whitespaces(Whitespaces), Style(Style),
+        Keywords(Keywords) {}
 
   unsigned format(const SmallVectorImpl<AnnotatedLine *> &Lines, bool DryRun,
                   int AdditionalIndent = 0, bool FixBadIndentation = false);
@@ -153,6 +155,7 @@ private:
   ContinuationIndenter *Indenter;
   WhitespaceManager *Whitespaces;
   FormatStyle Style;
+  const AdditionalKeywords &Keywords;
 
   llvm::SpecificBumpPtrAllocator<StateNode> Allocator;
 

Modified: cfe/trunk/lib/Format/UnwrappedLineParser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/UnwrappedLineParser.cpp?rev=228148&r1=228147&r2=228148&view=diff
==============================================================================
--- cfe/trunk/lib/Format/UnwrappedLineParser.cpp (original)
+++ cfe/trunk/lib/Format/UnwrappedLineParser.cpp Wed Feb  4 09:26:27 2015
@@ -374,6 +374,7 @@ void UnwrappedLineParser::calculateBrace
     case tok::kw_for:
     case tok::kw_switch:
     case tok::kw_try:
+    case tok::kw___try:
       if (!LBraceStack.empty())
         LBraceStack.back()->BlockKind = BK_Block;
       break;
@@ -713,6 +714,7 @@ void UnwrappedLineParser::parseStructura
     parseCaseLabel();
     return;
   case tok::kw_try:
+  case tok::kw___try:
     parseTryCatch();
     return;
   case tok::kw_extern:
@@ -1149,7 +1151,7 @@ void UnwrappedLineParser::parseIfThenEls
 }
 
 void UnwrappedLineParser::parseTryCatch() {
-  assert(FormatTok->is(tok::kw_try) && "'try' expected");
+  assert(FormatTok->isOneOf(tok::kw_try, tok::kw___try) && "'try' expected");
   nextToken();
   bool NeedsUnwrappedLine = false;
   if (FormatTok->is(tok::colon)) {
@@ -1189,7 +1191,8 @@ void UnwrappedLineParser::parseTryCatch(
     parseStructuralElement();
     --Line->Level;
   }
-  while (FormatTok->is(tok::kw_catch) ||
+  while (FormatTok->isOneOf(tok::kw_catch, Keywords.kw___except,
+                            tok::kw___finally) ||
          ((Style.Language == FormatStyle::LK_Java ||
            Style.Language == FormatStyle::LK_JavaScript) &&
           FormatTok->is(Keywords.kw_finally))) {

Modified: cfe/trunk/unittests/Format/FormatTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTest.cpp?rev=228148&r1=228147&r2=228148&view=diff
==============================================================================
--- cfe/trunk/unittests/Format/FormatTest.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTest.cpp Wed Feb  4 09:26:27 2015
@@ -2244,6 +2244,26 @@ TEST_F(FormatTest, FormatTryCatch) {
   verifyFormat("try {} catch (");
 }
 
+TEST_F(FormatTest, FormatSEHTryCatch) {
+  verifyFormat("__try {\n"
+               "  int a = b * c;\n"
+               "} __except (EXCEPTION_EXECUTE_HANDLER) {\n"
+               "  // Do nothing.\n"
+               "}");
+
+  verifyFormat("__try {\n"
+               "  int a = b * c;\n"
+               "} __finally {\n"
+               "  // Do nothing.\n"
+               "}");
+
+  verifyFormat("DEBUG({\n"
+               "  __try {\n"
+               "  } __finally {\n"
+               "  }\n"
+               "});\n");
+}
+
 TEST_F(FormatTest, IncompleteTryCatchBlocks) {
   verifyFormat("try {\n"
                "  f();\n"
@@ -2276,6 +2296,13 @@ TEST_F(FormatTest, FormatTryCatchBraceSt
                "  // something\n"
                "}",
                Style);
+  verifyFormat("__try {\n"
+               "  // something\n"
+               "}\n"
+               "__finally {\n"
+               "  // something\n"
+               "}",
+               Style);
   Style.BreakBeforeBraces = FormatStyle::BS_Allman;
   verifyFormat("try\n"
                "{\n"





More information about the cfe-commits mailing list