aboutsummaryrefslogtreecommitdiff
path: root/flang/lib/Frontend/CompilerInvocation.cpp
diff options
context:
space:
mode:
authorFaris Rehman <faris.rehman@arm.com>2021-01-06 15:42:24 +0000
committerAndrzej Warzynski <andrzej.warzynski@arm.com>2021-01-06 16:17:13 +0000
commit7809fa20400000fd40b4a4b56696c7fbcd0f0fa9 (patch)
tree61cf88345108683a3df19a7760ce81a9e1eed9b8 /flang/lib/Frontend/CompilerInvocation.cpp
parent1307e3f6c46cc3a6e6ad9cd46fc67efafcac939e (diff)
downloadllvm-7809fa20400000fd40b4a4b56696c7fbcd0f0fa9.zip
llvm-7809fa20400000fd40b4a4b56696c7fbcd0f0fa9.tar.gz
llvm-7809fa20400000fd40b4a4b56696c7fbcd0f0fa9.tar.bz2
[flang][driver] Add support for `-D`, `-U`
Add support for options -D and -U in the new Flang driver. Summary of changes: - Create PreprocessorOptions, to be used by the driver then translated into Fortran::parser::Options - Create CompilerInvocation::setFortranOpts to pass preprocessor options into the parser options - Add a dedicated method, Flang::AddPreprocessingOptions, to extract preprocessing options from the driver arguments into the preprocessor command arguments Macros specified like -DName will default to definition 1. When defining macros, the new driver will drop anything after an end-of-line character. This is consistent with gfortran and clang, but different to what currently f18 does. However, flang (which is a bash wrapper for f18), also drops everything after an end-of-line character. So gfortran-like behaviour felt like the natural choice. Test is added to demonstrate this behaviour. Reviewed By: awarzynski Differential Revision: https://reviews.llvm.org/D93401
Diffstat (limited to 'flang/lib/Frontend/CompilerInvocation.cpp')
-rw-r--r--flang/lib/Frontend/CompilerInvocation.cpp69
1 files changed, 67 insertions, 2 deletions
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp
index db3ae741..df7fe44 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "flang/Frontend/CompilerInvocation.h"
+#include "flang/Frontend/PreprocessorOptions.h"
#include "clang/Basic/AllDiagnostics.h"
#include "clang/Basic/DiagnosticDriver.h"
#include "clang/Basic/DiagnosticOptions.h"
@@ -26,10 +27,12 @@ using namespace Fortran::frontend;
// Initialization.
//===----------------------------------------------------------------------===//
CompilerInvocationBase::CompilerInvocationBase()
- : diagnosticOpts_(new clang::DiagnosticOptions()) {}
+ : diagnosticOpts_(new clang::DiagnosticOptions()),
+ preprocessorOpts_(new PreprocessorOptions()) {}
CompilerInvocationBase::CompilerInvocationBase(const CompilerInvocationBase &x)
- : diagnosticOpts_(new clang::DiagnosticOptions(x.GetDiagnosticOpts())) {}
+ : diagnosticOpts_(new clang::DiagnosticOptions(x.GetDiagnosticOpts())),
+ preprocessorOpts_(new PreprocessorOptions(x.preprocessorOpts())) {}
CompilerInvocationBase::~CompilerInvocationBase() = default;
@@ -155,6 +158,24 @@ static InputKind ParseFrontendArgs(FrontendOptions &opts,
return dashX;
}
+/// Parses all preprocessor input arguments and populates the preprocessor
+/// options accordingly.
+///
+/// \param [in] opts The preprocessor options instance
+/// \param [out] args The list of input arguments
+static void parsePreprocessorArgs(
+ Fortran::frontend::PreprocessorOptions &opts, llvm::opt::ArgList &args) {
+ // Add macros from the command line.
+ for (const auto *currentArg : args.filtered(
+ clang::driver::options::OPT_D, clang::driver::options::OPT_U)) {
+ if (currentArg->getOption().matches(clang::driver::options::OPT_D)) {
+ opts.addMacroDef(currentArg->getValue());
+ } else {
+ opts.addMacroUndef(currentArg->getValue());
+ }
+ }
+}
+
bool CompilerInvocation::CreateFromArgs(CompilerInvocation &res,
llvm::ArrayRef<const char *> commandLineArgs,
clang::DiagnosticsEngine &diags) {
@@ -183,10 +204,47 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &res,
// Parse the frontend args
ParseFrontendArgs(res.frontendOpts(), args, diags);
+ // Parse the preprocessor args
+ parsePreprocessorArgs(res.preprocessorOpts(), args);
return success;
}
+/// Collect the macro definitions provided by the given preprocessor
+/// options into the parser options.
+///
+/// \param [in] ppOpts The preprocessor options
+/// \param [out] opts The fortran options
+static void collectMacroDefinitions(
+ const PreprocessorOptions &ppOpts, Fortran::parser::Options &opts) {
+ for (unsigned i = 0, n = ppOpts.macros.size(); i != n; ++i) {
+ llvm::StringRef macro = ppOpts.macros[i].first;
+ bool isUndef = ppOpts.macros[i].second;
+
+ std::pair<llvm::StringRef, llvm::StringRef> macroPair = macro.split('=');
+ llvm::StringRef macroName = macroPair.first;
+ llvm::StringRef macroBody = macroPair.second;
+
+ // For an #undef'd macro, we only care about the name.
+ if (isUndef) {
+ opts.predefinitions.emplace_back(
+ macroName.str(), std::optional<std::string>{});
+ continue;
+ }
+
+ // For a #define'd macro, figure out the actual definition.
+ if (macroName.size() == macro.size())
+ macroBody = "1";
+ else {
+ // Note: GCC drops anything following an end-of-line character.
+ llvm::StringRef::size_type End = macroBody.find_first_of("\n\r");
+ macroBody = macroBody.substr(0, End);
+ }
+ opts.predefinitions.emplace_back(
+ macroName, std::optional<std::string>(macroBody.str()));
+ }
+}
+
void CompilerInvocation::SetDefaultFortranOpts() {
auto &fortranOptions = fortranOpts();
@@ -195,3 +253,10 @@ void CompilerInvocation::SetDefaultFortranOpts() {
fortranOptions.searchDirectories = searchDirectories;
fortranOptions.isFixedForm = false;
}
+
+void CompilerInvocation::setFortranOpts() {
+ auto &fortranOptions = fortranOpts();
+ const auto &preprocessorOptions = preprocessorOpts();
+
+ collectMacroDefinitions(preprocessorOptions, fortranOptions);
+}