xref: /llvm-project/flang/lib/Common/Fortran-features.cpp (revision fc97d2e68b03bc2979395e84b645e5b3ba35aecd)
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