[clang] [clang-format] Don't split "DPI"/"DPI-C" in Verilog imports (PR #66951)

via cfe-commits cfe-commits at lists.llvm.org
Thu Sep 21 03:23:09 PDT 2023


================
@@ -2270,7 +2270,18 @@ ContinuationIndenter::createBreakableToken(const FormatToken &Current,
     if (State.Stack.back().IsInsideObjCArrayLiteral)
       return nullptr;
 
+    // The "DPI"/"DPI-C" in SystemVerilog direct programming interface imports
+    // cannot be split, e.g.
+    // `import "DPI" function foo();`
     StringRef Text = Current.TokenText;
+    if (Style.isVerilog()) {
+      const FormatToken *Prev = Current.getPreviousNonComment();
+      if (Prev && Prev == State.Line->getFirstNonComment() &&
+          Prev->TokenText == "import") {
+        return nullptr;
+      }
+    }
+
----------------
alexfh wrote:

`isOneOf` won't work here, since the token has the type of `identifier` rather than a keyword:
```
Unwrapped lines:
Line(0, FSC=0): identifier[T=125, OC=0, "import"] string_literal[T=125, OC=7, ""DPI-C""] identifier[T=125, OC=15, "function"] identifier[T=125, OC=24, "t"] identifier[T=125, OC=26, "foo"]
Line(0, FSC=0): l_paren[T=120, OC=29, "("] r_paren[T=125, OC=30, ")"] semi[T=125, OC=31, ";"]
Line(1, FSC=0): eof[T=125, OC=32, ""]
Run 0...
AnnotatedTokens(L=0, P=0, T=5, C=0):
 M=0 C=0 T=Unknown S=1 F=0 B=0 BK=0 P=0 Name=identifier L=6 PPK=2 FakeLParens= FakeRParens=0 II=0x56180dc60ce8 Text='import'
 M=0 C=1 T=Unknown S=1 F=0 B=0 BK=0 P=23 Name=string_literal L=14 PPK=2 FakeLParens= FakeRParens=0 II=0x0 Text='"DPI-C"'
 M=0 C=0 T=Unknown S=1 F=0 B=0 BK=1 P=23 Name=identifier L=23 PPK=2 FakeLParens= FakeRParens=0 II=0x56180dc611f8 Text='function'
 M=0 C=0 T=Unknown S=1 F=0 B=0 BK=0 P=23 Name=identifier L=25 PPK=2 FakeLParens= FakeRParens=0 II=0x56180dc9b370 Text='t'
 M=0 C=0 T=Unknown S=1 F=0 B=0 BK=0 P=23 Name=identifier L=29 PPK=2 FakeLParens= FakeRParens=0 II=0x56180dc9b3a0 Text='foo'
----
AnnotatedTokens(L=0, P=0, T=5, C=1):
 M=0 C=0 T=VerilogMultiLineListLParen S=1 F=0 B=0 BK=0 P=0 Name=l_paren L=1 PPK=2 FakeLParens= FakeRParens=0 II=0x0 Text='('
 M=0 C=0 T=Unknown S=0 F=0 B=0 BK=0 P=140 Name=r_paren L=2 PPK=2 FakeLParens= FakeRParens=0 II=0x0 Text=')'
 M=0 C=0 T=Unknown S=0 F=0 B=0 BK=0 P=23 Name=semi L=3 PPK=2 FakeLParens= FakeRParens=0 II=0x0 Text=';'
----
AnnotatedTokens(L=1, P=0, T=5, C=0):
 M=0 C=0 T=Unknown S=1 F=0 B=0 BK=0 P=0 Name=eof L=0 PPK=2 FakeLParens= FakeRParens=0 II=0x0 Text=''
----
```

We should leave `Current.getPreviousNonComment()` to handle comments in the middle of the statement (something like `import /*"DPI"*/ "DPI-C" ...` comes to mind).

> Shouldn't we handle export as well?

Indeed, `export "DPI-C"` is also a valid construct, and thus, string literals after `export` should be exempt from breaking too.

> I don't think this is Verilog specific.

I'd suggest to address known cases with targeted exemptions to avoid surprises in random places.


```
      if (Style.isVerilog()) {
        const FormatToken *Prev = Current.getPreviousNonComment();
        if (Prev && Prev == State.Line->getFirstNonComment() &&
            (Prev->TokenText == "import" || Prev->TokenText == "export")) {
          return nullptr;
        }
      }
```

https://github.com/llvm/llvm-project/pull/66951


More information about the cfe-commits mailing list