164ab3302SCarolineConcatto //===-- lib/Common/Fortran-features.cpp -----------------------------------===// 264ab3302SCarolineConcatto // 364ab3302SCarolineConcatto // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 464ab3302SCarolineConcatto // See https://llvm.org/LICENSE.txt for license information. 564ab3302SCarolineConcatto // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 664ab3302SCarolineConcatto // 764ab3302SCarolineConcatto //===----------------------------------------------------------------------===// 864ab3302SCarolineConcatto 964ab3302SCarolineConcatto #include "flang/Common/Fortran-features.h" 1064ab3302SCarolineConcatto #include "flang/Common/Fortran.h" 1164ab3302SCarolineConcatto #include "flang/Common/idioms.h" 1264ab3302SCarolineConcatto 1364ab3302SCarolineConcatto namespace Fortran::common { 1464ab3302SCarolineConcatto 150f973ac7SPeter Klausler LanguageFeatureControl::LanguageFeatureControl() { 160f973ac7SPeter Klausler // These features must be explicitly enabled by command line options. 170f973ac7SPeter Klausler disable_.set(LanguageFeature::OldDebugLines); 180f973ac7SPeter Klausler disable_.set(LanguageFeature::OpenACC); 190f973ac7SPeter Klausler disable_.set(LanguageFeature::OpenMP); 200f973ac7SPeter Klausler disable_.set(LanguageFeature::CUDA); // !@cuf 210f973ac7SPeter Klausler disable_.set(LanguageFeature::CudaManaged); 220f973ac7SPeter Klausler disable_.set(LanguageFeature::CudaUnified); 230f973ac7SPeter Klausler disable_.set(LanguageFeature::ImplicitNoneTypeNever); 240f973ac7SPeter Klausler disable_.set(LanguageFeature::ImplicitNoneTypeAlways); 250f973ac7SPeter Klausler disable_.set(LanguageFeature::DefaultSave); 260f973ac7SPeter Klausler disable_.set(LanguageFeature::SaveMainProgram); 270f973ac7SPeter Klausler // These features, if enabled, conflict with valid standard usage, 280f973ac7SPeter Klausler // so there are disabled here by default. 290f973ac7SPeter Klausler disable_.set(LanguageFeature::BackslashEscapes); 300f973ac7SPeter Klausler disable_.set(LanguageFeature::LogicalAbbreviations); 310f973ac7SPeter Klausler disable_.set(LanguageFeature::XOROperator); 320f973ac7SPeter Klausler disable_.set(LanguageFeature::OldStyleParameter); 33aa68dd57SPeter Klausler // Possibly an accidental "feature" of nvfortran. 34aa68dd57SPeter Klausler disable_.set(LanguageFeature::AssumedRankPassedToNonAssumedRank); 350f973ac7SPeter Klausler // These warnings are enabled by default, but only because they used 360f973ac7SPeter Klausler // to be unconditional. TODO: prune this list 370f973ac7SPeter Klausler warnLanguage_.set(LanguageFeature::ExponentMatchingKindParam); 380f973ac7SPeter Klausler warnLanguage_.set(LanguageFeature::RedundantAttribute); 390f973ac7SPeter Klausler warnLanguage_.set(LanguageFeature::SubroutineAndFunctionSpecifics); 400f973ac7SPeter Klausler warnLanguage_.set(LanguageFeature::EmptySequenceType); 410f973ac7SPeter Klausler warnLanguage_.set(LanguageFeature::NonSequenceCrayPointee); 420f973ac7SPeter Klausler warnLanguage_.set(LanguageFeature::BranchIntoConstruct); 430f973ac7SPeter Klausler warnLanguage_.set(LanguageFeature::BadBranchTarget); 440f973ac7SPeter Klausler warnLanguage_.set(LanguageFeature::HollerithPolymorphic); 450f973ac7SPeter Klausler warnLanguage_.set(LanguageFeature::ListDirectedSize); 46c1c99290SPeter Klausler warnLanguage_.set(LanguageFeature::IgnoreIrrelevantAttributes); 470f973ac7SPeter Klausler warnUsage_.set(UsageWarning::ShortArrayActual); 480f973ac7SPeter Klausler warnUsage_.set(UsageWarning::FoldingException); 490f973ac7SPeter Klausler warnUsage_.set(UsageWarning::FoldingAvoidsRuntimeCrash); 500f973ac7SPeter Klausler warnUsage_.set(UsageWarning::FoldingValueChecks); 510f973ac7SPeter Klausler warnUsage_.set(UsageWarning::FoldingFailure); 520f973ac7SPeter Klausler warnUsage_.set(UsageWarning::FoldingLimit); 530f973ac7SPeter Klausler warnUsage_.set(UsageWarning::Interoperability); 545a9d6841SPeter Klausler // CharacterInteroperability warnings about length are off by default 550f973ac7SPeter Klausler warnUsage_.set(UsageWarning::Bounds); 560f973ac7SPeter Klausler warnUsage_.set(UsageWarning::Preprocessing); 570f973ac7SPeter Klausler warnUsage_.set(UsageWarning::Scanning); 580f973ac7SPeter Klausler warnUsage_.set(UsageWarning::OpenAccUsage); 590f973ac7SPeter Klausler warnUsage_.set(UsageWarning::ProcPointerCompatibility); 600f973ac7SPeter Klausler warnUsage_.set(UsageWarning::VoidMold); 610f973ac7SPeter Klausler warnUsage_.set(UsageWarning::KnownBadImplicitInterface); 620f973ac7SPeter Klausler warnUsage_.set(UsageWarning::EmptyCase); 630f973ac7SPeter Klausler warnUsage_.set(UsageWarning::CaseOverflow); 640f973ac7SPeter Klausler warnUsage_.set(UsageWarning::CUDAUsage); 650f973ac7SPeter Klausler warnUsage_.set(UsageWarning::IgnoreTKRUsage); 660f973ac7SPeter Klausler warnUsage_.set(UsageWarning::ExternalInterfaceMismatch); 670f973ac7SPeter Klausler warnUsage_.set(UsageWarning::DefinedOperatorArgs); 680f973ac7SPeter Klausler warnUsage_.set(UsageWarning::Final); 690f973ac7SPeter Klausler warnUsage_.set(UsageWarning::ZeroDoStep); 700f973ac7SPeter Klausler warnUsage_.set(UsageWarning::UnusedForallIndex); 710f973ac7SPeter Klausler warnUsage_.set(UsageWarning::OpenMPUsage); 720f973ac7SPeter Klausler warnUsage_.set(UsageWarning::DataLength); 730f973ac7SPeter Klausler warnUsage_.set(UsageWarning::IgnoredDirective); 740f973ac7SPeter Klausler warnUsage_.set(UsageWarning::HomonymousSpecific); 750f973ac7SPeter Klausler warnUsage_.set(UsageWarning::HomonymousResult); 760f973ac7SPeter Klausler warnUsage_.set(UsageWarning::IgnoredIntrinsicFunctionType); 770f973ac7SPeter Klausler warnUsage_.set(UsageWarning::PreviousScalarUse); 780f973ac7SPeter Klausler warnUsage_.set(UsageWarning::RedeclaredInaccessibleComponent); 790f973ac7SPeter Klausler warnUsage_.set(UsageWarning::ImplicitShared); 800f973ac7SPeter Klausler warnUsage_.set(UsageWarning::IndexVarRedefinition); 810f973ac7SPeter Klausler warnUsage_.set(UsageWarning::IncompatibleImplicitInterfaces); 820f973ac7SPeter Klausler warnUsage_.set(UsageWarning::BadTypeForTarget); 830f973ac7SPeter Klausler warnUsage_.set(UsageWarning::VectorSubscriptFinalization); 840f973ac7SPeter Klausler warnUsage_.set(UsageWarning::UndefinedFunctionResult); 850f973ac7SPeter Klausler warnUsage_.set(UsageWarning::UselessIomsg); 86*fc97d2e6SPeter Klausler warnUsage_.set(UsageWarning::UnsignedLiteralTruncation); 870f973ac7SPeter Klausler // New warnings, on by default 880f973ac7SPeter Klausler warnLanguage_.set(LanguageFeature::SavedLocalInSpecExpr); 890f973ac7SPeter Klausler } 900f973ac7SPeter Klausler 910f973ac7SPeter Klausler // Ignore case and any inserted punctuation (like '-'/'_') 920f973ac7SPeter Klausler static std::optional<char> GetWarningChar(char ch) { 930f973ac7SPeter Klausler if (ch >= 'a' && ch <= 'z') { 940f973ac7SPeter Klausler return ch; 950f973ac7SPeter Klausler } else if (ch >= 'A' && ch <= 'Z') { 960f973ac7SPeter Klausler return ch - 'A' + 'a'; 970f973ac7SPeter Klausler } else if (ch >= '0' && ch <= '9') { 980f973ac7SPeter Klausler return ch; 990f973ac7SPeter Klausler } else { 1000f973ac7SPeter Klausler return std::nullopt; 1010f973ac7SPeter Klausler } 1020f973ac7SPeter Klausler } 1030f973ac7SPeter Klausler 1040f973ac7SPeter Klausler static bool WarningNameMatch(const char *a, const char *b) { 1050f973ac7SPeter Klausler while (true) { 1060f973ac7SPeter Klausler auto ach{GetWarningChar(*a)}; 1070f973ac7SPeter Klausler while (!ach && *a) { 1080f973ac7SPeter Klausler ach = GetWarningChar(*++a); 1090f973ac7SPeter Klausler } 1100f973ac7SPeter Klausler auto bch{GetWarningChar(*b)}; 1110f973ac7SPeter Klausler while (!bch && *b) { 1120f973ac7SPeter Klausler bch = GetWarningChar(*++b); 1130f973ac7SPeter Klausler } 1140f973ac7SPeter Klausler if (!ach && !bch) { 1150f973ac7SPeter Klausler return true; 1160f973ac7SPeter Klausler } else if (!ach || !bch || *ach != *bch) { 1170f973ac7SPeter Klausler return false; 1180f973ac7SPeter Klausler } 1190f973ac7SPeter Klausler ++a, ++b; 1200f973ac7SPeter Klausler } 1210f973ac7SPeter Klausler } 1220f973ac7SPeter Klausler 1230f973ac7SPeter Klausler template <typename ENUM, std::size_t N> 1240f973ac7SPeter Klausler std::optional<ENUM> ScanEnum(const char *name) { 1250f973ac7SPeter Klausler if (name) { 1260f973ac7SPeter Klausler for (std::size_t j{0}; j < N; ++j) { 1270f973ac7SPeter Klausler auto feature{static_cast<ENUM>(j)}; 1280f973ac7SPeter Klausler if (WarningNameMatch(name, EnumToString(feature).data())) { 1290f973ac7SPeter Klausler return feature; 1300f973ac7SPeter Klausler } 1310f973ac7SPeter Klausler } 1320f973ac7SPeter Klausler } 1330f973ac7SPeter Klausler return std::nullopt; 1340f973ac7SPeter Klausler } 1350f973ac7SPeter Klausler 1360f973ac7SPeter Klausler std::optional<LanguageFeature> FindLanguageFeature(const char *name) { 1370f973ac7SPeter Klausler return ScanEnum<LanguageFeature, LanguageFeature_enumSize>(name); 1380f973ac7SPeter Klausler } 1390f973ac7SPeter Klausler 1400f973ac7SPeter Klausler std::optional<UsageWarning> FindUsageWarning(const char *name) { 1410f973ac7SPeter Klausler return ScanEnum<UsageWarning, UsageWarning_enumSize>(name); 1420f973ac7SPeter Klausler } 1430f973ac7SPeter Klausler 14464ab3302SCarolineConcatto std::vector<const char *> LanguageFeatureControl::GetNames( 14564ab3302SCarolineConcatto LogicalOperator opr) const { 14664ab3302SCarolineConcatto std::vector<const char *> result; 14764ab3302SCarolineConcatto result.push_back(AsFortran(opr)); 14864ab3302SCarolineConcatto if (opr == LogicalOperator::Neqv && IsEnabled(LanguageFeature::XOROperator)) { 14964ab3302SCarolineConcatto result.push_back(".xor."); 15064ab3302SCarolineConcatto } 15164ab3302SCarolineConcatto if (IsEnabled(LanguageFeature::LogicalAbbreviations)) { 15264ab3302SCarolineConcatto switch (opr) { 15364ab3302SCarolineConcatto SWITCH_COVERS_ALL_CASES 1541f879005STim Keith case LogicalOperator::And: 1551f879005STim Keith result.push_back(".a."); 1561f879005STim Keith break; 1571f879005STim Keith case LogicalOperator::Or: 1581f879005STim Keith result.push_back(".o."); 1591f879005STim Keith break; 1601f879005STim Keith case LogicalOperator::Not: 1611f879005STim Keith result.push_back(".n."); 1621f879005STim Keith break; 16364ab3302SCarolineConcatto case LogicalOperator::Neqv: 16464ab3302SCarolineConcatto if (IsEnabled(LanguageFeature::XOROperator)) { 16564ab3302SCarolineConcatto result.push_back(".x."); 16664ab3302SCarolineConcatto } 16764ab3302SCarolineConcatto break; 1681f879005STim Keith case LogicalOperator::Eqv: 1691f879005STim Keith break; 17064ab3302SCarolineConcatto } 17164ab3302SCarolineConcatto } 17264ab3302SCarolineConcatto return result; 17364ab3302SCarolineConcatto } 17464ab3302SCarolineConcatto 17564ab3302SCarolineConcatto std::vector<const char *> LanguageFeatureControl::GetNames( 17664ab3302SCarolineConcatto RelationalOperator opr) const { 17764ab3302SCarolineConcatto switch (opr) { 17864ab3302SCarolineConcatto SWITCH_COVERS_ALL_CASES 1791f879005STim Keith case RelationalOperator::LT: 1801f879005STim Keith return {".lt.", "<"}; 1811f879005STim Keith case RelationalOperator::LE: 1821f879005STim Keith return {".le.", "<="}; 1831f879005STim Keith case RelationalOperator::EQ: 1841f879005STim Keith return {".eq.", "=="}; 1851f879005STim Keith case RelationalOperator::GE: 1861f879005STim Keith return {".ge.", ">="}; 1871f879005STim Keith case RelationalOperator::GT: 1881f879005STim Keith return {".gt.", ">"}; 18964ab3302SCarolineConcatto case RelationalOperator::NE: 19064ab3302SCarolineConcatto if (IsEnabled(LanguageFeature::AlternativeNE)) { 19164ab3302SCarolineConcatto return {".ne.", "/=", "<>"}; 19264ab3302SCarolineConcatto } else { 19364ab3302SCarolineConcatto return {".ne.", "/="}; 19464ab3302SCarolineConcatto } 19564ab3302SCarolineConcatto } 19664ab3302SCarolineConcatto } 19764ab3302SCarolineConcatto 1981f879005STim Keith } // namespace Fortran::common 199