diff options
Diffstat (limited to 'flang/lib/Semantics/check-declarations.cpp')
-rw-r--r-- | flang/lib/Semantics/check-declarations.cpp | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/flang/lib/Semantics/check-declarations.cpp b/flang/lib/Semantics/check-declarations.cpp index 69607c466e16..0b28a3188e5d 100644 --- a/flang/lib/Semantics/check-declarations.cpp +++ b/flang/lib/Semantics/check-declarations.cpp @@ -19,6 +19,8 @@ #include "flang/Semantics/tools.h" #include "flang/Semantics/type.h" #include <algorithm> +#include <map> +#include <string> namespace Fortran::semantics { @@ -100,6 +102,7 @@ private: } } bool IsResultOkToDiffer(const FunctionResult &); + void CheckBindCName(const Symbol &); SemanticsContext &context_; evaluate::FoldingContext &foldingContext_{context_.foldingContext()}; @@ -112,6 +115,8 @@ private: // Cache of calls to Procedure::Characterize(Symbol) std::map<SymbolRef, std::optional<Procedure>, SymbolAddressCompare> characterizeCache_; + // Collection of symbols with BIND(C) names + std::map<std::string, SymbolRef> bindC_; }; class DistinguishabilityHelper { @@ -195,6 +200,7 @@ void CheckHelper::Check(const Symbol &symbol) { if (symbol.attrs().test(Attr::VOLATILE)) { CheckVolatile(symbol, derived); } + CheckBindCName(symbol); if (isDone) { return; // following checks do not apply } @@ -1654,6 +1660,35 @@ void CheckHelper::CheckGenericOps(const Scope &scope) { helper.Check(scope); } +static const std::string *DefinesBindCName(const Symbol &symbol) { + const auto *subp{symbol.detailsIf<SubprogramDetails>()}; + if ((subp && !subp->isInterface()) || symbol.has<ObjectEntityDetails>()) { + // Symbol defines data or entry point + return symbol.GetBindName(); + } else { + return nullptr; + } +} + +// Check that BIND(C) names are distinct +void CheckHelper::CheckBindCName(const Symbol &symbol) { + if (const std::string * name{DefinesBindCName(symbol)}) { + auto pair{bindC_.emplace(*name, symbol)}; + if (!pair.second) { + const Symbol &other{*pair.first->second}; + if (DefinesBindCName(other) && !context_.HasError(other)) { + if (auto *msg{messages_.Say( + "Two symbols have the same BIND(C) name '%s'"_err_en_US, + *name)}) { + msg->Attach(other.name(), "Conflicting symbol"_en_US); + } + context_.SetError(symbol); + context_.SetError(other); + } + } + } +} + void SubprogramMatchHelper::Check( const Symbol &symbol1, const Symbol &symbol2) { const auto details1{symbol1.get<SubprogramDetails>()}; |