[llvm-branch-commits] [flang][runtime] Added custom visitor for IoStatementState variants. (PR #85179)
https://github.com/klausler requested changes to this pull request. It would be better to have the types that are available on the device declare themselves so in their declarations via a member or (better) inherited trait. The big variant union in `IoStatementState` could omit the host-only options when compiled for the device. https://github.com/llvm/llvm-project/pull/85179 ___ 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] [NFC][flang] Reorder const and RT_API_ATTRS. (PR #85180)
https://github.com/klausler approved this pull request. https://github.com/llvm/llvm-project/pull/85180 ___ 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][runtime] Added self-printing for InternalUnit. (PR #85181)
@@ -48,6 +55,10 @@ template class InternalDescriptorUnit : public ConnectionState { void BlankFillOutputRecord(); StaticDescriptor staticDescriptor_; + RT_OFFLOAD_VAR_GROUP_BEGIN + static constexpr std::size_t ownBufferSizeInBytes{1024}; + RT_OFFLOAD_VAR_GROUP_END klausler wrote: Should this be one line lower? https://github.com/llvm/llvm-project/pull/85181 ___ 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][runtime] Added self-printing for InternalUnit. (PR #85181)
https://github.com/klausler edited https://github.com/llvm/llvm-project/pull/85181 ___ 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][runtime] Added self-printing for InternalUnit. (PR #85181)
https://github.com/klausler commented: If you want to support child I/O (user-defined derived type I/O) on the device, this approach of adding special behavior to the internal units won't work -- child I/O is embedded in external units. It might be clearer to support this device output path by extending the external unit class instead -- its `FileFrame` template in buffer.h can be instantiated on a `Store` that has no `Read` and only a rudimentary `Write`. https://github.com/llvm/llvm-project/pull/85181 ___ 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][runtime] Added self-printing for InternalUnit. (PR #85181)
@@ -119,6 +120,9 @@ template void InternalIoStatementState::BackspaceRecord() { } template int InternalIoStatementState::EndIoStatement() { + if constexpr (DIR == Direction::Output) { klausler wrote: If it is possible for the buffer flush to raise an error that the program can catch via `ERR=` or `IOSTAT=`, do this in `CompleteOperation` instead. https://github.com/llvm/llvm-project/pull/85181 ___ 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][runtime] Added self-printing for InternalUnit. (PR #85181)
@@ -41,6 +52,26 @@ InternalDescriptorUnit::InternalDescriptorUnit( endfileRecordNumber = d.Elements() + 1; } +template void InternalDescriptorUnit::EndIoStatement() { + if constexpr (DIR == Direction::Output) { +if (usesOwnBuffer) { + // Null terminate the buffer that contains just a single record. + Terminator terminator{__FILE__, __LINE__}; + RUNTIME_CHECK(terminator, + furthestPositionInRecord < + static_cast(ownBufferSizeInBytes)); + *reinterpret_cast(CurrentRecord() + furthestPositionInRecord) = + '\0'; + + // Print the buffer and deallocate memory. + // FIXME: this output does not match the regular unit 5 output. klausler wrote: The default output unit is 6. https://github.com/llvm/llvm-project/pull/85181 ___ 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][runtime] Added self-printing for InternalUnit. (PR #85181)
@@ -41,6 +52,26 @@ InternalDescriptorUnit::InternalDescriptorUnit( endfileRecordNumber = d.Elements() + 1; } +template void InternalDescriptorUnit::EndIoStatement() { + if constexpr (DIR == Direction::Output) { +if (usesOwnBuffer) { + // Null terminate the buffer that contains just a single record. + Terminator terminator{__FILE__, __LINE__}; + RUNTIME_CHECK(terminator, + furthestPositionInRecord < + static_cast(ownBufferSizeInBytes)); + *reinterpret_cast(CurrentRecord() + furthestPositionInRecord) = + '\0'; + + // Print the buffer and deallocate memory. + // FIXME: this output does not match the regular unit 5 output. + std::printf("%s\n", descriptor().OffsetElement()); + FreeMemory(descriptor().OffsetElement()); klausler wrote: Why not `descriptor().Deallocate()` (and `descriptor().Allocate()`)? https://github.com/llvm/llvm-project/pull/85181 ___ 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][runtime] Added self-printing for InternalUnit. (PR #85181)
@@ -48,6 +55,10 @@ template class InternalDescriptorUnit : public ConnectionState { void BlankFillOutputRecord(); StaticDescriptor staticDescriptor_; + RT_OFFLOAD_VAR_GROUP_BEGIN + static constexpr std::size_t ownBufferSizeInBytes{1024}; + RT_OFFLOAD_VAR_GROUP_END + bool usesOwnBuffer{false}; klausler wrote: The naming convention in the runtime (and front-end) has an underscore at the end of the name of a private `class` data member. https://github.com/llvm/llvm-project/pull/85181 ___ 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][runtime] Enable PRINT of integer32 for device. (PR #85182)
https://github.com/klausler edited https://github.com/llvm/llvm-project/pull/85182 ___ 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][runtime] Enable PRINT of integer32 for device. (PR #85182)
https://github.com/klausler approved this pull request. https://github.com/llvm/llvm-project/pull/85182 ___ 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][runtime] Enable PRINT of integer32 for device. (PR #85182)
@@ -368,7 +368,12 @@ static bool FormattedDerivedTypeIO(IoStatementState &io, ++j, descriptor.IncrementSubscripts(subscripts)) { Fortran::common::optional result; if (special) { +#if !defined(RT_DEVICE_COMPILATION) result = DefinedFormattedIo(io, descriptor, *type, *special, subscripts); +#else + io.GetIoErrorHandler().Crash("not implemented yet: defined formatted IO"); klausler wrote: "... from the device" https://github.com/llvm/llvm-project/pull/85182 ___ 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] [flang][openacc] Carry device dependent info for acc routine in the module file (PR #77804)
Valentin Clement =?utf-8?b?KOODkOODrOODsw==?= Message-ID: In-Reply-To: https://github.com/klausler approved this pull request. https://github.com/llvm/llvm-project/pull/77804 ___ 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] a50bb84 - [flang] Fix classification of shape inquiries in specification exprs
Author: peter klausler Date: 2021-01-13T10:05:14-08:00 New Revision: a50bb84ec0c2d47a2a7403ad29842ca48cd6b828 URL: https://github.com/llvm/llvm-project/commit/a50bb84ec0c2d47a2a7403ad29842ca48cd6b828 DIFF: https://github.com/llvm/llvm-project/commit/a50bb84ec0c2d47a2a7403ad29842ca48cd6b828.diff LOG: [flang] Fix classification of shape inquiries in specification exprs In some contexts, including the motivating case of determining whether the expressions that define the shape of a variable are "constant expressions" in the sense of the Fortran standard, expression rewriting via Fold() is not necessary, and should not be required. The inquiry intrinsics LBOUND, UBOUND, and SIZE work correctly now in specification expressions and are classified correctly as being constant expressions (or not). Getting this right led to a fair amount of API clean-up as a consequence, including the folding of shapes and TypeAndShape objects, and new APIs for shapes that do not fold for those cases where folding isn't needed. Further, the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any associations of their symbols and work transparently on use-, host-, and construct-association symbols; the tools used to resolve those associations have been defined and documented more precisely, and their clients adjusted as needed. Differential Revision: https://reviews.llvm.org/D94561 Added: Modified: flang/include/flang/Evaluate/characteristics.h flang/include/flang/Evaluate/fold.h flang/include/flang/Evaluate/shape.h flang/include/flang/Evaluate/tools.h flang/include/flang/Evaluate/type.h flang/include/flang/Semantics/tools.h flang/lib/Evaluate/characteristics.cpp flang/lib/Evaluate/check-expression.cpp flang/lib/Evaluate/fold.cpp flang/lib/Evaluate/intrinsics.cpp flang/lib/Evaluate/shape.cpp flang/lib/Evaluate/tools.cpp flang/lib/Semantics/check-call.cpp flang/lib/Semantics/check-declarations.cpp flang/lib/Semantics/check-do-forall.cpp flang/lib/Semantics/resolve-names.cpp flang/lib/Semantics/semantics.cpp flang/lib/Semantics/tools.cpp flang/test/Semantics/data04.f90 flang/test/Semantics/resolve44.f90 flang/test/Semantics/shape.f90 Removed: diff --git a/flang/include/flang/Evaluate/characteristics.h b/flang/include/flang/Evaluate/characteristics.h index c7ef66e800a9..6b7b2f5408e4 100644 --- a/flang/include/flang/Evaluate/characteristics.h +++ b/flang/include/flang/Evaluate/characteristics.h @@ -81,9 +81,9 @@ class TypeAndShape { static std::optional Characterize( const semantics::ObjectEntityDetails &, FoldingContext &); static std::optional Characterize( - const semantics::ProcInterface &); + const semantics::ProcInterface &, FoldingContext &); static std::optional Characterize( - const semantics::DeclTypeSpec &); + const semantics::DeclTypeSpec &, FoldingContext &); static std::optional Characterize( const ActualArgument &, FoldingContext &); @@ -101,15 +101,16 @@ class TypeAndShape { if (type->category() == TypeCategory::Character) { if (const auto *chExpr{UnwrapExpr>(x)}) { if (auto length{chExpr->LEN()}) { - result.set_LEN(Fold(context, std::move(*length))); + result.set_LEN(std::move(*length)); } } } -return result; +return std::move(result.Rewrite(context)); } } return std::nullopt; } + template static std::optional Characterize( const std::optional &x, FoldingContext &context) { @@ -121,9 +122,9 @@ class TypeAndShape { } template static std::optional Characterize( - const A *x, FoldingContext &context) { -if (x) { - return Characterize(*x, context); + const A *p, FoldingContext &context) { +if (p) { + return Characterize(*p, context); } else { return std::nullopt; } @@ -151,14 +152,17 @@ class TypeAndShape { std::optional> MeasureSizeInBytes( FoldingContext &) const; + // called by Fold() to rewrite in place + TypeAndShape &Rewrite(FoldingContext &); + llvm::raw_ostream &Dump(llvm::raw_ostream &) const; private: static std::optional Characterize( const semantics::AssocEntityDetails &, FoldingContext &); static std::optional Characterize( - const semantics::ProcEntityDetails &); - void AcquireShape(const semantics::ObjectEntityDetails &, FoldingContext &); + const semantics::ProcEntityDetails &, FoldingContext &); + void AcquireShape(const semantics::ObjectEntityDetails &); void AcquireLEN(); protected: @@ -325,6 +329,5 @@ struct Procedure { private: Procedure() {} }; - } // namespace Fortran::evaluate::characteristics #endif // FORTRAN_EVALUATE_CHARACTERISTICS_H_ diff --git a/flang/include/flang/Evaluate/fold.h b/flang
[llvm-branch-commits] [flang] 166e5c3 - [flang] Do not create HostAssoc symbols in derived type scopes
Author: peter klausler Date: 2021-01-13T11:01:27-08:00 New Revision: 166e5c335cbe9f8144a7822ca655dc3352ec9e56 URL: https://github.com/llvm/llvm-project/commit/166e5c335cbe9f8144a7822ca655dc3352ec9e56 DIFF: https://github.com/llvm/llvm-project/commit/166e5c335cbe9f8144a7822ca655dc3352ec9e56.diff LOG: [flang] Do not create HostAssoc symbols in derived type scopes When needed due to a specification expression in a derived type, the host association symbols should be created in the surrounding subprogram's scope instead. Differential Revision: https://reviews.llvm.org/D94567 Added: Modified: flang/lib/Semantics/resolve-names.cpp Removed: diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index cee49175d7f4..d66f561fc3c5 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -2050,7 +2050,9 @@ Symbol &ScopeHandler::MakeSymbol(const parser::Name &name, Attrs attrs) { } Symbol &ScopeHandler::MakeHostAssocSymbol( const parser::Name &name, const Symbol &hostSymbol) { - Symbol &symbol{MakeSymbol(name, HostAssocDetails{hostSymbol})}; + Symbol &symbol{*NonDerivedTypeScope() + .try_emplace(name.source, HostAssocDetails{hostSymbol}) + .first->second}; name.symbol = &symbol; symbol.attrs() = hostSymbol.attrs(); // TODO: except PRIVATE, PUBLIC? symbol.flags() = hostSymbol.flags(); ___ 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] 4864d9f - [flang] Fix some module file issues exposed by Whizard
Author: peter klausler Date: 2021-01-14T09:44:50-08:00 New Revision: 4864d9f7e91fdd58a84e4ae576f1ad16f71f9d91 URL: https://github.com/llvm/llvm-project/commit/4864d9f7e91fdd58a84e4ae576f1ad16f71f9d91 DIFF: https://github.com/llvm/llvm-project/commit/4864d9f7e91fdd58a84e4ae576f1ad16f71f9d91.diff LOG: [flang] Fix some module file issues exposed by Whizard Generic type-bound interfaces for user-defined operators need to be formatted as "OPERATOR(.op.)", not just ".op." PRIVATE generics need to be marked as such. Declaration ordering: when a generic interface shadows a derived type of the same name, it needs to be emitted to the module file at the point of definition of the derived type; otherwise, the derived type's definition may appear after its first use. The module symbol for a module read from a module file needs to be marked as coming from a module file before semantic processing is performed on the contents of the module so that any special handling for declarations in module files can be properly activated. IMPORT statements were sometimes missing for use-associated symbols in surrounding scopes; fine-tune NeedImport(). Differential Revision: https://reviews.llvm.org/D94636 Added: flang/test/Semantics/modfile37.f90 flang/test/Semantics/modfile38.f90 Modified: flang/lib/Semantics/mod-file.cpp flang/test/Semantics/modfile35.f90 Removed: diff --git a/flang/lib/Semantics/mod-file.cpp b/flang/lib/Semantics/mod-file.cpp index 23733f944d8c..af3267a1c9a0 100644 --- a/flang/lib/Semantics/mod-file.cpp +++ b/flang/lib/Semantics/mod-file.cpp @@ -198,6 +198,15 @@ bool ModFileWriter::PutSymbols(const Scope &scope) { } } +static llvm::raw_ostream &PutGenericName( +llvm::raw_ostream &os, const Symbol &symbol) { + if (IsGenericDefinedOp(symbol)) { +return os << "operator(" << symbol.name() << ')'; + } else { +return os << symbol.name(); + } +} + // Emit a symbol to decls_, except for bindings in a derived type (type-bound // procedures, type-bound generics, final procedures) which go to typeBindings. void ModFileWriter::PutSymbol( @@ -210,8 +219,8 @@ void ModFileWriter::PutSymbol( if (symbol.owner().IsDerivedType()) { // generic binding for (const Symbol &proc : x.specificProcs()) { - typeBindings << "generic::" << symbol.name() << "=>" -<< proc.name() << '\n'; + PutGenericName(typeBindings << "generic::", symbol) + << "=>" << proc.name() << '\n'; } } else { PutGeneric(symbol); @@ -392,15 +401,6 @@ static bool IsIntrinsicOp(const Symbol &symbol) { } } -static llvm::raw_ostream &PutGenericName( -llvm::raw_ostream &os, const Symbol &symbol) { - if (IsGenericDefinedOp(symbol)) { -return os << "operator(" << symbol.name() << ')'; - } else { -return os << symbol.name(); - } -} - void ModFileWriter::PutGeneric(const Symbol &symbol) { const auto &genericOwner{symbol.owner()}; auto &details{symbol.get()}; @@ -427,9 +427,11 @@ 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); + if (symbol.attrs().test(Attr::PRIVATE)) { +PutGenericName(useExtraAttrs_ << "private::", symbol) << '\n'; + } } // We have "USE local => use" in this module. If attr was added locally @@ -442,6 +444,31 @@ void ModFileWriter::PutUseExtraAttr( } } +// When a generic interface has the same name as a derived type +// in the same scope, the generic shadows the derived type. +// If the derived type were declared first, emit the generic +// interface at the position of derived type's declaration. +// (ReplaceName() is not used for this purpose because doing so +// would confusingly position error messages pertaining to the generic +// interface upon the derived type's declaration.) +static inline SourceName NameInModuleFile(const Symbol &symbol) { + if (const auto *generic{symbol.detailsIf()}) { +if (const auto *derivedTypeOverload{generic->derivedType()}) { + if (derivedTypeOverload->name().begin() < symbol.name().begin()) { +return derivedTypeOverload->name(); + } +} + } else if (const auto *use{symbol.detailsIf()}) { +if (use->symbol().attrs().test(Attr::PRIVATE)) { + // Avoid the use in sorting of names created to access private + // specific procedures as a result of generic resolution; + // they're not in the cooked source. + return use->symbol().name(); +} + } + return symbol.name(); +} + // Collect the symbols of this scope sorted by their original order, not name.
[llvm-branch-commits] [flang] 1bd083b - [flang] Create names to allow access to inaccessible specifics
Author: peter klausler Date: 2021-01-15T16:56:38-08:00 New Revision: 1bd083b5d6d0619f532a7310e72887ea6d2e87eb URL: https://github.com/llvm/llvm-project/commit/1bd083b5d6d0619f532a7310e72887ea6d2e87eb DIFF: https://github.com/llvm/llvm-project/commit/1bd083b5d6d0619f532a7310e72887ea6d2e87eb.diff LOG: [flang] Create names to allow access to inaccessible specifics When a reference to a generic interface occurs in a specification expression that must be emitted to a module file, we have a problem when the generic resolves to a function whose name is inaccessible due to being PRIVATE or due to a conflict with another use of the same name in the scope. In these cases, construct a new name for the specific procedure and emit a renaming USE to the module file. Also, relax enforcement of PRIVATE when analyzing module files. Differential Revision: https://reviews.llvm.org/D94815 Added: flang/test/Semantics/modfile39.f90 Modified: flang/include/flang/Semantics/expression.h flang/include/flang/Semantics/semantics.h flang/include/flang/Semantics/tools.h flang/lib/Evaluate/check-expression.cpp flang/lib/Semantics/expression.cpp flang/lib/Semantics/resolve-names.cpp flang/lib/Semantics/semantics.cpp flang/lib/Semantics/tools.cpp Removed: diff --git a/flang/include/flang/Semantics/expression.h b/flang/include/flang/Semantics/expression.h index e095928656a8..7b252baa6c7d 100644 --- a/flang/include/flang/Semantics/expression.h +++ b/flang/include/flang/Semantics/expression.h @@ -363,6 +363,8 @@ class ExpressionAnalyzer { const Symbol *ResolveGeneric(const Symbol &, const ActualArguments &, const AdjustActuals &, bool mightBeStructureConstructor = false); void EmitGenericResolutionError(const Symbol &); + const Symbol &AccessSpecific( + const Symbol &originalGeneric, const Symbol &specific); std::optional GetCalleeAndArguments(const parser::Name &, ActualArguments &&, bool isSubroutine = false, bool mightBeStructureConstructor = false); diff --git a/flang/include/flang/Semantics/semantics.h b/flang/include/flang/Semantics/semantics.h index de3d9aeac144..4f4bfc7fea2d 100644 --- a/flang/include/flang/Semantics/semantics.h +++ b/flang/include/flang/Semantics/semantics.h @@ -16,6 +16,7 @@ #include "flang/Evaluate/intrinsics.h" #include "flang/Parser/message.h" #include +#include #include #include @@ -170,6 +171,7 @@ class SemanticsContext { void ActivateIndexVar(const parser::Name &, IndexVarKind); void DeactivateIndexVar(const parser::Name &); SymbolVector GetIndexVars(IndexVarKind); + SourceName SaveTempName(std::string &&); SourceName GetTempName(const Scope &); private: @@ -198,7 +200,7 @@ class SemanticsContext { }; std::map activeIndexVars_; std::set errorSymbols_; - std::vector tempNames_; + std::set tempNames_; }; class Semantics { diff --git a/flang/include/flang/Semantics/tools.h b/flang/include/flang/Semantics/tools.h index 1a0e2845534b..e809b300b3ad 100644 --- a/flang/include/flang/Semantics/tools.h +++ b/flang/include/flang/Semantics/tools.h @@ -38,6 +38,7 @@ const Scope &GetProgramUnitContaining(const Scope &); const Scope &GetProgramUnitContaining(const Symbol &); const Scope *FindModuleContaining(const Scope &); +const Scope *FindModuleFileContaining(const Scope &); const Scope *FindPureProcedureContaining(const Scope &); const Scope *FindPureProcedureContaining(const Symbol &); const Symbol *FindPointerComponent(const Scope &); diff --git a/flang/lib/Evaluate/check-expression.cpp b/flang/lib/Evaluate/check-expression.cpp index 45bfde08dfb9..4bedbe8d1d8f 100644 --- a/flang/lib/Evaluate/check-expression.cpp +++ b/flang/lib/Evaluate/check-expression.cpp @@ -485,16 +485,17 @@ class CheckSpecificationExprHelper template Result operator()(const FunctionRef &x) const { if (const auto *symbol{x.proc().GetSymbol()}) { - if (!semantics::IsPureProcedure(*symbol)) { -return "reference to impure function '"s + symbol->name().ToString() + + const Symbol &ultimate{symbol->GetUltimate()}; + if (!semantics::IsPureProcedure(ultimate)) { +return "reference to impure function '"s + ultimate.name().ToString() + "'"; } - if (semantics::IsStmtFunction(*symbol)) { + if (semantics::IsStmtFunction(ultimate)) { return "reference to statement function '"s + -symbol->name().ToString() + "'"; +ultimate.name().ToString() + "'"; } if (scope_.IsDerivedType()) { // C750, C754 -return "reference to function '"s + symbol->name().ToString() + +return "reference to function '"s + ultimate.name().ToString() + "' not allowed for derived type components or type parameter" " values"; } diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/e
[llvm-branch-commits] [flang] 24e8e21 - [flang] Refine WhyNotModifiable()
Author: peter klausler Date: 2021-01-19T11:44:51-08:00 New Revision: 24e8e21f19f4380e8410a12f9135bfef3c046142 URL: https://github.com/llvm/llvm-project/commit/24e8e21f19f4380e8410a12f9135bfef3c046142 DIFF: https://github.com/llvm/llvm-project/commit/24e8e21f19f4380e8410a12f9135bfef3c046142.diff LOG: [flang] Refine WhyNotModifiable() The utility routine WhyNotModifiable() needed to become more aware of the use of pointers in data-refs; the targets of pointer components are sometimes modifiable even when the leftmost ("base") symbol of a data-ref is not. Added a new unit test for WhyNotModifiable() that uses internal READ statements (mostly), since I/O semantic checking uses WhyNotModifiable() for all its definability checking. Differential Revision: https://reviews.llvm.org/D94849 Added: flang/test/Semantics/modifiable01.f90 Modified: flang/include/flang/Evaluate/tools.h flang/lib/Evaluate/tools.cpp flang/lib/Semantics/check-io.cpp flang/lib/Semantics/tools.cpp Removed: diff --git a/flang/include/flang/Evaluate/tools.h b/flang/include/flang/Evaluate/tools.h index 69eab61f25b2..3fe3dc1843ec 100644 --- a/flang/include/flang/Evaluate/tools.h +++ b/flang/include/flang/Evaluate/tools.h @@ -336,6 +336,9 @@ template const Symbol *GetFirstSymbol(const A &x) { } } +// GetLastPointerSymbol(A%PTR1%B%PTR2%C) -> PTR2 +const Symbol *GetLastPointerSymbol(const evaluate::DataRef &); + // Creation of conversion expressions can be done to either a known // specific intrinsic type with ConvertToType(x) or by converting // one arbitrary expression to the type of another with ConvertTo(to, from). diff --git a/flang/lib/Evaluate/tools.cpp b/flang/lib/Evaluate/tools.cpp index b1c01d4f4711..2b04ed8a6550 100644 --- a/flang/lib/Evaluate/tools.cpp +++ b/flang/lib/Evaluate/tools.cpp @@ -896,6 +896,31 @@ std::optional CheckProcCompatibility(bool isCall, return msg; } +// GetLastPointerSymbol() +static const Symbol *GetLastPointerSymbol(const Symbol &symbol) { + return IsPointer(GetAssociationRoot(symbol)) ? &symbol : nullptr; +} +static const Symbol *GetLastPointerSymbol(const SymbolRef &symbol) { + return GetLastPointerSymbol(*symbol); +} +static const Symbol *GetLastPointerSymbol(const Component &x) { + const Symbol &c{x.GetLastSymbol()}; + return IsPointer(c) ? &c : GetLastPointerSymbol(x.base()); +} +static const Symbol *GetLastPointerSymbol(const NamedEntity &x) { + const auto *c{x.UnwrapComponent()}; + return c ? GetLastPointerSymbol(*c) : GetLastPointerSymbol(x.GetLastSymbol()); +} +static const Symbol *GetLastPointerSymbol(const ArrayRef &x) { + return GetLastPointerSymbol(x.base()); +} +static const Symbol *GetLastPointerSymbol(const CoarrayRef &x) { + return nullptr; +} +const Symbol *GetLastPointerSymbol(const DataRef &x) { + return std::visit([](const auto &y) { return GetLastPointerSymbol(y); }, x.u); +} + } // namespace Fortran::evaluate namespace Fortran::semantics { diff --git a/flang/lib/Semantics/check-io.cpp b/flang/lib/Semantics/check-io.cpp index 9095951389f2..de19ed4d6d40 100644 --- a/flang/lib/Semantics/check-io.cpp +++ b/flang/lib/Semantics/check-io.cpp @@ -928,9 +928,12 @@ void IoChecker::CheckForDefinableVariable( const A &var, const std::string &s) const { const Symbol *sym{ GetFirstName(*parser::Unwrap(var)).symbol}; - if (WhyNotModifiable(*sym, context_.FindScope(*context_.location( { -context_.Say(parser::FindSourceLocation(var), -"%s variable '%s' must be definable"_err_en_US, s, sym->name()); + if (auto whyNot{ + WhyNotModifiable(*sym, context_.FindScope(*context_.location()))}) { +auto at{parser::FindSourceLocation(var)}; +context_ +.Say(at, "%s variable '%s' must be definable"_err_en_US, s, sym->name()) +.Attach(at, std::move(*whyNot), sym->name()); } } diff --git a/flang/lib/Semantics/tools.cpp b/flang/lib/Semantics/tools.cpp index 1bc008610bf0..f7d3c20de2a0 100644 --- a/flang/lib/Semantics/tools.cpp +++ b/flang/lib/Semantics/tools.cpp @@ -776,27 +776,62 @@ bool InProtectedContext(const Symbol &symbol, const Scope ¤tScope) { } // C1101 and C1158 -std::optional WhyNotModifiable( -const Symbol &original, const Scope &scope) { - const Symbol &symbol{GetAssociationRoot(original)}; +// Modifiability checks on the leftmost symbol ("base object") +// of a data-ref +std::optional WhyNotModifiableFirst( +const Symbol &symbol, const Scope &scope) { if (symbol.has()) { return "'%s' is construct associated with an expression"_en_US; - } else if (InProtectedContext(symbol, scope)) { -return "'%s' is protected in this scope"_en_US; } else if (IsExternalInPureContext(symbol, scope)) { return "'%s' is externally visible and referenced in a pure" " procedure"_en_US; - } else if (IsOrContainsEventOrLockComponent(symbol)) { + } else if (!I
[llvm-branch-commits] [flang] ff3b51b - [flang] Fix ASSOCIATE statement name resolution
Author: peter klausler Date: 2021-01-20T11:18:27-08:00 New Revision: ff3b51b0549343b6ef7d718e036116d5b502458c URL: https://github.com/llvm/llvm-project/commit/ff3b51b0549343b6ef7d718e036116d5b502458c DIFF: https://github.com/llvm/llvm-project/commit/ff3b51b0549343b6ef7d718e036116d5b502458c.diff LOG: [flang] Fix ASSOCIATE statement name resolution F18 Clause 19.4p9 says: The associate names of an ASSOCIATE construct have the scope of the block. Clause 11.3.1p1 says the ASSOCIATE statement is not itself in the block: R1102 associate-construct is: associate-stmt block end-associate-stmt Associate statement associations are currently fully processed from left to right, incorrectly interposing associating entities earlier in the list on same-named entities in the host scope. 1 program p 2logical :: a = .false. 3real :: b = 9.73 4associate (b => a, a => b) 5 print*, a, b 6end associate 7print*, a, b 8 end Associating names 'a' and 'b' at line 4 in this code are now both aliased to logical host entity 'a' at line 2. This happens because the reference to 'b' in the second association incorrectly resolves 'b' to the entity in line 4 (already associated to 'a' at line 2), rather than the 'b' at line 3. With bridge code to process these associations, f18 output is: F F F 9.73 It should be: 9.73 F F 9.73 To fix this, names in right-hand side selector variables/expressions must all be resolved before any left-hand side entities are resolved. This is done by maintaining a stack of lists of associations, rather than a stack of associations. Each ASSOCIATE statement's list of assocations is then visited once for right-hand side processing, and once for left-hand side processing. Note that other construct associations do not have this problem. SELECT RANK and SELECT TYPE each have a single assocation, not a list. Constraint C1113 prohibits the right-hand side of a CHANGE TEAM association from referencing any left-hand side entity. Differential Revision: https://reviews.llvm.org/D95010 Added: flang/test/Semantics/resolve100.f90 Modified: flang/lib/Semantics/resolve-names.cpp Removed: diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index 5d9ee35b79b3..3bc9a85cbf41 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -1010,9 +1010,9 @@ class ConstructVisitor : public virtual DeclarationVisitor { bool Pre(const parser::BlockStmt &); bool Pre(const parser::EndBlockStmt &); void Post(const parser::Selector &); - bool Pre(const parser::AssociateStmt &); + void Post(const parser::AssociateStmt &); void Post(const parser::EndAssociateStmt &); - void Post(const parser::Association &); + bool Pre(const parser::Association &); void Post(const parser::SelectTypeStmt &); void Post(const parser::SelectRankStmt &); bool Pre(const parser::SelectTypeConstruct &); @@ -1081,6 +1081,7 @@ class ConstructVisitor : public virtual DeclarationVisitor { Selector selector; }; std::vector associationStack_; + Association *currentAssociation_{nullptr}; template bool CheckDef(const T &t) { return CheckDef(std::get>(t)); @@ -1098,9 +1099,10 @@ class ConstructVisitor : public virtual DeclarationVisitor { void SetAttrsFromAssociation(Symbol &); Selector ResolveSelector(const parser::Selector &); void ResolveIndexName(const parser::ConcurrentControl &control); + void SetCurrentAssociation(std::size_t n); Association &GetCurrentAssociation(); void PushAssociation(); - void PopAssociation(); + void PopAssociation(std::size_t count = 1); }; // Create scopes for OpenACC constructs @@ -5153,29 +5155,33 @@ void ConstructVisitor::Post(const parser::Selector &x) { GetCurrentAssociation().selector = ResolveSelector(x); } -bool ConstructVisitor::Pre(const parser::AssociateStmt &x) { +void ConstructVisitor::Post(const parser::AssociateStmt &x) { CheckDef(x.t); PushScope(Scope::Kind::Block, nullptr); - PushAssociation(); - return true; + const auto assocCount{std::get>(x.t).size()}; + for (auto nthLastAssoc{assocCount}; nthLastAssoc > 0; --nthLastAssoc) { +SetCurrentAssociation(nthLastAssoc); +if (auto *symbol{MakeAssocEntity()}) { + if (ExtractCoarrayRef(GetCurrentAssociation().selector.expr)) { // C1103 +Say("Selector must not be a coindexed object"_err_en_US); + } + SetTypeFromAssociation(*symbol); + SetAttrsFromAssociation(*symbol); +} + } + PopAssociation(assocCount); } + void ConstructVisitor::Post(const parser::EndAssociateStmt &x) { - PopAssociation(); PopScope(); CheckRef(x.v); } -void ConstructVisitor::Post(const parser::Association &x) { +bool ConstructVisitor::Pre(const parser::Association &x) { + PushAssociation(); const auto &name{st
[llvm-branch-commits] [flang] 0996b59 - [flang] Infrastructure improvements in utility routines
Author: peter klausler Date: 2021-01-20T12:40:25-08:00 New Revision: 0996b590aaafe2de8378fd45a5094c13a4de3360 URL: https://github.com/llvm/llvm-project/commit/0996b590aaafe2de8378fd45a5094c13a4de3360 DIFF: https://github.com/llvm/llvm-project/commit/0996b590aaafe2de8378fd45a5094c13a4de3360.diff LOG: [flang] Infrastructure improvements in utility routines * IsArrayElement() needs another option to control whether it should ignore trailing component references. * Add IsObjectPointer(). * Add const Scope& variants of IsFunction() and IsProcedure(). * Make TypeAndShape::Characterize() work with procedure bindings. * Handle CHARACTER length in MeasureSizeInBytes(). * Fine-tune FindExternallyVisibleObject()'s handling of dummy arguments to conform with Fortran 2018: only INTENT(IN) and dummy pointers in pure functions signify; update two tests accordingly. Also: resolve some stylistic inconsistencies and add a missing "const" in the expression traversal template framework. Differential Revision: https://reviews.llvm.org/D95011 Added: Modified: flang/include/flang/Evaluate/call.h flang/include/flang/Evaluate/tools.h flang/include/flang/Evaluate/traverse.h flang/lib/Evaluate/characteristics.cpp flang/lib/Evaluate/tools.cpp flang/lib/Semantics/tools.cpp flang/test/Semantics/structconst03.f90 flang/test/Semantics/structconst04.f90 Removed: diff --git a/flang/include/flang/Evaluate/call.h b/flang/include/flang/Evaluate/call.h index 0e78839b2ccc..e74e82d86f87 100644 --- a/flang/include/flang/Evaluate/call.h +++ b/flang/include/flang/Evaluate/call.h @@ -111,12 +111,18 @@ class ActualArgument { llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const; std::optional keyword() const { return keyword_; } - void set_keyword(parser::CharBlock x) { keyword_ = x; } + ActualArgument &set_keyword(parser::CharBlock x) { +keyword_ = x; +return *this; + } bool isAlternateReturn() const { return std::holds_alternative(u_); } bool isPassedObject() const { return isPassedObject_; } - void set_isPassedObject(bool yes = true) { isPassedObject_ = yes; } + ActualArgument &set_isPassedObject(bool yes = true) { +isPassedObject_ = yes; +return *this; + } bool Matches(const characteristics::DummyArgument &) const; common::Intent dummyIntent() const { return dummyIntent_; } diff --git a/flang/include/flang/Evaluate/tools.h b/flang/include/flang/Evaluate/tools.h index 3fe3dc1843ec..351dc8715cdd 100644 --- a/flang/include/flang/Evaluate/tools.h +++ b/flang/include/flang/Evaluate/tools.h @@ -235,11 +235,14 @@ std::optional ExtractSubstringBase(const Substring &); // Predicate: is an expression is an array element reference? template -bool IsArrayElement(const Expr &expr, bool intoSubstring = false) { +bool IsArrayElement(const Expr &expr, bool intoSubstring = true, +bool skipComponents = false) { if (auto dataRef{ExtractDataRef(expr, intoSubstring)}) { const DataRef *ref{&*dataRef}; -while (const Component * component{std::get_if(&ref->u)}) { - ref = &component->base(); +if (skipComponents) { + while (const Component * component{std::get_if(&ref->u)}) { +ref = &component->base(); + } } if (const auto *coarrayRef{std::get_if(&ref->u)}) { return !coarrayRef->subscript().empty(); @@ -789,6 +792,7 @@ bool IsProcedure(const Expr &); bool IsFunction(const Expr &); bool IsProcedurePointer(const Expr &); bool IsNullPointer(const Expr &); +bool IsObjectPointer(const Expr &, FoldingContext &); // Extracts the chain of symbols from a designator, which has perhaps been // wrapped in an Expr<>, removing all of the (co)subscripts. The @@ -913,12 +917,13 @@ class Scope; // These functions are used in Evaluate so they are defined here rather than in // Semantics to avoid a link-time dependency on Semantics. // All of these apply GetUltimate() or ResolveAssociations() to their arguments. - bool IsVariableName(const Symbol &); bool IsPureProcedure(const Symbol &); bool IsPureProcedure(const Scope &); bool IsFunction(const Symbol &); +bool IsFunction(const Scope &); bool IsProcedure(const Symbol &); +bool IsProcedure(const Scope &); bool IsProcedurePointer(const Symbol &); bool IsSaved(const Symbol &); // saved implicitly or explicitly bool IsDummy(const Symbol &); diff --git a/flang/include/flang/Evaluate/traverse.h b/flang/include/flang/Evaluate/traverse.h index 9238e58a1fb3..c9455910aa41 100644 --- a/flang/include/flang/Evaluate/traverse.h +++ b/flang/include/flang/Evaluate/traverse.h @@ -50,7 +50,7 @@ template class Traverse { Result operator()(const common::Indirection &x) const { return visitor_(x.value()); } - template Result operator()(SymbolRef x) const { + template Result operator()(const SymbolRef x) const { return visitor_(*x); } template Re
[llvm-branch-commits] [flang] a75840a - [flang] Better C_LOC and C_ASSOCIATED in flang/module
Author: peter klausler Date: 2021-01-21T09:41:05-08:00 New Revision: a75840a09c65582e3ec4eb1654bd17386b71397d URL: https://github.com/llvm/llvm-project/commit/a75840a09c65582e3ec4eb1654bd17386b71397d DIFF: https://github.com/llvm/llvm-project/commit/a75840a09c65582e3ec4eb1654bd17386b71397d.diff LOG: [flang] Better C_LOC and C_ASSOCIATED in flang/module The place-holding implementation of C_LOC just didn't work when used with our more complete semantic checking, specifically in the case of a polymorphic argument; convert it to an external function with an implicit interface. C_ASSOCIATED needs to be a generic interface with specific implementations for C_PTR and C_FUNPTR. Differential Revision: https://reviews.llvm.org/D94714 Added: Modified: flang/module/__fortran_builtins.f90 flang/module/iso_c_binding.f90 Removed: diff --git a/flang/module/__fortran_builtins.f90 b/flang/module/__fortran_builtins.f90 index 167bd80d6ad9..852a7a973fac 100644 --- a/flang/module/__fortran_builtins.f90 +++ b/flang/module/__fortran_builtins.f90 @@ -29,4 +29,6 @@ type :: __builtin_team_type integer(kind=int64) :: __id end type + + procedure(type(__builtin_c_ptr)) :: __builtin_c_loc end module diff --git a/flang/module/iso_c_binding.f90 b/flang/module/iso_c_binding.f90 index eed264f531a4..3668daab46ee 100644 --- a/flang/module/iso_c_binding.f90 +++ b/flang/module/iso_c_binding.f90 @@ -14,7 +14,8 @@ module iso_c_binding c_f_pointer => __builtin_c_f_pointer, & c_ptr => __builtin_c_ptr, & c_funptr => __builtin_c_funptr, & -c_sizeof => sizeof +c_sizeof => sizeof, & +c_loc => __builtin_c_loc type(c_ptr), parameter :: c_null_ptr = c_ptr(0) type(c_funptr), parameter :: c_null_funptr = c_funptr(0) @@ -76,25 +77,42 @@ module iso_c_binding character(kind=c_char, len=1), parameter :: c_horizontal_tab = achar(9) character(kind=c_char, len=1), parameter :: c_vertical_tab = achar(11) + interface c_associated +module procedure c_associated_c_ptr +module procedure c_associated_c_funptr + end interface + private :: c_associated_c_ptr, c_associated_c_funptr + + ! gfortran extensions + integer, parameter :: & +c_float128 = 16, & +c_float128_complex = c_float128 + contains - logical function c_associated(c_ptr_1, c_ptr_2) + logical function c_associated_c_ptr(c_ptr_1, c_ptr_2) type(c_ptr), intent(in) :: c_ptr_1 type(c_ptr), intent(in), optional :: c_ptr_2 if (c_ptr_1%__address == c_null_ptr%__address) then - c_associated = .false. + c_associated_c_ptr = .false. else if (present(c_ptr_2)) then - c_associated = c_ptr_1%__address == c_ptr_2%__address + c_associated_c_ptr = c_ptr_1%__address == c_ptr_2%__address else - c_associated = .true. + c_associated_c_ptr = .true. end if - end function c_associated + end function c_associated_c_ptr - function c_loc(x) -type(c_ptr) :: c_loc -type(*), dimension(..), intent(in) :: x -c_loc = c_ptr(loc(x)) - end function c_loc + logical function c_associated_c_funptr(c_funptr_1, c_funptr_2) +type(c_funptr), intent(in) :: c_funptr_1 +type(c_funptr), intent(in), optional :: c_funptr_2 +if (c_funptr_1%__address == c_null_ptr%__address) then + c_associated_c_funptr = .false. +else if (present(c_funptr_2)) then + c_associated_c_funptr = c_funptr_1%__address == c_funptr_2%__address +else + c_associated_c_funptr = .true. +end if + end function c_associated_c_funptr function c_funloc(x) type(c_funptr) :: c_funloc ___ 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] 3738447 - [flang] Address name resolution problems
Author: peter klausler Date: 2021-01-21T16:15:38-08:00 New Revision: 3738447c96c7400d0e9b9b00b583dca45fb0807f URL: https://github.com/llvm/llvm-project/commit/3738447c96c7400d0e9b9b00b583dca45fb0807f DIFF: https://github.com/llvm/llvm-project/commit/3738447c96c7400d0e9b9b00b583dca45fb0807f.diff LOG: [flang] Address name resolution problems Don't emit a bogus error message about a bad forward reference when it's an IMPORT of a USE-associated symbol; don't ignore intrinsic functions when USE-associating the contents of a module when the intrinsic has been explicitly USE'd; allow PUBLIC or PRIVATE accessibility attribute to be specified for an enumerator before the declaration of the enumerator. Differential Revision: https://reviews.llvm.org/D95175 Added: Modified: flang/lib/Semantics/resolve-names.cpp Removed: diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index d76abbf68a08..2b7ee045bc8f 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -2238,6 +2238,12 @@ std::optional ScopeHandler::HadForwardRef( bool ScopeHandler::CheckPossibleBadForwardRef(const Symbol &symbol) { if (!context().HasError(symbol)) { if (auto fwdRef{HadForwardRef(symbol)}) { + const Symbol *outer{symbol.owner().FindSymbol(symbol.name())}; + if (outer && symbol.has() && + &symbol.GetUltimate() == &outer->GetUltimate()) { +// e.g. IMPORT of host's USE association +return false; + } Say(*fwdRef, "Forward reference to '%s' is not allowed in the same specification part"_err_en_US, *fwdRef) @@ -2332,7 +2338,8 @@ void ModuleVisitor::Post(const parser::UseStmt &x) { } for (const auto &[name, symbol] : *useModuleScope_) { if (symbol->attrs().test(Attr::PUBLIC) && - !symbol->attrs().test(Attr::INTRINSIC) && + (!symbol->attrs().test(Attr::INTRINSIC) || + symbol->has()) && !symbol->has() && useNames.count(name) == 0) { SourceName location{x.moduleName.source}; if (auto *localSymbol{FindInScope(name)}) { @@ -3310,10 +3317,11 @@ bool DeclarationVisitor::Pre(const parser::NamedConstant &x) { bool DeclarationVisitor::Pre(const parser::Enumerator &enumerator) { const parser::Name &name{std::get(enumerator.t).v}; Symbol *symbol{FindSymbol(name)}; - if (symbol) { + if (symbol && !symbol->has()) { // Contrary to named constants appearing in a PARAMETER statement, // enumerator names should not have their type, dimension or any other -// attributes defined before they are declared in the enumerator statement. +// attributes defined before they are declared in the enumerator statement, +// with the exception of accessibility. // This is not explicitly forbidden by the standard, but they are scalars // which type is left for the compiler to chose, so do not let users try to // tamper with that. ___ 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] 0cfadb3 - [flang] Allow NULL() actual argument for pointer dummy
Author: peter klausler Date: 2021-01-21T16:37:35-08:00 New Revision: 0cfadb37f4fef016998cb412270cfe87b0683090 URL: https://github.com/llvm/llvm-project/commit/0cfadb37f4fef016998cb412270cfe87b0683090 DIFF: https://github.com/llvm/llvm-project/commit/0cfadb37f4fef016998cb412270cfe87b0683090.diff LOG: [flang] Allow NULL() actual argument for pointer dummy Fixes a bogus error message about an actual argument not being an object. Differential Revision: https://reviews.llvm.org/D95176 Added: Modified: flang/lib/Semantics/check-call.cpp Removed: diff --git a/flang/lib/Semantics/check-call.cpp b/flang/lib/Semantics/check-call.cpp index ffae3410a852..1bd0b0ab6f08 100644 --- a/flang/lib/Semantics/check-call.cpp +++ b/flang/lib/Semantics/check-call.cpp @@ -139,8 +139,8 @@ static bool DefersSameTypeParameters( static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy, const std::string &dummyName, evaluate::Expr &actual, characteristics::TypeAndShape &actualType, bool isElemental, -bool actualIsArrayElement, evaluate::FoldingContext &context, -const Scope *scope, const evaluate::SpecificIntrinsic *intrinsic) { +evaluate::FoldingContext &context, const Scope *scope, +const evaluate::SpecificIntrinsic *intrinsic) { // Basic type & rank checking parser::ContextualMessages &messages{context.messages()}; @@ -153,7 +153,7 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy, characteristics::TypeAndShape::Attr::AssumedRank)) { } else if (!dummy.type.attrs().test( characteristics::TypeAndShape::Attr::AssumedShape) && -(actualType.Rank() > 0 || actualIsArrayElement)) { +(actualType.Rank() > 0 || IsArrayElement(actual))) { // Sequence association (15.5.2.11) applies -- rank need not match // if the actual argument is an array or array element designator. } else { @@ -271,8 +271,7 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy, ? actualLastSymbol->detailsIf() : nullptr}; int actualRank{evaluate::GetRank(actualType.shape())}; - bool actualIsPointer{(actualLastSymbol && IsPointer(*actualLastSymbol)) || - evaluate::IsNullPointer(actual)}; + bool actualIsPointer{evaluate::IsObjectPointer(actual, context)}; if (dummy.type.attrs().test( characteristics::TypeAndShape::Attr::AssumedShape)) { // 15.5.2.4(16) @@ -293,7 +292,9 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy, "Coindexed scalar actual argument must be associated with a scalar %s"_err_en_US, dummyName); } -if (actualLastSymbol && actualLastSymbol->Rank() == 0 && +if (!IsArrayElement(actual) && +!(actualType.type().category() == TypeCategory::Character && +actualType.type().kind() == 1) && !(dummy.type.type().IsAssumedType() && dummyIsAssumedSize)) { messages.Say( "Whole scalar actual argument may not be associated with a %s array"_err_en_US, @@ -624,15 +625,18 @@ static void CheckExplicitInterfaceArg(evaluate::ActualArgument &arg, arg.set_dummyIntent(object.intent); bool isElemental{object.type.Rank() == 0 && proc.IsElemental()}; CheckExplicitDataArg(object, dummyName, *expr, *type, -isElemental, IsArrayElement(*expr), context, scope, -intrinsic); +isElemental, context, scope, intrinsic); } else if (object.type.type().IsTypelessIntrinsicArgument() && std::holds_alternative( expr->u)) { // ok } else if (object.type.type().IsTypelessIntrinsicArgument() && evaluate::IsNullPointer(*expr)) { -// ok, calling ASSOCIATED(NULL()) +// ok, ASSOCIATED(NULL()) + } else if (object.attrs.test( + characteristics::DummyDataObject::Attr::Pointer) && + evaluate::IsNullPointer(*expr)) { +// ok, FOO(NULL()) } else { messages.Say( "Actual argument '%s' associated with %s is not a variable or typed expression"_err_en_US, ___ 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] 2de5ea3 - [flang] Fix bogus error message with binding
Author: peter klausler Date: 2021-01-21T16:59:51-08:00 New Revision: 2de5ea3b3ed9882026d9dc6c5d8ec462ebe5f8ec URL: https://github.com/llvm/llvm-project/commit/2de5ea3b3ed9882026d9dc6c5d8ec462ebe5f8ec DIFF: https://github.com/llvm/llvm-project/commit/2de5ea3b3ed9882026d9dc6c5d8ec462ebe5f8ec.diff LOG: [flang] Fix bogus error message with binding ProcedureDesignator::GetInterfaceSymbol() needs to return the procedure bound to a bindings. Differential Revision: https://reviews.llvm.org/D95178 Added: flang/test/Semantics/call17.f90 Modified: flang/lib/Evaluate/call.cpp flang/lib/Semantics/check-declarations.cpp flang/test/Semantics/resolve88.f90 Removed: diff --git a/flang/lib/Evaluate/call.cpp b/flang/lib/Evaluate/call.cpp index 3fe56ab4874b..395751acabda 100644 --- a/flang/lib/Evaluate/call.cpp +++ b/flang/lib/Evaluate/call.cpp @@ -117,9 +117,12 @@ int ProcedureDesignator::Rank() const { const Symbol *ProcedureDesignator::GetInterfaceSymbol() const { if (const Symbol * symbol{GetSymbol()}) { -if (const auto *details{ -symbol->detailsIf()}) { - return details->interface().symbol(); +const Symbol &ultimate{symbol->GetUltimate()}; +if (const auto *proc{ultimate.detailsIf()}) { + return proc->interface().symbol(); +} else if (const auto *binding{ + ultimate.detailsIf()}) { + return &binding->symbol(); } } return nullptr; diff --git a/flang/lib/Semantics/check-declarations.cpp b/flang/lib/Semantics/check-declarations.cpp index aca5392e507f..cd35047681e3 100644 --- a/flang/lib/Semantics/check-declarations.cpp +++ b/flang/lib/Semantics/check-declarations.cpp @@ -53,8 +53,7 @@ class CheckHelper { evaluate::CheckSpecificationExpr(x, DEREF(scope_), foldingContext_); } void CheckValue(const Symbol &, const DerivedTypeSpec *); - void CheckVolatile( - const Symbol &, bool isAssociated, const DerivedTypeSpec *); + void CheckVolatile(const Symbol &, const DerivedTypeSpec *); void CheckPointer(const Symbol &); void CheckPassArg( const Symbol &proc, const Symbol *interface, const WithPassArg &); @@ -172,22 +171,18 @@ void CheckHelper::Check(const Symbol &symbol) { context_.set_location(symbol.name()); const DeclTypeSpec *type{symbol.GetType()}; const DerivedTypeSpec *derived{type ? type->AsDerived() : nullptr}; - bool isAssociated{symbol.has() || symbol.has()}; - if (symbol.attrs().test(Attr::VOLATILE)) { -CheckVolatile(symbol, isAssociated, derived); - } - if (isAssociated) { -if (const auto *details{symbol.detailsIf()}) { - CheckHostAssoc(symbol, *details); -} -return; // no other checks on associated symbols - } - if (IsPointer(symbol)) { -CheckPointer(symbol); - } + bool isDone{false}; std::visit( common::visitors{ - [&](const ProcBindingDetails &x) { CheckProcBinding(symbol, x); }, + [&](const UseDetails &x) { isDone = true; }, + [&](const HostAssocDetails &x) { +CheckHostAssoc(symbol, x); +isDone = true; + }, + [&](const ProcBindingDetails &x) { +CheckProcBinding(symbol, x); +isDone = true; + }, [&](const ObjectEntityDetails &x) { CheckObjectEntity(symbol, x); }, [&](const ProcEntityDetails &x) { CheckProcEntity(symbol, x); }, [&](const SubprogramDetails &x) { CheckSubprogram(symbol, x); }, @@ -196,6 +191,15 @@ void CheckHelper::Check(const Symbol &symbol) { [](const auto &) {}, }, symbol.details()); + if (symbol.attrs().test(Attr::VOLATILE)) { +CheckVolatile(symbol, derived); + } + if (isDone) { +return; // following checks do not apply + } + if (IsPointer(symbol)) { +CheckPointer(symbol); + } if (InPure()) { if (IsSaved(symbol)) { messages_.Say( @@ -1279,7 +1283,7 @@ const Procedure *CheckHelper::Characterize(const Symbol &symbol) { return common::GetPtrFromOptional(it->second); } -void CheckHelper::CheckVolatile(const Symbol &symbol, bool isAssociated, +void CheckHelper::CheckVolatile(const Symbol &symbol, const DerivedTypeSpec *derived) { // C866 - C868 if (IsIntentIn(symbol)) { messages_.Say( @@ -1288,7 +1292,7 @@ void CheckHelper::CheckVolatile(const Symbol &symbol, bool isAssociated, if (IsProcedure(symbol)) { messages_.Say("VOLATILE attribute may apply only to a variable"_err_en_US); } - if (isAssociated) { + if (symbol.has() || symbol.has()) { const Symbol &ultimate{symbol.GetUltimate()}; if (IsCoarray(ultimate)) { messages_.Say( diff --git a/flang/test/Semantics/call17.f90 b/flang/test/Semantics/call17.f90 new file mode 100644 index ..1f4d2c4d9186 --- /dev/null +++ b/flang/test/Semantics/call17.f90 @@ -0,0 +1,19 @@ +! RUN: %f18 -fparse-only $s 2>&1 | FileCheck %s + +! Regression
[llvm-branch-commits] [flang] 59bf9a8 - [flang] Remove some needless operations in expr rewriting
Author: peter klausler Date: 2021-01-22T10:08:51-08:00 New Revision: 59bf9a89d825c1f23b249e0ce43d8bf7b486a203 URL: https://github.com/llvm/llvm-project/commit/59bf9a89d825c1f23b249e0ce43d8bf7b486a203 DIFF: https://github.com/llvm/llvm-project/commit/59bf9a89d825c1f23b249e0ce43d8bf7b486a203.diff LOG: [flang] Remove some needless operations in expr rewriting Expressions emitted to module files and error messages sometimes contain conversions of integer results of inquiry intrinsics; these are usually not needed, and can conflict with "int" in the user's namespace. Improve folding so that these conversions don't appear, and do some other clean-up in adjacent code. Differential Revision: https://reviews.llvm.org/D95172 Added: Modified: flang/lib/Evaluate/fold-implementation.h flang/test/Semantics/modfile17.f90 flang/test/Semantics/modfile30.f90 Removed: diff --git a/flang/lib/Evaluate/fold-implementation.h b/flang/lib/Evaluate/fold-implementation.h index 7232715600fd..37116bb6bca4 100644 --- a/flang/lib/Evaluate/fold-implementation.h +++ b/flang/lib/Evaluate/fold-implementation.h @@ -1105,12 +1105,13 @@ Expr FoldOperation( // This variable is a workaround for msvc which emits an error when // using the FROMCAT template parameter below. TypeCategory constexpr FromCat{FROMCAT}; +static_assert(FromCat == Operand::category); auto &convert{msvcWorkaround.convert}; char buffer[64]; if (auto value{GetScalarConstantValue(kindExpr)}) { FoldingContext &ctx{msvcWorkaround.context}; if constexpr (TO::category == TypeCategory::Integer) { -if constexpr (Operand::category == TypeCategory::Integer) { +if constexpr (FromCat == TypeCategory::Integer) { auto converted{Scalar::ConvertSigned(*value)}; if (converted.overflow) { ctx.messages().Say( @@ -1118,7 +1119,7 @@ Expr FoldOperation( Operand::kind, TO::kind); } return ScalarConstantToExpr(std::move(converted.value)); -} else if constexpr (Operand::category == TypeCategory::Real) { +} else if constexpr (FromCat == TypeCategory::Real) { auto converted{value->template ToInteger>()}; if (converted.flags.test(RealFlag::InvalidArgument)) { ctx.messages().Say( @@ -1132,7 +1133,7 @@ Expr FoldOperation( return ScalarConstantToExpr(std::move(converted.value)); } } else if constexpr (TO::category == TypeCategory::Real) { -if constexpr (Operand::category == TypeCategory::Integer) { +if constexpr (FromCat == TypeCategory::Integer) { auto converted{Scalar::FromInteger(*value)}; if (!converted.flags.empty()) { std::snprintf(buffer, sizeof buffer, @@ -1141,7 +1142,7 @@ Expr FoldOperation( RealFlagWarnings(ctx, converted.flags, buffer); } return ScalarConstantToExpr(std::move(converted.value)); -} else if constexpr (Operand::category == TypeCategory::Real) { +} else if constexpr (FromCat == TypeCategory::Real) { auto converted{Scalar::Convert(*value)}; if (!converted.flags.empty()) { std::snprintf(buffer, sizeof buffer, @@ -1154,7 +1155,7 @@ Expr FoldOperation( return ScalarConstantToExpr(std::move(converted.value)); } } else if constexpr (TO::category == TypeCategory::Complex) { -if constexpr (Operand::category == TypeCategory::Complex) { +if constexpr (FromCat == TypeCategory::Complex) { return FoldOperation(ctx, ComplexConstructor{ AsExpr(Convert{AsCategoryExpr( @@ -1163,17 +1164,31 @@ Expr FoldOperation( Constant{value->AIMAG()})})}); } } else if constexpr (TO::category == TypeCategory::Character && - Operand::category == TypeCategory::Character) { + FromCat == TypeCategory::Character) { if (auto converted{ConvertString>(std::move(*value))}) { return ScalarConstantToExpr(std::move(*converted)); } } else if constexpr (TO::category == TypeCategory::Logical && - Operand::category == TypeCategory::Logical) { + FromCat == TypeCategory::Logical) { return Expr{value->IsTrue()}; } -} else if constexpr (std::is_same_v && +} else if constexpr (TO::category == FromCat && FromCat != TypeCategory::Character) { - return std::move(kindExpr); // remove needless conversion + // Conversion of non-constant in same type category + if constexpr (st
[llvm-branch-commits] [flang] 07f1e1f - [flang] Correct shape analysis for transformational intrinsic functions
Author: peter klausler Date: 2021-01-22T10:48:58-08:00 New Revision: 07f1e1f44c87d1ee84caf13d6e5aa64eb7e1b068 URL: https://github.com/llvm/llvm-project/commit/07f1e1f44c87d1ee84caf13d6e5aa64eb7e1b068 DIFF: https://github.com/llvm/llvm-project/commit/07f1e1f44c87d1ee84caf13d6e5aa64eb7e1b068.diff LOG: [flang] Correct shape analysis for transformational intrinsic functions Correct the analysis of references to transformational intrinsic functions that have different semantics based on the presence or absence of a DIM= argument; add shape analysis for UNPACK(). Differential Revision: https://reviews.llvm.org/D94716 Added: Modified: flang/lib/Evaluate/intrinsics.cpp flang/lib/Evaluate/shape.cpp Removed: diff --git a/flang/lib/Evaluate/intrinsics.cpp b/flang/lib/Evaluate/intrinsics.cpp index 3de43fd88d7e..98fbe92e2815 100644 --- a/flang/lib/Evaluate/intrinsics.cpp +++ b/flang/lib/Evaluate/intrinsics.cpp @@ -181,12 +181,13 @@ ENUM_CLASS(Rank, conformable, // scalar, or array of same rank & shape as "array" argument reduceOperation, // a pure function with constraints for REDUCE dimReduced, // scalar if no DIM= argument, else rank(array)-1 -dimRemoved, // scalar, or rank(array)-1 +dimRemovedOrScalar, // rank(array)-1 (less DIM) or scalar +locReduced, // vector(1:rank) if no DIM= argument, else rank(array)-1 rankPlus1, // rank(known)+1 shaped, // rank is length of SHAPE vector ) -ENUM_CLASS(Optionality, required, optional, +ENUM_CLASS(Optionality, required, optional, missing, defaultsToSameKind, // for MatchingDefaultKIND defaultsToDefaultForResult, // for DefaultingKIND defaultsToSizeKind, // for SizeDefaultKIND @@ -227,6 +228,9 @@ static constexpr IntrinsicDummyArgument RequiredDIM{"dim", static constexpr IntrinsicDummyArgument OptionalDIM{"dim", {IntType, KindCode::dimArg}, Rank::scalar, Optionality::optional, common::Intent::In}; +static constexpr IntrinsicDummyArgument MissingDIM{"dim", +{IntType, KindCode::dimArg}, Rank::scalar, Optionality::missing, +common::Intent::In}; static constexpr IntrinsicDummyArgument OptionalMASK{"mask", AnyLogical, Rank::conformable, Optionality::optional, common::Intent::In}; @@ -346,8 +350,8 @@ static const IntrinsicInterface genericIntrinsicFunction[]{ {"count", {{"mask", AnyLogical, Rank::array}, OptionalDIM, DefaultingKIND}, KINDInt, Rank::dimReduced, IntrinsicClass::transformationalFunction}, {"cshift", -{{"array", SameType, Rank::array}, {"shift", AnyInt, Rank::dimRemoved}, -OptionalDIM}, +{{"array", SameType, Rank::array}, +{"shift", AnyInt, Rank::dimRemovedOrScalar}, OptionalDIM}, SameType, Rank::conformable, IntrinsicClass::transformationalFunction}, {"dble", {{"a", AnyNumeric, Rank::elementalOrBOZ}}, DoublePrecision}, {"digits", {{"x", AnyIntOrReal, Rank::anyOrAssumedRank}}, DefaultInt, @@ -380,16 +384,16 @@ static const IntrinsicInterface genericIntrinsicFunction[]{ {"dshiftr", {{"i", BOZ}, {"j", SameInt}, {"shift", AnyInt}}, SameInt}, {"eoshift", {{"array", SameIntrinsic, Rank::array}, -{"shift", AnyInt, Rank::dimRemoved}, -{"boundary", SameIntrinsic, Rank::dimRemoved, +{"shift", AnyInt, Rank::dimRemovedOrScalar}, +{"boundary", SameIntrinsic, Rank::dimReduced, Optionality::optional}, OptionalDIM}, SameIntrinsic, Rank::conformable, IntrinsicClass::transformationalFunction}, {"eoshift", {{"array", SameDerivedType, Rank::array}, -{"shift", AnyInt, Rank::dimRemoved}, -{"boundary", SameDerivedType, Rank::dimRemoved}, OptionalDIM}, +{"shift", AnyInt, Rank::dimReduced}, +{"boundary", SameDerivedType, Rank::dimReduced}, OptionalDIM}, SameDerivedType, Rank::conformable, IntrinsicClass::transformationalFunction}, {"epsilon", {{"x", SameReal, Rank::anyOrAssumedRank}}, SameReal, @@ -410,20 +414,21 @@ static const IntrinsicInterface genericIntrinsicFunction[]{ {"value", AnyNumeric, Rank::scalar}, RequiredDIM, OptionalMASK, SizeDefaultKIND, {"back", AnyLogical, Rank::scalar, Optionality::optional}}, -KINDInt, Rank::dimRemoved, IntrinsicClass::transformationalFunction}, +KINDInt, Rank::locReduced, IntrinsicClass::transformationalFunction}, {"findloc", {{"array", AnyNumeric, Rank::array}, -{"value", AnyNumeric, Rank::scalar}, OptionalMASK, SizeDefaultKIND, +{"value", AnyNumeric, Rank::scalar}, MissingDIM, OptionalMASK, +SizeDefaultKIND, {"back", AnyLogical, Rank::scalar, Optionality::optional}}, KINDInt, Rank::vector, IntrinsicClass::transformationalFunction}, {"findloc", {{"a
[llvm-branch-commits] [flang] f187d64 - [flang][nfc] Fix comments, remove needless API, tweak script
Author: peter klausler Date: 2021-01-22T10:55:53-08:00 New Revision: f187d64c80acd84f3f60799b80eba2485f8866df URL: https://github.com/llvm/llvm-project/commit/f187d64c80acd84f3f60799b80eba2485f8866df DIFF: https://github.com/llvm/llvm-project/commit/f187d64c80acd84f3f60799b80eba2485f8866df.diff LOG: [flang][nfc] Fix comments, remove needless API, tweak script * Remove an unimplemented and unused member function declaration * Remove a misleading comment about an unrelated constraint number * Fix a comment * Add f18 crash message to "flang" driver script Differential Revision: https://reviews.llvm.org/D95180 Added: Modified: flang/include/flang/Parser/provenance.h flang/include/flang/Semantics/symbol.h flang/lib/Semantics/assignment.cpp flang/tools/f18/flang Removed: diff --git a/flang/include/flang/Parser/provenance.h b/flang/include/flang/Parser/provenance.h index 1f0a0a90e7019..73661d954854a 100644 --- a/flang/include/flang/Parser/provenance.h +++ b/flang/include/flang/Parser/provenance.h @@ -173,7 +173,6 @@ class AllSources { std::string GetPath(Provenance) const; // __FILE__ int GetLineNumber(Provenance) const; // __LINE__ Provenance CompilerInsertionProvenance(char ch); - Provenance CompilerInsertionProvenance(const char *, std::size_t); ProvenanceRange IntersectionWithSourceFiles(ProvenanceRange) const; llvm::raw_ostream &Dump(llvm::raw_ostream &) const; diff --git a/flang/include/flang/Semantics/symbol.h b/flang/include/flang/Semantics/symbol.h index dc7196cfd5eab..f04b05afd6e4b 100644 --- a/flang/include/flang/Semantics/symbol.h +++ b/flang/include/flang/Semantics/symbol.h @@ -356,7 +356,7 @@ class TypeParamDetails { }; // Record the USE of a symbol: location is where (USE statement or renaming); -// symbol is the USEd module. +// symbol is in the USEd module. class UseDetails { public: UseDetails(const SourceName &location, const Symbol &symbol) diff --git a/flang/lib/Semantics/assignment.cpp b/flang/lib/Semantics/assignment.cpp index 090aae0af8cb7..1fae92c61f3cb 100644 --- a/flang/lib/Semantics/assignment.cpp +++ b/flang/lib/Semantics/assignment.cpp @@ -70,7 +70,7 @@ void AssignmentContext::Analyze(const parser::AssignmentStmt &stmt) { const Scope &scope{context_.FindScope(lhsLoc)}; if (auto whyNot{WhyNotModifiable(lhsLoc, lhs, scope, true)}) { if (auto *msg{Say(lhsLoc, -"Left-hand side of assignment is not modifiable"_err_en_US)}) { // C1158 +"Left-hand side of assignment is not modifiable"_err_en_US)}) { msg->Attach(*whyNot); } } diff --git a/flang/tools/f18/flang b/flang/tools/f18/flang index 01bdffdd20c72..7109cd7f547a9 100644 --- a/flang/tools/f18/flang +++ b/flang/tools/f18/flang @@ -12,4 +12,9 @@ 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 "$@" +opts="-module-suffix .f18.mod -intrinsic-module-directory $module_dir" +if ! $wd/bin/f18 $opts "$@" +then status=$? + echo flang: in $PWD, f18 failed with exit status $status: $wd/bin/f18 $opts "$@" >&2 + exit $status +fi ___ 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] b1afbce - [flang] Minor fix to list-directed REAL output editing
Author: peter klausler Date: 2020-12-15T13:04:44-08:00 New Revision: b1afbceb9296a9ce14a0bd38f36e93b8c77fa18a URL: https://github.com/llvm/llvm-project/commit/b1afbceb9296a9ce14a0bd38f36e93b8c77fa18a DIFF: https://github.com/llvm/llvm-project/commit/b1afbceb9296a9ce14a0bd38f36e93b8c77fa18a.diff LOG: [flang] Minor fix to list-directed REAL output editing Always emit the letter 'E' in list-directed REAL output; the library was omitting it for exponents greater than 99, as should be done for E and D formatting of large exponents without an Ed exponent digit count. Differential Revision: https://reviews.llvm.org/D93319 Added: Modified: flang/runtime/edit-output.cpp Removed: diff --git a/flang/runtime/edit-output.cpp b/flang/runtime/edit-output.cpp index 31ba9f152d74..76f24cb07437 100644 --- a/flang/runtime/edit-output.cpp +++ b/flang/runtime/edit-output.cpp @@ -116,7 +116,7 @@ const char *RealOutputEditingBase::FormatExponent( } } *--exponent = expo < 0 ? '-' : '+'; - if (edit.expoDigits || exponent + 3 == eEnd) { + if (edit.expoDigits || edit.IsListDirected() || exponent + 3 == eEnd) { *--exponent = edit.descriptor == 'D' ? 'D' : 'E'; // not 'G' } length = eEnd - exponent; ___ 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] 9a883bf - [flang] Clean up TODO comments and fix one (DATA constant ambiguity)
Author: peter klausler Date: 2020-12-15T13:36:07-08:00 New Revision: 9a883bfa11dd77cf2d45a25c5efc364e256e6d9a URL: https://github.com/llvm/llvm-project/commit/9a883bfa11dd77cf2d45a25c5efc364e256e6d9a DIFF: https://github.com/llvm/llvm-project/commit/9a883bfa11dd77cf2d45a25c5efc364e256e6d9a.diff LOG: [flang] Clean up TODO comments and fix one (DATA constant ambiguity) Remove resolved & moot TODO comments in Common/, Parser/, and Evaluate/. Address a pending one relating to parsing ambiguity in DATA statement constants, handling it with symbol table information in Semantics and adding a test. Differential Revision: https://reviews.llvm.org/D93323 Added: flang/test/Semantics/data10.f90 Modified: flang/include/flang/Evaluate/real.h flang/include/flang/Parser/dump-parse-tree.h flang/include/flang/Parser/parse-state.h flang/include/flang/Parser/parse-tree.h flang/lib/Evaluate/check-expression.cpp flang/lib/Evaluate/type.cpp flang/lib/Parser/Fortran-parsers.cpp flang/lib/Parser/program-parsers.cpp flang/lib/Semantics/data-to-inits.cpp flang/lib/Semantics/rewrite-parse-tree.cpp flang/test/Semantics/data01.f90 flang/test/Semantics/data06.f90 Removed: diff --git a/flang/include/flang/Evaluate/real.h b/flang/include/flang/Evaluate/real.h index 8ceb4639aa93..5864bdd7bd3a 100644 --- a/flang/include/flang/Evaluate/real.h +++ b/flang/include/flang/Evaluate/real.h @@ -63,10 +63,6 @@ class Real : public common::RealDetails { return word_ == that.word_; } - // TODO: DIM, MAX, MIN, DPROD, FRACTION, - // INT/NINT, NEAREST, OUT_OF_RANGE, - // RRSPACING/SPACING, SCALE, SET_EXPONENT - constexpr bool IsSignBitSet() const { return word_.BTEST(bits - 1); } constexpr bool IsNegative() const { return !IsNotANumber() && IsSignBitSet(); @@ -118,7 +114,7 @@ class Real : public common::RealDetails { const Real &, Rounding rounding = defaultRounding) const; // SQRT(x**2 + y**2) but computed so as to avoid spurious overflow - // TODO: needed for CABS + // TODO: not yet implemented; needed for CABS ValueWithRealFlags HYPOT( const Real &, Rounding rounding = defaultRounding) const; diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h index 0d819f861495..8a7d1d1302b2 100644 --- a/flang/include/flang/Parser/dump-parse-tree.h +++ b/flang/include/flang/Parser/dump-parse-tree.h @@ -200,7 +200,6 @@ class ParseTreeDumper { NODE_ENUM(ConnectSpec::CharExpr, Kind) NODE(ConnectSpec, Newunit) NODE(ConnectSpec, Recl) - NODE(parser, ConstantValue) NODE(parser, ContainsStmt) NODE(parser, Contiguous) NODE(parser, ContiguousStmt) diff --git a/flang/include/flang/Parser/parse-state.h b/flang/include/flang/Parser/parse-state.h index 00291bac4dbb..76cbb3470dc0 100644 --- a/flang/include/flang/Parser/parse-state.h +++ b/flang/include/flang/Parser/parse-state.h @@ -34,7 +34,6 @@ using common::LanguageFeature; class ParseState { public: - // TODO: Add a constructor for parsing a normalized module file. ParseState(const CookedSource &cooked) : p_{cooked.AsCharBlock().begin()}, limit_{cooked.AsCharBlock().end()} {} ParseState(const ParseState &that) diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h index 27998c308cc0..a2beac4737f6 100644 --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -426,8 +426,9 @@ struct DeclarationConstruct { // R504 specification-part -> [use-stmt]... [import-stmt]... [implicit-part] //[declaration-construct]... -// TODO: transfer any statements after the last IMPLICIT (if any) -// from the implicit part to the declaration constructs +// PARAMETER, FORMAT, and ENTRY statements that appear before any other +// kind of declaration-construct will be parsed into the implicit-part, +// even if there are no IMPLICIT statements. struct SpecificationPart { TUPLE_CLASS_BOILERPLATE(SpecificationPart); std::tuple, @@ -861,13 +862,6 @@ struct LiteralConstant { u; }; -// R604 constant -> literal-constant | named-constant -// Renamed to dodge a clash with Constant<> template class. -struct ConstantValue { - UNION_CLASS_BOILERPLATE(ConstantValue); - std::variant u; -}; - // R807 access-spec -> PUBLIC | PRIVATE struct AccessSpec { ENUM_CLASS(Kind, Public, Private) @@ -1412,14 +1406,15 @@ using TypedExpr = common::ForwardOwningPointer; //signed-int-literal-constant | signed-real-literal-constant | //null-init | initial-data-target | //structure-constructor +// N.B. Parsing ambiguities abound here without recourse to symbols +// (see comments on R845's parser). struct DataStmtConstant { UNION_CLASS_BOILERPLATE(DataStmtConstant); CharBlock source; mutable TypedExpr typedExpr; - s
[llvm-branch-commits] [flang] d6a74ec - [flang] Fix false error message for "ptr => func()" array conformance
Author: peter klausler Date: 2020-12-15T16:26:18-08:00 New Revision: d6a74ec826adac16f715c5700fc102c62d1a8bf0 URL: https://github.com/llvm/llvm-project/commit/d6a74ec826adac16f715c5700fc102c62d1a8bf0 DIFF: https://github.com/llvm/llvm-project/commit/d6a74ec826adac16f715c5700fc102c62d1a8bf0.diff LOG: [flang] Fix false error message for "ptr => func()" array conformance Pointers must have deferred shapes, so CheckConformance must be extended to allow for them. Differential Revision: https://reviews.llvm.org/D93320 Added: Modified: flang/include/flang/Evaluate/characteristics.h flang/include/flang/Evaluate/shape.h flang/lib/Evaluate/characteristics.cpp flang/lib/Evaluate/shape.cpp flang/lib/Semantics/pointer-assignment.cpp flang/test/Semantics/null01.f90 Removed: diff --git a/flang/include/flang/Evaluate/characteristics.h b/flang/include/flang/Evaluate/characteristics.h index bd0e1bf8186e..5d140a642c86 100644 --- a/flang/include/flang/Evaluate/characteristics.h +++ b/flang/include/flang/Evaluate/characteristics.h @@ -145,8 +145,9 @@ class TypeAndShape { int Rank() const { return GetRank(shape_); } bool IsCompatibleWith(parser::ContextualMessages &, const TypeAndShape &that, - const char *thisIs = "POINTER", const char *thatIs = "TARGET", - bool isElemental = false) const; + const char *thisIs = "pointer", const char *thatIs = "target", + bool isElemental = false, bool thisIsDeferredShape = false, + bool thatIsDeferredShape = false) const; std::optional> MeasureSizeInBytes( FoldingContext * = nullptr) const; diff --git a/flang/include/flang/Evaluate/shape.h b/flang/include/flang/Evaluate/shape.h index dc76afe57b40..da0b958a3beb 100644 --- a/flang/include/flang/Evaluate/shape.h +++ b/flang/include/flang/Evaluate/shape.h @@ -211,7 +211,8 @@ std::optional GetConstantExtents( bool CheckConformance(parser::ContextualMessages &, const Shape &left, const Shape &right, const char *leftIs = "left operand", const char *rightIs = "right operand", bool leftScalarExpandable = true, -bool rightScalarExpandable = true); +bool rightScalarExpandable = true, bool leftIsDeferredShape = false, +bool rightIsDeferredShape = false); // Increments one-based subscripts in element order (first varies fastest) // and returns true when they remain in range; resets them all to one and diff --git a/flang/lib/Evaluate/characteristics.cpp b/flang/lib/Evaluate/characteristics.cpp index f88e518b4891..7b7e62ee179e 100644 --- a/flang/lib/Evaluate/characteristics.cpp +++ b/flang/lib/Evaluate/characteristics.cpp @@ -150,7 +150,8 @@ std::optional TypeAndShape::Characterize( bool TypeAndShape::IsCompatibleWith(parser::ContextualMessages &messages, const TypeAndShape &that, const char *thisIs, const char *thatIs, -bool isElemental) const { +bool isElemental, bool thisIsDeferredShape, +bool thatIsDeferredShape) const { if (!type_.IsTkCompatibleWith(that.type_)) { const auto &len{that.LEN()}; messages.Say( @@ -161,7 +162,8 @@ bool TypeAndShape::IsCompatibleWith(parser::ContextualMessages &messages, } return isElemental || CheckConformance(messages, shape_, that.shape_, thisIs, thatIs, false, - false /* no scalar expansion */); + false /* no scalar expansion */, thisIsDeferredShape, + thatIsDeferredShape); } std::optional> TypeAndShape::MeasureSizeInBytes( diff --git a/flang/lib/Evaluate/shape.cpp b/flang/lib/Evaluate/shape.cpp index 37373ae95692..b740c81e0796 100644 --- a/flang/lib/Evaluate/shape.cpp +++ b/flang/lib/Evaluate/shape.cpp @@ -683,7 +683,8 @@ auto GetShapeHelper::operator()(const ProcedureRef &call) const -> Result { // that they conform bool CheckConformance(parser::ContextualMessages &messages, const Shape &left, const Shape &right, const char *leftIs, const char *rightIs, -bool leftScalarExpandable, bool rightScalarExpandable) { +bool leftScalarExpandable, bool rightScalarExpandable, +bool leftIsDeferredShape, bool rightIsDeferredShape) { int n{GetRank(left)}; if (n == 0 && leftScalarExpandable) { return true; @@ -698,15 +699,18 @@ bool CheckConformance(parser::ContextualMessages &messages, const Shape &left, return false; } for (int j{0}; j < n; ++j) { -auto leftDim{ToInt64(left[j])}; -auto rightDim{ToInt64(right[j])}; -if (!leftDim || !rightDim) { - return false; -} -if (*leftDim != *rightDim) { - messages.Say("Dimension %1$d of %2$s has extent %3$jd, " - "but %4$s has extent %5$jd"_err_en_US, - j + 1, leftIs, *leftDim, rightIs, *rightDim); +if (auto leftDim{ToInt64(left[j])}) { + if (auto rightDim{ToInt64(right[j])}) { +if (*leftDim != *rightDim) { + messages.Say("Dimension %1$d of %2$s has extent %3$jd, " +
[llvm-branch-commits] [flang] 6aa3591 - [flang] Implement STORAGE_SIZE(), SIZEOF(), C_SIZEOF()
Author: peter klausler Date: 2020-12-15T17:26:20-08:00 New Revision: 6aa3591e98402418e110c506cdd488ed1e3021b6 URL: https://github.com/llvm/llvm-project/commit/6aa3591e98402418e110c506cdd488ed1e3021b6 DIFF: https://github.com/llvm/llvm-project/commit/6aa3591e98402418e110c506cdd488ed1e3021b6.diff LOG: [flang] Implement STORAGE_SIZE(), SIZEOF(), C_SIZEOF() STORAGE_SIZE() is a standard inquiry intrinsic (size in bits of an array element of the same type as the argument); SIZEOF() is a common extension that returns the size in bytes of its argument; C_SIZEOF() is a renaming of SIZEOF() in module ISO_C_BINDING. STORAGE_SIZE() and SIZEOF() are implemented via rewrites to expressions; these expressions will be constant when the necessary type parameters and bounds are also constant. Code to calculate the sizes of types (with and without alignment) was isolated into Evaluate/type.* and /characteristics.*. Code in Semantics/compute-offsets.* to calculate sizes and alignments of derived types' scopes was exposed so that it can be called at type instantiation time (earlier than before) so that these inquiry intrinsics could be called from specification expressions. Differential Revision: https://reviews.llvm.org/D93322 Added: flang/test/Evaluate/folding17.f90 Modified: flang/docs/Extensions.md flang/include/flang/Evaluate/characteristics.h flang/include/flang/Evaluate/common.h flang/include/flang/Evaluate/initial-image.h flang/include/flang/Evaluate/type.h flang/lib/Evaluate/characteristics.cpp flang/lib/Evaluate/fold-designator.cpp flang/lib/Evaluate/fold-integer.cpp flang/lib/Evaluate/initial-image.cpp flang/lib/Evaluate/intrinsics.cpp flang/lib/Evaluate/shape.cpp flang/lib/Evaluate/type.cpp flang/lib/Semantics/compute-offsets.cpp flang/lib/Semantics/compute-offsets.h flang/lib/Semantics/data-to-inits.cpp flang/lib/Semantics/semantics.cpp flang/lib/Semantics/type.cpp flang/module/__fortran_builtins.f90 flang/module/iso_c_binding.f90 flang/test/Semantics/resolve92.f90 flang/test/Semantics/typeinfo01.f90 Removed: diff --git a/flang/docs/Extensions.md b/flang/docs/Extensions.md index d0b24969b41b..ea90db1aa77c 100644 --- a/flang/docs/Extensions.md +++ b/flang/docs/Extensions.md @@ -129,7 +129,7 @@ accepted if enabled by command-line options. * A `RETURN` statement may appear in a main program. * DATA statement initialization is allowed for procedure pointers outside structure constructors. -* Nonstandard intrinsic functions: ISNAN +* Nonstandard intrinsic functions: ISNAN, SIZEOF ### Extensions supported when enabled by options @@ -144,10 +144,11 @@ accepted if enabled by command-line options. rule imposes an artificially small constraint in some cases where Fortran mandates that something have the default `INTEGER` type: specifically, the results of references to the intrinsic functions - `SIZE`, `LBOUND`, `UBOUND`, `SHAPE`, and the location reductions + `SIZE`, `STORAGE_SIZE`,`LBOUND`, `UBOUND`, `SHAPE`, and the location reductions `FINDLOC`, `MAXLOC`, and `MINLOC` in the absence of an explicit `KIND=` actual argument. We return `INTEGER(KIND=8)` by default in these cases when the `-flarge-sizes` option is enabled. + `SIZEOF` and `C_SIZEOF` always return `INTEGER(KIND=8)`. * Treat each specification-part like is has `IMPLICIT NONE` [-fimplicit-none-type-always] * Ignore occurrences of `IMPLICIT NONE` and `IMPLICIT NONE(TYPE)` diff --git a/flang/include/flang/Evaluate/characteristics.h b/flang/include/flang/Evaluate/characteristics.h index 5d140a642c86..c7ef66e800a9 100644 --- a/flang/include/flang/Evaluate/characteristics.h +++ b/flang/include/flang/Evaluate/characteristics.h @@ -149,7 +149,7 @@ class TypeAndShape { bool isElemental = false, bool thisIsDeferredShape = false, bool thatIsDeferredShape = false) const; std::optional> MeasureSizeInBytes( - FoldingContext * = nullptr) const; + FoldingContext &) const; llvm::raw_ostream &Dump(llvm::raw_ostream &) const; diff --git a/flang/include/flang/Evaluate/common.h b/flang/include/flang/Evaluate/common.h index 5328f007bf40..284014fb5fb9 100644 --- a/flang/include/flang/Evaluate/common.h +++ b/flang/include/flang/Evaluate/common.h @@ -235,6 +235,7 @@ class FoldingContext { Rounding rounding() const { return rounding_; } bool flushSubnormalsToZero() const { return flushSubnormalsToZero_; } bool bigEndian() const { return bigEndian_; } + std::size_t maxAlignment() const { return maxAlignment_; } const semantics::DerivedTypeSpec *pdtInstance() const { return pdtInstance_; } const IntrinsicProcTable &intrinsics() const { return intrinsics_; } @@ -257,7 +258,8 @@ class FoldingContext { const IntrinsicProcTable &intrinsics_; Rounding rounding_{defaultRounding}; bool flushSubnormalsTo
[llvm-branch-commits] [flang] 0775131 - [flang] Fix crash in folding (#48437)
Author: peter klausler Date: 2020-12-16T07:55:44-08:00 New Revision: 07751310580fa5b7b94b6efa85d7964af0f699a6 URL: https://github.com/llvm/llvm-project/commit/07751310580fa5b7b94b6efa85d7964af0f699a6 DIFF: https://github.com/llvm/llvm-project/commit/07751310580fa5b7b94b6efa85d7964af0f699a6.diff LOG: [flang] Fix crash in folding (#48437) Elemental intrinsic function folding was not taking the lower bounds of constant array arguments into account; these lower bounds can be distinct from 1 when named constants appear as arguments. LLVM bugzilla #48437. Differential Revision: https://reviews.llvm.org/D93321 Added: flang/test/Evaluate/folding16.f90 Modified: flang/include/flang/Evaluate/constant.h flang/lib/Evaluate/fold-implementation.h Removed: diff --git a/flang/include/flang/Evaluate/constant.h b/flang/include/flang/Evaluate/constant.h index a9f6e87c9db0..89a5867722f7 100644 --- a/flang/include/flang/Evaluate/constant.h +++ b/flang/include/flang/Evaluate/constant.h @@ -140,7 +140,8 @@ template class Constant : public ConstantBase { } } - // Apply subscripts. + // Apply subscripts. An empty subscript list is allowed for + // a scalar constant. Element At(const ConstantSubscripts &) const; Constant Reshape(ConstantSubscripts &&) const; @@ -177,7 +178,7 @@ class Constant> : public ConstantBounds { } } - // Apply subscripts + // Apply subscripts, if any. Scalar At(const ConstantSubscripts &) const; Constant Reshape(ConstantSubscripts &&) const; diff --git a/flang/lib/Evaluate/fold-implementation.h b/flang/lib/Evaluate/fold-implementation.h index 4fa5f6a4c883..7232715600fd 100644 --- a/flang/lib/Evaluate/fold-implementation.h +++ b/flang/lib/Evaluate/fold-implementation.h @@ -443,9 +443,8 @@ Expr FoldElementalIntrinsicHelper(FoldingContext &context, // Compute the shape of the result based on shapes of arguments ConstantSubscripts shape; int rank{0}; -const ConstantSubscripts *shapes[sizeof...(TA)]{ -&std::get(*args)->shape()...}; -const int ranks[sizeof...(TA)]{std::get(*args)->Rank()...}; +const ConstantSubscripts *shapes[]{&std::get(*args)->shape()...}; +const int ranks[]{std::get(*args)->Rank()...}; for (unsigned int i{0}; i < sizeof...(TA); ++i) { if (ranks[i] > 0) { if (rank == 0) { @@ -470,20 +469,19 @@ Expr FoldElementalIntrinsicHelper(FoldingContext &context, std::vector> results; if (TotalElementCount(shape) > 0) { ConstantBounds bounds{shape}; - ConstantSubscripts index(rank, 1); + ConstantSubscripts resultIndex(rank, 1); + ConstantSubscripts argIndex[]{std::get(*args)->lbounds()...}; do { if constexpr (std::is_same_v, ScalarFuncWithContext>) { - results.emplace_back(func(context, - (ranks[I] ? std::get(*args)->At(index) -: std::get(*args)->GetScalarValue().value())...)); + results.emplace_back( + func(context, std::get(*args)->At(argIndex[I])...)); } else if constexpr (std::is_same_v, ScalarFunc>) { - results.emplace_back(func( - (ranks[I] ? std::get(*args)->At(index) -: std::get(*args)->GetScalarValue().value())...)); + results.emplace_back(func(std::get(*args)->At(argIndex[I])...)); } - } while (bounds.IncrementSubscripts(index)); +(std::get(*args)->IncrementSubscripts(argIndex[I]), ...); + } while (bounds.IncrementSubscripts(resultIndex)); } // Build and return constant result if constexpr (TR::category == TypeCategory::Character) { @@ -732,17 +730,11 @@ template class ArrayConstructorFolder { Expr folded{Fold(context_, common::Clone(expr.value()))}; if (const auto *c{UnwrapConstantValue(folded)}) { // Copy elements in Fortran array element order - ConstantSubscripts shape{c->shape()}; - int rank{c->Rank()}; - ConstantSubscripts index(GetRank(shape), 1); - for (std::size_t n{c->size()}; n-- > 0;) { -elements_.emplace_back(c->At(index)); -for (int d{0}; d < rank; ++d) { - if (++index[d] <= shape[d]) { -break; - } - index[d] = 1; -} + if (c->size() > 0) { +ConstantSubscripts index{c->lbounds()}; +do { + elements_.emplace_back(c->At(index)); +} while (c->IncrementSubscripts(index)); } return true; } else { diff --git a/flang/test/Evaluate/folding16.f90 b/flang/test/Evaluate/folding16.f90 new file mode 100644 index ..0918381040bf --- /dev/null +++ b/flang/test/Evaluate/folding16.f90 @@ -0,0 +1,8 @@ +! RUN: %S/test_folding.sh %s %t %f18 +! Ensure that lower bounds are accounted for in intrinsic folding; +! this is a regression test f
[llvm-branch-commits] [flang] 4fede8b - [flang] Implement derived type description table encoding
Author: peter klausler Date: 2020-12-08T10:26:58-08:00 New Revision: 4fede8bc8a015477f2a8feeb30a1d2a2e155106d URL: https://github.com/llvm/llvm-project/commit/4fede8bc8a015477f2a8feeb30a1d2a2e155106d DIFF: https://github.com/llvm/llvm-project/commit/4fede8bc8a015477f2a8feeb30a1d2a2e155106d.diff LOG: [flang] Implement derived type description table encoding Define Fortran derived types that describe the characteristics of derived types, and instantiations of parameterized derived types, that are of relevance to the runtime language support library. Define a suite of corresponding C++ structure types for the runtime library to use to interpret instances of the descriptions. Create instances of these description types in Semantics as static initializers for compiler-created objects in the scopes that define or instantiate user derived types. Delete obsolete code from earlier attempts to package runtime type information. Differential Revision: https://reviews.llvm.org/D92802 Added: flang/include/flang/Semantics/runtime-type-info.h flang/lib/Semantics/runtime-type-info.cpp flang/module/__fortran_type_info.f90 flang/runtime/derived.cpp flang/runtime/derived.h flang/runtime/type-info.h flang/test/Semantics/typeinfo01.f90 Modified: flang/docs/RuntimeTypeInfo.md flang/include/flang/Semantics/scope.h flang/lib/Semantics/CMakeLists.txt flang/lib/Semantics/compute-offsets.cpp flang/lib/Semantics/semantics.cpp flang/lib/Semantics/tools.cpp flang/module/__fortran_builtins.f90 flang/module/iso_c_binding.f90 flang/runtime/CMakeLists.txt flang/runtime/allocatable.cpp flang/runtime/allocatable.h flang/runtime/descriptor.cpp flang/runtime/descriptor.h flang/runtime/transformational.cpp flang/tools/f18/CMakeLists.txt flang/tools/f18/f18.cpp Removed: flang/runtime/derived-type.cpp flang/runtime/derived-type.h diff --git a/flang/docs/RuntimeTypeInfo.md b/flang/docs/RuntimeTypeInfo.md index 2a511b208d0e..391b6ea5f88b 100644 --- a/flang/docs/RuntimeTypeInfo.md +++ b/flang/docs/RuntimeTypeInfo.md @@ -216,7 +216,7 @@ So the derived type information for a defined assignment needs to comprise: * address(es) of the subroutine * whether the first, second, or both arguments are descriptors -* whether the subroutine is elemental +* whether the subroutine is elemental (necessarily also impure) ### User defined derived type I/O diff --git a/flang/include/flang/Semantics/runtime-type-info.h b/flang/include/flang/Semantics/runtime-type-info.h new file mode 100644 index ..71b5cac58eb5 --- /dev/null +++ b/flang/include/flang/Semantics/runtime-type-info.h @@ -0,0 +1,38 @@ +//===-- include/flang/Semantics/runtime-type-info.h -*- C++ -*-===// +// +// 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 +// +//===--===// + +// BuildRuntimeDerivedTypeTables() translates the scopes of derived types +// and parameterized derived type instantiations into the type descriptions +// defined in module/__fortran_type_info.f90, packaging these descriptions +// as static initializers for compiler-created objects. + +#ifndef FORTRAN_SEMANTICS_RUNTIME_TYPE_INFO_H_ +#define FORTRAN_SEMANTICS_RUNTIME_TYPE_INFO_H_ + +#include +#include + +namespace llvm { +class raw_ostream; +} + +namespace Fortran::semantics { +class Scope; +class SemanticsContext; +class Symbol; + +struct RuntimeDerivedTypeTables { + Scope *schemata{nullptr}; + std::set names; +}; + +RuntimeDerivedTypeTables BuildRuntimeDerivedTypeTables(SemanticsContext &); + +void Dump(llvm::raw_ostream &, const RuntimeDerivedTypeTables &); +} // namespace Fortran::semantics +#endif // FORTRAN_SEMANTICS_RUNTIME_TYPE_INFO_H_ diff --git a/flang/include/flang/Semantics/scope.h b/flang/include/flang/Semantics/scope.h index cae94dfac9e8..535e2bd50dce 100644 --- a/flang/include/flang/Semantics/scope.h +++ b/flang/include/flang/Semantics/scope.h @@ -197,8 +197,11 @@ class Scope { std::size_t size() const { return size_; } void set_size(std::size_t size) { size_ = size; } - std::size_t alignment() const { return alignment_; } - void set_alignment(std::size_t alignment) { alignment_ = alignment; } + std::optional alignment() const { return alignment_; } + + void SetAlignment(std::size_t n) { +alignment_ = std::max(alignment_.value_or(0), n); + } ImportKind GetImportKind() const; // Names appearing in IMPORT statements in this scope @@ -242,11 +245,18 @@ class Scope { void InstantiateDerivedTypes(SemanticsContext &); + const Symbol *runtimeDerivedTypeDescription() const { +return runtimeDerivedTypeDescription_; + } + void set_run
[llvm-branch-commits] [flang] [llvm] [Flang] Move runtime library files to FortranRuntime. NFC (PR #110298)
klausler wrote: > While it would be possible to only have a `FortranRuntime/CMakeLists.txt` and > leave all the other files in `flang/`, I strongly believe this is a bad idea. > It is the norm for LLVM runtimes to have separate sources. A Fortran compiler and its runtime are tightly coupled; the compiler can only work with this runtime, this runtime can only be used by this compiler, and they share common API definitions and data structures. I don't mind if you move the sources and headers that are used *only* by the runtime into a new top-level directory, if you must. But moving common headers and sources used by *both* the compiler and the runtime builds out of the compiler tree makes no sense to me. https://github.com/llvm/llvm-project/pull/110298 ___ 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] [llvm] [Flang] Move runtime library files to FortranRuntime. NFC (PR #110298)
https://github.com/klausler commented: This is a gigantic change and I don't understand why it's being made. Why is so much code moving out of flang/ ? https://github.com/llvm/llvm-project/pull/110298 ___ 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] [Flang] Split runtime headers in preparation for cross-compilation. NFC. (PR #112188)
klausler wrote: On what targets would the size or member byte offsets in a descriptor differ? https://github.com/llvm/llvm-project/pull/112188 ___ 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] [clang] [flang] [lld] [llvm] [Flang] LLVM_ENABLE_RUNTIMES=FortranRuntime (PR #110217)
@@ -11,8 +11,11 @@ using namespace Fortran::parser::literals; + klausler wrote: why are these new blank lines necessary? https://github.com/llvm/llvm-project/pull/110217 ___ 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] [llvm] [Flang] Move runtime library files to clang-rt. NFC (PR #110298)
@@ -1,13 +1,13 @@ -//===-- include/flang/Runtime/CUDA/allocator.h --*- C++ -*-===// +//===-- include/flang-rt/CufRuntime/allocator.h -*- C++ -*-===// klausler wrote: CUDA Fortran is the name of the language. "cuf" is a filename extension. https://github.com/llvm/llvm-project/pull/110298 ___ 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] [llvm] [Flang] Move runtime library files to FortranRuntime. NFC (PR #110298)
klausler wrote: > > A Fortran compiler and its runtime are tightly coupled; the compiler can > > only work with this runtime, this runtime can only be used by this > > compiler, and they share common API definitions and data structures. > > So is c C/C++ compiler and its runtime(s). There is still a need to support > cross-compilation and other build modes like > `FLANG_EXPERIMENTAL_CUDA_RUNTIME`. > > > I don't mind if you move the sources and headers that are used _only_ by > > the runtime into a new top-level directory, if you must. But moving common > > headers and sources used by _both_ the compiler and the runtime builds out > > of the compiler tree makes no sense to me. > > As said, this was the result of the RFC. I can update the PR and leave them > in `flang/`. I am not in disagreement with your objectives. But I think that you will be able to achieve them without scrambling the source locations so much that I won't be able to continue maintaining them upstream. https://github.com/llvm/llvm-project/pull/110298 ___ 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] [flang] handle fir.call in AliasAnalysis::getModRef (PR #117164)
https://github.com/klausler approved this pull request. https://github.com/llvm/llvm-project/pull/117164 ___ 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] [flang] handle fir.call in AliasAnalysis::getModRef (PR #117164)
@@ -0,0 +1,135 @@ +! RUN: bbc -emit-hlfir %s -o - | %python %S/gen_mod_ref_test.py | \ +! RUN: fir-opt -pass-pipeline='builtin.module(func.func(test-fir-alias-analysis-modref))' \ +! RUN: --mlir-disable-threading -o /dev/null 2>&1 | FileCheck %s + +! Test fir.call modref with internal procedures + +subroutine simple_modref_test(test_var_x) + implicit none + real :: test_var_x + call test_effect_internal() +contains + subroutine test_effect_internal() +test_var_x = 0. + end subroutine +end subroutine +! CHECK-LABEL: Testing : "_QPsimple_modref_test" +! CHECK: test_effect_internal -> test_var_x#0: ModRef + +subroutine simple_nomodref_test(test_var_x) + implicit none + real :: test_var_x + call test_effect_internal() +contains + subroutine test_effect_internal() +call some_external() + end subroutine +end subroutine +! CHECK-LABEL: Testing : "_QPsimple_nomodref_test" +! CHECK: test_effect_internal -> test_var_x#0: NoModRef + +! Test that effects on captured variable are propagated to associated variables +! in associate construct. + +subroutine test_associate() + implicit none + real :: test_var_x(10) + associate (test_var_y=>test_var_x) +test_var_y = test_effect_internal() klausler wrote: Is it necessary for this test that `test_var_y` be the LHS of the assignment statement? You would expect ModRef even if it were not modified by/after the call. Might be more clear if the result were stored elsewhere. https://github.com/llvm/llvm-project/pull/117164 ___ 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] [flang] handle fir.call in AliasAnalysis::getModRef (PR #117164)
@@ -0,0 +1,68 @@ +! RUN: bbc -emit-hlfir %s -o - | %python %S/gen_mod_ref_test.py | \ +! RUN: fir-opt -pass-pipeline='builtin.module(func.func(test-fir-alias-analysis-modref))' \ +! RUN: --mlir-disable-threading -o /dev/null 2>&1 | FileCheck %s + +! Test fir.call modref for global variables (module, saved, common). + + +module somemod + implicit none + real :: test_var_xmod + interface +subroutine may_capture(x) + real, target :: x +end subroutine + end interface +end module + +subroutine test_module + use somemod, only : test_var_xmod + implicit none + call test_effect_external() +end subroutine +! CHECK-LABEL: Testing : "_QPtest_module" +! CHECK: test_effect_external -> test_var_xmod#0: ModRef + +subroutine test_saved_local + use somemod, only : may_capture + implicit none + real, save :: test_var_xsaved + ! Capture is invalid after the call because test_var_xsaved does not have the + ! target attribute. + call may_capture(test_var_xsaved) + call test_effect_external() +end subroutine +! CHECK-LABEL: Testing : "_QPtest_saved_local" +! CHECK: test_effect_external -> test_var_xsaved#0: NoModRef + +subroutine test_saved_target + use somemod, only : may_capture + implicit none + real, save, target :: test_var_target_xsaved klausler wrote: The 'save' attribute shouldn't matter; the result would be ModRef with and without `save`, yes? https://github.com/llvm/llvm-project/pull/117164 ___ 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] [Flang] Introduce FortranSupport (PR #122069)
klausler wrote: There's an implicit assumption here that either future runtime work won't occur, or won't need anything from Common that you're moving away into the new compiler-only directory. Is this change required for your work that restructures the runtime builds? https://github.com/llvm/llvm-project/pull/122069 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits