Skip to content

Commit 33feef7

Browse files
authored
Eliminate singleton configuration with custom FrontendActionFactory. (#281)
This PR eliminates the need for the singleton instantiation of the chimera::Configuration by implementing custom factory classes that allow the configuration to be passed to the ASTConsumer directly.
1 parent 2cd2918 commit 33feef7

15 files changed

+115
-62
lines changed

.dockerignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
build/
22
ci/
3-
test/
43
.codecov.yml
54
.gitignore
65
.travis.yml

CMakeLists.txt

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,9 @@ set(${PROJECT_NAME}_SOURCES
9595
src/configuration.cpp
9696
src/consumer.cpp
9797
src/frontend_action.cpp
98-
src/visitor.cpp
99-
src/util.cpp
10098
src/mstch.cpp
99+
src/util.cpp
100+
src/visitor.cpp
101101
)
102102

103103
## Use LLVM CMake macro to collate and order link libraries.
@@ -171,8 +171,11 @@ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
171171
)
172172

173173
# Enable unit testing by including the `test` subdirectory.
174-
enable_testing()
175-
add_subdirectory(test EXCLUDE_FROM_ALL)
174+
include(CTest)
175+
if(BUILD_TESTING)
176+
enable_testing()
177+
add_subdirectory(test EXCLUDE_FROM_ALL)
178+
endif()
176179

177180
#####################
178181
## CODE FORMATTING ##

Dockerfile

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
1-
FROM ubuntu:16.04 as builder
1+
FROM ubuntu:18.04 as builder
22

33
# Install APT dependencies required for building chimera.
44
RUN apt-get update -qq \
55
&& apt-get install -y -qq \
66
cmake \
77
clang \
8-
llvm-3.7-dev \
9-
llvm-3.7-tools \
8+
clang-format \
9+
llvm-6.0-dev \
10+
llvm-6.0-tools \
1011
libboost-dev \
11-
libclang-3.7-dev \
12+
libclang-6.0-dev \
1213
libedit-dev \
1314
libyaml-cpp-dev \
1415
libz-dev \
@@ -22,13 +23,13 @@ RUN mkdir build && cd build \
2223
&& make install
2324

2425
#############################################################################
25-
FROM ubuntu:16.04
26+
FROM ubuntu:18.04
2627

2728
# Install APT dependencies required for running chimera.
2829
RUN apt-get update -qq \
2930
&& apt-get install -y -qq \
30-
llvm-3.7-tools \
31-
libclang-3.7 \
31+
llvm-6.0-tools \
32+
libclang-6.0 \
3233
libedit2 \
3334
libyaml-cpp0.5v5 \
3435
zlib1g \

include/chimera/configuration.h

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,10 @@ class CompiledConfiguration;
3434
class Configuration
3535
{
3636
public:
37+
Configuration();
3738
Configuration(const Configuration &) = delete;
3839
Configuration &operator=(const Configuration &) = delete;
3940

40-
/**
41-
* Gets the chimera configuration singleton for this process.
42-
*/
43-
static Configuration &GetInstance();
44-
4541
/**
4642
* Loads the specified file to use as the YAML configuration.
4743
*/
@@ -108,9 +104,6 @@ class Configuration
108104
*/
109105
const std::string &GetOutputModuleName() const;
110106

111-
private:
112-
Configuration();
113-
114107
protected:
115108
YAML::Node configNode_;
116109
std::string bindingName_;

include/chimera/consumer.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#ifndef __CHIMERA_CONSUMER_H__
22
#define __CHIMERA_CONSUMER_H__
33

4+
#include "chimera/configuration.h"
5+
46
#include <clang/AST/ASTConsumer.h>
57
#include <clang/Frontend/CompilerInstance.h>
68

@@ -11,13 +13,14 @@ class Consumer : public clang::ASTConsumer
1113
{
1214
public:
1315
// Overrides the constructor in order to receive CompilerInstance.
14-
Consumer(clang::CompilerInstance *ci);
16+
Consumer(clang::CompilerInstance *ci, const chimera::Configuration &config);
1517

1618
// Overrides method to call our ChimeraVisitor on the entire source file.
1719
void HandleTranslationUnit(clang::ASTContext &context) override;
1820

1921
private:
2022
clang::CompilerInstance *ci_;
23+
const chimera::Configuration &config_;
2124
};
2225

2326
} // namespace chimera

include/chimera/frontend_action.h

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
#ifndef __CHIMERA_FRONTEND_ACTION_H__
22
#define __CHIMERA_FRONTEND_ACTION_H__
33

4+
#include "chimera/configuration.h"
5+
#include "chimera/util.h"
6+
7+
#include <memory>
48
#include <clang/AST/ASTConsumer.h>
59
#include <clang/Frontend/CompilerInstance.h>
6-
#include "clang/Frontend/FrontendActions.h"
10+
#include <clang/Frontend/FrontendActions.h>
11+
#include <clang/Tooling/Tooling.h>
712

813
namespace chimera
914
{
@@ -14,10 +19,41 @@ namespace chimera
1419
class FrontendAction : public clang::ASTFrontendAction
1520
{
1621
public:
22+
// Overrides the constructor in order to receive ChimeraConfiguration.
23+
FrontendAction(const chimera::Configuration &config);
24+
1725
std::unique_ptr<clang::ASTConsumer> CreateASTConsumer(
1826
clang::CompilerInstance &CI, clang::StringRef file) override;
27+
28+
protected:
29+
const chimera::Configuration &config_;
30+
};
31+
32+
// Create a custom action factory that forwards the ChimeraConfiguration.
33+
class ChimeraFrontendActionFactory
34+
: public clang::tooling::FrontendActionFactory
35+
{
36+
public:
37+
ChimeraFrontendActionFactory(const chimera::Configuration &config);
38+
39+
// Between Clang 9 and Clang 10, the return value for
40+
// FrontendActionFactory::create() changed from raw pointer to std::unique_ptr.
41+
#if LLVM_VERSION_AT_LEAST(10, 0, 0)
42+
std::unique_ptr<clang::FrontendAction> create() override;
43+
#else
44+
clang::FrontendAction *create() override;
45+
#endif
46+
47+
protected:
48+
const chimera::Configuration &config_;
1949
};
2050

51+
/**
52+
* Custom frontend factory that forwards a ChimeraConfiguration.
53+
*/
54+
std::unique_ptr<clang::tooling::FrontendActionFactory> newFrontendActionFactory(
55+
const chimera::Configuration &config);
56+
2157
} // namespace chimera
2258

2359
#endif // __CHIMERA_FRONTEND_ACTION_H__

src/chimera.cpp

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
#include <string>
1111
#include <clang/Tooling/ArgumentsAdjusters.h>
1212
#include <clang/Tooling/CommonOptionsParser.h>
13-
#include <clang/Tooling/Tooling.h>
1413
#include <llvm/Support/CommandLine.h>
1514

1615
#define STR_DETAIL(x) #x
@@ -99,38 +98,40 @@ int run(int argc, const char **argv)
9998
// Create parser that handles clang options.
10099
CommonOptionsParser OptionsParser(argc, argv, ChimeraCategory);
101100

101+
// Create a new configuration that will be used for the run.
102+
chimera::Configuration Config;
103+
102104
// Parse the YAML configuration file if it exists, otherwise initialize it
103105
// to an empty node.
104106
if (!ConfigFilename.empty())
105-
chimera::Configuration::GetInstance().LoadFile(ConfigFilename);
107+
Config.LoadFile(ConfigFilename);
106108

107109
// If a binding definition was specified, set configuration to use it.
108110
if (!BindingName.empty())
109-
chimera::Configuration::GetInstance().SetBindingName(BindingName);
111+
Config.SetBindingName(BindingName);
110112

111113
// If an output path was specified, set configuration to use it.
112114
if (!OutputPath.empty())
113-
chimera::Configuration::GetInstance().SetOutputPath(OutputPath);
115+
Config.SetOutputPath(OutputPath);
114116

115117
// If a top-level binding file was specified, set configuration to use it.
116118
if (!OutputModuleName.empty())
117-
chimera::Configuration::GetInstance().SetOutputModuleName(
118-
OutputModuleName);
119+
Config.SetOutputModuleName(OutputModuleName);
119120

120121
// Add top-level namespaces to the configuration.
121122
if (NamespaceNames.size())
122123
for (const std::string &name : NamespaceNames)
123-
chimera::Configuration::GetInstance().AddInputNamespaceName(name);
124+
Config.AddInputNamespaceName(name);
124125

125126
// Add compilation source paths to the configuration.
126127
// These will be made available to templates.
127128
if (!SuppressSources)
128129
for (const std::string &path : OptionsParser.getSourcePathList())
129-
chimera::Configuration::GetInstance().AddSourcePath(path);
130+
Config.AddSourcePath(path);
130131

131132
// If strict option is on, treats unresolvable configuration as errors.
132133
if (Strict)
133-
chimera::Configuration::GetInstance().SetStrict(true);
134+
Config.SetStrict(true);
134135

135136
// Create tool that uses the command-line options.
136137
ClangTool Tool(OptionsParser.getCompilations(),
@@ -153,7 +154,7 @@ int run(int argc, const char **argv)
153154
ArgumentInsertPosition::END));
154155

155156
// Run the instantiated tool on the Chimera frontend.
156-
return Tool.run(newFrontendActionFactory<chimera::FrontendAction>().get());
157+
return Tool.run(chimera::newFrontendActionFactory(Config).get());
157158
}
158159

159160
} // namespace chimera

src/configuration.cpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -67,12 +67,6 @@ chimera::Configuration::Configuration()
6767
// Do nothing.
6868
}
6969

70-
chimera::Configuration &chimera::Configuration::GetInstance()
71-
{
72-
static chimera::Configuration config;
73-
return config;
74-
}
75-
7670
void chimera::Configuration::LoadFile(const std::string &filename)
7771
{
7872
try

src/consumer.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,22 @@
11
#include "chimera/consumer.h"
2-
#include "chimera/configuration.h"
32
#include "chimera/visitor.h"
43

54
#include <iostream>
65

76
using namespace clang;
87

9-
chimera::Consumer::Consumer(CompilerInstance *ci) : ci_(ci)
8+
chimera::Consumer::Consumer(CompilerInstance *ci,
9+
const chimera::Configuration &config)
10+
: ci_(ci), config_(config)
1011
{
1112
// Do nothing.
1213
}
1314

1415
void chimera::Consumer::HandleTranslationUnit(ASTContext &context)
1516
{
1617
// Use the current translation unit to resolve the YAML configuration.
17-
chimera::Configuration &config = chimera::Configuration::GetInstance();
18-
1918
std::unique_ptr<chimera::CompiledConfiguration> compiled_config
20-
= config.Process(ci_);
19+
= config_.Process(ci_);
2120
chimera::Visitor visitor(ci_, *compiled_config);
2221

2322
// We can use ASTContext to get the TranslationUnitDecl, which is

src/frontend_action.cpp

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@
55

66
using namespace clang;
77

8+
chimera::FrontendAction::FrontendAction(const chimera::Configuration &config)
9+
: config_(config)
10+
{
11+
// Do nothing.
12+
}
13+
814
std::unique_ptr<clang::ASTConsumer> chimera::FrontendAction::CreateASTConsumer(
915
CompilerInstance &CI, StringRef /*file*/)
1016
{
@@ -17,5 +23,36 @@ std::unique_ptr<clang::ASTConsumer> chimera::FrontendAction::CreateASTConsumer(
1723
is_first = false;
1824

1925
CI.getPreprocessor().getDiagnostics().setIgnoreAllWarnings(true);
20-
return std::unique_ptr<chimera::Consumer>(new chimera::Consumer(&CI));
26+
return std::unique_ptr<chimera::Consumer>(
27+
new chimera::Consumer(&CI, config_));
28+
}
29+
30+
// Create a custom action factory that forwards the ChimeraConfiguration.
31+
chimera::ChimeraFrontendActionFactory::ChimeraFrontendActionFactory(
32+
const chimera::Configuration &config)
33+
: config_(config)
34+
{
35+
// Do nothing.
36+
}
37+
38+
// Between Clang 9 and Clang 10, the return value for
39+
// FrontendActionFactory::create() changed from raw pointer to std::unique_ptr.
40+
#if LLVM_VERSION_AT_LEAST(10, 0, 0)
41+
std::unique_ptr<FrontendAction> chimera::ChimeraFrontendActionFactory::create()
42+
{
43+
return std::unique_ptr<FrontendAction>(
44+
new chimera::FrontendAction(config_));
45+
}
46+
#else
47+
FrontendAction *chimera::ChimeraFrontendActionFactory::create()
48+
{
49+
return new chimera::FrontendAction(config_);
50+
}
51+
#endif
52+
53+
std::unique_ptr<tooling::FrontendActionFactory>
54+
chimera::newFrontendActionFactory(const chimera::Configuration &config)
55+
{
56+
return std::unique_ptr<tooling::FrontendActionFactory>(
57+
new chimera::ChimeraFrontendActionFactory(config));
2158
}

0 commit comments

Comments
 (0)