[flang-commits] [flang] 46ade6d - [flang] Order Symbols by source provenance
peter klausler via flang-commits
flang-commits at lists.llvm.org
Tue Mar 16 15:25:25 PDT 2021
Author: peter klausler
Date: 2021-03-16T15:25:15-07:00
New Revision: 46ade6d0ef8fea94fbc28c75bb4bed4d928fd64b
URL: https://github.com/llvm/llvm-project/commit/46ade6d0ef8fea94fbc28c75bb4bed4d928fd64b
DIFF: https://github.com/llvm/llvm-project/commit/46ade6d0ef8fea94fbc28c75bb4bed4d928fd64b.diff
LOG: [flang] Order Symbols by source provenance
In parser::AllCookedSources, implement a map from CharBlocks to
the CookedSource instances that they cover. This permits a fast
Find() operation based on std::map::equal_range to map a CharBlock
to its enclosing CookedSource instance.
Add a creation order number to each CookedSource. This allows
AllCookedSources to provide a Precedes(x,y) predicate that is a
true source stream ordering between two CharBlocks -- x is less
than y if it is in an earlier CookedSource, or in the same
CookedSource at an earlier position.
Add a reference to the singleton SemanticsContext to each Scope.
All of this allows operator< to be implemented on Symbols by
means of a true source ordering. From a Symbol, we get to
its Scope, then to the SemanticsContext, and then use its
AllCookedSources reference to call Precedes().
Differential Revision: https://reviews.llvm.org/D98743
Added:
Modified:
flang/include/flang/Parser/char-block.h
flang/include/flang/Parser/provenance.h
flang/include/flang/Semantics/scope.h
flang/include/flang/Semantics/symbol.h
flang/lib/Evaluate/tools.cpp
flang/lib/Parser/parsing.cpp
flang/lib/Parser/provenance.cpp
flang/lib/Semantics/check-io.cpp
flang/lib/Semantics/resolve-names.cpp
flang/lib/Semantics/scope.cpp
flang/lib/Semantics/semantics.cpp
flang/test/Semantics/data05.f90
flang/test/Semantics/modfile21.f90
flang/test/Semantics/resolve102.f90
flang/test/Semantics/typeinfo01.f90
flang/unittests/Evaluate/intrinsics.cpp
Removed:
################################################################################
diff --git a/flang/include/flang/Parser/char-block.h b/flang/include/flang/Parser/char-block.h
index 7c29c9aa41a0..0f5758f8c552 100644
--- a/flang/include/flang/Parser/char-block.h
+++ b/flang/include/flang/Parser/char-block.h
@@ -138,6 +138,13 @@ inline bool operator>(const char *left, const CharBlock &right) {
return right < left;
}
+// An alternative comparator based on pointer values; use with care!
+struct CharBlockPointerComparator {
+ bool operator()(CharBlock x, CharBlock y) const {
+ return x.end() < y.begin();
+ }
+};
+
llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const CharBlock &x);
} // namespace Fortran::parser
diff --git a/flang/include/flang/Parser/provenance.h b/flang/include/flang/Parser/provenance.h
index bce79809c766..56b78a2aef9a 100644
--- a/flang/include/flang/Parser/provenance.h
+++ b/flang/include/flang/Parser/provenance.h
@@ -47,6 +47,7 @@ namespace Fortran::parser {
// necessary.)
class AllSources;
+class AllCookedSources;
class Provenance {
public:
@@ -219,6 +220,9 @@ class AllSources {
// single instances of CookedSource.
class CookedSource {
public:
+ int number() const { return number_; }
+ void set_number(int n) { number_ = n; }
+
CharBlock AsCharBlock() const { return CharBlock{data_}; }
std::optional<ProvenanceRange> GetProvenanceRange(CharBlock) const;
std::optional<CharBlock> GetCharBlock(ProvenanceRange) const;
@@ -242,11 +246,12 @@ class CookedSource {
}
std::size_t BufferedBytes() const;
- void Marshal(AllSources &); // marshals text into one contiguous block
+ void Marshal(AllCookedSources &); // marshals text into one contiguous block
void CompileProvenanceRangeToOffsetMappings(AllSources &);
llvm::raw_ostream &Dump(llvm::raw_ostream &) const;
private:
+ int number_{0}; // for sorting purposes
CharBuffer buffer_; // before Marshal()
std::string data_; // all of it, prescanned and preprocessed
OffsetToProvenanceMappings provenanceMap_;
@@ -263,15 +268,8 @@ class AllCookedSources {
CookedSource &NewCookedSource();
- template <typename A> // const char * or CharBlock
- const CookedSource *Find(A x) const {
- for (const auto &c : cooked_) {
- if (c.AsCharBlock().Contains(x)) {
- return &c;
- }
- }
- return nullptr;
- }
+ const CookedSource *Find(CharBlock) const;
+ const CookedSource *Find(const char *p) const { return Find(CharBlock{p}); }
bool IsValid(ProvenanceRange r) const { return allSources_.IsValid(r); }
@@ -283,9 +281,30 @@ class AllCookedSources {
std::optional<CharBlock> GetCharBlock(ProvenanceRange) const;
void Dump(llvm::raw_ostream &) const;
+ // For sorting symbol names without being dependent on pointer values
+ bool Precedes(CharBlock, CharBlock) const;
+
+ // Once a CookedSource is complete, add it to index_ and assign its number_
+ void Register(CookedSource &);
+
private:
AllSources &allSources_;
std::list<CookedSource> cooked_; // owns all CookedSource instances
+ int counter_{0};
+ std::map<CharBlock, const CookedSource &, CharBlockPointerComparator> index_;
};
+
+// For use as a Comparator for maps, sets, sorting, &c.
+class CharBlockComparator {
+public:
+ explicit CharBlockComparator(const AllCookedSources &all) : all_{all} {}
+ bool operator()(CharBlock x, CharBlock y) const {
+ return all_.Precedes(x, y);
+ }
+
+private:
+ const AllCookedSources &all_;
+};
+
} // namespace Fortran::parser
#endif // FORTRAN_PARSER_PROVENANCE_H_
diff --git a/flang/include/flang/Semantics/scope.h b/flang/include/flang/Semantics/scope.h
index 81840bdb0122..f1d5b0c87d48 100644
--- a/flang/include/flang/Semantics/scope.h
+++ b/flang/include/flang/Semantics/scope.h
@@ -62,9 +62,10 @@ class Scope {
using ImportKind = common::ImportKind;
// Create the Global scope -- the root of the scope tree
- Scope() : Scope{*this, Kind::Global, nullptr} {}
- Scope(Scope &parent, Kind kind, Symbol *symbol)
- : parent_{parent}, kind_{kind}, symbol_{symbol} {
+ explicit Scope(SemanticsContext &context)
+ : Scope{*this, Kind::Global, nullptr, context} {}
+ Scope(Scope &parent, Kind kind, Symbol *symbol, SemanticsContext &context)
+ : parent_{parent}, kind_{kind}, symbol_{symbol}, context_{context} {
if (symbol) {
symbol->set_scope(this);
}
@@ -99,6 +100,7 @@ class Scope {
}
Symbol *symbol() { return symbol_; }
const Symbol *symbol() const { return symbol_; }
+ SemanticsContext &context() const { return context_; }
inline const Symbol *GetSymbol() const;
const Scope *GetDerivedTypeParent() const;
@@ -107,6 +109,9 @@ class Scope {
bool Contains(const Scope &) const;
/// Make a scope nested in this one
Scope &MakeScope(Kind kind, Symbol *symbol = nullptr);
+ SemanticsContext &GetMutableSemanticsContext() const {
+ return const_cast<SemanticsContext &>(context());
+ }
using size_type = mapType::size_type;
using iterator = mapType::iterator;
@@ -244,7 +249,7 @@ class Scope {
symbol_->test(Symbol::Flag::ModFile);
}
- void InstantiateDerivedTypes(SemanticsContext &);
+ void InstantiateDerivedTypes();
const Symbol *runtimeDerivedTypeDescription() const {
return runtimeDerivedTypeDescription_;
@@ -273,8 +278,9 @@ class Scope {
parser::Message::Reference instantiationContext_;
bool hasSAVE_{false}; // scope has a bare SAVE statement
const Symbol *runtimeDerivedTypeDescription_{nullptr};
+ SemanticsContext &context_;
// When additional data members are added to Scope, remember to
- // copy them, if appropriate, in InstantiateDerivedType().
+ // copy them, if appropriate, in FindOrInstantiateDerivedType().
// Storage for all Symbols. Every Symbol is in allSymbols and every Symbol*
// or Symbol& points to one in there.
diff --git a/flang/include/flang/Semantics/symbol.h b/flang/include/flang/Semantics/symbol.h
index fb53c61c7d23..957bffdb4833 100644
--- a/flang/include/flang/Semantics/symbol.h
+++ b/flang/include/flang/Semantics/symbol.h
@@ -18,7 +18,7 @@
#include <functional>
#include <list>
#include <optional>
-#include <unordered_set>
+#include <set>
#include <vector>
namespace llvm {
@@ -595,10 +595,13 @@ class Symbol {
bool operator==(const Symbol &that) const { return this == &that; }
bool operator!=(const Symbol &that) const { return !(*this == that); }
- bool operator<(const Symbol &that) const {
- // Used to collate symbols by creation order
- return sortIndex_ < that.sortIndex_;
- }
+
+ // Symbol comparison is based on the order of cooked source
+ // stream creation and, when both are from the same cooked source,
+ // their positions in that cooked source stream.
+ // (This function is implemented in Evaluate/tools.cpp to
+ // satisfy complicated shared library interdependency.)
+ bool operator<(const Symbol &) const;
int Rank() const {
return std::visit(
@@ -651,10 +654,11 @@ class Symbol {
// for a parameterized derived type instantiation with the instance's scope.
const DerivedTypeSpec *GetParentTypeSpec(const Scope * = nullptr) const;
+ SemanticsContext &GetSemanticsContext() const;
+
private:
const Scope *owner_;
SourceName name_;
- std::size_t sortIndex_; // to implement "operator<" platform independently
Attrs attrs_;
Flags flags_;
Scope *scope_{nullptr};
@@ -689,7 +693,6 @@ template <std::size_t BLOCK_SIZE> class Symbols {
Symbol &symbol = Get();
symbol.owner_ = &owner;
symbol.name_ = name;
- symbol.sortIndex_ = ++symbolCount_;
symbol.attrs_ = attrs;
symbol.details_ = std::move(details);
return symbol;
@@ -700,7 +703,6 @@ template <std::size_t BLOCK_SIZE> class Symbols {
std::list<blockType *> blocks_;
std::size_t nextIndex_{0};
blockType *currBlock_{nullptr};
- static inline std::size_t symbolCount_ = 0;
Symbol &Get() {
if (nextIndex_ == 0) {
@@ -765,17 +767,13 @@ inline const DeclTypeSpec *Symbol::GetType() const {
details_);
}
-inline bool operator<(SymbolRef x, SymbolRef y) { return *x < *y; }
+inline bool operator<(SymbolRef x, SymbolRef y) {
+ return *x < *y; // name source position ordering
+}
inline bool operator<(MutableSymbolRef x, MutableSymbolRef y) {
- return *x < *y;
+ return *x < *y; // name source position ordering
}
-struct SymbolHash {
- std::size_t operator()(SymbolRef symRef) const {
- std::hash<std::string> hasher;
- return hasher(symRef->name().ToString());
- }
-};
-using SymbolSet = std::unordered_set<SymbolRef, SymbolHash>;
+using SymbolSet = std::set<SymbolRef>;
} // namespace Fortran::semantics
diff --git a/flang/lib/Evaluate/tools.cpp b/flang/lib/Evaluate/tools.cpp
index 0685f14088a6..638b7941c9e8 100644
--- a/flang/lib/Evaluate/tools.cpp
+++ b/flang/lib/Evaluate/tools.cpp
@@ -1203,4 +1203,16 @@ const Symbol *FindFunctionResult(const Symbol &symbol) {
return FindFunctionResult(symbol, seen);
}
+// These are here in Evaluate/tools.cpp so that Evaluate can use
+// them; they cannot be defined in symbol.h due to the dependence
+// on Scope.
+
+bool Symbol::operator<(const Symbol &that) const {
+ return GetSemanticsContext().allCookedSources().Precedes(name_, that.name_);
+}
+
+SemanticsContext &Symbol::GetSemanticsContext() const {
+ return DEREF(owner_).context();
+}
+
} // namespace Fortran::semantics
diff --git a/flang/lib/Parser/parsing.cpp b/flang/lib/Parser/parsing.cpp
index 81097b2d08d1..0afa2a94ac40 100644
--- a/flang/lib/Parser/parsing.cpp
+++ b/flang/lib/Parser/parsing.cpp
@@ -88,7 +88,7 @@ const SourceFile *Parsing::Prescan(const std::string &path, Options options) {
// message about nonstandard usage will have provenance.
currentCooked_->Put('\n', range.start());
}
- currentCooked_->Marshal(allSources);
+ currentCooked_->Marshal(allCooked_);
if (options.needProvenanceRangeToCharBlockMappings) {
currentCooked_->CompileProvenanceRangeToOffsetMappings(allSources);
}
diff --git a/flang/lib/Parser/provenance.cpp b/flang/lib/Parser/provenance.cpp
index 14124a546d1e..79cb28615b95 100644
--- a/flang/lib/Parser/provenance.cpp
+++ b/flang/lib/Parser/provenance.cpp
@@ -442,11 +442,13 @@ std::optional<CharBlock> CookedSource::GetCharBlock(
std::size_t CookedSource::BufferedBytes() const { return buffer_.bytes(); }
-void CookedSource::Marshal(AllSources &allSources) {
+void CookedSource::Marshal(AllCookedSources &allCookedSources) {
CHECK(provenanceMap_.SizeInBytes() == buffer_.bytes());
- provenanceMap_.Put(allSources.AddCompilerInsertion("(after end of source)"));
+ provenanceMap_.Put(allCookedSources.allSources().AddCompilerInsertion(
+ "(after end of source)"));
data_ = buffer_.Marshal();
buffer_.clear();
+ allCookedSources.Register(*this);
}
void CookedSource::CompileProvenanceRangeToOffsetMappings(
@@ -534,6 +536,16 @@ CookedSource &AllCookedSources::NewCookedSource() {
return cooked_.emplace_back();
}
+const CookedSource *AllCookedSources::Find(CharBlock x) const {
+ auto pair{index_.equal_range(x)};
+ for (auto iter{pair.first}; iter != pair.second; ++iter) {
+ if (iter->second.AsCharBlock().Contains(x)) {
+ return &iter->second;
+ }
+ }
+ return nullptr;
+}
+
std::optional<ProvenanceRange> AllCookedSources::GetProvenanceRange(
CharBlock cb) const {
if (const CookedSource * c{Find(cb)}) {
@@ -589,4 +601,27 @@ void AllCookedSources::Dump(llvm::raw_ostream &o) const {
}
}
+bool AllCookedSources::Precedes(CharBlock x, CharBlock y) const {
+ const CookedSource *ySource{Find(y)};
+ if (const CookedSource * xSource{Find(x)}) {
+ if (ySource) {
+ int xNum{xSource->number()};
+ int yNum{ySource->number()};
+ return xNum < yNum || (xNum == yNum && x.begin() < y.begin());
+ } else {
+ return true; // by fiat, all cooked source < anything outside
+ }
+ } else if (ySource) {
+ return false;
+ } else {
+ // Both names are compiler-created (SaveTempName).
+ return x < y;
+ }
+}
+
+void AllCookedSources::Register(CookedSource &cooked) {
+ index_.emplace(cooked.AsCharBlock(), cooked);
+ cooked.set_number(static_cast<int>(index_.size()));
+}
+
} // namespace Fortran::parser
diff --git a/flang/lib/Semantics/check-io.cpp b/flang/lib/Semantics/check-io.cpp
index c6b67a5046e0..897b7fd6570a 100644
--- a/flang/lib/Semantics/check-io.cpp
+++ b/flang/lib/Semantics/check-io.cpp
@@ -930,7 +930,8 @@ void IoChecker::CheckForDefinableVariable(
if (const auto *var{parser::Unwrap<parser::Variable>(variable)}) {
if (auto expr{AnalyzeExpr(context_, *var)}) {
auto at{var->GetSource()};
- if (auto whyNot{WhyNotModifiable(at, *expr, context_.FindScope(at))}) {
+ if (auto whyNot{WhyNotModifiable(at, *expr, context_.FindScope(at),
+ true /*vectorSubscriptIsOk*/)}) {
const Symbol *base{GetFirstSymbol(*expr)};
context_
.Say(at, "%s variable '%s' must be definable"_err_en_US, s,
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index df358d880445..813debbe1d86 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -6393,7 +6393,7 @@ void ResolveNamesVisitor::FinishSpecificationPart(
CheckPossibleBadForwardRef(symbol);
}
}
- currScope().InstantiateDerivedTypes(context());
+ currScope().InstantiateDerivedTypes();
for (const auto &decl : decls) {
if (const auto *statement{std::get_if<
parser::Statement<common::Indirection<parser::StmtFunctionStmt>>>(
diff --git a/flang/lib/Semantics/scope.cpp b/flang/lib/Semantics/scope.cpp
index 597f554abcb9..2e2b8f77f16e 100644
--- a/flang/lib/Semantics/scope.cpp
+++ b/flang/lib/Semantics/scope.cpp
@@ -50,7 +50,7 @@ std::string EquivalenceObject::AsFortran() const {
}
Scope &Scope::MakeScope(Kind kind, Symbol *symbol) {
- return children_.emplace_back(*this, kind, symbol);
+ return children_.emplace_back(*this, kind, symbol, context_);
}
template <typename T>
@@ -404,11 +404,11 @@ const Scope &Scope::GetDerivedTypeBase() const {
return *child;
}
-void Scope::InstantiateDerivedTypes(SemanticsContext &context) {
+void Scope::InstantiateDerivedTypes() {
for (DeclTypeSpec &type : declTypeSpecs_) {
if (type.category() == DeclTypeSpec::TypeDerived ||
type.category() == DeclTypeSpec::ClassDerived) {
- type.derivedTypeSpec().Instantiate(*this, context);
+ type.derivedTypeSpec().Instantiate(*this, context_);
}
}
}
diff --git a/flang/lib/Semantics/semantics.cpp b/flang/lib/Semantics/semantics.cpp
index f299897603d9..24bc5e3ea816 100644
--- a/flang/lib/Semantics/semantics.cpp
+++ b/flang/lib/Semantics/semantics.cpp
@@ -185,8 +185,9 @@ SemanticsContext::SemanticsContext(
: defaultKinds_{defaultKinds}, languageFeatures_{languageFeatures},
allCookedSources_{allCookedSources},
intrinsics_{evaluate::IntrinsicProcTable::Configure(defaultKinds_)},
- foldingContext_{
- parser::ContextualMessages{&messages_}, defaultKinds_, intrinsics_} {}
+ globalScope_{*this}, foldingContext_{
+ parser::ContextualMessages{&messages_},
+ defaultKinds_, intrinsics_} {}
SemanticsContext::~SemanticsContext() {}
diff --git a/flang/test/Semantics/data05.f90 b/flang/test/Semantics/data05.f90
index ff4d0686ffc7..8e059c2c0652 100644
--- a/flang/test/Semantics/data05.f90
+++ b/flang/test/Semantics/data05.f90
@@ -73,15 +73,15 @@ integer function ifunc2(n)
end function
subroutine s11
real, target, save :: arr(3,4) ! CHECK: arr, SAVE, TARGET size=48 offset=0: ObjectEntity type: REAL(4) shape: 1_8:3_8,1_8:4_8
- type(t1) :: d1 = t1(1,reshape([1,2,3,4],[2,2]),(6.,7.),.false.,'ab',arr,ifunc2,rfunc,extrfunc) ! CHECK: d1 size=192 offset=48: ObjectEntity type: TYPE(t1(kind=4_1,len=1_2)) init:t1(kind=4_1,len=1_2)(c=[CHARACTER(KIND=1,LEN=1)::"a","a"],ifptr=ifunc2,j=1_4,rp=rfunc,t=.false._4,x=reshape([REAL(4)::1._4,2._4,3._4,4._4],shape=[2,2]),xp=arr,xrp=extrfunc,z=(6._4,7._4))
+ type(t1) :: d1 = t1(1,reshape([1,2,3,4],[2,2]),(6.,7.),.false.,'ab',arr,ifunc2,rfunc,extrfunc) ! CHECK: d1 size=184 offset=48: ObjectEntity type: TYPE(t1(kind=4_1,len=1_2)) init:t1(kind=4_1,len=1_2)(j=1_4,x=reshape([REAL(4)::1._4,2._4,3._4,4._4],shape=[2,2]),z=(6._4,7._4),t=.false._4,c=[CHARACTER(KIND=1,LEN=1)::"a","a"],xp=arr,ifptr=ifunc2,rp=rfunc,xrp=extrfunc)
type(t1(4,len=1)) :: d2 = t1(4)(xrp=extrfunc,rp=rfunc,ifptr=ifunc2,xp=arr,c='a&
- &b',t=.false.,z=(6.,7.),x=reshape([1,2,3,4],[2,2]),j=1) ! CHECK: d2 size=192 offset=240: ObjectEntity type: TYPE(t1(kind=4_1,len=1_2)) init:t1(kind=4_1,len=1_2)(c=[CHARACTER(KIND=1,LEN=1)::"a","a"],ifptr=ifunc2,j=1_4,rp=rfunc,t=.false._4,x=reshape([REAL(4)::1._4,2._4,3._4,4._4],shape=[2,2]),xp=arr,xrp=extrfunc,z=(6._4,7._4))
- type(t1(2+2)) :: d3 ! CHECK: d3 (InDataStmt) size=192 offset=432: ObjectEntity type: TYPE(t1(kind=4_1,len=1_2)) init:t1(kind=4_1,len=1_2)(c=[CHARACTER(KIND=1,LEN=1)::"a","a"],ifptr=ifunc2,j=1_4,rp=rfunc,t=.false._4,x=reshape([REAL(4)::1._4,2._4,3._4,4._4],shape=[2,2]),xp=arr,xrp=extrfunc,z=(6._4,7._4))
+ &b',t=.false.,z=(6.,7.),x=reshape([1,2,3,4],[2,2]),j=1) ! CHECK: d2 size=184 offset=232: ObjectEntity type: TYPE(t1(kind=4_1,len=1_2)) init:t1(kind=4_1,len=1_2)(j=1_4,x=reshape([REAL(4)::1._4,2._4,3._4,4._4],shape=[2,2]),z=(6._4,7._4),t=.false._4,c=[CHARACTER(KIND=1,LEN=1)::"a","a"],xp=arr,ifptr=ifunc2,rp=rfunc,xrp=extrfunc)
+ type(t1(2+2)) :: d3 ! CHECK: d3 (InDataStmt) size=184 offset=416: ObjectEntity type: TYPE(t1(kind=4_1,len=1_2)) init:t1(kind=4_1,len=1_2)(j=1_4,x=reshape([REAL(4)::1._4,2._4,3._4,4._4],shape=[2,2]),z=(6._4,7._4),t=.false._4,c=[CHARACTER(KIND=1,LEN=1)::"a","a"],xp=arr,ifptr=ifunc2,rp=rfunc,xrp=extrfunc)
data d3/t1(1,reshape([1,2,3,4],[2,2]),(6.,7.),.false.,'ab',arr,ifunc2,rfunc,extrfunc)/
- type(t1) :: d4 ! CHECK: d4 (InDataStmt) size=192 offset=624: ObjectEntity type: TYPE(t1(kind=4_1,len=1_2)) init:t1(kind=4_1,len=1_2)(c=[CHARACTER(KIND=1,LEN=1)::"a","a"],ifptr=ifunc2,j=1_4,rp=rfunc,t=.false._4,x=reshape([REAL(4)::1._4,2._4,3._4,4._4],shape=[2,2]),xp=arr,xrp=extrfunc,z=(6._4,7._4))
+ type(t1) :: d4 ! CHECK: d4 (InDataStmt) size=184 offset=600: ObjectEntity type: TYPE(t1(kind=4_1,len=1_2)) init:t1(kind=4_1,len=1_2)(j=1_4,x=reshape([REAL(4)::1._4,2._4,3._4,4._4],shape=[2,2]),z=(6._4,7._4),t=.false._4,c=[CHARACTER(KIND=1,LEN=1)::"a","a"],xp=arr,ifptr=ifunc2,rp=rfunc,xrp=extrfunc)
data d4/t1(4)(xrp=extrfunc,rp=rfunc,ifptr=ifunc2,xp=arr,c='ab',t=.false.,z=(6&
&.,7.),x=reshape([1,2,3,4],[2,2]),j=1)/
- type(t1) :: d5 ! CHECK: d5 (InDataStmt) size=192 offset=816: ObjectEntity type: TYPE(t1(kind=4_1,len=1_2)) init:t1(kind=4_1,len=1_2)(c=[CHARACTER(KIND=1,LEN=1)::"a","b"],ifptr=ifunc2,j=1_4,rp=rfunc,t=.false._4,x=reshape([REAL(4)::1._4,2._4,3._4,4._4],shape=[2,2]),xp=arr,xrp=extrfunc,z=(6._4,7._4))
+ type(t1) :: d5 ! CHECK: d5 (InDataStmt) size=184 offset=784: ObjectEntity type: TYPE(t1(kind=4_1,len=1_2)) init:t1(kind=4_1,len=1_2)(j=1_4,x=reshape([REAL(4)::1._4,2._4,3._4,4._4],shape=[2,2]),z=(6._4,7._4),t=.false._4,c=[CHARACTER(KIND=1,LEN=1)::"a","b"],xp=arr,ifptr=ifunc2,rp=rfunc,xrp=extrfunc)
data d5%j/1/,d5%x/1,2,3,4/,d5%z%re/6./,d5%z%im/7./,d5%t/.false./,d5%c(1:1)/'a'/,d5%c(2:&
&2)/'b'/,d5%xp/arr/,d5%ifptr/ifunc2/,d5%rp/rfunc/,d5%xrp/extrfunc/
end subroutine
diff --git a/flang/test/Semantics/modfile21.f90 b/flang/test/Semantics/modfile21.f90
index d7b45f70c00d..e48f6334fa37 100644
--- a/flang/test/Semantics/modfile21.f90
+++ b/flang/test/Semantics/modfile21.f90
@@ -26,10 +26,10 @@ module m
! real(4)::v
! complex(4)::w
! real(4)::cb
-! common//t,w,u,v
! common/cb/x,y,z
! bind(c, name="CB")::/cb/
! common/cb2/a,b,c
! bind(c)::/cb2/
! common/b/cb
+! common//t,w,u,v
!end
diff --git a/flang/test/Semantics/resolve102.f90 b/flang/test/Semantics/resolve102.f90
index fec8314641e4..4f900a1309f3 100644
--- a/flang/test/Semantics/resolve102.f90
+++ b/flang/test/Semantics/resolve102.f90
@@ -9,7 +9,7 @@ subroutine sub(p2)
end subroutine
subroutine circular
- !ERROR: Procedure 'p' is recursively defined. Procedures in the cycle: 'sub', 'p', 'p2'
+ !ERROR: Procedure 'p' is recursively defined. Procedures in the cycle: 'p', 'sub', 'p2'
procedure(sub) :: p
call p(sub)
@@ -21,7 +21,7 @@ subroutine sub(p2)
end subroutine circular
program iface
- !ERROR: Procedure 'p' is recursively defined. Procedures in the cycle: 'sub', 'p', 'p2'
+ !ERROR: Procedure 'p' is recursively defined. Procedures in the cycle: 'p', 'sub', 'p2'
procedure(sub) :: p
interface
subroutine sub(p2)
@@ -38,7 +38,7 @@ Program mutual
Call p(sub)
contains
- !ERROR: Procedure 'sub1' is recursively defined. Procedures in the cycle: 'sub1', 'p', 'arg'
+ !ERROR: Procedure 'sub1' is recursively defined. Procedures in the cycle: 'p', 'sub1', 'arg'
Subroutine sub1(arg)
procedure(sub1) :: arg
End Subroutine
@@ -54,7 +54,7 @@ Program mutual1
Call p(sub)
contains
- !ERROR: Procedure 'sub1' is recursively defined. Procedures in the cycle: 'sub1', 'sub', 'p', 'arg', 'p2'
+ !ERROR: Procedure 'sub1' is recursively defined. Procedures in the cycle: 'p', 'sub1', 'arg', 'sub', 'p2'
Subroutine sub1(arg)
procedure(sub) :: arg
End Subroutine
@@ -68,6 +68,7 @@ program twoCycle
!ERROR: The interface for procedure 'p1' is recursively defined
!ERROR: The interface for procedure 'p2' is recursively defined
procedure(p1) p2
+ !ERROR: 'p2' must be an abstract interface or a procedure with an explicit interface
procedure(p2) p1
call p1
call p2
@@ -75,8 +76,10 @@ program twoCycle
program threeCycle
!ERROR: The interface for procedure 'p1' is recursively defined
+ !ERROR: 'p1' must be an abstract interface or a procedure with an explicit interface
!ERROR: The interface for procedure 'p2' is recursively defined
procedure(p1) p2
+ !ERROR: 'p2' must be an abstract interface or a procedure with an explicit interface
!ERROR: The interface for procedure 'p3' is recursively defined
procedure(p2) p3
procedure(p3) p1
diff --git a/flang/test/Semantics/typeinfo01.f90 b/flang/test/Semantics/typeinfo01.f90
index 3e8b8181fe4a..3575aca6e7a1 100644
--- a/flang/test/Semantics/typeinfo01.f90
+++ b/flang/test/Semantics/typeinfo01.f90
@@ -231,7 +231,7 @@ module m11
subroutine s1(x)
!CHECK: .b.t.1.allocatable, SAVE, TARGET: ObjectEntity type: TYPE(value) shape: 0_8:1_8,0_8:0_8 init:reshape([value::value(genre=1_1,value=0_8),value(genre=1_1,value=0_8)],shape=[2,1])
!CHECK: .b.t.1.automatic, SAVE, TARGET: ObjectEntity type: TYPE(value) shape: 0_8:1_8,0_8:0_8 init:reshape([value::value(genre=2_1,value=1_8),value(genre=3_1,value=0_8)],shape=[2,1])
-!CHECK: .c.t.1, SAVE, TARGET: ObjectEntity type: TYPE(component) shape: 0_8:3_8 init:[component::component(name=.n.allocatable,genre=3_1,category=1_1,kind=4_1,rank=1_1,offset=0_8,characterlen=value(genre=1_1,value=0_8),derived=NULL(),lenvalue=NULL(),bounds=.b.t.1.allocatable,initialization=NULL()),component(name=.n.automatic,genre=4_1,category=1_1,kind=4_1,rank=1_1,offset=48_8,characterlen=value(genre=1_1,value=0_8),derived=NULL(),lenvalue=NULL(),bounds=.b.t.1.automatic,initialization=NULL()),component(name=.n.chauto,genre=4_1,category=3_1,kind=1_1,rank=0_1,offset=96_8,characterlen=value(genre=3_1,value=0_8),derived=NULL(),lenvalue=NULL(),bounds=NULL(),initialization=NULL()),component(name=.n.pointer,genre=2_1,category=1_1,kind=4_1,rank=0_1,offset=120_8,characterlen=value(genre=1_1,value=0_8),derived=NULL(),lenvalue=NULL(),bounds=NULL(),initialization=target)]
+!CHECK: .c.t.1, SAVE, TARGET: ObjectEntity type: TYPE(component) shape: 0_8:3_8 init:[component::component(name=.n.allocatable,genre=3_1,category=1_1,kind=4_1,rank=1_1,offset=0_8,characterlen=value(genre=1_1,value=0_8),derived=NULL(),lenvalue=NULL(),bounds=.b.t.1.allocatable,initialization=NULL()),component(name=.n.automatic,genre=4_1,category=1_1,kind=4_1,rank=1_1,offset=96_8,characterlen=value(genre=1_1,value=0_8),derived=NULL(),lenvalue=NULL(),bounds=.b.t.1.automatic,initialization=NULL()),component(name=.n.chauto,genre=4_1,category=3_1,kind=1_1,rank=0_1,offset=72_8,characterlen=value(genre=3_1,value=0_8),derived=NULL(),lenvalue=NULL(),bounds=NULL(),initialization=NULL()),component(name=.n.pointer,genre=2_1,category=1_1,kind=4_1,rank=0_1,offset=48_8,characterlen=value(genre=1_1,value=0_8),derived=NULL(),lenvalue=NULL(),bounds=NULL(),initialization=target)]
!CHECK: .dt.t.1, SAVE, TARGET: ObjectEntity type: TYPE(derivedtype) init:derivedtype(binding=NULL(),name=.n.t,sizeinbytes=144_8,parent=NULL(),uninstantiated=.dt.t,kindparameter=NULL(),lenparameterkind=.lpk.t.1,component=.c.t.1,procptr=NULL(),special=NULL())
!CHECK: .lpk.t.1, SAVE, TARGET: ObjectEntity type: INTEGER(1) shape: 0_8:0_8 init:[INTEGER(1)::8_1]
type(t(*)), intent(in) :: x
diff --git a/flang/unittests/Evaluate/intrinsics.cpp b/flang/unittests/Evaluate/intrinsics.cpp
index 52507b8ef8b6..a36dbf581822 100644
--- a/flang/unittests/Evaluate/intrinsics.cpp
+++ b/flang/unittests/Evaluate/intrinsics.cpp
@@ -24,7 +24,7 @@ class CookedStrings {
offsets_[s] = cooked_.Put(s);
cooked_.PutProvenance(allSources_.AddCompilerInsertion(s));
}
- void Marshal() { cooked_.Marshal(allSources_); }
+ void Marshal() { cooked_.Marshal(allCookedSources_); }
parser::CharBlock operator()(const std::string &s) {
return {cooked_.AsCharBlock().begin() + offsets_[s], s.size()};
}
More information about the flang-commits
mailing list