brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.3 KiB · 4a6fb8d Raw
269 lines · cpp
1//===-- lib/Support/Fortran-features.cpp ------------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "flang/Support/Fortran-features.h"10#include "flang/Common/idioms.h"11#include "flang/Parser/characters.h"12#include "flang/Support/Fortran.h"13#include <string>14#include <string_view>15 16namespace Fortran::common {17 18static std::vector<std::string_view> SplitCamelCase(std::string_view x) {19  std::vector<std::string_view> result;20  // NB, we start at 1 because the first character is never a word boundary.21  size_t xSize{x.size()}, wordStart{0}, wordEnd{1};22  for (; wordEnd < xSize; ++wordEnd) {23    // Identify when wordEnd is at the start of a new word.24    if ((!parser::IsUpperCaseLetter(x[wordEnd - 1]) &&25            parser::IsUpperCaseLetter(x[wordEnd])) ||26        // ACCUsage => ACC-Usage, CComment => C-Comment, etc.27        (parser::IsUpperCaseLetter(x[wordEnd]) && wordEnd + 1 < xSize &&28            parser::IsLowerCaseLetter(x[wordEnd + 1]))) {29      result.push_back(x.substr(wordStart, wordEnd - wordStart));30      wordStart = wordEnd;31    }32  }33  // We went one past the end of the last word.34  result.push_back(x.substr(wordStart, wordEnd - wordStart));35  return result;36}37 38// Namespace for helper functions for parsing Cli options used instead of static39// so that there can be unit tests for this function.40namespace details {41std::string CamelCaseToLowerCaseHyphenated(std::string_view x) {42  std::vector<std::string_view> words{SplitCamelCase(x)};43  std::string result{};44  result.reserve(x.size() + words.size() + 1);45  for (size_t i{0}; i < words.size(); ++i) {46    std::string word{parser::ToLowerCaseLetters(words[i])};47    result += i == 0 ? "" : "-";48    result += word;49  }50  return result;51}52} // namespace details53 54LanguageFeatureControl::LanguageFeatureControl() {55  // Initialize the bidirectional maps with the default spellings.56  cliOptions_.reserve(LanguageFeature_enumSize + UsageWarning_enumSize);57  ForEachLanguageFeature([&](auto feature) {58    std::string_view name{Fortran::common::EnumToString(feature)};59    std::string cliOption{details::CamelCaseToLowerCaseHyphenated(name)};60    cliOptions_.insert({cliOption, {feature}});61    languageFeatureCliCanonicalSpelling_[EnumToInt(feature)] =62        std::move(cliOption);63  });64 65  ForEachUsageWarning([&](auto warning) {66    std::string_view name{Fortran::common::EnumToString(warning)};67    std::string cliOption{details::CamelCaseToLowerCaseHyphenated(name)};68    cliOptions_.insert({cliOption, {warning}});69    usageWarningCliCanonicalSpelling_[EnumToInt(warning)] =70        std::move(cliOption);71  });72 73  // These features must be explicitly enabled by command line options.74  disable_.set(LanguageFeature::OldDebugLines);75  disable_.set(LanguageFeature::OpenACC);76  disable_.set(LanguageFeature::OpenMP);77  disable_.set(LanguageFeature::CUDA); // !@cuf78  disable_.set(LanguageFeature::CudaManaged);79  disable_.set(LanguageFeature::CudaUnified);80  disable_.set(LanguageFeature::ImplicitNoneTypeNever);81  disable_.set(LanguageFeature::ImplicitNoneTypeAlways);82  disable_.set(LanguageFeature::ImplicitNoneExternal);83  disable_.set(LanguageFeature::DefaultSave);84  disable_.set(LanguageFeature::SaveMainProgram);85  // These features, if enabled, conflict with valid standard usage,86  // so there are disabled here by default.87  disable_.set(LanguageFeature::BackslashEscapes);88  disable_.set(LanguageFeature::LogicalAbbreviations);89  disable_.set(LanguageFeature::XOROperator);90  disable_.set(LanguageFeature::OldStyleParameter);91  // Possibly an accidental "feature" of nvfortran.92  disable_.set(LanguageFeature::AssumedRankPassedToNonAssumedRank);93  disable_.set(LanguageFeature::Coarray);94  // These warnings are enabled by default, but only because they used95  // to be unconditional.  TODO: prune this list96  warnLanguage_.set(LanguageFeature::ExponentMatchingKindParam);97  warnLanguage_.set(LanguageFeature::RedundantAttribute);98  warnLanguage_.set(LanguageFeature::SubroutineAndFunctionSpecifics);99  warnLanguage_.set(LanguageFeature::EmptySequenceType);100  warnLanguage_.set(LanguageFeature::NonSequenceCrayPointee);101  warnLanguage_.set(LanguageFeature::BranchIntoConstruct);102  warnLanguage_.set(LanguageFeature::BadBranchTarget);103  warnLanguage_.set(LanguageFeature::HollerithPolymorphic);104  warnLanguage_.set(LanguageFeature::ListDirectedSize);105  warnLanguage_.set(LanguageFeature::IgnoreIrrelevantAttributes);106  warnLanguage_.set(LanguageFeature::AmbiguousStructureConstructor);107  warnLanguage_.set(LanguageFeature::TransferBOZ);108  warnUsage_.set(UsageWarning::ShortArrayActual);109  warnUsage_.set(UsageWarning::FoldingException);110  warnUsage_.set(UsageWarning::FoldingAvoidsRuntimeCrash);111  warnUsage_.set(UsageWarning::FoldingValueChecks);112  warnUsage_.set(UsageWarning::FoldingFailure);113  warnUsage_.set(UsageWarning::FoldingLimit);114  warnUsage_.set(UsageWarning::Interoperability);115  // CharacterInteroperability warnings about length are off by default116  warnUsage_.set(UsageWarning::Bounds);117  warnUsage_.set(UsageWarning::Preprocessing);118  warnUsage_.set(UsageWarning::Scanning);119  warnUsage_.set(UsageWarning::OpenAccUsage);120  warnUsage_.set(UsageWarning::ProcPointerCompatibility);121  warnUsage_.set(UsageWarning::VoidMold);122  warnUsage_.set(UsageWarning::KnownBadImplicitInterface);123  warnUsage_.set(UsageWarning::EmptyCase);124  warnUsage_.set(UsageWarning::CaseOverflow);125  warnUsage_.set(UsageWarning::CUDAUsage);126  warnUsage_.set(UsageWarning::IgnoreTKRUsage);127  warnUsage_.set(UsageWarning::ExternalInterfaceMismatch);128  warnUsage_.set(UsageWarning::DefinedOperatorArgs);129  warnUsage_.set(UsageWarning::Final);130  warnUsage_.set(UsageWarning::ZeroDoStep);131  warnUsage_.set(UsageWarning::UnusedForallIndex);132  warnUsage_.set(UsageWarning::OpenMPUsage);133  warnUsage_.set(UsageWarning::DataLength);134  warnUsage_.set(UsageWarning::IgnoredDirective);135  warnUsage_.set(UsageWarning::HomonymousSpecific);136  warnUsage_.set(UsageWarning::HomonymousResult);137  warnUsage_.set(UsageWarning::IgnoredIntrinsicFunctionType);138  warnUsage_.set(UsageWarning::PreviousScalarUse);139  warnUsage_.set(UsageWarning::RedeclaredInaccessibleComponent);140  warnUsage_.set(UsageWarning::ImplicitShared);141  warnUsage_.set(UsageWarning::IndexVarRedefinition);142  warnUsage_.set(UsageWarning::IncompatibleImplicitInterfaces);143  warnUsage_.set(UsageWarning::VectorSubscriptFinalization);144  warnUsage_.set(UsageWarning::UndefinedFunctionResult);145  warnUsage_.set(UsageWarning::UselessIomsg);146  warnUsage_.set(UsageWarning::UnsignedLiteralTruncation);147  warnUsage_.set(UsageWarning::NullActualForDefaultIntentAllocatable);148  warnUsage_.set(UsageWarning::UseAssociationIntoSameNameSubprogram);149  warnUsage_.set(UsageWarning::HostAssociatedIntentOutInSpecExpr);150  warnUsage_.set(UsageWarning::NonVolatilePointerToVolatile);151  warnUsage_.set(UsageWarning::RealConstantWidening);152  // New warnings, on by default153  warnLanguage_.set(LanguageFeature::SavedLocalInSpecExpr);154  warnLanguage_.set(LanguageFeature::NullActualForAllocatable);155}156 157std::optional<LanguageControlFlag> LanguageFeatureControl::FindWarning(158    std::string_view input) {159  bool negated{false};160  if (input.size() > 3 && input.substr(0, 3) == "no-") {161    negated = true;162    input = input.substr(3);163  }164  if (auto it{cliOptions_.find(std::string{input})}; it != cliOptions_.end()) {165    return std::make_pair(it->second, !negated);166  }167  return std::nullopt;168}169 170bool LanguageFeatureControl::EnableWarning(std::string_view input) {171  if (auto warningAndEnabled{FindWarning(input)}) {172    EnableWarning(warningAndEnabled->first, warningAndEnabled->second);173    return true;174  }175  return false;176}177 178void LanguageFeatureControl::ReplaceCliCanonicalSpelling(179    LanguageFeature f, std::string input) {180  cliOptions_.erase(languageFeatureCliCanonicalSpelling_[EnumToInt(f)]);181  cliOptions_.insert({input, {f}});182  languageFeatureCliCanonicalSpelling_[EnumToInt(f)] = std::move(input);183}184 185void LanguageFeatureControl::ReplaceCliCanonicalSpelling(186    UsageWarning w, std::string input) {187  cliOptions_.erase(usageWarningCliCanonicalSpelling_[EnumToInt(w)]);188  cliOptions_.insert({input, {w}});189  usageWarningCliCanonicalSpelling_[EnumToInt(w)] = std::move(input);190}191 192std::vector<const char *> LanguageFeatureControl::GetNames(193    LogicalOperator opr) const {194  std::vector<const char *> result;195  result.push_back(AsFortran(opr));196  if (opr == LogicalOperator::Neqv && IsEnabled(LanguageFeature::XOROperator)) {197    result.push_back(".xor.");198  }199  if (IsEnabled(LanguageFeature::LogicalAbbreviations)) {200    switch (opr) {201      SWITCH_COVERS_ALL_CASES202    case LogicalOperator::And:203      result.push_back(".a.");204      break;205    case LogicalOperator::Or:206      result.push_back(".o.");207      break;208    case LogicalOperator::Not:209      result.push_back(".n.");210      break;211    case LogicalOperator::Neqv:212      if (IsEnabled(LanguageFeature::XOROperator)) {213        result.push_back(".x.");214      }215      break;216    case LogicalOperator::Eqv:217      break;218    }219  }220  return result;221}222 223std::vector<const char *> LanguageFeatureControl::GetNames(224    RelationalOperator opr) const {225  switch (opr) {226    SWITCH_COVERS_ALL_CASES227  case RelationalOperator::LT:228    return {".lt.", "<"};229  case RelationalOperator::LE:230    return {".le.", "<="};231  case RelationalOperator::EQ:232    return {".eq.", "=="};233  case RelationalOperator::GE:234    return {".ge.", ">="};235  case RelationalOperator::GT:236    return {".gt.", ">"};237  case RelationalOperator::NE:238    if (IsEnabled(LanguageFeature::AlternativeNE)) {239      return {".ne.", "/=", "<>"};240    } else {241      return {".ne.", "/="};242    }243  }244}245 246void LanguageFeatureControl::WarnOnAllNonstandard(bool yes) {247  warnAllLanguage_ = yes;248  warnLanguage_.reset();249  if (yes) {250    disableAllWarnings_ = false;251    warnLanguage_.flip();252    // These three features do not need to be warned about,253    // but we do want their feature flags.254    warnLanguage_.set(LanguageFeature::OpenMP, false);255    warnLanguage_.set(LanguageFeature::OpenACC, false);256    warnLanguage_.set(LanguageFeature::CUDA, false);257  }258}259 260void LanguageFeatureControl::WarnOnAllUsage(bool yes) {261  warnAllUsage_ = yes;262  warnUsage_.reset();263  if (yes) {264    disableAllWarnings_ = false;265    warnUsage_.flip();266  }267}268} // namespace Fortran::common269