mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-19 13:26:45 +00:00
[flang][Frontend] Implement printing defined macros via -dM (#87627)
This should work the same way as in clang.
This commit is contained in:
parent
f1ee458ddb
commit
7d60232b38
@ -2147,8 +2147,10 @@ flang/include/flang/Parser/message.h
|
||||
flang/include/flang/Parser/parse-state.h
|
||||
flang/include/flang/Parser/parse-tree-visitor.h
|
||||
flang/include/flang/Parser/parsing.h
|
||||
flang/include/flang/Parser/preprocessor.h
|
||||
flang/include/flang/Parser/provenance.h
|
||||
flang/include/flang/Parser/source.h
|
||||
flang/include/flang/Parser/token-sequence.h
|
||||
flang/include/flang/Parser/tools.h
|
||||
flang/include/flang/Parser/unparse.h
|
||||
flang/include/flang/Parser/user-state.h
|
||||
@ -2319,7 +2321,6 @@ flang/lib/Parser/openmp-parsers.cpp
|
||||
flang/lib/Parser/parse-tree.cpp
|
||||
flang/lib/Parser/parsing.cpp
|
||||
flang/lib/Parser/preprocessor.cpp
|
||||
flang/lib/Parser/preprocessor.h
|
||||
flang/lib/Parser/prescan.cpp
|
||||
flang/lib/Parser/prescan.h
|
||||
flang/lib/Parser/program-parsers.cpp
|
||||
@ -2328,7 +2329,6 @@ flang/lib/Parser/source.cpp
|
||||
flang/lib/Parser/stmt-parser.h
|
||||
flang/lib/Parser/token-parsers.h
|
||||
flang/lib/Parser/token-sequence.cpp
|
||||
flang/lib/Parser/token-sequence.h
|
||||
flang/lib/Parser/tools.cpp
|
||||
flang/lib/Parser/type-parser-implementation.h
|
||||
flang/lib/Parser/type-parsers.h
|
||||
|
@ -1449,7 +1449,7 @@ def dD : Flag<["-"], "dD">, Group<d_Group>, Visibility<[ClangOption, CC1Option]>
|
||||
def dI : Flag<["-"], "dI">, Group<d_Group>, Visibility<[ClangOption, CC1Option]>,
|
||||
HelpText<"Print include directives in -E mode in addition to normal output">,
|
||||
MarshallingInfoFlag<PreprocessorOutputOpts<"ShowIncludeDirectives">>;
|
||||
def dM : Flag<["-"], "dM">, Group<d_Group>, Visibility<[ClangOption, CC1Option]>,
|
||||
def dM : Flag<["-"], "dM">, Group<d_Group>, Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>,
|
||||
HelpText<"Print macro definitions in -E mode instead of normal output">;
|
||||
def dead__strip : Flag<["-"], "dead_strip">;
|
||||
def dependency_file : Separate<["-"], "dependency-file">,
|
||||
|
@ -679,7 +679,10 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA,
|
||||
CmdArgs.push_back(Args.MakeArgString(TripleStr));
|
||||
|
||||
if (isa<PreprocessJobAction>(JA)) {
|
||||
CmdArgs.push_back("-E");
|
||||
CmdArgs.push_back("-E");
|
||||
if (Args.getLastArg(options::OPT_dM)) {
|
||||
CmdArgs.push_back("-dM");
|
||||
}
|
||||
} else if (isa<CompileJobAction>(JA) || isa<BackendJobAction>(JA)) {
|
||||
if (JA.getType() == types::TY_Nothing) {
|
||||
CmdArgs.push_back("-fsyntax-only");
|
||||
|
@ -56,6 +56,9 @@ struct PreprocessorOptions {
|
||||
// -fno-reformat: Emit cooked character stream as -E output
|
||||
bool noReformat{false};
|
||||
|
||||
// -dM: Show macro definitions with -dM -E
|
||||
bool showMacros{false};
|
||||
|
||||
void addMacroDef(llvm::StringRef name) {
|
||||
macros.emplace_back(std::string(name), false);
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "parse-tree.h"
|
||||
#include "provenance.h"
|
||||
#include "flang/Common/Fortran-features.h"
|
||||
#include "flang/Parser/preprocessor.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <optional>
|
||||
#include <string>
|
||||
@ -59,6 +60,7 @@ public:
|
||||
const SourceFile *Prescan(const std::string &path, Options);
|
||||
void EmitPreprocessedSource(
|
||||
llvm::raw_ostream &, bool lineDirectives = true) const;
|
||||
void EmitPreprocessorMacros(llvm::raw_ostream &) const;
|
||||
void DumpCookedChars(llvm::raw_ostream &) const;
|
||||
void DumpProvenance(llvm::raw_ostream &) const;
|
||||
void DumpParsingLog(llvm::raw_ostream &) const;
|
||||
@ -83,6 +85,7 @@ private:
|
||||
const char *finalRestingPlace_{nullptr};
|
||||
std::optional<Program> parseTree_;
|
||||
ParsingLog log_;
|
||||
Preprocessor preprocessor_{allCooked_.allSources()};
|
||||
};
|
||||
} // namespace Fortran::parser
|
||||
#endif // FORTRAN_PARSER_PARSING_H_
|
||||
|
@ -15,9 +15,10 @@
|
||||
// performed, so that special compiler command options &/or source file name
|
||||
// extensions for preprocessing will not be necessary.
|
||||
|
||||
#include "token-sequence.h"
|
||||
#include "flang/Parser/char-block.h"
|
||||
#include "flang/Parser/provenance.h"
|
||||
#include "flang/Parser/token-sequence.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <cstddef>
|
||||
#include <list>
|
||||
#include <stack>
|
||||
@ -39,7 +40,7 @@ public:
|
||||
Definition(const std::string &predefined, AllSources &);
|
||||
|
||||
bool isFunctionLike() const { return isFunctionLike_; }
|
||||
std::size_t argumentCount() const { return argumentCount_; }
|
||||
std::size_t argumentCount() const { return argNames_.size(); }
|
||||
bool isVariadic() const { return isVariadic_; }
|
||||
bool isDisabled() const { return isDisabled_; }
|
||||
bool isPredefined() const { return isPredefined_; }
|
||||
@ -49,15 +50,21 @@ public:
|
||||
|
||||
TokenSequence Apply(const std::vector<TokenSequence> &args, Prescanner &);
|
||||
|
||||
void Print(llvm::raw_ostream &out, const char *macroName = "") const;
|
||||
|
||||
private:
|
||||
static TokenSequence Tokenize(const std::vector<std::string> &argNames,
|
||||
const TokenSequence &token, std::size_t firstToken, std::size_t tokens);
|
||||
// For a given token, return the index of the argument to which the token
|
||||
// corresponds, or `argumentCount` if the token does not correspond to any
|
||||
// argument.
|
||||
std::size_t GetArgumentIndex(const CharBlock &token) const;
|
||||
|
||||
bool isFunctionLike_{false};
|
||||
std::size_t argumentCount_{0};
|
||||
bool isVariadic_{false};
|
||||
bool isDisabled_{false};
|
||||
bool isPredefined_{false};
|
||||
std::vector<std::string> argNames_;
|
||||
TokenSequence replacement_;
|
||||
};
|
||||
|
||||
@ -89,6 +96,8 @@ public:
|
||||
// Implements a preprocessor directive.
|
||||
void Directive(const TokenSequence &, Prescanner &);
|
||||
|
||||
void PrintMacros(llvm::raw_ostream &out) const;
|
||||
|
||||
private:
|
||||
enum class IsElseActive { No, Yes };
|
||||
enum class CanDeadElseAppear { No, Yes };
|
@ -42,8 +42,8 @@ public:
|
||||
}
|
||||
TokenSequence(TokenSequence &&that)
|
||||
: start_{std::move(that.start_)}, nextStart_{that.nextStart_},
|
||||
char_{std::move(that.char_)}, provenances_{
|
||||
std::move(that.provenances_)} {}
|
||||
char_{std::move(that.char_)},
|
||||
provenances_{std::move(that.provenances_)} {}
|
||||
TokenSequence(const std::string &s, Provenance p) { Put(s, p); }
|
||||
|
||||
TokenSequence &operator=(const TokenSequence &that) {
|
@ -772,6 +772,7 @@ static void parsePreprocessorArgs(Fortran::frontend::PreprocessorOptions &opts,
|
||||
|
||||
opts.noReformat = args.hasArg(clang::driver::options::OPT_fno_reformat);
|
||||
opts.noLineDirectives = args.hasArg(clang::driver::options::OPT_P);
|
||||
opts.showMacros = args.hasArg(clang::driver::options::OPT_dM);
|
||||
}
|
||||
|
||||
/// Parses all semantic related arguments and populates the variables
|
||||
|
@ -399,7 +399,9 @@ void PrintPreprocessedAction::executeAction() {
|
||||
|
||||
// Format or dump the prescanner's output
|
||||
CompilerInstance &ci = this->getInstance();
|
||||
if (ci.getInvocation().getPreprocessorOpts().noReformat) {
|
||||
if (ci.getInvocation().getPreprocessorOpts().showMacros) {
|
||||
ci.getParsing().EmitPreprocessorMacros(outForPP);
|
||||
} else if (ci.getInvocation().getPreprocessorOpts().noReformat) {
|
||||
ci.getParsing().DumpCookedChars(outForPP);
|
||||
} else {
|
||||
ci.getParsing().EmitPreprocessedSource(
|
||||
|
@ -7,10 +7,10 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "flang/Parser/parsing.h"
|
||||
#include "preprocessor.h"
|
||||
#include "prescan.h"
|
||||
#include "type-parsers.h"
|
||||
#include "flang/Parser/message.h"
|
||||
#include "flang/Parser/preprocessor.h"
|
||||
#include "flang/Parser/provenance.h"
|
||||
#include "flang/Parser/source.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
@ -60,20 +60,19 @@ const SourceFile *Parsing::Prescan(const std::string &path, Options options) {
|
||||
}
|
||||
}
|
||||
|
||||
Preprocessor preprocessor{allSources};
|
||||
if (!options.predefinitions.empty()) {
|
||||
preprocessor.DefineStandardMacros();
|
||||
preprocessor_.DefineStandardMacros();
|
||||
for (const auto &predef : options.predefinitions) {
|
||||
if (predef.second) {
|
||||
preprocessor.Define(predef.first, *predef.second);
|
||||
preprocessor_.Define(predef.first, *predef.second);
|
||||
} else {
|
||||
preprocessor.Undefine(predef.first);
|
||||
preprocessor_.Undefine(predef.first);
|
||||
}
|
||||
}
|
||||
}
|
||||
currentCooked_ = &allCooked_.NewCookedSource();
|
||||
Prescanner prescanner{
|
||||
messages_, *currentCooked_, preprocessor, options.features};
|
||||
messages_, *currentCooked_, preprocessor_, options.features};
|
||||
prescanner.set_fixedForm(options.isFixedForm)
|
||||
.set_fixedFormColumnLimit(options.fixedFormColumns)
|
||||
.AddCompilerDirectiveSentinel("dir$");
|
||||
@ -87,7 +86,7 @@ const SourceFile *Parsing::Prescan(const std::string &path, Options options) {
|
||||
if (options.features.IsEnabled(LanguageFeature::CUDA)) {
|
||||
prescanner.AddCompilerDirectiveSentinel("$cuf");
|
||||
prescanner.AddCompilerDirectiveSentinel("@cuf");
|
||||
preprocessor.Define("_CUDA", "1");
|
||||
preprocessor_.Define("_CUDA", "1");
|
||||
}
|
||||
ProvenanceRange range{allSources.AddIncludedFile(
|
||||
*sourceFile, ProvenanceRange{}, options.isModuleFile)};
|
||||
@ -107,6 +106,10 @@ const SourceFile *Parsing::Prescan(const std::string &path, Options options) {
|
||||
return sourceFile;
|
||||
}
|
||||
|
||||
void Parsing::EmitPreprocessorMacros(llvm::raw_ostream &out) const {
|
||||
preprocessor_.PrintMacros(out);
|
||||
}
|
||||
|
||||
void Parsing::EmitPreprocessedSource(
|
||||
llvm::raw_ostream &out, bool lineDirectives) const {
|
||||
const std::string *sourcePath{nullptr};
|
||||
|
@ -6,7 +6,8 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "preprocessor.h"
|
||||
#include "flang/Parser/preprocessor.h"
|
||||
|
||||
#include "prescan.h"
|
||||
#include "flang/Common/idioms.h"
|
||||
#include "flang/Parser/characters.h"
|
||||
@ -21,6 +22,7 @@
|
||||
#include <optional>
|
||||
#include <set>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace Fortran::parser {
|
||||
|
||||
@ -31,8 +33,7 @@ Definition::Definition(
|
||||
Definition::Definition(const std::vector<std::string> &argNames,
|
||||
const TokenSequence &repl, std::size_t firstToken, std::size_t tokens,
|
||||
bool isVariadic)
|
||||
: isFunctionLike_{true},
|
||||
argumentCount_(argNames.size()), isVariadic_{isVariadic},
|
||||
: isFunctionLike_{true}, isVariadic_{isVariadic}, argNames_{argNames},
|
||||
replacement_{Tokenize(argNames, repl, firstToken, tokens)} {}
|
||||
|
||||
Definition::Definition(const std::string &predefined, AllSources &sources)
|
||||
@ -46,6 +47,37 @@ bool Definition::set_isDisabled(bool disable) {
|
||||
return was;
|
||||
}
|
||||
|
||||
void Definition::Print(llvm::raw_ostream &out, const char *macroName) const {
|
||||
if (!isFunctionLike_) {
|
||||
// If it's not a function-like macro, then just print the replacement.
|
||||
out << ' ' << replacement_.ToString();
|
||||
return;
|
||||
}
|
||||
|
||||
size_t argCount{argumentCount()};
|
||||
|
||||
out << '(';
|
||||
for (size_t i{0}; i != argCount; ++i) {
|
||||
if (i != 0) {
|
||||
out << ", ";
|
||||
}
|
||||
out << argNames_[i];
|
||||
}
|
||||
if (isVariadic_) {
|
||||
out << ", ...";
|
||||
}
|
||||
out << ") ";
|
||||
|
||||
for (size_t i{0}, e{replacement_.SizeInTokens()}; i != e; ++i) {
|
||||
std::string tok{replacement_.TokenAt(i).ToString()};
|
||||
if (size_t idx{GetArgumentIndex(tok)}; idx < argCount) {
|
||||
out << argNames_[idx];
|
||||
} else {
|
||||
out << tok;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool IsLegalIdentifierStart(const CharBlock &cpl) {
|
||||
return cpl.size() > 0 && IsLegalIdentifierStart(cpl[0]);
|
||||
}
|
||||
@ -73,6 +105,13 @@ TokenSequence Definition::Tokenize(const std::vector<std::string> &argNames,
|
||||
return result;
|
||||
}
|
||||
|
||||
std::size_t Definition::GetArgumentIndex(const CharBlock &token) const {
|
||||
if (token.size() >= 2 && token[0] == '~') {
|
||||
return static_cast<size_t>(token[1] - 'A');
|
||||
}
|
||||
return argumentCount();
|
||||
}
|
||||
|
||||
static TokenSequence Stringify(
|
||||
const TokenSequence &tokens, AllSources &allSources) {
|
||||
TokenSequence result;
|
||||
@ -159,7 +198,7 @@ TokenSequence Definition::Apply(
|
||||
continue;
|
||||
}
|
||||
if (bytes == 2 && token[0] == '~') { // argument substitution
|
||||
std::size_t index = token[1] - 'A';
|
||||
std::size_t index{GetArgumentIndex(token)};
|
||||
if (index >= args.size()) {
|
||||
continue;
|
||||
}
|
||||
@ -202,8 +241,8 @@ TokenSequence Definition::Apply(
|
||||
Provenance commaProvenance{
|
||||
prescanner.preprocessor().allSources().CompilerInsertionProvenance(
|
||||
',')};
|
||||
for (std::size_t k{argumentCount_}; k < args.size(); ++k) {
|
||||
if (k > argumentCount_) {
|
||||
for (std::size_t k{argumentCount()}; k < args.size(); ++k) {
|
||||
if (k > argumentCount()) {
|
||||
result.Put(","s, commaProvenance);
|
||||
}
|
||||
result.Put(args[k]);
|
||||
@ -212,7 +251,7 @@ TokenSequence Definition::Apply(
|
||||
j + 2 < tokens && replacement_.TokenAt(j + 1).OnlyNonBlank() == '(' &&
|
||||
parenthesesNesting == 0) {
|
||||
parenthesesNesting = 1;
|
||||
skipping = args.size() == argumentCount_;
|
||||
skipping = args.size() == argumentCount();
|
||||
++j;
|
||||
} else {
|
||||
if (parenthesesNesting > 0) {
|
||||
@ -713,6 +752,21 @@ void Preprocessor::Directive(const TokenSequence &dir, Prescanner &prescanner) {
|
||||
}
|
||||
}
|
||||
|
||||
void Preprocessor::PrintMacros(llvm::raw_ostream &out) const {
|
||||
// std::set is ordered. Use that to print the macros in an
|
||||
// alphabetical order.
|
||||
std::set<std::string> macroNames;
|
||||
for (const auto &[name, _] : definitions_) {
|
||||
macroNames.insert(name.ToString());
|
||||
}
|
||||
|
||||
for (const std::string &name : macroNames) {
|
||||
out << "#define " << name;
|
||||
definitions_.at(name).Print(out, name.c_str());
|
||||
out << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
CharBlock Preprocessor::SaveTokenAsName(const CharBlock &t) {
|
||||
names_.push_back(t.ToString());
|
||||
return {names_.back().data(), names_.back().size()};
|
||||
|
@ -7,12 +7,12 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "prescan.h"
|
||||
#include "preprocessor.h"
|
||||
#include "token-sequence.h"
|
||||
#include "flang/Common/idioms.h"
|
||||
#include "flang/Parser/characters.h"
|
||||
#include "flang/Parser/message.h"
|
||||
#include "flang/Parser/preprocessor.h"
|
||||
#include "flang/Parser/source.h"
|
||||
#include "flang/Parser/token-sequence.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
|
@ -16,11 +16,11 @@
|
||||
// fixed form character literals on truncated card images, file
|
||||
// inclusion, and driving the Fortran source preprocessor.
|
||||
|
||||
#include "token-sequence.h"
|
||||
#include "flang/Common/Fortran-features.h"
|
||||
#include "flang/Parser/characters.h"
|
||||
#include "flang/Parser/message.h"
|
||||
#include "flang/Parser/provenance.h"
|
||||
#include "flang/Parser/token-sequence.h"
|
||||
#include <bitset>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
@ -6,7 +6,8 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "token-sequence.h"
|
||||
#include "flang/Parser/token-sequence.h"
|
||||
|
||||
#include "prescan.h"
|
||||
#include "flang/Parser/characters.h"
|
||||
#include "flang/Parser/message.h"
|
||||
|
@ -21,6 +21,7 @@
|
||||
! CHECK-NEXT: -ccc-print-phases Dump list of actions to perform
|
||||
! CHECK-NEXT: -cpp Enable predefined and command line preprocessor macros
|
||||
! CHECK-NEXT: -c Only run preprocess, compile, and assemble steps
|
||||
! CHECK-NEXT: -dM Print macro definitions in -E mode instead of normal output
|
||||
! CHECK-NEXT: -dumpmachine Display the compiler's target processor
|
||||
! CHECK-NEXT: -dumpversion Display the version of the compiler
|
||||
! CHECK-NEXT: -D <macro>=<value> Define <macro> to <value> (or 1 if <value> omitted)
|
||||
|
@ -17,6 +17,7 @@
|
||||
! HELP-NEXT: -### Print (but do not run) the commands to run for this compilation
|
||||
! HELP-NEXT: -cpp Enable predefined and command line preprocessor macros
|
||||
! HELP-NEXT: -c Only run preprocess, compile, and assemble steps
|
||||
! HELP-NEXT: -dM Print macro definitions in -E mode instead of normal output
|
||||
! HELP-NEXT: -dumpmachine Display the compiler's target processor
|
||||
! HELP-NEXT: -dumpversion Display the version of the compiler
|
||||
! HELP-NEXT: -D <macro>=<value> Define <macro> to <value> (or 1 if <value> omitted)
|
||||
@ -155,6 +156,7 @@
|
||||
! HELP-FC1-NEXT:OPTIONS:
|
||||
! HELP-FC1-NEXT: -cpp Enable predefined and command line preprocessor macros
|
||||
! HELP-FC1-NEXT: --dependent-lib=<value> Add dependent library
|
||||
! HELP-FC1-NEXT: -dM Print macro definitions in -E mode instead of normal output
|
||||
! HELP-FC1-NEXT: -D <macro>=<value> Define <macro> to <value> (or 1 if <value> omitted)
|
||||
! HELP-FC1-NEXT: -emit-fir Build the parse tree, then lower it to FIR
|
||||
! HELP-FC1-NEXT: -emit-hlfir Build the parse tree, then lower it to HLFIR
|
||||
|
14
flang/test/Preprocessing/show-macros1.F90
Normal file
14
flang/test/Preprocessing/show-macros1.F90
Normal file
@ -0,0 +1,14 @@
|
||||
! RUN: %flang -dM -E -o - %s | FileCheck %s
|
||||
|
||||
! Check the default macros. Omit certain ones such as __LINE__
|
||||
! or __FILE__, or target-specific ones, like __x86_64__.
|
||||
|
||||
! Macros are printed in the alphabetical order.
|
||||
|
||||
! CHECK: #define __DATE__
|
||||
! CHECK: #define __TIME__
|
||||
! CHECK: #define __flang__
|
||||
! CHECK: #define __flang_major__
|
||||
! CHECK: #define __flang_minor__
|
||||
! CHECK: #define __flang_patchlevel__
|
||||
|
6
flang/test/Preprocessing/show-macros2.F90
Normal file
6
flang/test/Preprocessing/show-macros2.F90
Normal file
@ -0,0 +1,6 @@
|
||||
! RUN: %flang -DFOO -DBAR=FOO -dM -E -o - %s | FileCheck %s
|
||||
|
||||
! Check command line definitions
|
||||
|
||||
! CHECK: #define BAR FOO
|
||||
! CHECK: #define FOO 1
|
9
flang/test/Preprocessing/show-macros3.F90
Normal file
9
flang/test/Preprocessing/show-macros3.F90
Normal file
@ -0,0 +1,9 @@
|
||||
! RUN: %flang -dM -E -o - %s | FileCheck %s
|
||||
|
||||
! Variadic macro
|
||||
#define FOO1(X, Y, ...) bar(bar(X, Y), __VA_ARGS__)
|
||||
! CHECK: #define FOO1(X, Y, ...) bar(bar(X, Y), __VA_ARGS__)
|
||||
|
||||
! Macro with an unused parameter
|
||||
#define FOO2(X, Y, Z) (X + Z)
|
||||
! CHECK: #define FOO2(X, Y, Z) (X + Z)
|
Loading…
x
Reference in New Issue
Block a user