Skip to content

Commit 2e32ff1

Browse files
committed
[clang-format] Handle Verilog preprocessor directives
Verilog uses the backtick instead of the hash. In this revision backticks are lexed manually and then get labeled as hashes so the logic for handling C preprocessor stuff don't have to change. Hashes get labeled as identifiers for Verilog-specific stuff like delays. Reviewed By: HazardyKnusperkeks Differential Revision: https://reviews.llvm.org/D124749
1 parent 9ed2e68 commit 2e32ff1

File tree

6 files changed

+449
-44
lines changed

6 files changed

+449
-44
lines changed

clang/lib/Format/FormatToken.h

Lines changed: 205 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -988,6 +988,7 @@ struct AdditionalKeywords {
988988
kw_automatic = &IdentTable.get("automatic");
989989
kw_before = &IdentTable.get("before");
990990
kw_begin = &IdentTable.get("begin");
991+
kw_begin_keywords = &IdentTable.get("begin_keywords");
991992
kw_bins = &IdentTable.get("bins");
992993
kw_binsof = &IdentTable.get("binsof");
993994
kw_casex = &IdentTable.get("casex");
@@ -999,10 +1000,20 @@ struct AdditionalKeywords {
9991000
kw_cover = &IdentTable.get("cover");
10001001
kw_covergroup = &IdentTable.get("covergroup");
10011002
kw_coverpoint = &IdentTable.get("coverpoint");
1003+
kw_default_decay_time = &IdentTable.get("default_decay_time");
1004+
kw_default_nettype = &IdentTable.get("default_nettype");
1005+
kw_default_trireg_strength = &IdentTable.get("default_trireg_strength");
1006+
kw_delay_mode_distributed = &IdentTable.get("delay_mode_distributed");
1007+
kw_delay_mode_path = &IdentTable.get("delay_mode_path");
1008+
kw_delay_mode_unit = &IdentTable.get("delay_mode_unit");
1009+
kw_delay_mode_zero = &IdentTable.get("delay_mode_zero");
10021010
kw_disable = &IdentTable.get("disable");
10031011
kw_dist = &IdentTable.get("dist");
1012+
kw_elsif = &IdentTable.get("elsif");
10041013
kw_end = &IdentTable.get("end");
1014+
kw_end_keywords = &IdentTable.get("end_keywords");
10051015
kw_endcase = &IdentTable.get("endcase");
1016+
kw_endcelldefine = &IdentTable.get("endcelldefine");
10061017
kw_endchecker = &IdentTable.get("endchecker");
10071018
kw_endclass = &IdentTable.get("endclass");
10081019
kw_endclocking = &IdentTable.get("endclocking");
@@ -1043,6 +1054,7 @@ struct AdditionalKeywords {
10431054
kw_macromodule = &IdentTable.get("macromodule");
10441055
kw_matches = &IdentTable.get("matches");
10451056
kw_medium = &IdentTable.get("medium");
1057+
kw_nounconnected_drive = &IdentTable.get("nounconnected_drive");
10461058
kw_output = &IdentTable.get("output");
10471059
kw_packed = &IdentTable.get("packed");
10481060
kw_parameter = &IdentTable.get("parameter");
@@ -1058,6 +1070,7 @@ struct AdditionalKeywords {
10581070
kw_randcase = &IdentTable.get("randcase");
10591071
kw_randsequence = &IdentTable.get("randsequence");
10601072
kw_repeat = &IdentTable.get("repeat");
1073+
kw_resetall = &IdentTable.get("resetall");
10611074
kw_sample = &IdentTable.get("sample");
10621075
kw_scalared = &IdentTable.get("scalared");
10631076
kw_sequence = &IdentTable.get("sequence");
@@ -1073,12 +1086,15 @@ struct AdditionalKeywords {
10731086
kw_table = &IdentTable.get("table");
10741087
kw_tagged = &IdentTable.get("tagged");
10751088
kw_task = &IdentTable.get("task");
1089+
kw_timescale = &IdentTable.get("timescale");
10761090
kw_tri = &IdentTable.get("tri");
10771091
kw_tri0 = &IdentTable.get("tri0");
10781092
kw_tri1 = &IdentTable.get("tri1");
10791093
kw_triand = &IdentTable.get("triand");
10801094
kw_trior = &IdentTable.get("trior");
10811095
kw_trireg = &IdentTable.get("trireg");
1096+
kw_unconnected_drive = &IdentTable.get("unconnected_drive");
1097+
kw_undefineall = &IdentTable.get("undefineall");
10821098
kw_unique = &IdentTable.get("unique");
10831099
kw_unique0 = &IdentTable.get("unique0");
10841100
kw_uwire = &IdentTable.get("uwire");
@@ -1091,6 +1107,10 @@ struct AdditionalKeywords {
10911107
kw_with = &IdentTable.get("with");
10921108
kw_wor = &IdentTable.get("wor");
10931109

1110+
// Symbols that are treated as keywords.
1111+
kw_verilogHash = &IdentTable.get("#");
1112+
kw_verilogHashHash = &IdentTable.get("##");
1113+
10941114
// Keep this at the end of the constructor to make sure everything here
10951115
// is
10961116
// already initialized.
@@ -1118,38 +1138,132 @@ struct AdditionalKeywords {
11181138
// Some keywords are not included here because they don't need special
11191139
// treatment like `showcancelled` or they should be treated as identifiers
11201140
// like `int` and `logic`.
1121-
VerilogExtraKeywords = std::unordered_set<IdentifierInfo *>(
1122-
{kw_always, kw_always_comb, kw_always_ff, kw_always_latch,
1123-
kw_assert, kw_assign, kw_assume, kw_automatic,
1124-
kw_before, kw_begin, kw_bins, kw_binsof,
1125-
kw_casex, kw_casez, kw_celldefine, kw_checker,
1126-
kw_clocking, kw_constraint, kw_cover, kw_covergroup,
1127-
kw_coverpoint, kw_disable, kw_dist, kw_end,
1128-
kw_endcase, kw_endchecker, kw_endclass, kw_endclocking,
1129-
kw_endfunction, kw_endgenerate, kw_endgroup, kw_endinterface,
1130-
kw_endmodule, kw_endpackage, kw_endprimitive, kw_endprogram,
1131-
kw_endproperty, kw_endsequence, kw_endspecify, kw_endtable,
1132-
kw_endtask, kw_extends, kw_final, kw_foreach,
1133-
kw_forever, kw_fork, kw_function, kw_generate,
1134-
kw_highz0, kw_highz1, kw_iff, kw_ifnone,
1135-
kw_ignore_bins, kw_illegal_bins, kw_implements, kw_import,
1136-
kw_initial, kw_inout, kw_input, kw_inside,
1137-
kw_interconnect, kw_interface, kw_intersect, kw_join,
1138-
kw_join_any, kw_join_none, kw_large, kw_let,
1139-
kw_local, kw_localparam, kw_macromodule, kw_matches,
1140-
kw_medium, kw_output, kw_package, kw_packed,
1141-
kw_parameter, kw_primitive, kw_priority, kw_program,
1142-
kw_property, kw_pull0, kw_pull1, kw_pure,
1143-
kw_rand, kw_randc, kw_randcase, kw_randsequence,
1144-
kw_ref, kw_repeat, kw_sample, kw_scalared,
1145-
kw_sequence, kw_small, kw_soft, kw_solve,
1146-
kw_specify, kw_specparam, kw_strong0, kw_strong1,
1147-
kw_supply0, kw_supply1, kw_table, kw_tagged,
1148-
kw_task, kw_tri, kw_tri0, kw_tri1,
1149-
kw_triand, kw_trior, kw_trireg, kw_unique,
1150-
kw_unique0, kw_uwire, kw_var, kw_vectored,
1151-
kw_wand, kw_weak0, kw_weak1, kw_wildcard,
1152-
kw_wire, kw_with, kw_wor});
1141+
VerilogExtraKeywords =
1142+
std::unordered_set<IdentifierInfo *>({kw_always,
1143+
kw_always_comb,
1144+
kw_always_ff,
1145+
kw_always_latch,
1146+
kw_assert,
1147+
kw_assign,
1148+
kw_assume,
1149+
kw_automatic,
1150+
kw_before,
1151+
kw_begin,
1152+
kw_bins,
1153+
kw_binsof,
1154+
kw_casex,
1155+
kw_casez,
1156+
kw_celldefine,
1157+
kw_checker,
1158+
kw_clocking,
1159+
kw_constraint,
1160+
kw_cover,
1161+
kw_covergroup,
1162+
kw_coverpoint,
1163+
kw_disable,
1164+
kw_dist,
1165+
kw_end,
1166+
kw_endcase,
1167+
kw_endchecker,
1168+
kw_endclass,
1169+
kw_endclocking,
1170+
kw_endfunction,
1171+
kw_endgenerate,
1172+
kw_endgroup,
1173+
kw_endinterface,
1174+
kw_endmodule,
1175+
kw_endpackage,
1176+
kw_endprimitive,
1177+
kw_endprogram,
1178+
kw_endproperty,
1179+
kw_endsequence,
1180+
kw_endspecify,
1181+
kw_endtable,
1182+
kw_endtask,
1183+
kw_extends,
1184+
kw_final,
1185+
kw_foreach,
1186+
kw_forever,
1187+
kw_fork,
1188+
kw_function,
1189+
kw_generate,
1190+
kw_highz0,
1191+
kw_highz1,
1192+
kw_iff,
1193+
kw_ifnone,
1194+
kw_ignore_bins,
1195+
kw_illegal_bins,
1196+
kw_implements,
1197+
kw_import,
1198+
kw_initial,
1199+
kw_inout,
1200+
kw_input,
1201+
kw_inside,
1202+
kw_interconnect,
1203+
kw_interface,
1204+
kw_intersect,
1205+
kw_join,
1206+
kw_join_any,
1207+
kw_join_none,
1208+
kw_large,
1209+
kw_let,
1210+
kw_local,
1211+
kw_localparam,
1212+
kw_macromodule,
1213+
kw_matches,
1214+
kw_medium,
1215+
kw_output,
1216+
kw_package,
1217+
kw_packed,
1218+
kw_parameter,
1219+
kw_primitive,
1220+
kw_priority,
1221+
kw_program,
1222+
kw_property,
1223+
kw_pull0,
1224+
kw_pull1,
1225+
kw_pure,
1226+
kw_rand,
1227+
kw_randc,
1228+
kw_randcase,
1229+
kw_randsequence,
1230+
kw_ref,
1231+
kw_repeat,
1232+
kw_sample,
1233+
kw_scalared,
1234+
kw_sequence,
1235+
kw_small,
1236+
kw_soft,
1237+
kw_solve,
1238+
kw_specify,
1239+
kw_specparam,
1240+
kw_strong0,
1241+
kw_strong1,
1242+
kw_supply0,
1243+
kw_supply1,
1244+
kw_table,
1245+
kw_tagged,
1246+
kw_task,
1247+
kw_tri,
1248+
kw_tri0,
1249+
kw_tri1,
1250+
kw_triand,
1251+
kw_trior,
1252+
kw_trireg,
1253+
kw_unique,
1254+
kw_unique0,
1255+
kw_uwire,
1256+
kw_var,
1257+
kw_vectored,
1258+
kw_wand,
1259+
kw_weak0,
1260+
kw_weak1,
1261+
kw_wildcard,
1262+
kw_wire,
1263+
kw_with,
1264+
kw_wor,
1265+
kw_verilogHash,
1266+
kw_verilogHashHash});
11531267
}
11541268

11551269
// Context sensitive keywords.
@@ -1265,6 +1379,7 @@ struct AdditionalKeywords {
12651379
IdentifierInfo *kw_automatic;
12661380
IdentifierInfo *kw_before;
12671381
IdentifierInfo *kw_begin;
1382+
IdentifierInfo *kw_begin_keywords;
12681383
IdentifierInfo *kw_bins;
12691384
IdentifierInfo *kw_binsof;
12701385
IdentifierInfo *kw_casex;
@@ -1276,10 +1391,20 @@ struct AdditionalKeywords {
12761391
IdentifierInfo *kw_cover;
12771392
IdentifierInfo *kw_covergroup;
12781393
IdentifierInfo *kw_coverpoint;
1394+
IdentifierInfo *kw_default_decay_time;
1395+
IdentifierInfo *kw_default_nettype;
1396+
IdentifierInfo *kw_default_trireg_strength;
1397+
IdentifierInfo *kw_delay_mode_distributed;
1398+
IdentifierInfo *kw_delay_mode_path;
1399+
IdentifierInfo *kw_delay_mode_unit;
1400+
IdentifierInfo *kw_delay_mode_zero;
12791401
IdentifierInfo *kw_disable;
12801402
IdentifierInfo *kw_dist;
1403+
IdentifierInfo *kw_elsif;
12811404
IdentifierInfo *kw_end;
1405+
IdentifierInfo *kw_end_keywords;
12821406
IdentifierInfo *kw_endcase;
1407+
IdentifierInfo *kw_endcelldefine;
12831408
IdentifierInfo *kw_endchecker;
12841409
IdentifierInfo *kw_endclass;
12851410
IdentifierInfo *kw_endclocking;
@@ -1320,6 +1445,7 @@ struct AdditionalKeywords {
13201445
IdentifierInfo *kw_macromodule;
13211446
IdentifierInfo *kw_matches;
13221447
IdentifierInfo *kw_medium;
1448+
IdentifierInfo *kw_nounconnected_drive;
13231449
IdentifierInfo *kw_output;
13241450
IdentifierInfo *kw_packed;
13251451
IdentifierInfo *kw_parameter;
@@ -1335,6 +1461,7 @@ struct AdditionalKeywords {
13351461
IdentifierInfo *kw_randcase;
13361462
IdentifierInfo *kw_randsequence;
13371463
IdentifierInfo *kw_repeat;
1464+
IdentifierInfo *kw_resetall;
13381465
IdentifierInfo *kw_sample;
13391466
IdentifierInfo *kw_scalared;
13401467
IdentifierInfo *kw_sequence;
@@ -1350,12 +1477,15 @@ struct AdditionalKeywords {
13501477
IdentifierInfo *kw_table;
13511478
IdentifierInfo *kw_tagged;
13521479
IdentifierInfo *kw_task;
1353-
IdentifierInfo *kw_tri;
1480+
IdentifierInfo *kw_timescale;
13541481
IdentifierInfo *kw_tri0;
13551482
IdentifierInfo *kw_tri1;
1483+
IdentifierInfo *kw_tri;
13561484
IdentifierInfo *kw_triand;
13571485
IdentifierInfo *kw_trior;
13581486
IdentifierInfo *kw_trireg;
1487+
IdentifierInfo *kw_unconnected_drive;
1488+
IdentifierInfo *kw_undefineall;
13591489
IdentifierInfo *kw_unique;
13601490
IdentifierInfo *kw_unique0;
13611491
IdentifierInfo *kw_uwire;
@@ -1368,6 +1498,17 @@ struct AdditionalKeywords {
13681498
IdentifierInfo *kw_with;
13691499
IdentifierInfo *kw_wor;
13701500

1501+
// Workaround for hashes and backticks in Verilog.
1502+
IdentifierInfo *kw_verilogHash;
1503+
IdentifierInfo *kw_verilogHashHash;
1504+
1505+
/// Returns \c true if \p Tok is a keyword or an identifier.
1506+
bool isWordLike(const FormatToken &Tok) const {
1507+
// getIdentifierinfo returns non-null for keywords as well as identifiers.
1508+
return Tok.Tok.getIdentifierInfo() != nullptr &&
1509+
!Tok.isOneOf(kw_verilogHash, kw_verilogHashHash);
1510+
}
1511+
13711512
/// Returns \c true if \p Tok is a true JavaScript identifier, returns
13721513
/// \c false if it is a keyword or a pseudo keyword.
13731514
/// If \c AcceptIdentifierName is true, returns true not only for keywords,
@@ -1526,6 +1667,35 @@ struct AdditionalKeywords {
15261667
}
15271668
}
15281669

1670+
/// Returns whether \p Tok is a Verilog preprocessor directive. This is
1671+
/// needed because macro expansions start with a backtick as well and they
1672+
/// need to be treated differently.
1673+
bool isVerilogPPDirective(const FormatToken &Tok) const {
1674+
auto Info = Tok.Tok.getIdentifierInfo();
1675+
if (!Info)
1676+
return false;
1677+
switch (Info->getPPKeywordID()) {
1678+
case tok::pp_define:
1679+
case tok::pp_else:
1680+
case tok::pp_endif:
1681+
case tok::pp_ifdef:
1682+
case tok::pp_ifndef:
1683+
case tok::pp_include:
1684+
case tok::pp_line:
1685+
case tok::pp_pragma:
1686+
case tok::pp_undef:
1687+
return true;
1688+
default:
1689+
return Tok.isOneOf(kw_begin_keywords, kw_celldefine,
1690+
kw_default_decay_time, kw_default_nettype,
1691+
kw_default_trireg_strength, kw_delay_mode_distributed,
1692+
kw_delay_mode_path, kw_delay_mode_unit,
1693+
kw_delay_mode_zero, kw_elsif, kw_end_keywords,
1694+
kw_endcelldefine, kw_nounconnected_drive, kw_resetall,
1695+
kw_timescale, kw_unconnected_drive, kw_undefineall);
1696+
}
1697+
}
1698+
15291699
/// Returns whether \p Tok is a Verilog keyword that opens a block.
15301700
bool isVerilogBegin(const FormatToken &Tok) const {
15311701
// `table` is not included since it needs to be treated specially.
@@ -1541,8 +1711,8 @@ struct AdditionalKeywords {
15411711
kw_endgenerate, kw_endgroup, kw_endinterface,
15421712
kw_endmodule, kw_endpackage, kw_endprimitive,
15431713
kw_endprogram, kw_endproperty, kw_endsequence,
1544-
kw_endspecify, kw_endtable, kw_endtask, kw_join_any,
1545-
kw_join_none);
1714+
kw_endspecify, kw_endtable, kw_endtask, kw_join,
1715+
kw_join_any, kw_join_none);
15461716
}
15471717

15481718
/// Whether the token begins a block.

0 commit comments

Comments
 (0)