Skip to content

Commit 00f731f

Browse files
committed
[NFC][TableGen] Refactor preprocessor directive handling
- Make `PreprocessorDirs` array constexpr, move its definition outside the anonymous namespace, and make it static. - Change `Word` field to a StringRef. - Simplify `prepIsDirective` to use StringRef comparison and early `continue` per LLVM coding standards. - Use C++17 structured bindings to iterate over the array.
1 parent 0889809 commit 00f731f

File tree

1 file changed

+43
-54
lines changed

1 file changed

+43
-54
lines changed

llvm/lib/TableGen/TGLexer.cpp

Lines changed: 43 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,18 @@ using namespace llvm;
3232
namespace {
3333
// A list of supported preprocessing directives with their
3434
// internal token kinds and names.
35-
struct {
35+
struct PreprocessorDir {
3636
tgtok::TokKind Kind;
37-
const char *Word;
38-
} PreprocessorDirs[] = {
39-
{ tgtok::Ifdef, "ifdef" },
40-
{ tgtok::Ifndef, "ifndef" },
41-
{ tgtok::Else, "else" },
42-
{ tgtok::Endif, "endif" },
43-
{ tgtok::Define, "define" }
37+
StringRef Word;
4438
};
4539
} // end anonymous namespace
4640

41+
constexpr PreprocessorDir PreprocessorDirs[] = {{tgtok::Ifdef, "ifdef"},
42+
{tgtok::Ifndef, "ifndef"},
43+
{tgtok::Else, "else"},
44+
{tgtok::Endif, "endif"},
45+
{tgtok::Define, "define"}};
46+
4747
TGLexer::TGLexer(SourceMgr &SM, ArrayRef<std::string> Macros) : SrcMgr(SM) {
4848
CurBuffer = SrcMgr.getMainFileID();
4949
CurBuf = SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer();
@@ -641,54 +641,43 @@ bool TGLexer::prepExitInclude(bool IncludeStackMustBeEmpty) {
641641
}
642642

643643
tgtok::TokKind TGLexer::prepIsDirective() const {
644-
for (const auto &PD : PreprocessorDirs) {
645-
int NextChar = *CurPtr;
646-
bool Match = true;
647-
unsigned I = 0;
648-
for (; I < strlen(PD.Word); ++I) {
649-
if (NextChar != PD.Word[I]) {
650-
Match = false;
651-
break;
652-
}
653-
654-
NextChar = peekNextChar(I + 1);
655-
}
644+
for (const auto [Kind, Word] : PreprocessorDirs) {
645+
if (StringRef(CurPtr, Word.size()) != Word)
646+
continue;
647+
char NextChar = peekNextChar(Word.size());
656648

657-
// Check for whitespace after the directive. If there is no whitespace,
649+
// Check for whitespace after the directive. If there is no whitespace,
658650
// then we do not recognize it as a preprocessing directive.
659-
if (Match) {
660-
tgtok::TokKind Kind = PD.Kind;
661-
662-
// New line and EOF may follow only #else/#endif. It will be reported
663-
// as an error for #ifdef/#define after the call to prepLexMacroName().
664-
if (NextChar == ' ' || NextChar == '\t' || NextChar == EOF ||
665-
NextChar == '\n' ||
666-
// It looks like TableGen does not support '\r' as the actual
667-
// carriage return, e.g. getNextChar() treats a single '\r'
668-
// as '\n'. So we do the same here.
669-
NextChar == '\r')
670-
return Kind;
671651

672-
// Allow comments after some directives, e.g.:
673-
// #else// OR #else/**/
674-
// #endif// OR #endif/**/
675-
//
676-
// Note that we do allow comments after #ifdef/#define here, e.g.
677-
// #ifdef/**/ AND #ifdef//
678-
// #define/**/ AND #define//
679-
//
680-
// These cases will be reported as incorrect after calling
681-
// prepLexMacroName(). We could have supported C-style comments
682-
// after #ifdef/#define, but this would complicate the code
683-
// for little benefit.
684-
if (NextChar == '/') {
685-
NextChar = peekNextChar(I + 1);
652+
// New line and EOF may follow only #else/#endif. It will be reported
653+
// as an error for #ifdef/#define after the call to prepLexMacroName().
654+
if (NextChar == ' ' || NextChar == '\t' || NextChar == EOF ||
655+
NextChar == '\n' ||
656+
// It looks like TableGen does not support '\r' as the actual
657+
// carriage return, e.g. getNextChar() treats a single '\r'
658+
// as '\n'. So we do the same here.
659+
NextChar == '\r')
660+
return Kind;
686661

687-
if (NextChar == '*' || NextChar == '/')
688-
return Kind;
662+
// Allow comments after some directives, e.g.:
663+
// #else// OR #else/**/
664+
// #endif// OR #endif/**/
665+
//
666+
// Note that we do allow comments after #ifdef/#define here, e.g.
667+
// #ifdef/**/ AND #ifdef//
668+
// #define/**/ AND #define//
669+
//
670+
// These cases will be reported as incorrect after calling
671+
// prepLexMacroName(). We could have supported C-style comments
672+
// after #ifdef/#define, but this would complicate the code
673+
// for little benefit.
674+
if (NextChar == '/') {
675+
NextChar = peekNextChar(Word.size() + 1);
676+
677+
if (NextChar == '*' || NextChar == '/')
678+
return Kind;
689679

690-
// Pretend that we do not recognize the directive.
691-
}
680+
// Pretend that we do not recognize the directive.
692681
}
693682
}
694683

@@ -698,10 +687,10 @@ tgtok::TokKind TGLexer::prepIsDirective() const {
698687
bool TGLexer::prepEatPreprocessorDirective(tgtok::TokKind Kind) {
699688
TokStart = CurPtr;
700689

701-
for (const auto &PD : PreprocessorDirs)
702-
if (PD.Kind == Kind) {
690+
for (const auto [PKind, PWord] : PreprocessorDirs)
691+
if (PKind == Kind) {
703692
// Advance CurPtr to the end of the preprocessing word.
704-
CurPtr += strlen(PD.Word);
693+
CurPtr += PWord.size();
705694
return true;
706695
}
707696

0 commit comments

Comments
 (0)