Skip to content

Commit 7d60232

Browse files
authored
[flang][Frontend] Implement printing defined macros via -dM (llvm#87627)
This should work the same way as in clang.
1 parent f1ee458 commit 7d60232

File tree

19 files changed

+139
-28
lines changed

19 files changed

+139
-28
lines changed

clang/docs/tools/clang-formatted-files.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2147,8 +2147,10 @@ flang/include/flang/Parser/message.h
21472147
flang/include/flang/Parser/parse-state.h
21482148
flang/include/flang/Parser/parse-tree-visitor.h
21492149
flang/include/flang/Parser/parsing.h
2150+
flang/include/flang/Parser/preprocessor.h
21502151
flang/include/flang/Parser/provenance.h
21512152
flang/include/flang/Parser/source.h
2153+
flang/include/flang/Parser/token-sequence.h
21522154
flang/include/flang/Parser/tools.h
21532155
flang/include/flang/Parser/unparse.h
21542156
flang/include/flang/Parser/user-state.h
@@ -2319,7 +2321,6 @@ flang/lib/Parser/openmp-parsers.cpp
23192321
flang/lib/Parser/parse-tree.cpp
23202322
flang/lib/Parser/parsing.cpp
23212323
flang/lib/Parser/preprocessor.cpp
2322-
flang/lib/Parser/preprocessor.h
23232324
flang/lib/Parser/prescan.cpp
23242325
flang/lib/Parser/prescan.h
23252326
flang/lib/Parser/program-parsers.cpp
@@ -2328,7 +2329,6 @@ flang/lib/Parser/source.cpp
23282329
flang/lib/Parser/stmt-parser.h
23292330
flang/lib/Parser/token-parsers.h
23302331
flang/lib/Parser/token-sequence.cpp
2331-
flang/lib/Parser/token-sequence.h
23322332
flang/lib/Parser/tools.cpp
23332333
flang/lib/Parser/type-parser-implementation.h
23342334
flang/lib/Parser/type-parsers.h

clang/include/clang/Driver/Options.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1449,7 +1449,7 @@ def dD : Flag<["-"], "dD">, Group<d_Group>, Visibility<[ClangOption, CC1Option]>
14491449
def dI : Flag<["-"], "dI">, Group<d_Group>, Visibility<[ClangOption, CC1Option]>,
14501450
HelpText<"Print include directives in -E mode in addition to normal output">,
14511451
MarshallingInfoFlag<PreprocessorOutputOpts<"ShowIncludeDirectives">>;
1452-
def dM : Flag<["-"], "dM">, Group<d_Group>, Visibility<[ClangOption, CC1Option]>,
1452+
def dM : Flag<["-"], "dM">, Group<d_Group>, Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>,
14531453
HelpText<"Print macro definitions in -E mode instead of normal output">;
14541454
def dead__strip : Flag<["-"], "dead_strip">;
14551455
def dependency_file : Separate<["-"], "dependency-file">,

clang/lib/Driver/ToolChains/Flang.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -679,7 +679,10 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA,
679679
CmdArgs.push_back(Args.MakeArgString(TripleStr));
680680

681681
if (isa<PreprocessJobAction>(JA)) {
682-
CmdArgs.push_back("-E");
682+
CmdArgs.push_back("-E");
683+
if (Args.getLastArg(options::OPT_dM)) {
684+
CmdArgs.push_back("-dM");
685+
}
683686
} else if (isa<CompileJobAction>(JA) || isa<BackendJobAction>(JA)) {
684687
if (JA.getType() == types::TY_Nothing) {
685688
CmdArgs.push_back("-fsyntax-only");

flang/include/flang/Frontend/PreprocessorOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ struct PreprocessorOptions {
5656
// -fno-reformat: Emit cooked character stream as -E output
5757
bool noReformat{false};
5858

59+
// -dM: Show macro definitions with -dM -E
60+
bool showMacros{false};
61+
5962
void addMacroDef(llvm::StringRef name) {
6063
macros.emplace_back(std::string(name), false);
6164
}

flang/include/flang/Parser/parsing.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "parse-tree.h"
1616
#include "provenance.h"
1717
#include "flang/Common/Fortran-features.h"
18+
#include "flang/Parser/preprocessor.h"
1819
#include "llvm/Support/raw_ostream.h"
1920
#include <optional>
2021
#include <string>
@@ -59,6 +60,7 @@ class Parsing {
5960
const SourceFile *Prescan(const std::string &path, Options);
6061
void EmitPreprocessedSource(
6162
llvm::raw_ostream &, bool lineDirectives = true) const;
63+
void EmitPreprocessorMacros(llvm::raw_ostream &) const;
6264
void DumpCookedChars(llvm::raw_ostream &) const;
6365
void DumpProvenance(llvm::raw_ostream &) const;
6466
void DumpParsingLog(llvm::raw_ostream &) const;
@@ -83,6 +85,7 @@ class Parsing {
8385
const char *finalRestingPlace_{nullptr};
8486
std::optional<Program> parseTree_;
8587
ParsingLog log_;
88+
Preprocessor preprocessor_{allCooked_.allSources()};
8689
};
8790
} // namespace Fortran::parser
8891
#endif // FORTRAN_PARSER_PARSING_H_

flang/lib/Parser/preprocessor.h renamed to flang/include/flang/Parser/preprocessor.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,10 @@
1515
// performed, so that special compiler command options &/or source file name
1616
// extensions for preprocessing will not be necessary.
1717

18-
#include "token-sequence.h"
1918
#include "flang/Parser/char-block.h"
2019
#include "flang/Parser/provenance.h"
20+
#include "flang/Parser/token-sequence.h"
21+
#include "llvm/Support/raw_ostream.h"
2122
#include <cstddef>
2223
#include <list>
2324
#include <stack>
@@ -39,7 +40,7 @@ class Definition {
3940
Definition(const std::string &predefined, AllSources &);
4041

4142
bool isFunctionLike() const { return isFunctionLike_; }
42-
std::size_t argumentCount() const { return argumentCount_; }
43+
std::size_t argumentCount() const { return argNames_.size(); }
4344
bool isVariadic() const { return isVariadic_; }
4445
bool isDisabled() const { return isDisabled_; }
4546
bool isPredefined() const { return isPredefined_; }
@@ -49,15 +50,21 @@ class Definition {
4950

5051
TokenSequence Apply(const std::vector<TokenSequence> &args, Prescanner &);
5152

53+
void Print(llvm::raw_ostream &out, const char *macroName = "") const;
54+
5255
private:
5356
static TokenSequence Tokenize(const std::vector<std::string> &argNames,
5457
const TokenSequence &token, std::size_t firstToken, std::size_t tokens);
58+
// For a given token, return the index of the argument to which the token
59+
// corresponds, or `argumentCount` if the token does not correspond to any
60+
// argument.
61+
std::size_t GetArgumentIndex(const CharBlock &token) const;
5562

5663
bool isFunctionLike_{false};
57-
std::size_t argumentCount_{0};
5864
bool isVariadic_{false};
5965
bool isDisabled_{false};
6066
bool isPredefined_{false};
67+
std::vector<std::string> argNames_;
6168
TokenSequence replacement_;
6269
};
6370

@@ -89,6 +96,8 @@ class Preprocessor {
8996
// Implements a preprocessor directive.
9097
void Directive(const TokenSequence &, Prescanner &);
9198

99+
void PrintMacros(llvm::raw_ostream &out) const;
100+
92101
private:
93102
enum class IsElseActive { No, Yes };
94103
enum class CanDeadElseAppear { No, Yes };

flang/lib/Parser/token-sequence.h renamed to flang/include/flang/Parser/token-sequence.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ class TokenSequence {
4242
}
4343
TokenSequence(TokenSequence &&that)
4444
: start_{std::move(that.start_)}, nextStart_{that.nextStart_},
45-
char_{std::move(that.char_)}, provenances_{
46-
std::move(that.provenances_)} {}
45+
char_{std::move(that.char_)},
46+
provenances_{std::move(that.provenances_)} {}
4747
TokenSequence(const std::string &s, Provenance p) { Put(s, p); }
4848

4949
TokenSequence &operator=(const TokenSequence &that) {

flang/lib/Frontend/CompilerInvocation.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -772,6 +772,7 @@ static void parsePreprocessorArgs(Fortran::frontend::PreprocessorOptions &opts,
772772

773773
opts.noReformat = args.hasArg(clang::driver::options::OPT_fno_reformat);
774774
opts.noLineDirectives = args.hasArg(clang::driver::options::OPT_P);
775+
opts.showMacros = args.hasArg(clang::driver::options::OPT_dM);
775776
}
776777

777778
/// Parses all semantic related arguments and populates the variables

flang/lib/Frontend/FrontendActions.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,9 @@ void PrintPreprocessedAction::executeAction() {
399399

400400
// Format or dump the prescanner's output
401401
CompilerInstance &ci = this->getInstance();
402-
if (ci.getInvocation().getPreprocessorOpts().noReformat) {
402+
if (ci.getInvocation().getPreprocessorOpts().showMacros) {
403+
ci.getParsing().EmitPreprocessorMacros(outForPP);
404+
} else if (ci.getInvocation().getPreprocessorOpts().noReformat) {
403405
ci.getParsing().DumpCookedChars(outForPP);
404406
} else {
405407
ci.getParsing().EmitPreprocessedSource(

flang/lib/Parser/parsing.cpp

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "flang/Parser/parsing.h"
10-
#include "preprocessor.h"
1110
#include "prescan.h"
1211
#include "type-parsers.h"
1312
#include "flang/Parser/message.h"
13+
#include "flang/Parser/preprocessor.h"
1414
#include "flang/Parser/provenance.h"
1515
#include "flang/Parser/source.h"
1616
#include "llvm/Support/raw_ostream.h"
@@ -60,20 +60,19 @@ const SourceFile *Parsing::Prescan(const std::string &path, Options options) {
6060
}
6161
}
6262

63-
Preprocessor preprocessor{allSources};
6463
if (!options.predefinitions.empty()) {
65-
preprocessor.DefineStandardMacros();
64+
preprocessor_.DefineStandardMacros();
6665
for (const auto &predef : options.predefinitions) {
6766
if (predef.second) {
68-
preprocessor.Define(predef.first, *predef.second);
67+
preprocessor_.Define(predef.first, *predef.second);
6968
} else {
70-
preprocessor.Undefine(predef.first);
69+
preprocessor_.Undefine(predef.first);
7170
}
7271
}
7372
}
7473
currentCooked_ = &allCooked_.NewCookedSource();
7574
Prescanner prescanner{
76-
messages_, *currentCooked_, preprocessor, options.features};
75+
messages_, *currentCooked_, preprocessor_, options.features};
7776
prescanner.set_fixedForm(options.isFixedForm)
7877
.set_fixedFormColumnLimit(options.fixedFormColumns)
7978
.AddCompilerDirectiveSentinel("dir$");
@@ -87,7 +86,7 @@ const SourceFile *Parsing::Prescan(const std::string &path, Options options) {
8786
if (options.features.IsEnabled(LanguageFeature::CUDA)) {
8887
prescanner.AddCompilerDirectiveSentinel("$cuf");
8988
prescanner.AddCompilerDirectiveSentinel("@cuf");
90-
preprocessor.Define("_CUDA", "1");
89+
preprocessor_.Define("_CUDA", "1");
9190
}
9291
ProvenanceRange range{allSources.AddIncludedFile(
9392
*sourceFile, ProvenanceRange{}, options.isModuleFile)};
@@ -107,6 +106,10 @@ const SourceFile *Parsing::Prescan(const std::string &path, Options options) {
107106
return sourceFile;
108107
}
109108

109+
void Parsing::EmitPreprocessorMacros(llvm::raw_ostream &out) const {
110+
preprocessor_.PrintMacros(out);
111+
}
112+
110113
void Parsing::EmitPreprocessedSource(
111114
llvm::raw_ostream &out, bool lineDirectives) const {
112115
const std::string *sourcePath{nullptr};

flang/lib/Parser/preprocessor.cpp

Lines changed: 61 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9-
#include "preprocessor.h"
9+
#include "flang/Parser/preprocessor.h"
10+
1011
#include "prescan.h"
1112
#include "flang/Common/idioms.h"
1213
#include "flang/Parser/characters.h"
@@ -21,6 +22,7 @@
2122
#include <optional>
2223
#include <set>
2324
#include <utility>
25+
#include <vector>
2426

2527
namespace Fortran::parser {
2628

@@ -31,8 +33,7 @@ Definition::Definition(
3133
Definition::Definition(const std::vector<std::string> &argNames,
3234
const TokenSequence &repl, std::size_t firstToken, std::size_t tokens,
3335
bool isVariadic)
34-
: isFunctionLike_{true},
35-
argumentCount_(argNames.size()), isVariadic_{isVariadic},
36+
: isFunctionLike_{true}, isVariadic_{isVariadic}, argNames_{argNames},
3637
replacement_{Tokenize(argNames, repl, firstToken, tokens)} {}
3738

3839
Definition::Definition(const std::string &predefined, AllSources &sources)
@@ -46,6 +47,37 @@ bool Definition::set_isDisabled(bool disable) {
4647
return was;
4748
}
4849

50+
void Definition::Print(llvm::raw_ostream &out, const char *macroName) const {
51+
if (!isFunctionLike_) {
52+
// If it's not a function-like macro, then just print the replacement.
53+
out << ' ' << replacement_.ToString();
54+
return;
55+
}
56+
57+
size_t argCount{argumentCount()};
58+
59+
out << '(';
60+
for (size_t i{0}; i != argCount; ++i) {
61+
if (i != 0) {
62+
out << ", ";
63+
}
64+
out << argNames_[i];
65+
}
66+
if (isVariadic_) {
67+
out << ", ...";
68+
}
69+
out << ") ";
70+
71+
for (size_t i{0}, e{replacement_.SizeInTokens()}; i != e; ++i) {
72+
std::string tok{replacement_.TokenAt(i).ToString()};
73+
if (size_t idx{GetArgumentIndex(tok)}; idx < argCount) {
74+
out << argNames_[idx];
75+
} else {
76+
out << tok;
77+
}
78+
}
79+
}
80+
4981
static bool IsLegalIdentifierStart(const CharBlock &cpl) {
5082
return cpl.size() > 0 && IsLegalIdentifierStart(cpl[0]);
5183
}
@@ -73,6 +105,13 @@ TokenSequence Definition::Tokenize(const std::vector<std::string> &argNames,
73105
return result;
74106
}
75107

108+
std::size_t Definition::GetArgumentIndex(const CharBlock &token) const {
109+
if (token.size() >= 2 && token[0] == '~') {
110+
return static_cast<size_t>(token[1] - 'A');
111+
}
112+
return argumentCount();
113+
}
114+
76115
static TokenSequence Stringify(
77116
const TokenSequence &tokens, AllSources &allSources) {
78117
TokenSequence result;
@@ -159,7 +198,7 @@ TokenSequence Definition::Apply(
159198
continue;
160199
}
161200
if (bytes == 2 && token[0] == '~') { // argument substitution
162-
std::size_t index = token[1] - 'A';
201+
std::size_t index{GetArgumentIndex(token)};
163202
if (index >= args.size()) {
164203
continue;
165204
}
@@ -202,8 +241,8 @@ TokenSequence Definition::Apply(
202241
Provenance commaProvenance{
203242
prescanner.preprocessor().allSources().CompilerInsertionProvenance(
204243
',')};
205-
for (std::size_t k{argumentCount_}; k < args.size(); ++k) {
206-
if (k > argumentCount_) {
244+
for (std::size_t k{argumentCount()}; k < args.size(); ++k) {
245+
if (k > argumentCount()) {
207246
result.Put(","s, commaProvenance);
208247
}
209248
result.Put(args[k]);
@@ -212,7 +251,7 @@ TokenSequence Definition::Apply(
212251
j + 2 < tokens && replacement_.TokenAt(j + 1).OnlyNonBlank() == '(' &&
213252
parenthesesNesting == 0) {
214253
parenthesesNesting = 1;
215-
skipping = args.size() == argumentCount_;
254+
skipping = args.size() == argumentCount();
216255
++j;
217256
} else {
218257
if (parenthesesNesting > 0) {
@@ -713,6 +752,21 @@ void Preprocessor::Directive(const TokenSequence &dir, Prescanner &prescanner) {
713752
}
714753
}
715754

755+
void Preprocessor::PrintMacros(llvm::raw_ostream &out) const {
756+
// std::set is ordered. Use that to print the macros in an
757+
// alphabetical order.
758+
std::set<std::string> macroNames;
759+
for (const auto &[name, _] : definitions_) {
760+
macroNames.insert(name.ToString());
761+
}
762+
763+
for (const std::string &name : macroNames) {
764+
out << "#define " << name;
765+
definitions_.at(name).Print(out, name.c_str());
766+
out << '\n';
767+
}
768+
}
769+
716770
CharBlock Preprocessor::SaveTokenAsName(const CharBlock &t) {
717771
names_.push_back(t.ToString());
718772
return {names_.back().data(), names_.back().size()};

flang/lib/Parser/prescan.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "prescan.h"
10-
#include "preprocessor.h"
11-
#include "token-sequence.h"
1210
#include "flang/Common/idioms.h"
1311
#include "flang/Parser/characters.h"
1412
#include "flang/Parser/message.h"
13+
#include "flang/Parser/preprocessor.h"
1514
#include "flang/Parser/source.h"
15+
#include "flang/Parser/token-sequence.h"
1616
#include "llvm/Support/raw_ostream.h"
1717
#include <cstddef>
1818
#include <cstring>

flang/lib/Parser/prescan.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@
1616
// fixed form character literals on truncated card images, file
1717
// inclusion, and driving the Fortran source preprocessor.
1818

19-
#include "token-sequence.h"
2019
#include "flang/Common/Fortran-features.h"
2120
#include "flang/Parser/characters.h"
2221
#include "flang/Parser/message.h"
2322
#include "flang/Parser/provenance.h"
23+
#include "flang/Parser/token-sequence.h"
2424
#include <bitset>
2525
#include <optional>
2626
#include <string>

flang/lib/Parser/token-sequence.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9-
#include "token-sequence.h"
9+
#include "flang/Parser/token-sequence.h"
10+
1011
#include "prescan.h"
1112
#include "flang/Parser/characters.h"
1213
#include "flang/Parser/message.h"

flang/test/Driver/driver-help-hidden.f90

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
! CHECK-NEXT: -ccc-print-phases Dump list of actions to perform
2222
! CHECK-NEXT: -cpp Enable predefined and command line preprocessor macros
2323
! CHECK-NEXT: -c Only run preprocess, compile, and assemble steps
24+
! CHECK-NEXT: -dM Print macro definitions in -E mode instead of normal output
2425
! CHECK-NEXT: -dumpmachine Display the compiler's target processor
2526
! CHECK-NEXT: -dumpversion Display the version of the compiler
2627
! CHECK-NEXT: -D <macro>=<value> Define <macro> to <value> (or 1 if <value> omitted)

0 commit comments

Comments
 (0)