bindAttrs.set(Attr::BIND_C, true);
attrs.set(Attr::BIND_C, false);
}
+ bool isAbstract{attrs.test(Attr::ABSTRACT)};
+ if (isAbstract) {
+ attrs.set(Attr::ABSTRACT, false);
+ }
Attrs prefixAttrs{subprogramPrefixAttrs & attrs};
// emit any non-prefix attributes in an attribute statement
attrs &= ~subprogramPrefixAttrs;
bool isInterface{details.isInterface()};
llvm::raw_ostream &os{isInterface ? decls_ : contains_};
if (isInterface) {
- os << "interface\n";
+ os << (isAbstract ? "abstract " : "") << "interface\n";
}
PutAttrs(os, prefixAttrs, std::nullopt, ""s, " "s);
os << (details.isFunction() ? "function " : "subroutine ");
}
}
}
+ // Sort most symbols by name: use of Symbol::ReplaceName ensures the source
+ // location of a symbol's name is the first "real" use.
+ std::sort(sorted.begin(), sorted.end(), [](SymbolRef x, SymbolRef y) {
+ return x->name().begin() < y->name().begin();
+ });
sorted.insert(sorted.end(), namelist.begin(), namelist.end());
for (const auto &pair : scope.commonBlocks()) {
sorted.push_back(*pair.second);
symbol = &MakeSymbol(name, SubprogramDetails{});
}
symbol->set(subpFlag);
+ symbol->ReplaceName(name.source);
PushScope(Scope::Kind::Subprogram, symbol);
auto &details{symbol->get<SubprogramDetails>()};
if (inInterfaceBlock()) {
details.set_isInterface();
- if (!isAbstract()) {
+ if (isAbstract()) {
+ symbol->attrs().set(Attr::ABSTRACT);
+ } else {
MakeExternal(*symbol);
}
if (isGeneric()) {
!DEF: /module1 Module
module module1
abstract interface
- !DEF: /module1/abstract1 PUBLIC (Function) Subprogram REAL(4)
+ !DEF: /module1/abstract1 ABSTRACT, PUBLIC (Function) Subprogram REAL(4)
!DEF: /module1/abstract1/x INTENT(IN) ObjectEntity REAL(4)
real function abstract1(x)
!REF: /module1/abstract1/x