mirror of
https://github.com/intel/llvm.git
synced 2026-02-05 22:17:23 +08:00
Type interoperability warnings current issue for intrinsic types when their type, kind, or length do not meet the requirements for C interoperability. This turns out to be too noisy for the case of one-byte characters with lengths other than one when creating C pointers from C_LOC or C_F_POINTER -- it is not uncommon for programs to use pointers to longer character objects. So split the interoperability warning so that the case of a known bad character length for an otherwise interoperable type is controlled by its own UsageWarning enumerator, and leave that usage warning off by default. This will better fit expectations in the default case while still showing a warning under -pedantic.
196 lines
6.8 KiB
C++
196 lines
6.8 KiB
C++
//===-- lib/Common/Fortran-features.cpp -----------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "flang/Common/Fortran-features.h"
|
|
#include "flang/Common/Fortran.h"
|
|
#include "flang/Common/idioms.h"
|
|
|
|
namespace Fortran::common {
|
|
|
|
LanguageFeatureControl::LanguageFeatureControl() {
|
|
// These features must be explicitly enabled by command line options.
|
|
disable_.set(LanguageFeature::OldDebugLines);
|
|
disable_.set(LanguageFeature::OpenACC);
|
|
disable_.set(LanguageFeature::OpenMP);
|
|
disable_.set(LanguageFeature::CUDA); // !@cuf
|
|
disable_.set(LanguageFeature::CudaManaged);
|
|
disable_.set(LanguageFeature::CudaUnified);
|
|
disable_.set(LanguageFeature::ImplicitNoneTypeNever);
|
|
disable_.set(LanguageFeature::ImplicitNoneTypeAlways);
|
|
disable_.set(LanguageFeature::DefaultSave);
|
|
disable_.set(LanguageFeature::SaveMainProgram);
|
|
// These features, if enabled, conflict with valid standard usage,
|
|
// so there are disabled here by default.
|
|
disable_.set(LanguageFeature::BackslashEscapes);
|
|
disable_.set(LanguageFeature::LogicalAbbreviations);
|
|
disable_.set(LanguageFeature::XOROperator);
|
|
disable_.set(LanguageFeature::OldStyleParameter);
|
|
// These warnings are enabled by default, but only because they used
|
|
// to be unconditional. TODO: prune this list
|
|
warnLanguage_.set(LanguageFeature::ExponentMatchingKindParam);
|
|
warnLanguage_.set(LanguageFeature::RedundantAttribute);
|
|
warnLanguage_.set(LanguageFeature::SubroutineAndFunctionSpecifics);
|
|
warnLanguage_.set(LanguageFeature::EmptySequenceType);
|
|
warnLanguage_.set(LanguageFeature::NonSequenceCrayPointee);
|
|
warnLanguage_.set(LanguageFeature::BranchIntoConstruct);
|
|
warnLanguage_.set(LanguageFeature::BadBranchTarget);
|
|
warnLanguage_.set(LanguageFeature::HollerithPolymorphic);
|
|
warnLanguage_.set(LanguageFeature::ListDirectedSize);
|
|
warnUsage_.set(UsageWarning::ShortArrayActual);
|
|
warnUsage_.set(UsageWarning::FoldingException);
|
|
warnUsage_.set(UsageWarning::FoldingAvoidsRuntimeCrash);
|
|
warnUsage_.set(UsageWarning::FoldingValueChecks);
|
|
warnUsage_.set(UsageWarning::FoldingFailure);
|
|
warnUsage_.set(UsageWarning::FoldingLimit);
|
|
warnUsage_.set(UsageWarning::Interoperability);
|
|
// CharacterInteroperability warnings about length are off by default
|
|
warnUsage_.set(UsageWarning::Bounds);
|
|
warnUsage_.set(UsageWarning::Preprocessing);
|
|
warnUsage_.set(UsageWarning::Scanning);
|
|
warnUsage_.set(UsageWarning::OpenAccUsage);
|
|
warnUsage_.set(UsageWarning::ProcPointerCompatibility);
|
|
warnUsage_.set(UsageWarning::VoidMold);
|
|
warnUsage_.set(UsageWarning::KnownBadImplicitInterface);
|
|
warnUsage_.set(UsageWarning::EmptyCase);
|
|
warnUsage_.set(UsageWarning::CaseOverflow);
|
|
warnUsage_.set(UsageWarning::CUDAUsage);
|
|
warnUsage_.set(UsageWarning::IgnoreTKRUsage);
|
|
warnUsage_.set(UsageWarning::ExternalInterfaceMismatch);
|
|
warnUsage_.set(UsageWarning::DefinedOperatorArgs);
|
|
warnUsage_.set(UsageWarning::Final);
|
|
warnUsage_.set(UsageWarning::ZeroDoStep);
|
|
warnUsage_.set(UsageWarning::UnusedForallIndex);
|
|
warnUsage_.set(UsageWarning::OpenMPUsage);
|
|
warnUsage_.set(UsageWarning::ModuleFile);
|
|
warnUsage_.set(UsageWarning::DataLength);
|
|
warnUsage_.set(UsageWarning::IgnoredDirective);
|
|
warnUsage_.set(UsageWarning::HomonymousSpecific);
|
|
warnUsage_.set(UsageWarning::HomonymousResult);
|
|
warnUsage_.set(UsageWarning::IgnoredIntrinsicFunctionType);
|
|
warnUsage_.set(UsageWarning::PreviousScalarUse);
|
|
warnUsage_.set(UsageWarning::RedeclaredInaccessibleComponent);
|
|
warnUsage_.set(UsageWarning::ImplicitShared);
|
|
warnUsage_.set(UsageWarning::IndexVarRedefinition);
|
|
warnUsage_.set(UsageWarning::IncompatibleImplicitInterfaces);
|
|
warnUsage_.set(UsageWarning::BadTypeForTarget);
|
|
warnUsage_.set(UsageWarning::VectorSubscriptFinalization);
|
|
warnUsage_.set(UsageWarning::UndefinedFunctionResult);
|
|
warnUsage_.set(UsageWarning::UselessIomsg);
|
|
// New warnings, on by default
|
|
warnLanguage_.set(LanguageFeature::SavedLocalInSpecExpr);
|
|
}
|
|
|
|
// Ignore case and any inserted punctuation (like '-'/'_')
|
|
static std::optional<char> GetWarningChar(char ch) {
|
|
if (ch >= 'a' && ch <= 'z') {
|
|
return ch;
|
|
} else if (ch >= 'A' && ch <= 'Z') {
|
|
return ch - 'A' + 'a';
|
|
} else if (ch >= '0' && ch <= '9') {
|
|
return ch;
|
|
} else {
|
|
return std::nullopt;
|
|
}
|
|
}
|
|
|
|
static bool WarningNameMatch(const char *a, const char *b) {
|
|
while (true) {
|
|
auto ach{GetWarningChar(*a)};
|
|
while (!ach && *a) {
|
|
ach = GetWarningChar(*++a);
|
|
}
|
|
auto bch{GetWarningChar(*b)};
|
|
while (!bch && *b) {
|
|
bch = GetWarningChar(*++b);
|
|
}
|
|
if (!ach && !bch) {
|
|
return true;
|
|
} else if (!ach || !bch || *ach != *bch) {
|
|
return false;
|
|
}
|
|
++a, ++b;
|
|
}
|
|
}
|
|
|
|
template <typename ENUM, std::size_t N>
|
|
std::optional<ENUM> ScanEnum(const char *name) {
|
|
if (name) {
|
|
for (std::size_t j{0}; j < N; ++j) {
|
|
auto feature{static_cast<ENUM>(j)};
|
|
if (WarningNameMatch(name, EnumToString(feature).data())) {
|
|
return feature;
|
|
}
|
|
}
|
|
}
|
|
return std::nullopt;
|
|
}
|
|
|
|
std::optional<LanguageFeature> FindLanguageFeature(const char *name) {
|
|
return ScanEnum<LanguageFeature, LanguageFeature_enumSize>(name);
|
|
}
|
|
|
|
std::optional<UsageWarning> FindUsageWarning(const char *name) {
|
|
return ScanEnum<UsageWarning, UsageWarning_enumSize>(name);
|
|
}
|
|
|
|
std::vector<const char *> LanguageFeatureControl::GetNames(
|
|
LogicalOperator opr) const {
|
|
std::vector<const char *> result;
|
|
result.push_back(AsFortran(opr));
|
|
if (opr == LogicalOperator::Neqv && IsEnabled(LanguageFeature::XOROperator)) {
|
|
result.push_back(".xor.");
|
|
}
|
|
if (IsEnabled(LanguageFeature::LogicalAbbreviations)) {
|
|
switch (opr) {
|
|
SWITCH_COVERS_ALL_CASES
|
|
case LogicalOperator::And:
|
|
result.push_back(".a.");
|
|
break;
|
|
case LogicalOperator::Or:
|
|
result.push_back(".o.");
|
|
break;
|
|
case LogicalOperator::Not:
|
|
result.push_back(".n.");
|
|
break;
|
|
case LogicalOperator::Neqv:
|
|
if (IsEnabled(LanguageFeature::XOROperator)) {
|
|
result.push_back(".x.");
|
|
}
|
|
break;
|
|
case LogicalOperator::Eqv:
|
|
break;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
std::vector<const char *> LanguageFeatureControl::GetNames(
|
|
RelationalOperator opr) const {
|
|
switch (opr) {
|
|
SWITCH_COVERS_ALL_CASES
|
|
case RelationalOperator::LT:
|
|
return {".lt.", "<"};
|
|
case RelationalOperator::LE:
|
|
return {".le.", "<="};
|
|
case RelationalOperator::EQ:
|
|
return {".eq.", "=="};
|
|
case RelationalOperator::GE:
|
|
return {".ge.", ">="};
|
|
case RelationalOperator::GT:
|
|
return {".gt.", ">"};
|
|
case RelationalOperator::NE:
|
|
if (IsEnabled(LanguageFeature::AlternativeNE)) {
|
|
return {".ne.", "/=", "<>"};
|
|
} else {
|
|
return {".ne.", "/="};
|
|
}
|
|
}
|
|
}
|
|
|
|
} // namespace Fortran::common
|