diff --git a/flang/lib/Parser/parsing.cpp b/flang/lib/Parser/parsing.cpp --- a/flang/lib/Parser/parsing.cpp +++ b/flang/lib/Parser/parsing.cpp @@ -57,11 +57,14 @@ } Preprocessor preprocessor{allSources}; - for (const auto &predef : options.predefinitions) { - if (predef.second) { - preprocessor.Define(predef.first, *predef.second); - } else { - preprocessor.Undefine(predef.first); + if (!options.predefinitions.empty()) { + preprocessor.DefineStandardMacros(); + for (const auto &predef : options.predefinitions) { + if (predef.second) { + preprocessor.Define(predef.first, *predef.second); + } else { + preprocessor.Undefine(predef.first); + } } } currentCooked_ = &allCooked_.NewCookedSource(); diff --git a/flang/lib/Parser/preprocessor.h b/flang/lib/Parser/preprocessor.h --- a/flang/lib/Parser/preprocessor.h +++ b/flang/lib/Parser/preprocessor.h @@ -69,6 +69,7 @@ const AllSources &allSources() const { return allSources_; } AllSources &allSources() { return allSources_; } + void DefineStandardMacros(); void Define(std::string macro, std::string value); void Undefine(std::string macro); bool IsNameDefined(const CharBlock &); diff --git a/flang/lib/Parser/preprocessor.cpp b/flang/lib/Parser/preprocessor.cpp --- a/flang/lib/Parser/preprocessor.cpp +++ b/flang/lib/Parser/preprocessor.cpp @@ -232,20 +232,18 @@ std::strftime(buffer, sizeof buffer, format, std::localtime(&now))}; } -Preprocessor::Preprocessor(AllSources &allSources) : allSources_{allSources} { +Preprocessor::Preprocessor(AllSources &allSources) : allSources_{allSources} {} + +void Preprocessor::DefineStandardMacros() { // Capture current local date & time once now to avoid having the values // of __DATE__ or __TIME__ change during compilation. std::time_t now; std::time(&now); - definitions_.emplace(SaveTokenAsName("__DATE__"s), // e.g., "Jun 16 1904" - Definition{FormatTime(now, "\"%h %e %Y\""), allSources}); - definitions_.emplace(SaveTokenAsName("__TIME__"s), // e.g., "23:59:60" - Definition{FormatTime(now, "\"%T\""), allSources}); + Define("__DATE__"s, FormatTime(now, "\"%h %e %Y\"")); // e.g., "Jun 16 1904" + Define("__TIME__"s, FormatTime(now, "\"%T\"")); // e.g., "23:59:60" // The values of these predefined macros depend on their invocation sites. - definitions_.emplace( - SaveTokenAsName("__FILE__"s), Definition{"__FILE__"s, allSources}); - definitions_.emplace( - SaveTokenAsName("__LINE__"s), Definition{"__LINE__"s, allSources}); + Define("__FILE__"s, "__FILE__"s); + Define("__LINE__"s, "__LINE__"s); } void Preprocessor::Define(std::string macro, std::string value) { @@ -257,6 +255,9 @@ std::optional Preprocessor::MacroReplacement( const TokenSequence &input, Prescanner &prescanner) { // Do quick scan for any use of a defined name. + if (definitions_.empty()) { + return std::nullopt; + } std::size_t tokens{input.SizeInTokens()}; std::size_t j; for (j = 0; j < tokens; ++j) { diff --git a/flang/tools/f18/f18.cpp b/flang/tools/f18/f18.cpp --- a/flang/tools/f18/f18.cpp +++ b/flang/tools/f18/f18.cpp @@ -109,6 +109,7 @@ bool getDefinition{false}; GetDefinitionArgs getDefinitionArgs{0, 0, 0}; bool getSymbolsSources{false}; + std::optional forcePreprocessing; // -cpp & -nocpp }; void Exec(std::vector &argv, bool verbose = false) { @@ -410,19 +411,18 @@ driver.prefix = prefix.data(); Fortran::parser::Options options; - options.predefinitions.emplace_back("__F18", "1"); - options.predefinitions.emplace_back("__F18_MAJOR__", "1"); - options.predefinitions.emplace_back("__F18_MINOR__", "1"); - options.predefinitions.emplace_back("__F18_PATCHLEVEL__", "1"); - options.predefinitions.emplace_back("__flang__", FLANG_VERSION_STRING); - options.predefinitions.emplace_back( - "__flang_major__", FLANG_VERSION_MAJOR_STRING); - options.predefinitions.emplace_back( - "__flang_minor__", FLANG_VERSION_MINOR_STRING); - options.predefinitions.emplace_back( + std::vector predefinitions; + predefinitions.emplace_back("__F18", "1"); + predefinitions.emplace_back("__F18_MAJOR__", "1"); + predefinitions.emplace_back("__F18_MINOR__", "1"); + predefinitions.emplace_back("__F18_PATCHLEVEL__", "1"); + predefinitions.emplace_back("__flang__", FLANG_VERSION_STRING); + predefinitions.emplace_back("__flang_major__", FLANG_VERSION_MAJOR_STRING); + predefinitions.emplace_back("__flang_minor__", FLANG_VERSION_MINOR_STRING); + predefinitions.emplace_back( "__flang_patchlevel__", FLANG_VERSION_PATCHLEVEL_STRING); #if __x86_64__ - options.predefinitions.emplace_back("__x86_64__", "1"); + predefinitions.emplace_back("__x86_64__", "1"); #endif Fortran::common::IntrinsicTypeDefaultKinds defaultKinds; @@ -490,10 +490,10 @@ driver.warnOnNonstandardUsage = true; } else if (arg == "-fopenacc") { options.features.Enable(Fortran::common::LanguageFeature::OpenACC); - options.predefinitions.emplace_back("_OPENACC", "202011"); + predefinitions.emplace_back("_OPENACC", "202011"); } else if (arg == "-fopenmp") { options.features.Enable(Fortran::common::LanguageFeature::OpenMP); - options.predefinitions.emplace_back("_OPENMP", "201511"); + predefinitions.emplace_back("_OPENMP", "201511"); } else if (arg == "-Werror") { driver.warningsAreErrors = true; } else if (arg == "-ed") { @@ -554,14 +554,12 @@ } else if (arg.substr(0, 2) == "-D") { auto eq{arg.find('=')}; if (eq == std::string::npos) { - options.predefinitions.emplace_back(arg.substr(2), "1"); + predefinitions.emplace_back(arg.substr(2), "1"); } else { - options.predefinitions.emplace_back( - arg.substr(2, eq - 2), arg.substr(eq + 1)); + predefinitions.emplace_back(arg.substr(2, eq - 2), arg.substr(eq + 1)); } } else if (arg.substr(0, 2) == "-U") { - options.predefinitions.emplace_back( - arg.substr(2), std::optional{}); + predefinitions.emplace_back(arg.substr(2), std::optional{}); } else if (arg == "-fdefault-double-8") { defaultKinds.set_defaultRealKind(4); } else if (arg == "-r8" || arg == "-fdefault-real-8") { @@ -616,6 +614,10 @@ driver.getSymbolsSources = true; } else if (arg == "-byteswapio") { driver.byteswapio = true; // TODO: Pass to lowering, generate call + } else if (arg == "-cpp") { + driver.forcePreprocessing = true; + } else if (arg == "-nocpp") { + driver.forcePreprocessing = false; } else if (arg == "-h" || arg == "-help" || arg == "--help" || arg == "-?") { llvm::errs() @@ -662,6 +664,7 @@ << " -fget-definition\n" << " -fget-symbols-sources\n" << " -v -c -o -I -D -U have their usual meanings\n" + << " -cpp / -nocpp force / inhibit macro replacement\n" << " -help print this again\n" << "Unrecognised options are passed through to the external " "compiler\n" @@ -724,6 +727,21 @@ return exitStatus; } for (const auto &path : fortranSources) { + options.predefinitions.clear(); + if (driver.forcePreprocessing) { + if (*driver.forcePreprocessing) { + options.predefinitions = predefinitions; + } + } else { + auto dot{path.rfind(".")}; + if (dot != std::string::npos) { + std::string suffix{path.substr(dot + 1)}; + if (suffix == "F" || suffix == "F90" || suffix == "F95" || + suffix == "CUF" || suffix == "F18") { + options.predefinitions = predefinitions; + } + } + } std::string relo{CompileFortran(path, options, driver, defaultKinds)}; if (!driver.compileOnly && !relo.empty()) { objlist.push_back(relo);