Skip to content

Commit 973db23

Browse files
jgonzacrizsotto
authored andcommitted
Add ifort and ifx support to citnames
1 parent 74b699d commit 973db23

File tree

5 files changed

+302
-0
lines changed

5 files changed

+302
-0
lines changed

source/citnames/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ target_sources(citnames_a
3030
source/semantic/ToolClang.cc
3131
source/semantic/ToolCuda.cc
3232
source/semantic/ToolGcc.cc
33+
source/semantic/ToolIntelFortran.cc
3334
source/semantic/ToolWrapper.cc
3435
source/semantic/ToolExtendingWrapper.cc
3536
INTERFACE
@@ -67,6 +68,7 @@ if (ENABLE_UNIT_TESTS)
6768
test/ParserTest.cc
6869
test/ToolClangTest.cc
6970
test/ToolGccTest.cc
71+
test/ToolIntelFortranTest.cc
7072
test/ToolWrapperTest.cc
7173
)
7274

source/citnames/source/semantic/Build.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "ToolGcc.h"
2323
#include "ToolClang.h"
2424
#include "ToolCuda.h"
25+
#include "ToolIntelFortran.h"
2526
#include "ToolWrapper.h"
2627
#include "ToolExtendingWrapper.h"
2728
#include "Convert.h"
@@ -44,6 +45,7 @@ namespace {
4445
std::make_shared<cs::semantic::ToolClang>(),
4546
std::make_shared<cs::semantic::ToolWrapper>(),
4647
std::make_shared<cs::semantic::ToolCuda>(),
48+
std::make_shared<cs::semantic::ToolIntelFortran>(),
4749
};
4850
for (auto && compiler : cfg.compilers_to_recognize) {
4951
tools.emplace_front(std::make_shared<cs::semantic::ToolExtendingWrapper>(std::move(compiler)));
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
/* Copyright (C) 2012-2024 by László Nagy
2+
This file is part of Bear.
3+
4+
Bear is a tool to generate compilation database for clang tooling.
5+
6+
Bear is free software: you can redistribute it and/or modify
7+
it under the terms of the GNU General Public License as published by
8+
the Free Software Foundation, either version 3 of the License, or
9+
(at your option) any later version.
10+
11+
Bear is distributed in the hope that it will be useful,
12+
but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
GNU General Public License for more details.
15+
16+
You should have received a copy of the GNU General Public License
17+
along with this program. If not, see <http://www.gnu.org/licenses/>.
18+
*/
19+
20+
#include "ToolIntelFortran.h"
21+
#include "Common.h"
22+
#include "Parsers.h"
23+
#include "libsys/Path.h"
24+
25+
#include <regex>
26+
#include <utility>
27+
#include <functional>
28+
#include <set>
29+
#include <string_view>
30+
31+
using namespace cs::semantic;
32+
33+
namespace {
34+
Arguments create_argument_list(const Execution& execution)
35+
{
36+
Arguments input_arguments;
37+
std::copy(execution.arguments.begin(), execution.arguments.end(), std::back_inserter(input_arguments));
38+
return input_arguments;
39+
}
40+
41+
bool is_preprocessor(const CompilerFlags& flags)
42+
{
43+
return std::any_of(flags.begin(), flags.end(), [](const auto& flag) {
44+
const std::string& candidate = flag.arguments.front();
45+
46+
static const std::set<std::string_view> NO_COMPILATION_FLAG = { "-preprocess-only", "-P", "-E", "-Ep" };
47+
48+
return ((flag.type == CompilerFlagType::KIND_OF_OUTPUT_NO_LINKING) && (NO_COMPILATION_FLAG.find(candidate) != NO_COMPILATION_FLAG.end()))
49+
|| ((flag.type == CompilerFlagType::PREPROCESSOR_MAKE));
50+
});
51+
}
52+
}
53+
54+
namespace cs::semantic {
55+
56+
const FlagsByName ToolIntelFortran::FLAG_DEFINITION = {
57+
{"-c", {MatchInstruction::EXACTLY, CompilerFlagType::KIND_OF_OUTPUT_NO_LINKING}},
58+
{"-S", {MatchInstruction::EXACTLY, CompilerFlagType::KIND_OF_OUTPUT_NO_LINKING}},
59+
{"-E", {MatchInstruction::EXACTLY, CompilerFlagType::KIND_OF_OUTPUT_NO_LINKING}},
60+
{"-Ep", {MatchInstruction::EXACTLY, CompilerFlagType::KIND_OF_OUTPUT_NO_LINKING}},
61+
{"-preprocess-only", {MatchInstruction::EXACTLY, CompilerFlagType::KIND_OF_OUTPUT_NO_LINKING}},
62+
{"-P", {MatchInstruction::EXACTLY, CompilerFlagType::KIND_OF_OUTPUT_NO_LINKING}},
63+
{"-o", {MatchInstruction::EXACTLY_WITH_1_OPT_SEP, CompilerFlagType::KIND_OF_OUTPUT_OUTPUT}},
64+
{"-debug", {MatchInstruction::EXACTLY_WITH_1_OPT_SEP, CompilerFlagType::KIND_OF_OUTPUT}},
65+
{"-debug-parameters", {MatchInstruction::EXACTLY_WITH_1_OPT_SEP, CompilerFlagType::KIND_OF_OUTPUT}},
66+
{"@", {MatchInstruction::PREFIX, CompilerFlagType::KIND_OF_OUTPUT}},
67+
{"-Fa", {MatchInstruction::PREFIX, CompilerFlagType::KIND_OF_OUTPUT}},
68+
{"-FA", {MatchInstruction::PREFIX, CompilerFlagType::KIND_OF_OUTPUT}},
69+
{"-shared", {MatchInstruction::EXACTLY, CompilerFlagType::KIND_OF_OUTPUT}},
70+
{"-dryrun", {MatchInstruction::EXACTLY, CompilerFlagType::KIND_OF_OUTPUT_INFO}},
71+
{"-dumpmachine", {MatchInstruction::EXACTLY, CompilerFlagType::KIND_OF_OUTPUT_INFO}},
72+
{"-v", {MatchInstruction::PREFIX, CompilerFlagType::KIND_OF_OUTPUT_INFO}},
73+
{"-V", {MatchInstruction::EXACTLY, CompilerFlagType::KIND_OF_OUTPUT_INFO}},
74+
{"--help", {MatchInstruction::PREFIX, CompilerFlagType::KIND_OF_OUTPUT_INFO}},
75+
{"--version", {MatchInstruction::EXACTLY, CompilerFlagType::KIND_OF_OUTPUT_INFO}},
76+
{"-D", {MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::PREPROCESSOR}},
77+
{"-U", {MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::PREPROCESSOR}},
78+
{"-include", {MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::PREPROCESSOR}},
79+
{"-undef", {MatchInstruction::EXACTLY, CompilerFlagType::PREPROCESSOR}},
80+
{"-pthread", {MatchInstruction::EXACTLY, CompilerFlagType::PREPROCESSOR}},
81+
{"-MD", {MatchInstruction::EXACTLY, CompilerFlagType::PREPROCESSOR_MAKE}},
82+
{"-MMD", {MatchInstruction::EXACTLY, CompilerFlagType::PREPROCESSOR_MAKE}},
83+
{"-MF", {MatchInstruction::EXACTLY_WITH_1_OPT_SEP, CompilerFlagType::PREPROCESSOR_MAKE}},
84+
{"-gen-dep", {MatchInstruction::EXACTLY_WITH_1_OPT_SEP, CompilerFlagType::PREPROCESSOR_MAKE}},
85+
{"-C", {MatchInstruction::EXACTLY, CompilerFlagType::PREPROCESSOR}},
86+
{"-Xoption,cpp", {MatchInstruction::PREFIX, CompilerFlagType::PREPROCESSOR}},
87+
{"-Xoption,fpp", {MatchInstruction::PREFIX, CompilerFlagType::PREPROCESSOR}},
88+
{"-fpp", {MatchInstruction::EXACTLY, CompilerFlagType::PREPROCESSOR}},
89+
{"-nofpp", {MatchInstruction::EXACTLY, CompilerFlagType::PREPROCESSOR}},
90+
{"-Wp", {MatchInstruction::PREFIX, CompilerFlagType::PREPROCESSOR}},
91+
{"-I", {MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::DIRECTORY_SEARCH}},
92+
{"-iquote", {MatchInstruction::EXACTLY_WITH_1_OPT_SEP, CompilerFlagType::DIRECTORY_SEARCH}},
93+
{"-isystem", {MatchInstruction::EXACTLY_WITH_1_OPT_SEP, CompilerFlagType::DIRECTORY_SEARCH}},
94+
{"-isysroot", {MatchInstruction::EXACTLY_WITH_1_OPT_SEP, CompilerFlagType::DIRECTORY_SEARCH}},
95+
{"-L", {MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::DIRECTORY_SEARCH_LINKER}},
96+
{"--sysroot", {MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_WITH_EQ, CompilerFlagType::DIRECTORY_SEARCH}},
97+
{"-X", {MatchInstruction::EXACTLY, CompilerFlagType::DIRECTORY_SEARCH}},
98+
{"-l", {MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::LINKER}},
99+
{"-nostartfiles", {MatchInstruction::EXACTLY, CompilerFlagType::LINKER}},
100+
{"-nodefaultlibs", {MatchInstruction::EXACTLY, CompilerFlagType::LINKER}},
101+
{"-nostdlib", {MatchInstruction::EXACTLY, CompilerFlagType::LINKER}},
102+
{"-r", {MatchInstruction::EXACTLY, CompilerFlagType::LINKER}},
103+
{"-s", {MatchInstruction::EXACTLY, CompilerFlagType::LINKER}},
104+
{"-shared-intel", {MatchInstruction::EXACTLY, CompilerFlagType::LINKER}},
105+
{"shared-libgcc", {MatchInstruction::EXACTLY, CompilerFlagType::LINKER}},
106+
{"-static", {MatchInstruction::EXACTLY, CompilerFlagType::LINKER}},
107+
{"-static-intel", {MatchInstruction::EXACTLY, CompilerFlagType::LINKER}},
108+
{"-static-libgcc", {MatchInstruction::EXACTLY, CompilerFlagType::LINKER}},
109+
{"-T", {MatchInstruction::EXACTLY_WITH_1_OPT_SEP, CompilerFlagType::LINKER}},
110+
{"-Xlinker", {MatchInstruction::EXACTLY_WITH_1_OPT_SEP, CompilerFlagType::LINKER}},
111+
{"-Xoption,link", {MatchInstruction::PREFIX, CompilerFlagType::LINKER}},
112+
{"-u", {MatchInstruction::EXACTLY_WITH_1_OPT_SEP, CompilerFlagType::LINKER}},
113+
{"-Wl", {MatchInstruction::PREFIX, CompilerFlagType::LINKER}},
114+
{"-Xoption,asm", {MatchInstruction::PREFIX, CompilerFlagType::OTHER}},
115+
{"-std", {MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_WITH_EQ, CompilerFlagType::OTHER}},
116+
{"-O", {MatchInstruction::PREFIX, CompilerFlagType::OTHER}},
117+
{"-g", {MatchInstruction::PREFIX, CompilerFlagType::OTHER}},
118+
{"-f", {MatchInstruction::PREFIX, CompilerFlagType::OTHER}},
119+
{"-m", {MatchInstruction::PREFIX, CompilerFlagType::OTHER}},
120+
{"-x", {MatchInstruction::PREFIX, CompilerFlagType::OTHER}},
121+
{"-diag-", {MatchInstruction::PREFIX, CompilerFlagType::OTHER}},
122+
{"-no", {MatchInstruction::PREFIX, CompilerFlagType::OTHER}},
123+
{"-gen-interfaces", {MatchInstruction::EXACTLY_WITH_1_OPT_SEP, CompilerFlagType::OTHER}},
124+
{"-nogen-interfaces", {MatchInstruction::EXACTLY, CompilerFlagType::OTHER}},
125+
{"--", {MatchInstruction::PREFIX, CompilerFlagType::OTHER}},
126+
};
127+
128+
rust::Result<SemanticPtr> ToolIntelFortran::recognize(const Execution& execution) const
129+
{
130+
if (is_compiler_call(execution.executable)) {
131+
return compilation_impl(FLAG_DEFINITION, execution, create_argument_list, is_preprocessor);
132+
}
133+
return rust::Ok(SemanticPtr());
134+
}
135+
136+
bool ToolIntelFortran::is_compiler_call(const fs::path& program) const
137+
{
138+
static const auto pattern = std::regex(R"(^([^-]*-)*(ifx|ifort)(-?\w+(\.\d+){0,2})?$)");
139+
140+
std::cmatch m;
141+
return std::regex_match(program.filename().c_str(), m, pattern);
142+
}
143+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/* Copyright (C) 2012-2024 by László Nagy
2+
This file is part of Bear.
3+
4+
Bear is a tool to generate compilation database for clang tooling.
5+
6+
Bear is free software: you can redistribute it and/or modify
7+
it under the terms of the GNU General Public License as published by
8+
the Free Software Foundation, either version 3 of the License, or
9+
(at your option) any later version.
10+
11+
Bear is distributed in the hope that it will be useful,
12+
but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
GNU General Public License for more details.
15+
16+
You should have received a copy of the GNU General Public License
17+
along with this program. If not, see <http://www.gnu.org/licenses/>.
18+
*/
19+
20+
#pragma once
21+
22+
#include "Tool.h"
23+
#include "Parsers.h"
24+
25+
namespace cs::semantic {
26+
27+
struct ToolIntelFortran : public Tool {
28+
29+
[[nodiscard]]
30+
rust::Result<SemanticPtr> recognize(const Execution &execution) const override;
31+
32+
protected:
33+
[[nodiscard]] bool is_compiler_call(const fs::path& program) const;
34+
35+
static const FlagsByName FLAG_DEFINITION;
36+
};
37+
}
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
/* Copyright (C) 2012-2024 by László Nagy
2+
This file is part of Bear.
3+
4+
Bear is a tool to generate compilation database for clang tooling.
5+
6+
Bear is free software: you can redistribute it and/or modify
7+
it under the terms of the GNU General Public License as published by
8+
the Free Software Foundation, either version 3 of the License, or
9+
(at your option) any later version.
10+
11+
Bear is distributed in the hope that it will be useful,
12+
but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
GNU General Public License for more details.
15+
16+
You should have received a copy of the GNU General Public License
17+
along with this program. If not, see <http://www.gnu.org/licenses/>.
18+
*/
19+
20+
#include "gtest/gtest.h"
21+
22+
#include "semantic/Tool.h"
23+
#include "semantic/ToolIntelFortran.h"
24+
25+
using namespace cs::semantic;
26+
27+
namespace {
28+
29+
TEST(ToolIntelFortran, is_compiler_call) {
30+
struct Expose : public ToolIntelFortran {
31+
using ToolIntelFortran::is_compiler_call;
32+
};
33+
Expose sut;
34+
35+
EXPECT_TRUE(sut.is_compiler_call("ifx"));
36+
EXPECT_TRUE(sut.is_compiler_call("/usr/bin/ifx"));
37+
EXPECT_TRUE(sut.is_compiler_call("ifort"));
38+
EXPECT_TRUE(sut.is_compiler_call("/usr/bin/ifort"));
39+
EXPECT_TRUE(sut.is_compiler_call("/opt/intel/oneapi/compiler/2025.0/bin/ifx"));
40+
EXPECT_TRUE(sut.is_compiler_call("ifx2023"));
41+
EXPECT_TRUE(sut.is_compiler_call("ifx2025.0"));
42+
EXPECT_TRUE(sut.is_compiler_call("ifx-avx2"));
43+
44+
EXPECT_FALSE(sut.is_compiler_call("gfortran"));
45+
EXPECT_FALSE(sut.is_compiler_call("gcc"));
46+
}
47+
48+
TEST(ToolIntelFortran, fails_on_empty) {
49+
Execution input = {};
50+
51+
ToolIntelFortran sut;
52+
53+
EXPECT_TRUE(Tool::not_recognized(sut.recognize(input)));
54+
}
55+
56+
TEST(ToolIntelFortran, simple) {
57+
Execution input = {
58+
"/opt/intel/oneapi/compiler/2025.0/bin/ifx",
59+
{"ifx", "-c", "-o", "source.o", "source.c"},
60+
"/home/user/project",
61+
{},
62+
};
63+
SemanticPtr expected = SemanticPtr(
64+
new Compile(
65+
input.working_dir,
66+
input.executable,
67+
{"-c"},
68+
{fs::path("source.c")},
69+
{fs::path("source.o")})
70+
);
71+
72+
ToolIntelFortran sut({});
73+
74+
auto result = sut.recognize(input);
75+
EXPECT_TRUE(Tool::recognized_ok(result));
76+
EXPECT_PRED2([](auto lhs, auto rhs) { return lhs->operator==(*rhs); }, expected, result.unwrap());
77+
}
78+
79+
TEST(ToolIntelFortran, linker_flag_filtered) {
80+
Execution input = {
81+
"/opt/intel/oneapi/compiler/2025.0/bin/ifx",
82+
{"ifx", "-L.", "-lthing", "-o", "exe", "source.c"},
83+
"/home/user/project",
84+
{},
85+
};
86+
SemanticPtr expected = SemanticPtr(
87+
new Compile(
88+
input.working_dir,
89+
input.executable,
90+
{"-c"},
91+
{fs::path("source.c")},
92+
{fs::path("exe")}
93+
)
94+
);
95+
96+
ToolIntelFortran sut({});
97+
98+
auto result = sut.recognize(input);
99+
EXPECT_TRUE(Tool::recognized_ok(result));
100+
EXPECT_PRED2([](auto lhs, auto rhs) { return lhs->operator==(*rhs); }, expected, result.unwrap());
101+
}
102+
103+
TEST(ToolIntelFortran, pass_on_help) {
104+
Execution input = {
105+
"/opt/intel/oneapi/compiler/2025.0/bin/ifx",
106+
{"ifx", "--version"},
107+
"/home/user/project",
108+
{},
109+
};
110+
SemanticPtr expected = SemanticPtr(new QueryCompiler());
111+
112+
ToolIntelFortran sut({});
113+
114+
auto result = sut.recognize(input);
115+
EXPECT_TRUE(result.is_ok());
116+
EXPECT_PRED2([](auto lhs, auto rhs) { return lhs->operator==(*rhs); }, expected, result.unwrap());
117+
}
118+
}

0 commit comments

Comments
 (0)