MyDeveloperDay created this revision.
MyDeveloperDay added reviewers: krasimir, JakeMerdichAMD, mitchell-stellar.
MyDeveloperDay added projects: clang, clang-format.

https://bugs.llvm.org/show_bug.cgi?id=46159

Linux Kernel code using is try as a variable name (as its 'C' code they can), 
they interpreted as the 'try' keyword by clang-format causing odd formatting 
(see below)

We have no specific 'C' code handling, as this code could easily be in a '.h' 
file so need to handle this not based on extension alone.

This revision adds a FormatTokenLexer rule to identify either  try blocks "try 
{" or  function try block "try :" and if not, rename the "try" token to be an 
identifier

  static size_t get_kcore_size(int *nphdr, size_t *phdrs_len, size_t *notes_len,
                             size_t *data_offset)
  {
        size_t try, size;
        struct kcore_list *m;
  
        *nphdr = 1; /* PT_NOTE */
        size = 0;
  
        list_for_each_entry(m, &kclist_head, list) {
                try = kc_vaddr_to_offset((size_t)m->addr + m->size);
                if (try1 > size)
                        size = try1;
                *nphdr = *nphdr + 1;
        }
  }
  
  clang-format-10 formats it as:
  
  static size_t get_kcore_size(int *nphdr, size_t *phdrs_len, size_t *notes_len,
                               size_t *data_offset) {
    size_t try
      , size;
    struct kcore_list *m;
  
    *nphdr = 1; /* PT_NOTE */
    size = 0;
  
    list_for_each_entry(m, &kclist_head, list) {
      try
        = kc_vaddr_to_offset((size_t)m->addr + m->size);
      if (try > size)
        size = try
          ;
      *nphdr = *nphdr + 1;
    }
  }


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D80940

Files:
  clang/lib/Format/FormatTokenLexer.cpp
  clang/lib/Format/FormatTokenLexer.h
  clang/unittests/Format/FormatTest.cpp


Index: clang/unittests/Format/FormatTest.cpp
===================================================================
--- clang/unittests/Format/FormatTest.cpp
+++ clang/unittests/Format/FormatTest.cpp
@@ -2664,6 +2664,18 @@
   verifyIncompleteFormat("try {} catch (");
 }
 
+TEST_F(FormatTest, FormatTryAsAVariable) {
+  verifyFormat("int try;");
+  verifyFormat("int try, size;");
+  verifyFormat("try = foo();");
+  verifyFormat("if (try < size) {\n  return true;\n}");
+
+  verifyFormat("int catch;");
+  verifyFormat("int catch, size;");
+  verifyFormat("catch = foo();");
+  verifyFormat("if (catch < size) {\n  return true;\n}");
+}
+
 TEST_F(FormatTest, FormatSEHTryCatch) {
   verifyFormat("__try {\n"
                "  int a = b * c;\n"
Index: clang/lib/Format/FormatTokenLexer.h
===================================================================
--- clang/lib/Format/FormatTokenLexer.h
+++ clang/lib/Format/FormatTokenLexer.h
@@ -56,6 +56,7 @@
   bool tryMergeCSharpNullConditional();
   bool tryTransformCSharpForEach();
   bool tryMergeForEach();
+  bool tryTransformTryUsageForC();
 
   bool tryMergeTokens(ArrayRef<tok::TokenKind> Kinds, TokenType NewType);
 
Index: clang/lib/Format/FormatTokenLexer.cpp
===================================================================
--- clang/lib/Format/FormatTokenLexer.cpp
+++ clang/lib/Format/FormatTokenLexer.cpp
@@ -76,6 +76,8 @@
     return;
   if (tryMergeForEach())
     return;
+  if (Style.isCpp() && tryTransformTryUsageForC())
+    return;
 
   if (Style.isCSharp()) {
     if (tryMergeCSharpKeywordVariables())
@@ -383,6 +385,26 @@
   return true;
 }
 
+bool FormatTokenLexer::tryTransformTryUsageForC() {
+  if (Tokens.size() < 2)
+    return false;
+  auto &Try = *(Tokens.end() - 2);
+  auto &Brace = *(Tokens.end() - 1);
+  if (!Try->is(tok::kw_try))
+    return false;
+  if (Brace->isOneOf(tok::l_brace, tok::colon))
+    return false;
+
+  if (Tokens.size() > 2) {
+    auto &At = *(Tokens.end() - 3);
+    if (At->is(tok::at))
+      return false;
+  }
+
+  Try->Tok.setKind(tok::identifier);
+  return true;
+}
+
 bool FormatTokenLexer::tryMergeLessLess() {
   // Merge X,less,less,Y into X,lessless,Y unless X or Y is less.
   if (Tokens.size() < 3)


Index: clang/unittests/Format/FormatTest.cpp
===================================================================
--- clang/unittests/Format/FormatTest.cpp
+++ clang/unittests/Format/FormatTest.cpp
@@ -2664,6 +2664,18 @@
   verifyIncompleteFormat("try {} catch (");
 }
 
+TEST_F(FormatTest, FormatTryAsAVariable) {
+  verifyFormat("int try;");
+  verifyFormat("int try, size;");
+  verifyFormat("try = foo();");
+  verifyFormat("if (try < size) {\n  return true;\n}");
+
+  verifyFormat("int catch;");
+  verifyFormat("int catch, size;");
+  verifyFormat("catch = foo();");
+  verifyFormat("if (catch < size) {\n  return true;\n}");
+}
+
 TEST_F(FormatTest, FormatSEHTryCatch) {
   verifyFormat("__try {\n"
                "  int a = b * c;\n"
Index: clang/lib/Format/FormatTokenLexer.h
===================================================================
--- clang/lib/Format/FormatTokenLexer.h
+++ clang/lib/Format/FormatTokenLexer.h
@@ -56,6 +56,7 @@
   bool tryMergeCSharpNullConditional();
   bool tryTransformCSharpForEach();
   bool tryMergeForEach();
+  bool tryTransformTryUsageForC();
 
   bool tryMergeTokens(ArrayRef<tok::TokenKind> Kinds, TokenType NewType);
 
Index: clang/lib/Format/FormatTokenLexer.cpp
===================================================================
--- clang/lib/Format/FormatTokenLexer.cpp
+++ clang/lib/Format/FormatTokenLexer.cpp
@@ -76,6 +76,8 @@
     return;
   if (tryMergeForEach())
     return;
+  if (Style.isCpp() && tryTransformTryUsageForC())
+    return;
 
   if (Style.isCSharp()) {
     if (tryMergeCSharpKeywordVariables())
@@ -383,6 +385,26 @@
   return true;
 }
 
+bool FormatTokenLexer::tryTransformTryUsageForC() {
+  if (Tokens.size() < 2)
+    return false;
+  auto &Try = *(Tokens.end() - 2);
+  auto &Brace = *(Tokens.end() - 1);
+  if (!Try->is(tok::kw_try))
+    return false;
+  if (Brace->isOneOf(tok::l_brace, tok::colon))
+    return false;
+
+  if (Tokens.size() > 2) {
+    auto &At = *(Tokens.end() - 3);
+    if (At->is(tok::at))
+      return false;
+  }
+
+  Try->Tok.setKind(tok::identifier);
+  return true;
+}
+
 bool FormatTokenLexer::tryMergeLessLess() {
   // Merge X,less,less,Y into X,lessless,Y unless X or Y is less.
   if (Tokens.size() < 3)
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to