Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 39 additions & 5 deletions flang/include/flang/Common/enum-class.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@
#ifndef FORTRAN_COMMON_ENUM_CLASS_H_
#define FORTRAN_COMMON_ENUM_CLASS_H_

#include "optional.h"
#include <array>
#include <string>

#include <functional>
#include <string_view>
namespace Fortran::common {

constexpr std::size_t CountEnumNames(const char *p) {
Expand Down Expand Up @@ -62,11 +63,44 @@ constexpr std::array<std::string_view, ITEMS> EnumNames(const char *p) {
enum class NAME { __VA_ARGS__ }; \
[[maybe_unused]] static constexpr std::size_t NAME##_enumSize{ \
::Fortran::common::CountEnumNames(#__VA_ARGS__)}; \
[[maybe_unused]] static constexpr std::array<std::string_view, \
NAME##_enumSize> NAME##_names{ \
::Fortran::common::EnumNames<NAME##_enumSize>(#__VA_ARGS__)}; \
[[maybe_unused]] static inline std::string_view EnumToString(NAME e) { \
static const constexpr auto names{ \
::Fortran::common::EnumNames<NAME##_enumSize>(#__VA_ARGS__)}; \
return names[static_cast<std::size_t>(e)]; \
return NAME##_names[static_cast<std::size_t>(e)]; \
}

namespace EnumClass {

using Predicate = std::function<bool(const std::string_view)>;
// Finds the first index for which the predicate returns true.
optional<std::size_t> FindIndex(
Predicate pred, std::size_t size, const std::string_view *names);

using FindIndexType = std::function<optional<std::size_t>(Predicate)>;

template <typename NAME>
optional<NAME> inline Find(Predicate pred, FindIndexType findIndex) {
return MapOption<int, NAME>(
findIndex(pred), [](int x) { return static_cast<NAME>(x); });
}

} // namespace EnumClass

#define ENUM_CLASS_EXTRA(NAME) \
[[maybe_unused]] inline optional<std::size_t> Find##NAME##Index( \
::Fortran::common::EnumClass::Predicate p) { \
return ::Fortran::common::EnumClass::FindIndex( \
p, NAME##_enumSize, NAME##_names.data()); \
} \
[[maybe_unused]] inline optional<NAME> Find##NAME( \
::Fortran::common::EnumClass::Predicate p) { \
return ::Fortran::common::EnumClass::Find<NAME>(p, Find##NAME##Index); \
} \
[[maybe_unused]] inline optional<NAME> StringTo##NAME( \
const std::string_view name) { \
return Find##NAME( \
[name](const std::string_view s) -> bool { return name == s; }); \
}
} // namespace Fortran::common
#endif // FORTRAN_COMMON_ENUM_CLASS_H_
7 changes: 7 additions & 0 deletions flang/include/flang/Common/optional.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#define FORTRAN_COMMON_OPTIONAL_H

#include "api-attrs.h"
#include <functional>
#include <optional>
#include <type_traits>

Expand Down Expand Up @@ -238,6 +239,12 @@ using std::nullopt_t;
using std::optional;
#endif // !STD_OPTIONAL_UNSUPPORTED

template <typename T, typename U>
std::optional<U> inline MapOption(
std::optional<T> x, std::function<U(const T)> f) {
return x ? std::optional<U>{f(*x)} : std::nullopt;
}

} // namespace Fortran::common

#endif // FORTRAN_COMMON_OPTIONAL_H
37 changes: 20 additions & 17 deletions flang/include/flang/Support/Fortran-features.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@

#include "Fortran.h"
#include "flang/Common/enum-set.h"
#include "flang/Common/idioms.h"
#include <optional>
#include <vector>

namespace Fortran::common {
Expand Down Expand Up @@ -62,7 +60,7 @@ ENUM_CLASS(UsageWarning, Portability, PointerToUndefinable,
NonTargetPassedToTarget, PointerToPossibleNoncontiguous,
ShortCharacterActual, ShortArrayActual, ImplicitInterfaceActual,
PolymorphicTransferArg, PointerComponentTransferArg, TransferSizePresence,
F202XAllocatableBreakingChange, OptionalMustBePresent, CommonBlockPadding,
F202xAllocatableBreakingChange, OptionalMustBePresent, CommonBlockPadding,
LogicalVsCBool, BindCCharLength, ProcDummyArgShapes, ExternalNameConflict,
FoldingException, FoldingAvoidsRuntimeCrash, FoldingValueChecks,
FoldingFailure, FoldingLimit, Interoperability, CharacterInteroperability,
Expand All @@ -79,12 +77,13 @@ ENUM_CLASS(UsageWarning, Portability, PointerToUndefinable,
NullActualForDefaultIntentAllocatable, UseAssociationIntoSameNameSubprogram,
HostAssociatedIntentOutInSpecExpr, NonVolatilePointerToVolatile)

// Generate default String -> Enum mapping.
ENUM_CLASS_EXTRA(LanguageFeature)
ENUM_CLASS_EXTRA(UsageWarning)

using LanguageFeatures = EnumSet<LanguageFeature, LanguageFeature_enumSize>;
using UsageWarnings = EnumSet<UsageWarning, UsageWarning_enumSize>;

std::optional<LanguageFeature> FindLanguageFeature(const char *);
std::optional<UsageWarning> FindUsageWarning(const char *);

class LanguageFeatureControl {
public:
LanguageFeatureControl();
Expand All @@ -97,8 +96,10 @@ class LanguageFeatureControl {
void EnableWarning(UsageWarning w, bool yes = true) {
warnUsage_.set(w, yes);
}
void WarnOnAllNonstandard(bool yes = true) { warnAllLanguage_ = yes; }
void WarnOnAllUsage(bool yes = true) { warnAllUsage_ = yes; }
void WarnOnAllNonstandard(bool yes = true);
bool IsWarnOnAllNonstandard() const { return warnAllLanguage_; }
void WarnOnAllUsage(bool yes = true);
bool IsWarnOnAllUsage() const { return warnAllUsage_; }
void DisableAllNonstandardWarnings() {
warnAllLanguage_ = false;
warnLanguage_.clear();
Expand All @@ -107,16 +108,16 @@ class LanguageFeatureControl {
warnAllUsage_ = false;
warnUsage_.clear();
}

bool IsEnabled(LanguageFeature f) const { return !disable_.test(f); }
bool ShouldWarn(LanguageFeature f) const {
return (warnAllLanguage_ && f != LanguageFeature::OpenMP &&
f != LanguageFeature::OpenACC && f != LanguageFeature::CUDA) ||
warnLanguage_.test(f);
}
bool ShouldWarn(UsageWarning w) const {
return warnAllUsage_ || warnUsage_.test(w);
void DisableAllWarnings() {
disableAllWarnings_ = true;
DisableAllNonstandardWarnings();
DisableAllUsageWarnings();
}
bool applyCLIOption(std::string_view input, bool insensitive = false);
bool AreWarningsDisabled() const { return disableAllWarnings_; }
bool IsEnabled(LanguageFeature f) const { return !disable_.test(f); }
bool ShouldWarn(LanguageFeature f) const { return warnLanguage_.test(f); }
bool ShouldWarn(UsageWarning w) const { return warnUsage_.test(w); }
// Return all spellings of operators names, depending on features enabled
std::vector<const char *> GetNames(LogicalOperator) const;
std::vector<const char *> GetNames(RelationalOperator) const;
Expand All @@ -127,6 +128,8 @@ class LanguageFeatureControl {
bool warnAllLanguage_{false};
UsageWarnings warnUsage_;
bool warnAllUsage_{false};
bool disableAllWarnings_{false};
};

} // namespace Fortran::common
#endif // FORTRAN_SUPPORT_FORTRAN_FEATURES_H_
63 changes: 31 additions & 32 deletions flang/lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,9 @@
#include "flang/Support/Version.h"
#include "flang/Tools/TargetSetup.h"
#include "flang/Version.inc"
#include "clang/Basic/AllDiagnostics.h"
#include "clang/Basic/DiagnosticDriver.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/OptionUtils.h"
#include "clang/Driver/Options.h"
#include "llvm/ADT/StringRef.h"
Expand All @@ -35,7 +33,6 @@
#include "llvm/Option/OptTable.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FileUtilities.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/raw_ostream.h"
Expand Down Expand Up @@ -971,10 +968,23 @@ static bool parseSemaArgs(CompilerInvocation &res, llvm::opt::ArgList &args,

/// Parses all diagnostics related arguments and populates the variables
/// options accordingly. Returns false if new errors are generated.
/// FC1 driver entry point for parsing diagnostic arguments.
static bool parseDiagArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
clang::DiagnosticsEngine &diags) {
unsigned numErrorsBefore = diags.getNumErrors();

auto &features = res.getFrontendOpts().features;
// The order of these flags (-pedantic -W<feature> -w) is important and is
// chosen to match clang's behavior.

// -pedantic
if (args.hasArg(clang::driver::options::OPT_pedantic)) {
features.WarnOnAllNonstandard();
features.WarnOnAllUsage();
res.setEnableConformanceChecks();
res.setEnableUsageChecks();
}

// -Werror option
// TODO: Currently throws a Diagnostic for anything other than -W<error>,
// this has to change when other -W<opt>'s are supported.
Expand All @@ -984,21 +994,27 @@ static bool parseDiagArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
for (const auto &wArg : wArgs) {
if (wArg == "error") {
res.setWarnAsErr(true);
} else {
const unsigned diagID =
diags.getCustomDiagID(clang::DiagnosticsEngine::Error,
"Only `-Werror` is supported currently.");
diags.Report(diagID);
// -W(no-)<feature>
} else if (!features.applyCLIOption(wArg)) {
const unsigned diagID = diags.getCustomDiagID(
clang::DiagnosticsEngine::Error, "Unknown diagnostic option: -W%0");
diags.Report(diagID) << wArg;
}
}
}

// -w
if (args.hasArg(clang::driver::options::OPT_w)) {
features.DisableAllWarnings();
res.setDisableWarnings();
}

// Default to off for `flang -fc1`.
res.getFrontendOpts().showColors =
parseShowColorsArgs(args, /*defaultDiagColor=*/false);
bool showColors = parseShowColorsArgs(args, false);

// Honor color diagnostics.
res.getDiagnosticOpts().ShowColors = res.getFrontendOpts().showColors;
diags.getDiagnosticOptions().ShowColors = showColors;
res.getDiagnosticOpts().ShowColors = showColors;
res.getFrontendOpts().showColors = showColors;

return diags.getNumErrors() == numErrorsBefore;
}
Expand Down Expand Up @@ -1074,16 +1090,6 @@ static bool parseDialectArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
Fortran::common::LanguageFeature::OpenACC);
}

// -pedantic
if (args.hasArg(clang::driver::options::OPT_pedantic)) {
res.setEnableConformanceChecks();
res.setEnableUsageChecks();
}

// -w
if (args.hasArg(clang::driver::options::OPT_w))
res.setDisableWarnings();

// -std=f2018
// TODO: Set proper options when more fortran standards
// are supported.
Expand All @@ -1092,13 +1098,15 @@ static bool parseDialectArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
// We only allow f2018 as the given standard
if (standard == "f2018") {
res.setEnableConformanceChecks();
res.getFrontendOpts().features.WarnOnAllNonstandard();
} else {
const unsigned diagID =
diags.getCustomDiagID(clang::DiagnosticsEngine::Error,
"Only -std=f2018 is allowed currently.");
diags.Report(diagID);
}
}

return diags.getNumErrors() == numErrorsBefore;
}

Expand Down Expand Up @@ -1694,16 +1702,7 @@ void CompilerInvocation::setFortranOpts() {
if (frontendOptions.needProvenanceRangeToCharBlockMappings)
fortranOptions.needProvenanceRangeToCharBlockMappings = true;

if (getEnableConformanceChecks())
fortranOptions.features.WarnOnAllNonstandard();

if (getEnableUsageChecks())
fortranOptions.features.WarnOnAllUsage();

if (getDisableWarnings()) {
fortranOptions.features.DisableAllNonstandardWarnings();
fortranOptions.features.DisableAllUsageWarnings();
}
fortranOptions.features = frontendOptions.features;
}

std::unique_ptr<Fortran::semantics::SemanticsContext>
Expand Down
2 changes: 1 addition & 1 deletion flang/lib/Semantics/tools.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1672,7 +1672,7 @@ std::forward_list<std::string> GetAllNames(
void WarnOnDeferredLengthCharacterScalar(SemanticsContext &context,
const SomeExpr *expr, parser::CharBlock at, const char *what) {
if (context.languageFeatures().ShouldWarn(
common::UsageWarning::F202XAllocatableBreakingChange)) {
common::UsageWarning::F202xAllocatableBreakingChange)) {
if (const Symbol *
symbol{evaluate::UnwrapWholeSymbolOrComponentDataRef(expr)}) {
const Symbol &ultimate{ResolveAssociations(*symbol)};
Expand Down
1 change: 1 addition & 0 deletions flang/lib/Support/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ endif()

add_flang_library(FortranSupport
default-kinds.cpp
enum-class.cpp
Flags.cpp
Fortran.cpp
Fortran-features.cpp
Expand Down
Loading