[llvm] [Frontend][OpenMP] Implement directive name parser (PR #146776)
Krzysztof Parzyszek via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 3 08:05:05 PDT 2025
https://github.com/kparzysz updated https://github.com/llvm/llvm-project/pull/146776
>From 0e9eab649f7a515c0697c3fe58309c478108f6b1 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Wed, 2 Jul 2025 09:43:32 -0500
Subject: [PATCH 1/6] [Frontend][OpenMP] Implement directive name parser
Implement a state machine that consumes tokens (words delimited by white
space), and returns the corresponding directive id, or fails if the tokens
did not form a valid name.
---
.../Frontend/OpenMP/DirectiveNameParser.h | 76 ++++++++
llvm/lib/Frontend/OpenMP/CMakeLists.txt | 1 +
.../Frontend/OpenMP/DirectiveNameParser.cpp | 93 ++++++++++
llvm/unittests/Frontend/CMakeLists.txt | 1 +
.../OpenMPDirectiveNameParserTest.cpp | 171 ++++++++++++++++++
5 files changed, 342 insertions(+)
create mode 100644 llvm/include/llvm/Frontend/OpenMP/DirectiveNameParser.h
create mode 100644 llvm/lib/Frontend/OpenMP/DirectiveNameParser.cpp
create mode 100644 llvm/unittests/Frontend/OpenMPDirectiveNameParserTest.cpp
diff --git a/llvm/include/llvm/Frontend/OpenMP/DirectiveNameParser.h b/llvm/include/llvm/Frontend/OpenMP/DirectiveNameParser.h
new file mode 100644
index 0000000000000..db8986601b2ca
--- /dev/null
+++ b/llvm/include/llvm/Frontend/OpenMP/DirectiveNameParser.h
@@ -0,0 +1,76 @@
+//===- DirectiveNameParser.h ------------------------------------- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_FRONTEND_OPENMP_DIRECTIVENAMEPARSER_H
+#define LLVM_FRONTEND_OPENMP_DIRECTIVENAMEPARSER_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Frontend/OpenMP/OMP.h"
+
+#include <memory>
+
+namespace llvm::omp {
+/// Parser class for OpenMP directive names. It only recognizes names listed
+/// in OMP.td, in particular it does not recognize Fortran's end-directives
+/// if they are not explicitly listed in OMP.td.
+///
+/// The class itself may be a singleton, once it's constructed it never
+/// changes.
+///
+/// Usage:
+/// {
+/// DirectiveNameParser Parser; // Could be static const.
+///
+/// DirectiveNameParser::State *S = Parser.initial();
+/// for (StringRef Token : Tokens)
+/// S = Parser.apply(S, Token); // Passing nullptr is ok.
+///
+/// if (S == nullptr) {
+/// // Error: ended up in a state from which there is no possible path
+/// // to a successful parse.
+/// } else if (S->Value == OMPD_unknown)
+/// // Parsed a sequence of tokens that are not a complete name, but
+/// // parsing more tokens could lead to a successful parse.
+/// } else {
+/// // Success.
+/// ParsedId = S->Value;
+/// }
+/// }
+struct DirectiveNameParser {
+ DirectiveNameParser(SourceLanguage L = SourceLanguage::C);
+
+ struct State {
+ Directive Value = Directive::OMPD_unknown;
+
+ private:
+ using TransitionMapTy = StringMap<State>;
+ std::unique_ptr<TransitionMapTy> Transition;
+
+ State *next(StringRef Tok);
+ bool isValid() const {
+ return Value != Directive::OMPD_unknown || !Transition->empty();
+ }
+ friend struct DirectiveNameParser;
+ };
+
+ const State *initial() const { return &InitialState; }
+ const State *apply(const State *Current, StringRef Tok) const;
+
+ static SmallVector<StringRef> tokenize(StringRef N);
+
+private:
+ void insertName(StringRef Name, Directive D);
+ State *insertTransition(State *From, StringRef Tok);
+
+ State InitialState;
+};
+} // namespace llvm::omp
+
+#endif // LLVM_FRONTEND_OPENMP_DIRECTIVENAMEPARSER_H
diff --git a/llvm/lib/Frontend/OpenMP/CMakeLists.txt b/llvm/lib/Frontend/OpenMP/CMakeLists.txt
index 5bf15ca3a8991..e60b59c1203b9 100644
--- a/llvm/lib/Frontend/OpenMP/CMakeLists.txt
+++ b/llvm/lib/Frontend/OpenMP/CMakeLists.txt
@@ -2,6 +2,7 @@ add_llvm_component_library(LLVMFrontendOpenMP
OMP.cpp
OMPContext.cpp
OMPIRBuilder.cpp
+ DirectiveNameParser.cpp
ADDITIONAL_HEADER_DIRS
${LLVM_MAIN_INCLUDE_DIR}/llvm/Frontend
diff --git a/llvm/lib/Frontend/OpenMP/DirectiveNameParser.cpp b/llvm/lib/Frontend/OpenMP/DirectiveNameParser.cpp
new file mode 100644
index 0000000000000..02ff8327a3054
--- /dev/null
+++ b/llvm/lib/Frontend/OpenMP/DirectiveNameParser.cpp
@@ -0,0 +1,93 @@
+//===- DirectiveNameParser.cpp --------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Frontend/OpenMP/DirectiveNameParser.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Frontend/OpenMP/OMP.h"
+
+#include <cassert>
+#include <memory>
+
+namespace llvm::omp {
+DirectiveNameParser::DirectiveNameParser(SourceLanguage L) {
+ // Take every directive, get its name in every version, break the name up
+ // into whitespace-separated tokens, and insert each token.
+ for (size_t I = 0, E = Directive_enumSize; I != E; ++I) {
+ auto D = static_cast<Directive>(I);
+ if (D == Directive::OMPD_unknown || !(getDirectiveLanguages(D) & L))
+ continue;
+ for (unsigned Ver : getOpenMPVersions())
+ insertName(getOpenMPDirectiveName(D, Ver), D);
+ }
+}
+
+const DirectiveNameParser::State *
+DirectiveNameParser::apply(const State *Current, StringRef Tok) const {
+ if (!Current)
+ return Current;
+ assert(Current->isValid() && "Invalid input state");
+ if (const State *Next = const_cast<State *>(Current)->next(Tok))
+ return Next->isValid() ? Next : nullptr;
+ return nullptr;
+}
+
+SmallVector<StringRef> DirectiveNameParser::tokenize(StringRef Str) {
+ SmallVector<StringRef> Tokens;
+
+ auto nextChar = [](StringRef N, size_t I) {
+ while (I < N.size() && N[I] == ' ')
+ ++I;
+ return I;
+ };
+ auto nextSpace = [](StringRef N, size_t I) {
+ size_t S = N.find(' ', I);
+ return S != StringRef::npos ? S : N.size();
+ };
+
+ size_t From = nextChar(Str, 0);
+ size_t To = 0;
+
+ while (From != Str.size()) {
+ To = nextSpace(Str, From);
+ Tokens.push_back(Str.substr(From, To - From));
+ From = nextChar(Str, To);
+ }
+
+ return Tokens;
+}
+
+void DirectiveNameParser::insertName(StringRef Name, Directive D) {
+ State *Where = &InitialState;
+
+ for (StringRef Tok : tokenize(Name))
+ Where = insertTransition(Where, Tok);
+
+ Where->Value = D;
+}
+
+DirectiveNameParser::State *
+DirectiveNameParser::insertTransition(State *From, StringRef Tok) {
+ assert(From && "Expecting state");
+ if (!From->Transition) {
+ From->Transition = std::make_unique<State::TransitionMapTy>();
+ }
+ if (State *Next = From->next(Tok))
+ return Next;
+
+ auto [Where, DidIt] = From->Transition->try_emplace(Tok, State());
+ assert(DidIt && "Map insertion failed");
+ return &Where->second;
+}
+
+DirectiveNameParser::State *DirectiveNameParser::State::next(StringRef Tok) {
+ if (!Transition)
+ return nullptr;
+ auto F = Transition->find(Tok);
+ return F != Transition->end() ? &F->second : nullptr;
+}
+} // namespace llvm::omp
diff --git a/llvm/unittests/Frontend/CMakeLists.txt b/llvm/unittests/Frontend/CMakeLists.txt
index 2412cc9d26c7a..281d509227a46 100644
--- a/llvm/unittests/Frontend/CMakeLists.txt
+++ b/llvm/unittests/Frontend/CMakeLists.txt
@@ -20,6 +20,7 @@ add_llvm_unittest(LLVMFrontendTests
OpenMPCompositionTest.cpp
OpenMPDecompositionTest.cpp
OpenMPDirectiveNameTest.cpp
+ OpenMPDirectiveNameParserTest.cpp
DEPENDS
acc_gen
diff --git a/llvm/unittests/Frontend/OpenMPDirectiveNameParserTest.cpp b/llvm/unittests/Frontend/OpenMPDirectiveNameParserTest.cpp
new file mode 100644
index 0000000000000..11fef684dec4c
--- /dev/null
+++ b/llvm/unittests/Frontend/OpenMPDirectiveNameParserTest.cpp
@@ -0,0 +1,171 @@
+//===- llvm/unittests/Frontend/OpenMPDirectiveNameParserTest.cpp ----------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/Sequence.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Frontend/OpenMP/DirectiveNameParser.h"
+#include "llvm/Frontend/OpenMP/OMP.h"
+#include "gtest/gtest.h"
+
+#include <cctype>
+#include <sstream>
+#include <string>
+#include <tuple>
+#include <vector>
+
+using namespace llvm;
+
+static const omp::DirectiveNameParser &getParser() {
+ static omp::DirectiveNameParser Parser(omp::SourceLanguage::C |
+ omp::SourceLanguage::Fortran);
+ return Parser;
+}
+
+static std::vector<std::string> tokenize(StringRef S) {
+ std::vector<std::string> Tokens;
+
+ using TokenIterator = std::istream_iterator<std::string>;
+ std::string Copy = S.str();
+ std::istringstream Stream(Copy);
+
+ for (auto I = TokenIterator(Stream), E = TokenIterator(); I != E; ++I)
+ Tokens.push_back(*I);
+ return Tokens;
+}
+
+static std::string &prepareParamName(std::string &Name) {
+ for (size_t I = 0, E = Name.size(); I != E; ++I) {
+ // The parameter name must only have alphanumeric characters.
+ if (!isalnum(Name[I]))
+ Name[I] = 'X';
+ }
+ return Name;
+}
+
+namespace llvm {
+template <> struct enum_iteration_traits<omp::Directive> {
+ static constexpr bool is_iterable = true;
+};
+} // namespace llvm
+
+// Test tokenizing.
+
+class Tokenize : public testing::TestWithParam<omp::Directive> {};
+
+static bool isEqual(const SmallVector<StringRef> &A,
+ const std::vector<std::string> &B) {
+ if (A.size() != B.size())
+ return false;
+
+ for (size_t I = 0, E = A.size(); I != E; ++I) {
+ if (A[I] != StringRef(B[I]))
+ return false;
+ }
+ return true;
+}
+
+TEST_P(Tokenize, T) {
+ omp::Directive DirId = GetParam();
+ StringRef Name = omp::getOpenMPDirectiveName(DirId, omp::FallbackVersion);
+
+ SmallVector<StringRef> tokens1 = omp::DirectiveNameParser::tokenize(Name);
+ std::vector<std::string> tokens2 = tokenize(Name);
+ ASSERT_TRUE(isEqual(tokens1, tokens2));
+}
+
+static std::string
+getParamName1(const testing::TestParamInfo<Tokenize::ParamType> &Info) {
+ omp::Directive DirId = Info.param;
+ std::string Name =
+ omp::getOpenMPDirectiveName(DirId, omp::FallbackVersion).str();
+ return prepareParamName(Name);
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ DirectiveNameParserTest, Tokenize,
+ testing::ValuesIn(
+ llvm::enum_seq(static_cast<omp::Directive>(0),
+ static_cast<omp::Directive>(omp::Directive_enumSize))),
+ getParamName1);
+
+// Test parsing of valid names.
+
+using ValueType = std::tuple<omp::Directive, unsigned>;
+
+class ParseValid : public testing::TestWithParam<ValueType> {};
+
+TEST_P(ParseValid, T) {
+ auto [DirId, Version] = GetParam();
+ if (DirId == omp::Directive::OMPD_unknown)
+ return;
+
+ std::string Name = omp::getOpenMPDirectiveName(DirId, Version).str();
+
+ // Tokenize and parse
+ auto &Parser = getParser();
+ auto *State = Parser.initial();
+ ASSERT_TRUE(State != nullptr);
+
+ std::vector<std::string> Tokens = tokenize(Name);
+ for (auto &Tok : Tokens) {
+ State = Parser.apply(State, Tok);
+ ASSERT_TRUE(State != nullptr);
+ }
+
+ ASSERT_EQ(State->Value, DirId);
+}
+
+static std::string
+getParamName2(const testing::TestParamInfo<ParseValid::ParamType> &Info) {
+ auto [DirId, Version] = Info.param;
+ std::string Name = omp::getOpenMPDirectiveName(DirId, Version).str() + "v" +
+ std::to_string(Version);
+ return prepareParamName(Name);
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ DirectiveNameParserTest, ParseValid,
+ testing::Combine(testing::ValuesIn(llvm::enum_seq(
+ static_cast<omp::Directive>(0),
+ static_cast<omp::Directive>(omp::Directive_enumSize))),
+ testing::ValuesIn(omp::getOpenMPVersions())),
+ getParamName2);
+
+// Test parsing of invalid names
+
+class ParseInvalid : public testing::TestWithParam<std::string> {};
+
+TEST_P(ParseInvalid, T) {
+ std::string Name = GetParam();
+
+ auto &Parser = getParser();
+ auto *State = Parser.initial();
+ ASSERT_TRUE(State != nullptr);
+
+ std::vector<std::string> Tokens = tokenize(Name);
+ for (auto &Tok : Tokens)
+ State = Parser.apply(State, Tok);
+
+ ASSERT_TRUE(State == nullptr || State->Value == omp::Directive::OMPD_unknown);
+}
+
+namespace {
+using namespace std;
+
+INSTANTIATE_TEST_SUITE_P(DirectiveNameParserTest, ParseInvalid,
+ testing::Values(
+ // Names that contain invalid tokens
+ "bad"s, "target teams invalid"s,
+ "target sections parallel"s,
+ "target teams distribute parallel for wrong"s,
+ // Valid beginning, but not a complete name
+ "begin declare"s,
+ // Complete name with extra tokens
+ "distribute simd target"s));
+} // namespace
>From f49ba8b84a8218e52c09713be49a4a04bfa36920 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Wed, 2 Jul 2025 16:49:32 -0500
Subject: [PATCH 2/6] Use llvm::seq
---
llvm/lib/Frontend/OpenMP/DirectiveNameParser.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/Frontend/OpenMP/DirectiveNameParser.cpp b/llvm/lib/Frontend/OpenMP/DirectiveNameParser.cpp
index 02ff8327a3054..b560858b44df6 100644
--- a/llvm/lib/Frontend/OpenMP/DirectiveNameParser.cpp
+++ b/llvm/lib/Frontend/OpenMP/DirectiveNameParser.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/Frontend/OpenMP/DirectiveNameParser.h"
+#include "llvm/ADT/Sequence.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Frontend/OpenMP/OMP.h"
@@ -17,7 +18,7 @@ namespace llvm::omp {
DirectiveNameParser::DirectiveNameParser(SourceLanguage L) {
// Take every directive, get its name in every version, break the name up
// into whitespace-separated tokens, and insert each token.
- for (size_t I = 0, E = Directive_enumSize; I != E; ++I) {
+ for (size_t I : llvm::seq<size_t>(Directive_enumSize)) {
auto D = static_cast<Directive>(I);
if (D == Directive::OMPD_unknown || !(getDirectiveLanguages(D) & L))
continue;
>From 538cfcdd285c34d08ff6a67253e20343547982f1 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Wed, 2 Jul 2025 16:49:36 -0500
Subject: [PATCH 3/6] Add const version of next()
---
.../include/llvm/Frontend/OpenMP/DirectiveNameParser.h | 1 +
llvm/lib/Frontend/OpenMP/DirectiveNameParser.cpp | 10 +++++++++-
2 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/llvm/include/llvm/Frontend/OpenMP/DirectiveNameParser.h b/llvm/include/llvm/Frontend/OpenMP/DirectiveNameParser.h
index db8986601b2ca..9996375c9023e 100644
--- a/llvm/include/llvm/Frontend/OpenMP/DirectiveNameParser.h
+++ b/llvm/include/llvm/Frontend/OpenMP/DirectiveNameParser.h
@@ -54,6 +54,7 @@ struct DirectiveNameParser {
std::unique_ptr<TransitionMapTy> Transition;
State *next(StringRef Tok);
+ const State *next(StringRef Tok) const;
bool isValid() const {
return Value != Directive::OMPD_unknown || !Transition->empty();
}
diff --git a/llvm/lib/Frontend/OpenMP/DirectiveNameParser.cpp b/llvm/lib/Frontend/OpenMP/DirectiveNameParser.cpp
index b560858b44df6..4aaf25cc32e05 100644
--- a/llvm/lib/Frontend/OpenMP/DirectiveNameParser.cpp
+++ b/llvm/lib/Frontend/OpenMP/DirectiveNameParser.cpp
@@ -32,7 +32,7 @@ DirectiveNameParser::apply(const State *Current, StringRef Tok) const {
if (!Current)
return Current;
assert(Current->isValid() && "Invalid input state");
- if (const State *Next = const_cast<State *>(Current)->next(Tok))
+ if (const State *Next = Current->next(Tok))
return Next->isValid() ? Next : nullptr;
return nullptr;
}
@@ -85,6 +85,14 @@ DirectiveNameParser::insertTransition(State *From, StringRef Tok) {
return &Where->second;
}
+const DirectiveNameParser::State *
+DirectiveNameParser::State::next(StringRef Tok) const {
+ if (!Transition)
+ return nullptr;
+ auto F = Transition->find(Tok);
+ return F != Transition->end() ? &F->second : nullptr;
+}
+
DirectiveNameParser::State *DirectiveNameParser::State::next(StringRef Tok) {
if (!Transition)
return nullptr;
>From 9d35e461829665e3eb1d9c4cc03548b02b2c0925 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Wed, 2 Jul 2025 16:52:09 -0500
Subject: [PATCH 4/6] Add missing brace in comment
---
llvm/include/llvm/Frontend/OpenMP/DirectiveNameParser.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/include/llvm/Frontend/OpenMP/DirectiveNameParser.h b/llvm/include/llvm/Frontend/OpenMP/DirectiveNameParser.h
index 9996375c9023e..b1ff34c003295 100644
--- a/llvm/include/llvm/Frontend/OpenMP/DirectiveNameParser.h
+++ b/llvm/include/llvm/Frontend/OpenMP/DirectiveNameParser.h
@@ -35,7 +35,7 @@ namespace llvm::omp {
/// if (S == nullptr) {
/// // Error: ended up in a state from which there is no possible path
/// // to a successful parse.
-/// } else if (S->Value == OMPD_unknown)
+/// } else if (S->Value == OMPD_unknown) {
/// // Parsed a sequence of tokens that are not a complete name, but
/// // parsing more tokens could lead to a successful parse.
/// } else {
>From 5d2a8a367eb4e13b298897f85120e785dd97e39b Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Thu, 3 Jul 2025 10:03:58 -0500
Subject: [PATCH 5/6] Rename apply to consume
---
llvm/include/llvm/Frontend/OpenMP/DirectiveNameParser.h | 4 ++--
llvm/lib/Frontend/OpenMP/DirectiveNameParser.cpp | 2 +-
llvm/unittests/Frontend/OpenMPDirectiveNameParserTest.cpp | 4 ++--
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/llvm/include/llvm/Frontend/OpenMP/DirectiveNameParser.h b/llvm/include/llvm/Frontend/OpenMP/DirectiveNameParser.h
index b1ff34c003295..898c32aa4b8f2 100644
--- a/llvm/include/llvm/Frontend/OpenMP/DirectiveNameParser.h
+++ b/llvm/include/llvm/Frontend/OpenMP/DirectiveNameParser.h
@@ -30,7 +30,7 @@ namespace llvm::omp {
///
/// DirectiveNameParser::State *S = Parser.initial();
/// for (StringRef Token : Tokens)
-/// S = Parser.apply(S, Token); // Passing nullptr is ok.
+/// S = Parser.consume(S, Token); // Passing nullptr is ok.
///
/// if (S == nullptr) {
/// // Error: ended up in a state from which there is no possible path
@@ -62,7 +62,7 @@ struct DirectiveNameParser {
};
const State *initial() const { return &InitialState; }
- const State *apply(const State *Current, StringRef Tok) const;
+ const State *consume(const State *Current, StringRef Tok) const;
static SmallVector<StringRef> tokenize(StringRef N);
diff --git a/llvm/lib/Frontend/OpenMP/DirectiveNameParser.cpp b/llvm/lib/Frontend/OpenMP/DirectiveNameParser.cpp
index 4aaf25cc32e05..037ffe2c13f1e 100644
--- a/llvm/lib/Frontend/OpenMP/DirectiveNameParser.cpp
+++ b/llvm/lib/Frontend/OpenMP/DirectiveNameParser.cpp
@@ -28,7 +28,7 @@ DirectiveNameParser::DirectiveNameParser(SourceLanguage L) {
}
const DirectiveNameParser::State *
-DirectiveNameParser::apply(const State *Current, StringRef Tok) const {
+DirectiveNameParser::consume(const State *Current, StringRef Tok) const {
if (!Current)
return Current;
assert(Current->isValid() && "Invalid input state");
diff --git a/llvm/unittests/Frontend/OpenMPDirectiveNameParserTest.cpp b/llvm/unittests/Frontend/OpenMPDirectiveNameParserTest.cpp
index 11fef684dec4c..0363a08cc0f03 100644
--- a/llvm/unittests/Frontend/OpenMPDirectiveNameParserTest.cpp
+++ b/llvm/unittests/Frontend/OpenMPDirectiveNameParserTest.cpp
@@ -114,7 +114,7 @@ TEST_P(ParseValid, T) {
std::vector<std::string> Tokens = tokenize(Name);
for (auto &Tok : Tokens) {
- State = Parser.apply(State, Tok);
+ State = Parser.consume(State, Tok);
ASSERT_TRUE(State != nullptr);
}
@@ -150,7 +150,7 @@ TEST_P(ParseInvalid, T) {
std::vector<std::string> Tokens = tokenize(Name);
for (auto &Tok : Tokens)
- State = Parser.apply(State, Tok);
+ State = Parser.consume(State, Tok);
ASSERT_TRUE(State == nullptr || State->Value == omp::Directive::OMPD_unknown);
}
>From cde46dc3d14d224c4f4f1ec9ef8eafb4d9d12828 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Thu, 3 Jul 2025 10:04:23 -0500
Subject: [PATCH 6/6] Use isspace instead of ' '
---
.../Frontend/OpenMP/DirectiveNameParser.cpp | 18 ++++++++++--------
1 file changed, 10 insertions(+), 8 deletions(-)
diff --git a/llvm/lib/Frontend/OpenMP/DirectiveNameParser.cpp b/llvm/lib/Frontend/OpenMP/DirectiveNameParser.cpp
index 037ffe2c13f1e..d42a3e98adb37 100644
--- a/llvm/lib/Frontend/OpenMP/DirectiveNameParser.cpp
+++ b/llvm/lib/Frontend/OpenMP/DirectiveNameParser.cpp
@@ -12,6 +12,7 @@
#include "llvm/Frontend/OpenMP/OMP.h"
#include <cassert>
+#include <cctype>
#include <memory>
namespace llvm::omp {
@@ -40,23 +41,24 @@ DirectiveNameParser::consume(const State *Current, StringRef Tok) const {
SmallVector<StringRef> DirectiveNameParser::tokenize(StringRef Str) {
SmallVector<StringRef> Tokens;
- auto nextChar = [](StringRef N, size_t I) {
- while (I < N.size() && N[I] == ' ')
+ auto NextChar = [](StringRef N, size_t I) {
+ while (I < N.size() && isspace(N[I]))
++I;
return I;
};
- auto nextSpace = [](StringRef N, size_t I) {
- size_t S = N.find(' ', I);
- return S != StringRef::npos ? S : N.size();
+ auto NextSpace = [](StringRef N, size_t I) {
+ while (I < N.size() && !isspace(N[I]))
+ ++I;
+ return I;
};
- size_t From = nextChar(Str, 0);
+ size_t From = NextChar(Str, 0);
size_t To = 0;
while (From != Str.size()) {
- To = nextSpace(Str, From);
+ To = NextSpace(Str, From);
Tokens.push_back(Str.substr(From, To - From));
- From = nextChar(Str, To);
+ From = NextChar(Str, To);
}
return Tokens;
More information about the llvm-commits
mailing list