[llvm-branch-commits] [flang] 18278ff - [flang] Fix accessibility of USEd name in .mod file
Author: Tim Keith Date: 2021-01-13T12:52:44-08:00 New Revision: 18278ff1aac47d9bffa0231c74277ffc89def13e URL: https://github.com/llvm/llvm-project/commit/18278ff1aac47d9bffa0231c74277ffc89def13e DIFF: https://github.com/llvm/llvm-project/commit/18278ff1aac47d9bffa0231c74277ffc89def13e.diff LOG: [flang] Fix accessibility of USEd name in .mod file If a module specifies default private accessibility, names that have been use-associated are private by default. This was not reflected in .mod files. Differential Revision: https://reviews.llvm.org/D94602 Added: Modified: flang/lib/Semantics/mod-file.cpp flang/test/Semantics/modfile03.f90 Removed: diff --git a/flang/lib/Semantics/mod-file.cpp b/flang/lib/Semantics/mod-file.cpp index f8e5889e4698..23733f944d8c 100644 --- a/flang/lib/Semantics/mod-file.cpp +++ b/flang/lib/Semantics/mod-file.cpp @@ -427,6 +427,7 @@ void ModFileWriter::PutUse(const Symbol &symbol) { PutGenericName(uses_ << "=>", use); } uses_ << '\n'; + PutUseExtraAttr(Attr::PRIVATE, symbol, use); PutUseExtraAttr(Attr::VOLATILE, symbol, use); PutUseExtraAttr(Attr::ASYNCHRONOUS, symbol, use); } diff --git a/flang/test/Semantics/modfile03.f90 b/flang/test/Semantics/modfile03.f90 index 9bdb35695f03..a4b21c8287f5 100644 --- a/flang/test/Semantics/modfile03.f90 +++ b/flang/test/Semantics/modfile03.f90 @@ -158,3 +158,21 @@ subroutine s(x) ! end ! end interface !end + +module m7a + real :: x +end +!Expect: m7a.mod +!module m7a +! real(4)::x +!end + +module m7b + use m7a + private +end +!Expect: m7b.mod +!module m7b +! use m7a,only:x +! private::x +!end ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [flang] 3e41ab1 - [flang] Fix dangling pointer in LabelEnforce
Author: Tim Keith Date: 2021-01-14T06:52:21-08:00 New Revision: 3e41ab18db2255028c288a11665c08d260654299 URL: https://github.com/llvm/llvm-project/commit/3e41ab18db2255028c288a11665c08d260654299 DIFF: https://github.com/llvm/llvm-project/commit/3e41ab18db2255028c288a11665c08d260654299.diff LOG: [flang] Fix dangling pointer in LabelEnforce `DirectiveStructureChecker` was passing in a pointer to a temporary string for the `construct` argument to the constructor for `LabelEnforce`. The `LabelEnforce` object had a lifetime longer than the temporary, resulting in accessing a dangling pointer when emitting an error message for `omp-parallell01.f90`. The fix is to make the lifetime of the temporary as long as the lifetime of the `LabelEnforce` object. Differential Revision: https://reviews.llvm.org/D94618 Added: Modified: flang/lib/Semantics/check-directive-structure.h Removed: diff --git a/flang/lib/Semantics/check-directive-structure.h b/flang/lib/Semantics/check-directive-structure.h index 1075087feb4f..76157ac93925 100644 --- a/flang/lib/Semantics/check-directive-structure.h +++ b/flang/lib/Semantics/check-directive-structure.h @@ -280,9 +280,9 @@ void DirectiveStructureChecker::CheckNoBranching( context_, directiveSource, directive, ContextDirectiveAsFortran()}; parser::Walk(block, noBranchingEnforce); + auto construct{parser::ToUpperCaseLetters(getDirectiveName(directive).str())}; LabelEnforce directiveLabelEnforce{context_, noBranchingEnforce.labels(), - directiveSource, - parser::ToUpperCaseLetters(getDirectiveName(directive).str()).c_str()}; + directiveSource, construct.c_str()}; parser::Walk(block, directiveLabelEnforce); } ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [flang] d6acf3c - [flang] Fix use-associated procedure in generic
Author: Tim Keith Date: 2021-01-14T16:31:52-08:00 New Revision: d6acf3c2012b00f06a422e8704609676be7729b2 URL: https://github.com/llvm/llvm-project/commit/d6acf3c2012b00f06a422e8704609676be7729b2 DIFF: https://github.com/llvm/llvm-project/commit/d6acf3c2012b00f06a422e8704609676be7729b2.diff LOG: [flang] Fix use-associated procedure in generic When a use-associated procedure was included in a generic, we weren't correctly recording that fact. The ultimate symbol was added rather than the local symbol. Also, improve the message emitted for the specific procedure by mentioning the module it came from. This fixes one of the problems in https://bugs.llvm.org/show_bug.cgi?id=48648. Differential Revision: https://reviews.llvm.org/D94696 Added: Modified: flang/lib/Semantics/resolve-names.cpp flang/test/Semantics/modfile07.f90 flang/test/Semantics/resolve53.f90 Removed: diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index d66f561fc3c5..cef4f0010302 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -2603,36 +2603,43 @@ void InterfaceVisitor::ResolveSpecificsInGeneric(Symbol &generic) { Say(*name, "Procedure '%s' not found"_err_en_US); continue; } -symbol = &symbol->GetUltimate(); if (symbol == &generic) { if (auto *specific{generic.get().specific()}) { symbol = specific; } } -if (!symbol->has() && -!symbol->has()) { +const Symbol &ultimate{symbol->GetUltimate()}; +if (!ultimate.has() && +!ultimate.has()) { Say(*name, "'%s' is not a subprogram"_err_en_US); continue; } if (kind == ProcedureKind::ModuleProcedure) { - if (const auto *nd{symbol->detailsIf()}) { + if (const auto *nd{ultimate.detailsIf()}) { if (nd->kind() != SubprogramKind::Module) { Say(*name, "'%s' is not a module procedure"_err_en_US); } } else { // USE-associated procedure -const auto *sd{symbol->detailsIf()}; +const auto *sd{ultimate.detailsIf()}; CHECK(sd); -if (symbol->owner().kind() != Scope::Kind::Module || +if (ultimate.owner().kind() != Scope::Kind::Module || sd->isInterface()) { Say(*name, "'%s' is not a module procedure"_err_en_US); } } } -if (!symbolsSeen.insert(*symbol).second) { - Say(name->source, - "Procedure '%s' is already specified in generic '%s'"_err_en_US, - name->source, MakeOpName(generic.name())); +if (!symbolsSeen.insert(ultimate).second) { + if (symbol == &ultimate) { +Say(name->source, +"Procedure '%s' is already specified in generic '%s'"_err_en_US, +name->source, MakeOpName(generic.name())); + } else { +Say(name->source, +"Procedure '%s' from module '%s' is already specified in generic '%s'"_err_en_US, +ultimate.name(), ultimate.owner().GetName().value(), +MakeOpName(generic.name())); + } continue; } details.AddSpecificProc(*symbol, name->source); diff --git a/flang/test/Semantics/modfile07.f90 b/flang/test/Semantics/modfile07.f90 index f3e98bf195f9..878e342ff16a 100644 --- a/flang/test/Semantics/modfile07.f90 +++ b/flang/test/Semantics/modfile07.f90 @@ -598,3 +598,29 @@ module m10d ! end interface ! private::operator(.ne.) !end + +module m11a +contains + subroutine s1() + end +end +!Expect: m11a.mod +!module m11a +!contains +! subroutine s1() +! end +!end + +module m11b + use m11a + interface g +module procedure s1 + end interface +end +!Expect: m11b.mod +!module m11b +! use m11a,only:s1 +! interface g +! procedure::s1 +! end interface +!end diff --git a/flang/test/Semantics/resolve53.f90 b/flang/test/Semantics/resolve53.f90 index 1487873bd86b..64b0d536fa17 100644 --- a/flang/test/Semantics/resolve53.f90 +++ b/flang/test/Semantics/resolve53.f90 @@ -471,11 +471,11 @@ real function f(x) subroutine s1() use m20 interface operator(.not.) -!ERROR: Procedure 'f' is already specified in generic 'OPERATOR(.NOT.)' +!ERROR: Procedure 'f' from module 'm20' is already specified in generic 'OPERATOR(.NOT.)' procedure f end interface interface operator(+) -!ERROR: Procedure 'f' is already specified in generic 'OPERATOR(+)' +!ERROR: Procedure 'f' from module 'm20' is already specified in generic 'OPERATOR(+)' procedure f end interface end subroutine s1 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [flang] f782d5e - [flang] Detect call to abstract interface
Author: Tim Keith Date: 2020-12-28T16:36:34-08:00 New Revision: f782d5ea86f6fc82b51a0de688bf292f39cc4814 URL: https://github.com/llvm/llvm-project/commit/f782d5ea86f6fc82b51a0de688bf292f39cc4814 DIFF: https://github.com/llvm/llvm-project/commit/f782d5ea86f6fc82b51a0de688bf292f39cc4814.diff LOG: [flang] Detect call to abstract interface A subroutine call or function reference to an abstract interface is not legal. Differential Revision: https://reviews.llvm.org/D93872 Added: Modified: flang/lib/Semantics/resolve-names.cpp flang/test/Semantics/resolve20.f90 Removed: diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index 73c624aefa22..2412758f340b 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -5879,7 +5879,10 @@ void ResolveNamesVisitor::HandleProcedureName( return; // reported error } CheckImplicitNoneExternal(name.source, *symbol); -if (IsProcedure(*symbol) || symbol->has() || +if (symbol->has() && +symbol->attrs().test(Attr::ABSTRACT)) { + Say(name, "Abstract interface '%s' may not be called"_err_en_US); +} else if (IsProcedure(*symbol) || symbol->has() || symbol->has() || symbol->has()) { // Symbols with DerivedTypeDetails, ObjectEntityDetails and diff --git a/flang/test/Semantics/resolve20.f90 b/flang/test/Semantics/resolve20.f90 index f9cfc7cb1006..94bd4c18a6a0 100644 --- a/flang/test/Semantics/resolve20.f90 +++ b/flang/test/Semantics/resolve20.f90 @@ -61,7 +61,18 @@ subroutine forward procedure(proc), deferred :: p1 end type t1 + abstract interface +function f() +end function + end interface + contains subroutine bar end subroutine + subroutine test +!ERROR: Abstract interface 'foo' may not be called +call foo() +!ERROR: Abstract interface 'f' may not be called +x = f() + end subroutine end module ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [flang] 3a0352b - [flang] Fix bug with USE of USE of generic
Author: Tim Keith Date: 2020-12-15T16:11:59-08:00 New Revision: 3a0352b85c14cb83150df62a9ea9ac3c4129060d URL: https://github.com/llvm/llvm-project/commit/3a0352b85c14cb83150df62a9ea9ac3c4129060d DIFF: https://github.com/llvm/llvm-project/commit/3a0352b85c14cb83150df62a9ea9ac3c4129060d.diff LOG: [flang] Fix bug with USE of USE of generic When merging use associations into a generic, we weren't handling the case where the name that was use associated was itself a use association. This is fixed by following that association to its ultimate symbol (`useUltimate` in `DoAddUse`). An example of the bug is `m12d` in `resolve17.f90`. `g` is associated with `gc` in `m12c` which is associated with `gb` in `m12b`. It was that last association that we weren't correctly following. Differential Revision: https://reviews.llvm.org/D93343 Added: Modified: flang/lib/Semantics/resolve-names.cpp flang/lib/Semantics/symbol.cpp flang/test/Semantics/resolve17.f90 Removed: diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index b0e0b0b80ebf..5ac787b61d68 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -2371,38 +2371,40 @@ void ModuleVisitor::DoAddUse(const SourceName &location, const SourceName &localName, Symbol &localSymbol, const Symbol &useSymbol) { localSymbol.attrs() = useSymbol.attrs() & ~Attrs{Attr::PUBLIC, Attr::PRIVATE}; localSymbol.flags() = useSymbol.flags(); + const Symbol &useUltimate{useSymbol.GetUltimate()}; if (auto *useDetails{localSymbol.detailsIf()}) { -const Symbol &ultimate{localSymbol.GetUltimate()}; -if (ultimate == useSymbol.GetUltimate()) { +const Symbol &localUltimate{localSymbol.GetUltimate()}; +if (localUltimate == useUltimate) { // use-associating the same symbol again -- ok -} else if (ultimate.has() && -useSymbol.has()) { +} else if (localUltimate.has() && +useUltimate.has()) { // use-associating generics with the same names: merge them into a // new generic in this scope - auto generic1{ultimate.get()}; - AddGenericUse(generic1, localName, useSymbol); + auto generic1{localUltimate.get()}; + AddGenericUse(generic1, localName, useUltimate); generic1.AddUse(localSymbol); // useSymbol has specific g and so does generic1 - auto &generic2{useSymbol.get()}; + auto &generic2{useUltimate.get()}; if (generic1.derivedType() && generic2.derivedType() && generic1.derivedType() != generic2.derivedType()) { Say(location, "Generic interface '%s' has ambiguous derived types" " from modules '%s' and '%s'"_err_en_US, localSymbol.name(), GetUsedModule(*useDetails).name(), -useSymbol.owner().GetName().value()); +useUltimate.owner().GetName().value()); context().SetError(localSymbol); } else { generic1.CopyFrom(generic2); } EraseSymbol(localSymbol); - MakeSymbol(localSymbol.name(), ultimate.attrs(), std::move(generic1)); + MakeSymbol( + localSymbol.name(), localUltimate.attrs(), std::move(generic1)); } else { ConvertToUseError(localSymbol, location, *useModuleScope_); } } else if (auto *genericDetails{localSymbol.detailsIf()}) { -if (const auto *useDetails{useSymbol.detailsIf()}) { - AddGenericUse(*genericDetails, localName, useSymbol); +if (const auto *useDetails{useUltimate.detailsIf()}) { + AddGenericUse(*genericDetails, localName, useUltimate); if (genericDetails->derivedType() && useDetails->derivedType() && genericDetails->derivedType() != useDetails->derivedType()) { Say(location, diff --git a/flang/lib/Semantics/symbol.cpp b/flang/lib/Semantics/symbol.cpp index ee6a4a15de83..656c993935cd 100644 --- a/flang/lib/Semantics/symbol.cpp +++ b/flang/lib/Semantics/symbol.cpp @@ -431,8 +431,11 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const Details &details) { }, [&](const UseErrorDetails &x) { os << " uses:"; +char sep{':'}; for (const auto &[location, module] : x.occurrences()) { - os << " from " << module->GetName().value() << " at " << location; + os << sep << " from " << module->GetName().value() << " at " + << location; + sep = ','; } }, [](const HostAssocDetails &) {}, diff --git a/flang/test/Semantics/resolve17.f90 b/flang/test/Semantics/resolve17.f90 index 5aedaaa62003..2a2688749209 100644 --- a/flang/test/Semantics/resolve17.f90 +++ b/flang/test/Semantics/resolve17.f90 @@ -238,3 +238,30 @@ module m11c !ERROR: Generic interface 'g' has ambiguous derived types from modules 'm11a' and 'm11b' use m11b e
[llvm-branch-commits] [flang] 7082de5 - [flang] Handle multiple names for same operator
Author: Tim Keith Date: 2020-12-16T07:06:55-08:00 New Revision: 7082de56b7ad4b4eeb75e59e0d4c28bed44b5d23 URL: https://github.com/llvm/llvm-project/commit/7082de56b7ad4b4eeb75e59e0d4c28bed44b5d23 DIFF: https://github.com/llvm/llvm-project/commit/7082de56b7ad4b4eeb75e59e0d4c28bed44b5d23.diff LOG: [flang] Handle multiple names for same operator Some operators have more than one name, e.g. operator(==), operator(.eq). That was working correctly in generic definitions but they can also appear in other contexts: USE statements and access statements, for example. This changes FindInScope to always look for each of the names for a symbol. So an operator may be use-associated under one name but declared private under another name and it will be the same symbol. This replaces GenericSpecInfo::FindInScope which was only usable in some cases. Add a version of FindInScope() that looks in the current scope to simplify many of the calls. Differential Revision: https://reviews.llvm.org/D93344 Added: Modified: flang/lib/Semantics/resolve-names-utils.cpp flang/lib/Semantics/resolve-names-utils.h flang/lib/Semantics/resolve-names.cpp flang/test/Semantics/modfile07.f90 Removed: diff --git a/flang/lib/Semantics/resolve-names-utils.cpp b/flang/lib/Semantics/resolve-names-utils.cpp index 8dbd25e163ac..83bff78f426a 100644 --- a/flang/lib/Semantics/resolve-names-utils.cpp +++ b/flang/lib/Semantics/resolve-names-utils.cpp @@ -29,6 +29,8 @@ using common::NumericOperator; using common::RelationalOperator; using IntrinsicOperator = parser::DefinedOperator::IntrinsicOperator; +static constexpr const char *operatorPrefix{"operator("}; + static GenericKind MapIntrinsicOperator(IntrinsicOperator); Symbol *Resolve(const parser::Name &name, Symbol *symbol) { @@ -65,6 +67,37 @@ bool IsIntrinsicOperator( return false; } +template +std::forward_list GetOperatorNames( +const SemanticsContext &context, E opr) { + std::forward_list result; + for (const char *name : context.languageFeatures().GetNames(opr)) { +result.emplace_front(std::string{operatorPrefix} + name + ')'); + } + return result; +} + +std::forward_list GetAllNames( +const SemanticsContext &context, const SourceName &name) { + std::string str{name.ToString()}; + if (!name.empty() && name.end()[-1] == ')' && + name.ToString().rfind(std::string{operatorPrefix}, 0) == 0) { +for (int i{0}; i != common::LogicalOperator_enumSize; ++i) { + auto names{GetOperatorNames(context, LogicalOperator{i})}; + if (std::find(names.begin(), names.end(), str) != names.end()) { +return names; + } +} +for (int i{0}; i != common::RelationalOperator_enumSize; ++i) { + auto names{GetOperatorNames(context, RelationalOperator{i})}; + if (std::find(names.begin(), names.end(), str) != names.end()) { +return names; + } +} + } + return {str}; +} + bool IsLogicalConstant( const SemanticsContext &context, const SourceName &name) { std::string str{name.ToString()}; @@ -73,37 +106,6 @@ bool IsLogicalConstant( (str == ".t" || str == ".f.")); } -// The operators <, <=, >, >=, ==, and /= always have the same interpretations -// as the operators .LT., .LE., .GT., .GE., .EQ., and .NE., respectively. -std::forward_list GenericSpecInfo::GetAllNames( -SemanticsContext &context) const { - auto getNames{[&](auto opr) { -std::forward_list result; -for (const char *name : context.languageFeatures().GetNames(opr)) { - result.emplace_front("operator("s + name + ')'); -} -return result; - }}; - return std::visit( - common::visitors{[&](const LogicalOperator &x) { return getNames(x); }, - [&](const RelationalOperator &x) { return getNames(x); }, - [&](const auto &) -> std::forward_list { -return {symbolName_.value().ToString()}; - }}, - kind_.u); -} - -Symbol *GenericSpecInfo::FindInScope( -SemanticsContext &context, const Scope &scope) const { - for (const auto &name : GetAllNames(context)) { -auto iter{scope.find(SourceName{name})}; -if (iter != scope.end()) { - return &*iter->second; -} - } - return nullptr; -} - void GenericSpecInfo::Resolve(Symbol *symbol) const { if (symbol) { if (auto *details{symbol->detailsIf()}) { @@ -162,6 +164,16 @@ void GenericSpecInfo::Analyze(const parser::GenericSpec &x) { x.u); } +llvm::raw_ostream &operator<<( +llvm::raw_ostream &os, const GenericSpecInfo &info) { + os << "GenericSpecInfo: kind=" << info.kind_.ToString(); + os << " parseName=" + << (info.parseName_ ? info.parseName_->ToString() : "null"); + os << " symbolName=" + << (info.symbolName_ ? info.symbolName_->ToString() : "null"); + return os; +} + // parser::DefinedOperator::IntrinsicOperator -> GenericKind static GenericKind MapIntrinsicOperator(Intrinsic
[llvm-branch-commits] [flang] f6b577e - [flang] Fix -intrinsic-module-directory in flang script
Author: Tim Keith Date: 2020-12-17T19:08:19-08:00 New Revision: f6b577ed5bf61078cdcf60e94867b75c94f540a7 URL: https://github.com/llvm/llvm-project/commit/f6b577ed5bf61078cdcf60e94867b75c94f540a7 DIFF: https://github.com/llvm/llvm-project/commit/f6b577ed5bf61078cdcf60e94867b75c94f540a7.diff LOG: [flang] Fix -intrinsic-module-directory in flang script The flang wrapper script that was created as bin/flang in an in-tree build did not have a correct -intrinsic-module-directory option. It was correct for out-of-tree builds and for both kinds of installs. The fix is to pick the correct directory based on what exists. The script is no longer configured by cmake (just copied) so that mechanism can be deleted from the cmake file. Differential Revision: https://reviews.llvm.org/D93496 Added: flang/tools/f18/flang Modified: flang/tools/f18/CMakeLists.txt Removed: flang/tools/f18/flang.sh.in diff --git a/flang/tools/f18/CMakeLists.txt b/flang/tools/f18/CMakeLists.txt index cdc09fc7a68a..8f30bfa47b79 100644 --- a/flang/tools/f18/CMakeLists.txt +++ b/flang/tools/f18/CMakeLists.txt @@ -65,28 +65,12 @@ add_custom_target(module_files ALL DEPENDS ${MODULE_FILES}) install(TARGETS f18 DESTINATION bin) -set(FLANG_INTRINSIC_MODULES_DIR ${FLANG_BINARY_DIR}/include/flang) - # This flang shell script will only work in a POSIX shell. if (NOT WIN32) - if (FLANG_STANDALONE_BUILD) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/flang.sh.in ${CMAKE_BINARY_DIR}/tools/flang/bin/flang @ONLY) -file(COPY ${CMAKE_BINARY_DIR}/tools/flang/bin/flang DESTINATION ${CMAKE_BINARY_DIR}/bin FILE_PERMISSIONS OWNER_EXECUTE OWNER_READ OWNER_WRITE) - else() -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/flang.sh.in - ${CMAKE_CURRENT_BINARY_DIR}/tools/flang/bin/flang @ONLY) -add_custom_command(TARGET f18 -POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy - ${CMAKE_CURRENT_BINARY_DIR}/tools/flang/bin/flang - ${LLVM_RUNTIME_OUTPUT_INTDIR}/flang -COMMAND chmod +x ${LLVM_RUNTIME_OUTPUT_INTDIR}/flang) - endif() + file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/flang +DESTINATION ${CMAKE_BINARY_DIR}/bin +FILE_PERMISSIONS OWNER_EXECUTE OWNER_READ OWNER_WRITE) + install(PROGRAMS ${CMAKE_BINARY_DIR}/bin/flang DESTINATION bin) endif() -# The flang script to be installed needs a diff erent path to the headers. -set(FLANG_INTRINSIC_MODULES_DIR ${CMAKE_INSTALL_PREFIX}/include/flang) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/flang.sh.in ${FLANG_BINARY_DIR}/bin/flang-install.sh @ONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/f18_version.h.in ${CMAKE_CURRENT_BINARY_DIR}/f18_version.h @ONLY) - -install(PROGRAMS ${FLANG_BINARY_DIR}/bin/flang-install.sh DESTINATION bin RENAME flang) diff --git a/flang/tools/f18/flang b/flang/tools/f18/flang new file mode 100644 index ..01bdffdd20c7 --- /dev/null +++ b/flang/tools/f18/flang @@ -0,0 +1,15 @@ +#!/bin/bash +#===-- tools/f18/flang.sh -*- sh -*-===# +# +# 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 +# +#======# + +wd=$(cd $(dirname "$0")/.. && pwd) +module_dir=$wd/include/flang +if [[ ! -d $module_dir ]]; then + module_dir=$wd/tools/flang/include/flang +fi +$wd/bin/f18 -module-suffix .f18.mod -intrinsic-module-directory $module_dir "$@" diff --git a/flang/tools/f18/flang.sh.in b/flang/tools/f18/flang.sh.in deleted file mode 100644 index 295d93abbeb6.. --- a/flang/tools/f18/flang.sh.in +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/bash -#===-- tools/f18/flang.sh -*- sh -*-===# -# -# 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 -# -#======# - -function abspath() { - pushd . > /dev/null; - if [ -d "$1" ]; then -cd "$1"; -dirs -l +0; - else -cd "`dirname \"$1\"`"; -cur_dir=`dirs -l +0`; -if [ "$cur_dir" == "/" ]; then - echo "$cur_dir`basename \"$1\"`"; -else - echo "$cur_dir/`basename \"$1\"`"; -fi; - fi; - popd > /dev/null; -} - -wd=`abspath $(dirname "$0")/..` - -${wd}/bin/f18 -module-suffix .f18.mod -intrinsic-module-directory ${wd}/include/flang $* ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [flang] bf0870d - [flang] Fix bug in IMPLICIT NONE(EXTERNAL)
Author: Tim Keith Date: 2020-12-18T17:43:53-08:00 New Revision: bf0870d8640df27b6bb082de0347008240cb0e67 URL: https://github.com/llvm/llvm-project/commit/bf0870d8640df27b6bb082de0347008240cb0e67 DIFF: https://github.com/llvm/llvm-project/commit/bf0870d8640df27b6bb082de0347008240cb0e67.diff LOG: [flang] Fix bug in IMPLICIT NONE(EXTERNAL) We were only checking the restrictions of IMPLICIT NONE(EXTERNAL) when a procedure name is first encountered. But it can also happen with an existing symbol, e.g. if an external function's return type is declared before is it called. This change adds a check in that branch too. Differential Revision: https://reviews.llvm.org/D93552 Added: Modified: flang/lib/Semantics/resolve-names.cpp flang/test/Semantics/implicit07.f90 Removed: diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index 495d7d0f8584..8d5284131cc0 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -1364,6 +1364,7 @@ class ResolveNamesVisitor : public virtual ScopeHandler, void CheckImport(const SourceName &, const SourceName &); void HandleCall(Symbol::Flag, const parser::Call &); void HandleProcedureName(Symbol::Flag, const parser::Name &); + bool CheckImplicitNoneExternal(const SourceName &, const Symbol &); bool SetProcFlag(const parser::Name &, Symbol &, Symbol::Flag); void ResolveSpecificationParts(ProgramTree &); void AddSubpNames(ProgramTree &); @@ -5853,10 +5854,7 @@ void ResolveNamesVisitor::HandleProcedureName( return; } if (!symbol->attrs().test(Attr::INTRINSIC)) { - if (isImplicitNoneExternal() && !symbol->attrs().test(Attr::EXTERNAL)) { -Say(name, -"'%s' is an external procedure without the EXTERNAL" -" attribute in a scope with IMPLICIT NONE(EXTERNAL)"_err_en_US); + if (!CheckImplicitNoneExternal(name.source, *symbol)) { return; } MakeExternal(*symbol); @@ -5877,6 +5875,7 @@ void ResolveNamesVisitor::HandleProcedureName( if (!SetProcFlag(name, *symbol, flag)) { return; // reported error } +CheckImplicitNoneExternal(name.source, *symbol); if (IsProcedure(*symbol) || symbol->has() || symbol->has() || symbol->has()) { @@ -5895,6 +5894,18 @@ void ResolveNamesVisitor::HandleProcedureName( } } +bool ResolveNamesVisitor::CheckImplicitNoneExternal( +const SourceName &name, const Symbol &symbol) { + if (isImplicitNoneExternal() && !symbol.attrs().test(Attr::EXTERNAL) && + !symbol.attrs().test(Attr::INTRINSIC) && !symbol.HasExplicitInterface()) { +Say(name, +"'%s' is an external procedure without the EXTERNAL" +" attribute in a scope with IMPLICIT NONE(EXTERNAL)"_err_en_US); +return false; + } + return true; +} + // Variant of HandleProcedureName() for use while skimming the executable // part of a subprogram to catch calls to dummy procedures that are part // of the subprogram's interface, and to mark as procedures any symbols diff --git a/flang/test/Semantics/implicit07.f90 b/flang/test/Semantics/implicit07.f90 index df015f7bcc62..5362f91dcb02 100644 --- a/flang/test/Semantics/implicit07.f90 +++ b/flang/test/Semantics/implicit07.f90 @@ -1,9 +1,12 @@ ! RUN: %S/test_errors.sh %s %t %f18 implicit none(external) external x +integer :: f, i call x !ERROR: 'y' is an external procedure without the EXTERNAL attribute in a scope with IMPLICIT NONE(EXTERNAL) call y +!ERROR: 'f' is an external procedure without the EXTERNAL attribute in a scope with IMPLICIT NONE(EXTERNAL) +i = f() block !ERROR: 'z' is an external procedure without the EXTERNAL attribute in a scope with IMPLICIT NONE(EXTERNAL) call z ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [flang] d55627d - [flang] Fix bugs in .mod file for abstract interface
Author: Tim Keith Date: 2020-12-28T08:50:32-08:00 New Revision: d55627d221be8154cbdf454fa727afcc3f716b08 URL: https://github.com/llvm/llvm-project/commit/d55627d221be8154cbdf454fa727afcc3f716b08 DIFF: https://github.com/llvm/llvm-project/commit/d55627d221be8154cbdf454fa727afcc3f716b08.diff LOG: [flang] Fix bugs in .mod file for abstract interface When an abstract interface is defined, add the ABSTRACT attribute to subprogram symbols that define the interface body. Make use of that when writing .mod files to include "abstract" on the interface statement. Also, fix a problem with the order of symbols in a .mod file. Sometimes a name is mentioned before the "real" declaration, e.g. in an access statement. We want the order to be based on the real definitions. In these cases we replace the symbol name with an identical name with a different source location. Then by sorting based on the source location we get symbols in the right order. Differential Revision: https://reviews.llvm.org/D93572 Added: Modified: flang/lib/Semantics/mod-file.cpp flang/lib/Semantics/resolve-names.cpp flang/test/Semantics/modfile10.f90 flang/test/Semantics/procinterface01.f90 flang/test/Semantics/symbol15.f90 Removed: diff --git a/flang/lib/Semantics/mod-file.cpp b/flang/lib/Semantics/mod-file.cpp index 99ea65b753a6..f8e5889e4698 100644 --- a/flang/lib/Semantics/mod-file.cpp +++ b/flang/lib/Semantics/mod-file.cpp @@ -319,6 +319,10 @@ void ModFileWriter::PutSubprogram(const Symbol &symbol) { 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; @@ -331,7 +335,7 @@ void ModFileWriter::PutSubprogram(const Symbol &symbol) { 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 "); @@ -457,6 +461,11 @@ void CollectSymbols( } } } + // 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); diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index 8d5284131cc0..73c624aefa22 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -3085,11 +3085,14 @@ Symbol &SubprogramVisitor::PushSubprogramScope( symbol = &MakeSymbol(name, SubprogramDetails{}); } symbol->set(subpFlag); + symbol->ReplaceName(name.source); PushScope(Scope::Kind::Subprogram, symbol); auto &details{symbol->get()}; if (inInterfaceBlock()) { details.set_isInterface(); -if (!isAbstract()) { +if (isAbstract()) { + symbol->attrs().set(Attr::ABSTRACT); +} else { MakeExternal(*symbol); } if (isGeneric()) { diff --git a/flang/test/Semantics/modfile10.f90 b/flang/test/Semantics/modfile10.f90 index ef10f1f23e8e..996178f5896d 100644 --- a/flang/test/Semantics/modfile10.f90 +++ b/flang/test/Semantics/modfile10.f90 @@ -90,3 +90,40 @@ subroutine test ! subroutine test() ! end !end + +! Ensure the type is emitted before its use +module m2 + private s + type :: t + contains +procedure :: foo + end type + abstract interface +subroutine s(x) + import + type(t) :: x +end subroutine + end interface +contains + subroutine foo(x) +class(t) :: x + end subroutine +end module +!Expect: m2.mod +!module m2 +! type::t +! contains +!procedure::foo +! end type +! private::s +! abstract interface +!subroutine s(x) +! import::t +! type(t)::x +!end +! end interface +!contains +! subroutine foo(x) +!class(t)::x +! end +!end diff --git a/flang/test/Semantics/procinterface01.f90 b/flang/test/Semantics/procinterface01.f90 index a960922d5637..dd9fd3b66041 100644 --- a/flang/test/Semantics/procinterface01.f90 +++ b/flang/test/Semantics/procinterface01.f90 @@ -5,7 +5,7 @@ !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 functi
[llvm-branch-commits] [flang] 1f525ec - [flang][NFC] Add GetTopLevelUnitContaining functions
Author: Tim Keith Date: 2020-12-02T10:28:49-08:00 New Revision: 1f525ece4abfb6077d73e34acac0666855d19052 URL: https://github.com/llvm/llvm-project/commit/1f525ece4abfb6077d73e34acac0666855d19052 DIFF: https://github.com/llvm/llvm-project/commit/1f525ece4abfb6077d73e34acac0666855d19052.diff LOG: [flang][NFC] Add GetTopLevelUnitContaining functions `GetTopLevelUnitContaining` returns the Scope nested in the global scope that contains the given Scope or Symbol. Use "Get" rather than "Find" in the name because "Find" implies it might not be found, which can't happen. Following that logic, rename `FindProgramUnitContaining` to `GetProgramUnitContaining` and have it also return a reference rather that a pointer. Note that the use of "ProgramUnit" is slightly confusing. In the Fortran standard, "program-unit" refers to what is called a "TopLevelUnit" here. What we are calling a "ProgramUnit" (here and in `ProgramTree`) includes internal subprograms while "TopLevelUnit" does not. Differential Revision: https://reviews.llvm.org/D92491 Added: Modified: flang/include/flang/Semantics/tools.h flang/lib/Semantics/check-return.cpp flang/lib/Semantics/resolve-names.cpp flang/lib/Semantics/tools.cpp Removed: diff --git a/flang/include/flang/Semantics/tools.h b/flang/include/flang/Semantics/tools.h index 02faad4ecb2f..033c496c24b4 100644 --- a/flang/include/flang/Semantics/tools.h +++ b/flang/include/flang/Semantics/tools.h @@ -30,9 +30,14 @@ class DerivedTypeSpec; class Scope; class Symbol; +// Note: Here ProgramUnit includes internal subprograms while TopLevelUnit +// does not. "program-unit" in the Fortran standard matches TopLevelUnit. +const Scope &GetTopLevelUnitContaining(const Scope &); +const Scope &GetTopLevelUnitContaining(const Symbol &); +const Scope &GetProgramUnitContaining(const Scope &); +const Scope &GetProgramUnitContaining(const Symbol &); + const Scope *FindModuleContaining(const Scope &); -const Scope *FindProgramUnitContaining(const Scope &); -const Scope *FindProgramUnitContaining(const Symbol &); const Scope *FindPureProcedureContaining(const Scope &); const Scope *FindPureProcedureContaining(const Symbol &); const Symbol *FindPointerComponent(const Scope &); diff --git a/flang/lib/Semantics/check-return.cpp b/flang/lib/Semantics/check-return.cpp index 602ecc8a22f7..7830df034b55 100644 --- a/flang/lib/Semantics/check-return.cpp +++ b/flang/lib/Semantics/check-return.cpp @@ -16,11 +16,10 @@ namespace Fortran::semantics { static const Scope *FindContainingSubprogram(const Scope &start) { - const Scope *scope{FindProgramUnitContaining(start)}; - return scope && - (scope->kind() == Scope::Kind::MainProgram || - scope->kind() == Scope::Kind::Subprogram) - ? scope + const Scope &scope{GetProgramUnitContaining(start)}; + return scope.kind() == Scope::Kind::MainProgram || + scope.kind() == Scope::Kind::Subprogram + ? &scope : nullptr; } diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index a879d009d12d..fd994b9d2827 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -5602,11 +5602,11 @@ bool DeclarationVisitor::CheckForHostAssociatedImplicit( } bool DeclarationVisitor::IsUplevelReference(const Symbol &symbol) { - const Scope *symbolUnit{FindProgramUnitContaining(symbol)}; - if (symbolUnit == FindProgramUnitContaining(currScope())) { + const Scope &symbolUnit{GetProgramUnitContaining(symbol)}; + if (symbolUnit == GetProgramUnitContaining(currScope())) { return false; } else { -Scope::Kind kind{DEREF(symbolUnit).kind()}; +Scope::Kind kind{symbolUnit.kind()}; return kind == Scope::Kind::Subprogram || kind == Scope::Kind::MainProgram; } } diff --git a/flang/lib/Semantics/tools.cpp b/flang/lib/Semantics/tools.cpp index 0ab2b376b3e2..b27c8b7cc867 100644 --- a/flang/lib/Semantics/tools.cpp +++ b/flang/lib/Semantics/tools.cpp @@ -37,13 +37,24 @@ static const Scope *FindScopeContaining( } } +const Scope &GetTopLevelUnitContaining(const Scope &start) { + CHECK(!start.IsGlobal()); + return DEREF(FindScopeContaining( + start, [](const Scope &scope) { return scope.parent().IsGlobal(); })); +} + +const Scope &GetTopLevelUnitContaining(const Symbol &symbol) { + return GetTopLevelUnitContaining(symbol.owner()); +} + const Scope *FindModuleContaining(const Scope &start) { return FindScopeContaining( start, [](const Scope &scope) { return scope.IsModule(); }); } -const Scope *FindProgramUnitContaining(const Scope &start) { - return FindScopeContaining(start, [](const Scope &scope) { +const Scope &GetProgramUnitContaining(const Scope &start) { + CHECK(!start.IsGlobal()); + return DEREF(FindScopeContaining(start, [](const Scope &scope) { switch (scope.kind()) { case Sc
[llvm-branch-commits] [flang] 86f59de - [flang] Fix bugs related to merging generics during USE
Author: Tim Keith Date: 2020-12-02T15:13:50-08:00 New Revision: 86f59de13b8058280d468984727bd1e6727f2112 URL: https://github.com/llvm/llvm-project/commit/86f59de13b8058280d468984727bd1e6727f2112 DIFF: https://github.com/llvm/llvm-project/commit/86f59de13b8058280d468984727bd1e6727f2112.diff LOG: [flang] Fix bugs related to merging generics during USE When the same generic name is use-associated from two modules, the generics are merged into a single one in the current scope. This change fixes some bugs in that process. When a generic is merged, it can have two specific procedures with the same name as the generic (c.f. module m7c in modfile07.f90). We were disallowing that by checking for duplicate names in the generic rather than duplicate symbols. Changing `namesSeen` to `symbolsSeen` in `ResolveSpecificsInGeneric` fixes that. We weren't including each USE of those generics in the .mod file so in some cases they were incorrect. Extend GenericDetails to specify all use-associated symbols that are merged into the generic. This is used to write out .mod files correctly. The distinguishability check for specific procedures of a generic sometimes have to refer to procedures from a use-associated generic in error messages. In that case we don't have the source location of the procedure so adapt the message to say where is was use-associated from. This requires passing the scope through the checks to make that determination. Differential Revision: https://reviews.llvm.org/D92492 Added: Modified: flang/include/flang/Semantics/symbol.h flang/lib/Semantics/check-declarations.cpp flang/lib/Semantics/mod-file.cpp flang/lib/Semantics/resolve-names.cpp flang/lib/Semantics/symbol.cpp flang/test/Semantics/getsymbols03-a.f90 flang/test/Semantics/modfile07.f90 flang/test/Semantics/resolve17.f90 Removed: diff --git a/flang/include/flang/Semantics/symbol.h b/flang/include/flang/Semantics/symbol.h index 246bf2d0b338..833e3ab77720 100644 --- a/flang/include/flang/Semantics/symbol.h +++ b/flang/include/flang/Semantics/symbol.h @@ -155,6 +155,7 @@ class AssocEntityDetails : public EntityDetails { MaybeExpr expr_; std::optional rank_; }; +llvm::raw_ostream &operator<<(llvm::raw_ostream &, const AssocEntityDetails &); // An entity known to be an object. class ObjectEntityDetails : public EntityDetails { @@ -432,6 +433,7 @@ class GenericDetails { const SymbolVector &specificProcs() const { return specificProcs_; } const std::vector &bindingNames() const { return bindingNames_; } void AddSpecificProc(const Symbol &, SourceName bindingName); + const SymbolVector &uses() const { return uses_; } // specific and derivedType indicate a specific procedure or derived type // with the same name as this generic. Only one of them may be set. @@ -441,6 +443,7 @@ class GenericDetails { Symbol *derivedType() { return derivedType_; } const Symbol *derivedType() const { return derivedType_; } void set_derivedType(Symbol &derivedType); + void AddUse(const Symbol &); // Copy in specificProcs, specific, and derivedType from another generic void CopyFrom(const GenericDetails &); @@ -450,22 +453,19 @@ class GenericDetails { const Symbol *CheckSpecific() const; Symbol *CheckSpecific(); - const std::optional &useDetails() const { return useDetails_; } - void set_useDetails(const UseDetails &details) { useDetails_ = details; } - private: GenericKind kind_; // all of the specific procedures for this generic SymbolVector specificProcs_; std::vector bindingNames_; + // Symbols used from other modules merged into this one + SymbolVector uses_; // a specific procedure with the same name as this generic, if any Symbol *specific_{nullptr}; // a derived type with the same name as this generic, if any Symbol *derivedType_{nullptr}; - // If two USEs of generics were merged to form this one, this is the - // UseDetails for one of them. Used for reporting USE errors. - std::optional useDetails_; }; +llvm::raw_ostream &operator<<(llvm::raw_ostream &, const GenericDetails &); class UnknownDetails {}; diff --git a/flang/lib/Semantics/check-declarations.cpp b/flang/lib/Semantics/check-declarations.cpp index a0b445b8d046..782e4c864421 100644 --- a/flang/lib/Semantics/check-declarations.cpp +++ b/flang/lib/Semantics/check-declarations.cpp @@ -120,11 +120,12 @@ class DistinguishabilityHelper { public: DistinguishabilityHelper(SemanticsContext &context) : context_{context} {} void Add(const Symbol &, GenericKind, const Symbol &, const Procedure &); - void Check(); + void Check(const Scope &); private: - void SayNotDistinguishable( - const SourceName &, GenericKind, const Symbol &, const Symbol &); + void SayNotDistinguishable(const Scope &, const SourceName &, GenericKind, + const Symbol &, const Symbol &); + void A