diff options
author | Faris Rehman <faris.rehman@arm.com> | 2021-01-06 15:42:24 +0000 |
---|---|---|
committer | Andrzej Warzynski <andrzej.warzynski@arm.com> | 2021-01-06 16:17:13 +0000 |
commit | 7809fa20400000fd40b4a4b56696c7fbcd0f0fa9 (patch) | |
tree | 61cf88345108683a3df19a7760ce81a9e1eed9b8 /flang/lib/Frontend/CompilerInvocation.cpp | |
parent | 1307e3f6c46cc3a6e6ad9cd46fc67efafcac939e (diff) | |
download | llvm-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.cpp | 69 |
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); +} |