163 lines · cpp
1//===- llvm/unittests/Frontend/OpenMPDirectiveNameParserTest.cpp ----------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/ADT/Sequence.h"10#include "llvm/ADT/SmallVector.h"11#include "llvm/ADT/StringRef.h"12#include "llvm/Frontend/OpenMP/DirectiveNameParser.h"13#include "llvm/Frontend/OpenMP/OMP.h"14#include "gtest/gtest.h"15 16#include <cctype>17#include <sstream>18#include <string>19#include <tuple>20#include <vector>21 22using namespace llvm;23 24static const omp::DirectiveNameParser &getParser() {25 static omp::DirectiveNameParser Parser(omp::SourceLanguage::C |26 omp::SourceLanguage::Fortran);27 return Parser;28}29 30static std::vector<std::string> tokenize(StringRef S) {31 std::vector<std::string> Tokens;32 33 using TokenIterator = std::istream_iterator<std::string>;34 std::string Copy = S.str();35 std::istringstream Stream(Copy);36 37 for (auto I = TokenIterator(Stream), E = TokenIterator(); I != E; ++I)38 Tokens.push_back(*I);39 return Tokens;40}41 42static std::string &prepareParamName(std::string &Name) {43 for (size_t I = 0, E = Name.size(); I != E; ++I) {44 // The parameter name must only have alphanumeric characters.45 if (!isalnum(Name[I]))46 Name[I] = 'X';47 }48 return Name;49}50 51// Test tokenizing.52 53class Tokenize : public testing::TestWithParam<omp::Directive> {};54 55static bool isEqual(const SmallVector<StringRef> &A,56 const std::vector<std::string> &B) {57 if (A.size() != B.size())58 return false;59 60 for (size_t I = 0, E = A.size(); I != E; ++I) {61 if (A[I] != StringRef(B[I]))62 return false;63 }64 return true;65}66 67TEST_P(Tokenize, T) {68 omp::Directive DirId = GetParam();69 StringRef Name = omp::getOpenMPDirectiveName(DirId, omp::FallbackVersion);70 71 SmallVector<StringRef> tokens1 = omp::DirectiveNameParser::tokenize(Name);72 std::vector<std::string> tokens2 = tokenize(Name);73 ASSERT_TRUE(isEqual(tokens1, tokens2));74}75 76static std::string77getParamName1(const testing::TestParamInfo<Tokenize::ParamType> &Info) {78 omp::Directive DirId = Info.param;79 std::string Name =80 omp::getOpenMPDirectiveName(DirId, omp::FallbackVersion).str();81 return prepareParamName(Name);82}83 84INSTANTIATE_TEST_SUITE_P(DirectiveNameParserTest, Tokenize,85 testing::ValuesIn(llvm::enum_seq_inclusive(86 omp::Directive::First_, omp::Directive::Last_)),87 getParamName1);88 89// Test parsing of valid names.90 91using ValueType = std::tuple<omp::Directive, unsigned>;92 93class ParseValid : public testing::TestWithParam<ValueType> {};94 95TEST_P(ParseValid, T) {96 auto [DirId, Version] = GetParam();97 if (DirId == omp::Directive::OMPD_unknown)98 return;99 100 std::string Name = omp::getOpenMPDirectiveName(DirId, Version).str();101 102 // Tokenize and parse103 auto &Parser = getParser();104 auto *State = Parser.initial();105 ASSERT_TRUE(State != nullptr);106 107 std::vector<std::string> Tokens = tokenize(Name);108 for (auto &Tok : Tokens) {109 State = Parser.consume(State, Tok);110 ASSERT_TRUE(State != nullptr);111 }112 113 ASSERT_EQ(State->Value, DirId);114}115 116static std::string117getParamName2(const testing::TestParamInfo<ParseValid::ParamType> &Info) {118 auto [DirId, Version] = Info.param;119 std::string Name = omp::getOpenMPDirectiveName(DirId, Version).str() + "v" +120 std::to_string(Version);121 return prepareParamName(Name);122}123 124INSTANTIATE_TEST_SUITE_P(125 DirectiveNameParserTest, ParseValid,126 testing::Combine(testing::ValuesIn(llvm::enum_seq_inclusive(127 omp::Directive::First_, omp::Directive::Last_)),128 testing::ValuesIn(omp::getOpenMPVersions())),129 getParamName2);130 131// Test parsing of invalid names132 133class ParseInvalid : public testing::TestWithParam<std::string> {};134 135TEST_P(ParseInvalid, T) {136 std::string Name = GetParam();137 138 auto &Parser = getParser();139 auto *State = Parser.initial();140 ASSERT_TRUE(State != nullptr);141 142 std::vector<std::string> Tokens = tokenize(Name);143 for (auto &Tok : Tokens)144 State = Parser.consume(State, Tok);145 146 ASSERT_TRUE(State == nullptr || State->Value == omp::Directive::OMPD_unknown);147}148 149namespace {150using namespace std;151 152INSTANTIATE_TEST_SUITE_P(DirectiveNameParserTest, ParseInvalid,153 testing::Values(154 // Names that contain invalid tokens155 "bad"s, "target teams invalid"s,156 "target sections parallel"s,157 "target teams distribute parallel for wrong"s,158 // Valid beginning, but not a complete name159 "begin declare"s,160 // Complete name with extra tokens161 "distribute simd target"s));162} // namespace163