[flang-commits] [flang] d6e1f70 - [flang] Allow multiple identical DATA initializations (#177063)
via flang-commits
flang-commits at lists.llvm.org
Thu Jan 22 07:32:59 PST 2026
Author: Peter Klausler
Date: 2026-01-22T07:32:53-08:00
New Revision: d6e1f70e671032bcbce69f38d57deeed6db801b5
URL: https://github.com/llvm/llvm-project/commit/d6e1f70e671032bcbce69f38d57deeed6db801b5
DIFF: https://github.com/llvm/llvm-project/commit/d6e1f70e671032bcbce69f38d57deeed6db801b5.diff
LOG: [flang] Allow multiple identical DATA initializations (#177063)
ISO Fortran disallows DATA statements from affecting the same bit of
memory more than once; however, all (but one) other compilers allow this
usage. They differ, however, in the case of multiple distinct
initializations -- some compilers take the "last" value in source order,
some don't.
This patch accepts multiple identical DATA initializations, which is
portable usage that appears in code, and emits an optional warning. It
continues to detect and report multiple distinct DATA initializations,
since they are not portable.
Added:
flang/test/Semantics/bug2098.f90
Modified:
flang/docs/Extensions.md
flang/include/flang/Evaluate/initial-image.h
flang/include/flang/Support/Fortran-features.h
flang/lib/Evaluate/fold.cpp
flang/lib/Evaluate/initial-image.cpp
flang/lib/Semantics/data-to-inits.cpp
flang/lib/Semantics/data-to-inits.h
flang/lib/Semantics/semantics.cpp
flang/test/Semantics/data07.f90
flang/test/Semantics/data12.f90
flang/test/Semantics/data23.f90
flang/test/Semantics/equivalence02.f90
Removed:
################################################################################
diff --git a/flang/docs/Extensions.md b/flang/docs/Extensions.md
index 6f02a51c81492..493bb10af6f85 100644
--- a/flang/docs/Extensions.md
+++ b/flang/docs/Extensions.md
@@ -478,6 +478,9 @@ end
to be a pointer so long as it is `INTENT(IN)`.
(This extension is not yet supported for procedure pointer component
interfaces.)
+* A data object can be initialized multiple times by `DATA` statements
+ and default component initialization, but only when all initializations
+ are to the same value. Distinct initializations remain errors.
### Extensions supported when enabled by options
diff --git a/flang/include/flang/Evaluate/initial-image.h b/flang/include/flang/Evaluate/initial-image.h
index dc9a9bfbfdf22..9a767db95f6c6 100644
--- a/flang/include/flang/Evaluate/initial-image.h
+++ b/flang/include/flang/Evaluate/initial-image.h
@@ -24,11 +24,12 @@ class InitialImage {
public:
enum Result {
Ok,
+ OkNoChange,
NotAConstant,
OutOfRange,
SizeMismatch,
LengthMismatch,
- TooManyElems
+ TooManyElems,
};
explicit InitialImage(std::size_t bytes) : data_(bytes) {}
@@ -52,11 +53,17 @@ class InitialImage {
x.values().size() * static_cast<std::size_t>(*elementBytes)) {
return SizeMismatch;
} else if (bytes == 0) {
- return Ok;
+ return OkNoChange;
} else {
// TODO endianness
- std::memcpy(&data_.at(offset), &x.values().at(0), bytes);
- return Ok;
+ auto *to{&data_.at(offset)};
+ const auto *from{&x.values().at(0)};
+ if (std::memcmp(to, from, bytes) == 0) {
+ return OkNoChange;
+ } else {
+ std::memcpy(to, from, bytes);
+ return Ok;
+ }
}
}
}
@@ -76,9 +83,9 @@ class InitialImage {
if (elements * elementBytes != bytes) {
return SizeMismatch;
} else if (bytes == 0) {
- return Ok;
+ return OkNoChange;
} else {
- Result result{Ok};
+ Result result{OkNoChange};
for (auto at{x.lbounds()}; elements-- > 0; x.IncrementSubscripts(at)) {
auto scalar{x.At(at)}; // this is a std string; size() in chars
auto scalarBytes{scalar.size() * KIND};
@@ -90,7 +97,14 @@ class InitialImage {
scalar += ' ';
}
// TODO endianness
- std::memcpy(&data_.at(offset), scalar.data(), elementBytes);
+ auto *to{&data_.at(offset)};
+ const auto *from{scalar.data()};
+ if (std::memcmp(to, from, elementBytes) != 0) {
+ std::memcpy(to, from, elementBytes);
+ if (result == OkNoChange) {
+ result = Ok;
+ }
+ }
offset += elementBytes;
}
return result;
@@ -106,9 +120,10 @@ class InitialImage {
[&](const auto &y) { return Add(offset, bytes, y, c); }, x.u);
}
- void AddPointer(ConstantSubscript, const Expr<SomeType> &);
+ Result AddPointer(ConstantSubscript, const Expr<SomeType> &);
- void Incorporate(ConstantSubscript toOffset, const InitialImage &from,
+ // Returns true if anything changes
+ bool Incorporate(ConstantSubscript toOffset, const InitialImage &from,
ConstantSubscript fromOffset, ConstantSubscript bytes);
// Conversions to constant initializers
diff --git a/flang/include/flang/Support/Fortran-features.h b/flang/include/flang/Support/Fortran-features.h
index 8586a60c5b21c..c847e6d509878 100644
--- a/flang/include/flang/Support/Fortran-features.h
+++ b/flang/include/flang/Support/Fortran-features.h
@@ -56,7 +56,7 @@ ENUM_CLASS(LanguageFeature, BackslashEscapes, OldDebugLines,
IgnoreIrrelevantAttributes, Unsigned, AmbiguousStructureConstructor,
ContiguousOkForSeqAssociation, ForwardRefExplicitTypeDummy,
InaccessibleDeferredOverride, CudaWarpMatchFunction, DoConcurrentOffload,
- TransferBOZ, Coarray, PointerPassObject)
+ TransferBOZ, Coarray, PointerPassObject, MultipleIdenticalDATA)
// Portability and suspicious usage warnings
ENUM_CLASS(UsageWarning, Portability, PointerToUndefinable,
diff --git a/flang/lib/Evaluate/fold.cpp b/flang/lib/Evaluate/fold.cpp
index 1fbbbba909fbf..3c4f3ecc61996 100644
--- a/flang/lib/Evaluate/fold.cpp
+++ b/flang/lib/Evaluate/fold.cpp
@@ -278,7 +278,7 @@ std::optional<Expr<SomeType>> FoldTransfer(
(elements == 0 || totalBytes / elements == *sourceBytes)) {
InitialImage image{*sourceBytes};
auto status{image.Add(0, *sourceBytes, *source, context)};
- if (status == InitialImage::Ok) {
+ if (status == InitialImage::Ok || status == InitialImage::OkNoChange) {
return image.AsConstant(
context, *moldType, moldLength, *extents, true /*pad with 0*/);
} else {
diff --git a/flang/lib/Evaluate/initial-image.cpp b/flang/lib/Evaluate/initial-image.cpp
index 6a712bcfbe1bc..050c55e399b57 100644
--- a/flang/lib/Evaluate/initial-image.cpp
+++ b/flang/lib/Evaluate/initial-image.cpp
@@ -28,43 +28,57 @@ auto InitialImage::Add(ConstantSubscript offset, std::size_t bytes,
return SizeMismatch;
} else {
auto at{x.lbounds()};
+ Result result{OkNoChange};
for (; elements-- > 0; x.IncrementSubscripts(at)) {
auto scalar{x.At(at)};
// TODO: length type parameter values?
for (const auto &[symbolRef, indExpr] : scalar) {
const Symbol &component{*symbolRef};
+ Result status{OkNoChange};
if (component.offset() + component.size() > elementBytes) {
return SizeMismatch;
} else if (IsPointer(component)) {
- AddPointer(offset + component.offset(), indExpr.value());
+ status = AddPointer(offset + component.offset(), indExpr.value());
} else if (IsAllocatable(component) || IsAutomatic(component)) {
return NotAConstant;
- } else if (auto result{Add(offset + component.offset(),
- component.size(), indExpr.value(), context)};
- result != Ok) {
- return result;
+ } else {
+ status = Add(offset + component.offset(), component.size(),
+ indExpr.value(), context);
+ }
+ if (status == Ok) {
+ result = Ok;
+ } else if (status != OkNoChange) {
+ return status;
}
}
offset += elementBytes;
}
+ return result;
}
- return Ok;
}
}
-void InitialImage::AddPointer(
- ConstantSubscript offset, const Expr<SomeType> &pointer) {
- pointers_.emplace(offset, pointer);
+auto InitialImage::AddPointer(
+ ConstantSubscript offset, const Expr<SomeType> &pointer) -> Result {
+ auto [iter, isNew]{pointers_.emplace(offset, pointer)};
+ return !isNew && iter->second == pointer ? OkNoChange : Ok;
}
-void InitialImage::Incorporate(ConstantSubscript toOffset,
+bool InitialImage::Incorporate(ConstantSubscript toOffset,
const InitialImage &from, ConstantSubscript fromOffset,
ConstantSubscript bytes) {
CHECK(from.pointers_.empty()); // pointers are not allowed in EQUIVALENCE
CHECK(fromOffset >= 0 && bytes >= 0 &&
static_cast<std::size_t>(fromOffset + bytes) <= from.size());
CHECK(static_cast<std::size_t>(toOffset + bytes) <= size());
- std::memcpy(&data_[toOffset], &from.data_[fromOffset], bytes);
+ auto *dest{&data_[toOffset]};
+ const auto *source{&from.data_[fromOffset]};
+ if (std::memcmp(dest, source, bytes) != 0) {
+ std::memcpy(dest, source, bytes);
+ return true;
+ } else {
+ return false; // no change
+ }
}
// Classes used with common::SearchTypes() to (re)construct Constant<> values
diff --git a/flang/lib/Semantics/data-to-inits.cpp b/flang/lib/Semantics/data-to-inits.cpp
index d9e79340a6d91..cd9ec3059afec 100644
--- a/flang/lib/Semantics/data-to-inits.cpp
+++ b/flang/lib/Semantics/data-to-inits.cpp
@@ -335,7 +335,7 @@ bool DataInitializationCompiler<DSV>::InitElement(
return ss.str();
}
}};
- const auto GetImage{[&]() -> evaluate::InitialImage & {
+ const auto GetSymbolInit{[&]() -> SymbolDataInitialization & {
// This could be (and was) written to always call std::map<>::emplace(),
// which should handle duplicate entries gracefully, but it was still
// causing memory allocation & deallocation with gcc.
@@ -343,9 +343,7 @@ bool DataInitializationCompiler<DSV>::InitElement(
if (iter == inits_.end()) {
iter = inits_.emplace(&symbol, symbol.size()).first;
}
- auto &symbolInit{iter->second};
- symbolInit.NoteInitializedRange(offsetSymbol);
- return symbolInit.image;
+ return iter->second;
}};
const auto OutOfRangeError{[&]() {
evaluate::AttachDeclaration(
@@ -394,7 +392,10 @@ bool DataInitializationCompiler<DSV>::InitElement(
scope,
/*isBoundsRemapping=*/false, /*isAssumedRank=*/false)) {
if (lastSymbol->has<ProcEntityDetails>()) {
- GetImage().AddPointer(offsetSymbol.offset(), *expr);
+ auto &symInit{GetSymbolInit()};
+ symInit.NoteInitializedRange(offsetSymbol, /*isDuplicate=*/
+ symInit.image.AddPointer(offsetSymbol.offset(), *expr) ==
+ evaluate::InitialImage::OkNoChange);
return true;
} else {
evaluate::AttachDeclaration(
@@ -415,7 +416,10 @@ bool DataInitializationCompiler<DSV>::InitElement(
expr->AsFortran(), DescribeElement());
} else if (CheckInitialDataPointerTarget(
exprAnalyzer_.context(), designator, *expr, scope)) {
- GetImage().AddPointer(offsetSymbol.offset(), *expr);
+ auto &symInit{GetSymbolInit()};
+ symInit.NoteInitializedRange(offsetSymbol, /*isDuplicate=*/
+ symInit.image.AddPointer(offsetSymbol.offset(), *expr) ==
+ evaluate::InitialImage::OkNoChange);
return true;
}
} else if (evaluate::IsNullPointer(expr)) {
@@ -448,9 +452,14 @@ bool DataInitializationCompiler<DSV>::InitElement(
// Rewritten from a switch() in order to avoid getting complaints
// about a missing "default:" from some compilers and complaints
// about a redundant "default:" from others.
- auto status{GetImage().Add(
+ auto &symInit{GetSymbolInit()};
+ auto status{symInit.image.Add(
offsetSymbol.offset(), offsetSymbol.size(), folded, context)};
if (status == evaluate::InitialImage::Ok) {
+ symInit.NoteInitializedRange(offsetSymbol, /*isDuplicate=*/false);
+ return true;
+ } else if (status == evaluate::InitialImage::OkNoChange) {
+ symInit.NoteInitializedRange(offsetSymbol, /*isDuplicate=*/true);
return true;
} else if (status == evaluate::InitialImage::NotAConstant) {
exprAnalyzer_.Say(
@@ -567,48 +576,36 @@ static void PopulateWithComponentDefaults(SymbolDataInitialization &init,
if (!IsAllocatable(component) && !IsAutomatic(component)) {
bool initialized{false};
if (object->init()) {
- initialized = true;
if (IsPointer(component)) {
- if (auto extant{init.image.AsConstantPointer(componentOffset)}) {
- initialized = !(*extant == *object->init());
- }
- if (initialized) {
- init.image.AddPointer(componentOffset, *object->init());
+ if (init.image.AddPointer(componentOffset, *object->init()) ==
+ evaluate::InitialImage::Ok) {
+ initialized = true;
}
} else { // data, not pointer
- if (auto dyType{evaluate::DynamicType::From(component)}) {
- if (auto extents{evaluate::GetConstantExtents(
- foldingContext, component)}) {
- if (auto extant{init.image.AsConstant(foldingContext, *dyType,
- std::nullopt, *extents, false /*don't pad*/,
- componentOffset)}) {
- initialized = !(*extant == *object->init());
- }
- }
- }
- if (initialized) {
- init.image.Add(componentOffset, component.size(), *object->init(),
- foldingContext);
+ if (init.image.Add(componentOffset, component.size(),
+ *object->init(),
+ foldingContext) == evaluate::InitialImage::Ok) {
+ initialized = true;
}
}
- } else if (const DeclTypeSpec * type{component.GetType()}) {
+ } else if (const DeclTypeSpec *type{component.GetType()}) {
if (const DerivedTypeSpec * componentDerived{type->AsDerived()}) {
PopulateWithComponentDefaults(init, componentOffset,
*componentDerived, foldingContext, component);
}
}
if (initialized) {
- init.NoteInitializedRange(componentOffset, component.size());
+ init.NoteInitializedRange(componentOffset, component.size(),
+ /*isDuplicate=*/false);
}
}
} else if (const auto *proc{component.detailsIf<ProcEntityDetails>()}) {
if (proc->init() && *proc->init()) {
SomeExpr procPtrInit{evaluate::ProcedureDesignator{**proc->init()}};
- auto extant{init.image.AsConstantPointer(componentOffset)};
- if (!extant || !(*extant == procPtrInit)) {
- init.NoteInitializedRange(componentOffset, component.size());
- init.image.AddPointer(componentOffset, std::move(procPtrInit));
- }
+ init.NoteInitializedRange(componentOffset,
+ component.size(), /*isDuplicate=*/
+ init.image.AddPointer(componentOffset, std::move(procPtrInit)) ==
+ evaluate::InitialImage::OkNoChange);
}
}
}
@@ -620,22 +617,26 @@ static bool CheckForOverlappingInitialization(
evaluate::ExpressionAnalyzer &exprAnalyzer, const std::string &what) {
bool result{true};
auto &context{exprAnalyzer.GetFoldingContext()};
- initialization.initializedRanges.sort();
+ initialization.initializationItems.sort();
ConstantSubscript next{0};
- for (const auto &range : initialization.initializedRanges) {
- if (range.start() < next) {
+ SourceOrderedSymbolSet errors;
+ // Emit errors for multiple distinct initializations
+ for (const auto &item : initialization.initializationItems) {
+ const auto &range{item.range};
+ if (range.start() < next && !item.isDuplicate) {
result = false; // error: overlap
bool hit{false};
for (const Symbol &symbol : symbols) {
auto offset{range.start() -
static_cast<ConstantSubscript>(
symbol.offset() - symbols.front()->offset())};
- if (offset >= 0) {
+ if (offset >= 0 && static_cast<std::size_t>(offset) < symbol.size()) {
if (auto badDesignator{evaluate::OffsetToDesignator(
context, symbol, offset, range.size())}) {
hit = true;
+ errors.insert(symbol);
exprAnalyzer.Say(symbol.name(),
- "%s affect '%s' more than once"_err_en_US, what,
+ "%s affect '%s' more than once, distinctly"_err_en_US, what,
badDesignator->AsFortran());
}
}
@@ -645,6 +646,31 @@ static bool CheckForOverlappingInitialization(
next = range.start() + range.size();
CHECK(next <= static_cast<ConstantSubscript>(initialization.image.size()));
}
+ // Emit warnings for multiple identical initializations
+ next = 0;
+ for (const auto &item : initialization.initializationItems) {
+ const auto &range{item.range};
+ if (range.start() < next && item.isDuplicate) {
+ for (const Symbol &symbol : symbols) {
+ if (errors.find(symbol) == errors.end()) {
+ auto offset{range.start() -
+ static_cast<ConstantSubscript>(
+ symbol.offset() - symbols.front()->offset())};
+ if (offset >= 0) {
+ if (auto badDesignator{evaluate::OffsetToDesignator(
+ context, symbol, offset, range.size())}) {
+ exprAnalyzer.Warn(common::LanguageFeature::MultipleIdenticalDATA,
+ symbol.name(),
+ "%s affect '%s' more than once, identically"_port_en_US, what,
+ badDesignator->AsFortran());
+ }
+ }
+ }
+ }
+ }
+ next = range.start() + range.size();
+ CHECK(next <= static_cast<ConstantSubscript>(initialization.image.size()));
+ }
return result;
}
@@ -655,11 +681,13 @@ static void IncorporateExplicitInitialization(
auto iter{inits.find(&symbol)};
const auto offset{symbol.offset() - firstOffset};
if (iter != inits.end()) { // DATA statement initialization
- for (const auto &range : iter->second.initializedRanges) {
- auto at{offset + range.start()};
- combined.NoteInitializedRange(at, range.size());
- combined.image.Incorporate(
- at, iter->second.image, range.start(), range.size());
+ for (const auto &item : iter->second.initializationItems) {
+ auto at{offset + item.range.start()};
+ if (combined.image.Incorporate(
+ at, iter->second.image, item.range.start(), item.range.size())) {
+ combined.NoteInitializedRange(
+ at, item.range.size(), /*isDuplicate=*/false);
+ }
}
if (removeOriginalInits) {
inits.erase(iter);
@@ -669,17 +697,21 @@ static void IncorporateExplicitInitialization(
if (IsPointer(mutableSymbol)) {
if (auto *object{mutableSymbol.detailsIf<ObjectEntityDetails>()}) {
if (object->init()) {
- combined.NoteInitializedRange(offset, mutableSymbol.size());
- combined.image.AddPointer(offset, *object->init());
+ combined.NoteInitializedRange(offset,
+ mutableSymbol.size(), /*isDuplicate=*/
+ combined.image.AddPointer(offset, *object->init()) ==
+ evaluate::InitialImage::OkNoChange);
if (removeOriginalInits) {
object->init().reset();
}
}
} else if (auto *proc{mutableSymbol.detailsIf<ProcEntityDetails>()}) {
if (proc->init() && *proc->init()) {
- combined.NoteInitializedRange(offset, mutableSymbol.size());
- combined.image.AddPointer(
- offset, SomeExpr{evaluate::ProcedureDesignator{**proc->init()}});
+ combined.NoteInitializedRange(offset,
+ mutableSymbol.size(), /*isDuplicate=*/
+ combined.image.AddPointer(offset,
+ SomeExpr{evaluate::ProcedureDesignator{**proc->init()}}) ==
+ evaluate::InitialImage::OkNoChange);
if (removeOriginalInits) {
proc->init().reset();
}
@@ -687,9 +719,10 @@ static void IncorporateExplicitInitialization(
}
} else if (auto *object{mutableSymbol.detailsIf<ObjectEntityDetails>()}) {
if (!IsNamedConstant(mutableSymbol) && object->init()) {
- combined.NoteInitializedRange(offset, mutableSymbol.size());
- combined.image.Add(
- offset, mutableSymbol.size(), *object->init(), foldingContext);
+ auto status{combined.image.Add(
+ offset, mutableSymbol.size(), *object->init(), foldingContext)};
+ combined.NoteInitializedRange(offset, mutableSymbol.size(),
+ status == evaluate::InitialImage::OkNoChange);
if (removeOriginalInits) {
object->init().reset();
}
@@ -759,12 +792,12 @@ static bool CombineEquivalencedInitialization(
}
}
if (!CheckForOverlappingInitialization(associated, combined, exprAnalyzer,
- "Distinct default component initializations of equivalenced objects"s)) {
+ "Default component initializations of equivalenced objects"s)) {
return false;
}
// Don't complain about overlap between explicit initializations and
// default initializations.
- combined.initializedRanges.clear();
+ combined.initializationItems.clear();
// Now overlay all explicit initializations from DATA statements and
// from initializers in declarations.
for (const Symbol &symbol : associated) {
diff --git a/flang/lib/Semantics/data-to-inits.h b/flang/lib/Semantics/data-to-inits.h
index 330a6867a0732..9a0836c330b96 100644
--- a/flang/lib/Semantics/data-to-inits.h
+++ b/flang/lib/Semantics/data-to-inits.h
@@ -29,25 +29,39 @@ class Symbol;
struct SymbolDataInitialization {
using Range = common::Interval<common::ConstantSubscript>;
+ struct Item {
+ Item(Range r, bool isD) : range{r}, isDuplicate{isD} {}
+ bool operator<(const Item &that) const { return range < that.range; }
+ Range range;
+ bool isDuplicate;
+ };
explicit SymbolDataInitialization(std::size_t bytes) : image{bytes} {}
SymbolDataInitialization(SymbolDataInitialization &&) = default;
- void NoteInitializedRange(Range range) {
- if (initializedRanges.empty() ||
- !initializedRanges.back().AnnexIfPredecessor(range)) {
- initializedRanges.emplace_back(range);
+ void NoteInitializedRange(Range range, bool isDuplicate = false) {
+ if (!initializationItems.empty()) {
+ auto &last{initializationItems.back()};
+ if (last.isDuplicate == isDuplicate &&
+ last.range.AnnexIfPredecessor(range)) {
+ return;
+ }
+ }
+ if (!range.empty()) {
+ initializationItems.emplace_back(range, isDuplicate);
}
}
- void NoteInitializedRange(
- common::ConstantSubscript offset, std::size_t size) {
- NoteInitializedRange(Range{offset, size});
+ void NoteInitializedRange(common::ConstantSubscript offset, std::size_t size,
+ bool isDuplicate = false) {
+ NoteInitializedRange(Range{offset, size}, isDuplicate);
}
- void NoteInitializedRange(evaluate::OffsetSymbol offsetSymbol) {
- NoteInitializedRange(offsetSymbol.offset(), offsetSymbol.size());
+ void NoteInitializedRange(
+ evaluate::OffsetSymbol offsetSymbol, bool isDuplicate = false) {
+ NoteInitializedRange(
+ offsetSymbol.offset(), offsetSymbol.size(), isDuplicate);
}
evaluate::InitialImage image;
- std::list<Range> initializedRanges;
+ std::list<Item> initializationItems;
};
using DataInitializations = std::map<const Symbol *, SymbolDataInitialization>;
diff --git a/flang/lib/Semantics/semantics.cpp b/flang/lib/Semantics/semantics.cpp
index d9b14f7d17f0c..1f23a6c29bbe7 100644
--- a/flang/lib/Semantics/semantics.cpp
+++ b/flang/lib/Semantics/semantics.cpp
@@ -261,12 +261,8 @@ static bool PerformStatementSemantics(
}
if (!context.messages().AnyFatalError()) {
WarnUndefinedFunctionResult(context, context.globalScope());
- }
- if (!context.messages().AnyFatalError()) {
- WarnUnusedOrUndefinedLocal(context, context.globalScope());
- }
- if (!context.AnyFatalError()) {
pass2.CompileDataInitializationsIntoInitializers();
+ WarnUnusedOrUndefinedLocal(context, context.globalScope());
}
return !context.AnyFatalError();
}
diff --git a/flang/test/Semantics/bug2098.f90 b/flang/test/Semantics/bug2098.f90
new file mode 100644
index 0000000000000..4f8c2bef8fa1f
--- /dev/null
+++ b/flang/test/Semantics/bug2098.f90
@@ -0,0 +1,14 @@
+!RUN: %python %S/test_errors.py %s %flang_fc1 -pedantic
+!ERROR: DATA statement initializations affect 'a(1_8)' more than once, distinctly
+!PORTABILITY: DATA statement initializations affect 'b(1_8)' more than once, identically [-Wmultiple-identical-data]
+integer a(2), b(2)
+data a(1)/1/
+data a(2)/2/
+data a(1)/3/
+data a(2)/2/
+data b(1)/4/
+data b(2)/5/
+data b(1)/4/
+data b(2)/5/
+print *, a, b
+end
diff --git a/flang/test/Semantics/data07.f90 b/flang/test/Semantics/data07.f90
index ddb1f8b282353..1d5f6e0098304 100644
--- a/flang/test/Semantics/data07.f90
+++ b/flang/test/Semantics/data07.f90
@@ -2,7 +2,7 @@
module m
contains
subroutine s1
- !ERROR: DATA statement initializations affect 'jb(5_8)' more than once
+ !ERROR: DATA statement initializations affect 'jb(5_8)' more than once, distinctly
integer :: ja(10), jb(10)
data (ja(k),k=1,9,2) / 5*1 / ! ok
data (ja(k),k=10,2,-2) / 5*2 / ! ok
diff --git a/flang/test/Semantics/data12.f90 b/flang/test/Semantics/data12.f90
index fa6120c1b4282..b88b670f83e2a 100644
--- a/flang/test/Semantics/data12.f90
+++ b/flang/test/Semantics/data12.f90
@@ -1,4 +1,4 @@
-! RUN: %python %S/test_errors.py %s %flang_fc1
+! RUN: %python %S/test_errors.py %s %flang_fc1 -pedantic
type :: t1
sequence
integer :: m = 123
@@ -14,14 +14,14 @@
integer :: k = 234
integer :: pad
end type
-!ERROR: Distinct default component initializations of equivalenced objects affect 'x1a%m' more than once
+!ERROR: Default component initializations of equivalenced objects affect 'x1a%m' more than once, distinctly
type(t1) :: x1a
-!ERROR: Distinct default component initializations of equivalenced objects affect 'x2a%n' more than once
+!ERROR: Default component initializations of equivalenced objects affect 'x2a%n' more than once, distinctly
type(t2) :: x2a
-!ERROR: Distinct default component initializations of equivalenced objects affect 'x3%k' more than once
+!ERROR: Default component initializations of equivalenced objects affect 'x3%k' more than once, distinctly
type(t3), save :: x3
-!ERROR: Explicit initializations of equivalenced objects affect 'ja(2_8)' more than once
-!ERROR: Explicit initializations of equivalenced objects affect 'ka(1_8)' more than once
+!ERROR: Explicit initializations of equivalenced objects affect 'ja(2_8)' more than once, distinctly
+!ERROR: Explicit initializations of equivalenced objects affect 'ka(1_8)' more than once, distinctly
integer :: ja(2), ka(2)
data ja/345, 456/
data ka/456, 567/
diff --git a/flang/test/Semantics/data23.f90 b/flang/test/Semantics/data23.f90
index 8210e9e62b813..f53fe4603e009 100644
--- a/flang/test/Semantics/data23.f90
+++ b/flang/test/Semantics/data23.f90
@@ -1,18 +1,35 @@
-! RUN: %python %S/test_errors.py %s %flang_fc1
+! RUN: %python %S/test_errors.py %s %flang_fc1 -pedantic
program p
interface
- subroutine s
+ subroutine s1
+ end subroutine
+ subroutine s2
end subroutine
end interface
- !ERROR: DATA statement initializations affect 'p' more than once
- procedure(s), pointer :: p
+ !ERROR: DATA statement initializations affect 'p1' more than once, distinctly
+ procedure(s1), pointer :: p1
+ !PORTABILITY: DATA statement initializations affect 'p2' more than once, identically [-Wmultiple-identical-data]
+ procedure(s2), pointer :: p2
type t
- procedure(s), pointer, nopass :: p
+ procedure(s1), pointer, nopass :: p
end type
- !ERROR: DATA statement initializations affect 'x%p' more than once
- type(t) x
- data p /s/
- data p /s/
- data x%p /s/
- data x%p /s/
+ !ERROR: DATA statement initializations affect 'x1%p' more than once, distinctly
+ !PORTABILITY: DATA statement initializations affect 'x2%p' more than once, identically [-Wmultiple-identical-data]
+ type(t) x1, x2
+ !PORTABILITY: Procedure pointer 'p1' in a DATA statement is not standard [-Wdata-stmt-extensions]
+ data p1 /s1/
+ !PORTABILITY: Procedure pointer 'p1' in a DATA statement is not standard [-Wdata-stmt-extensions]
+ data p1 /s2/
+ !PORTABILITY: Procedure pointer 'p2' in a DATA statement is not standard [-Wdata-stmt-extensions]
+ data p2 /s1/
+ !PORTABILITY: Procedure pointer 'p2' in a DATA statement is not standard [-Wdata-stmt-extensions]
+ data p2 /s1/
+ !PORTABILITY: Procedure pointer 'p' in a DATA statement is not standard [-Wdata-stmt-extensions]
+ data x1%p /s1/
+ !PORTABILITY: Procedure pointer 'p' in a DATA statement is not standard [-Wdata-stmt-extensions]
+ data x1%p /s2/
+ !PORTABILITY: Procedure pointer 'p' in a DATA statement is not standard [-Wdata-stmt-extensions]
+ data x2%p /s1/
+ !PORTABILITY: Procedure pointer 'p' in a DATA statement is not standard [-Wdata-stmt-extensions]
+ data x2%p /s1/
end
diff --git a/flang/test/Semantics/equivalence02.f90 b/flang/test/Semantics/equivalence02.f90
index 87658c20b1f63..094c88f0b3efb 100644
--- a/flang/test/Semantics/equivalence02.f90
+++ b/flang/test/Semantics/equivalence02.f90
@@ -7,23 +7,21 @@ program main
end type
type t1
sequence
- integer, dimension(2):: i/41, 2/
+ integer, dimension(2):: i/41, 2/
end type
type t2
sequence
integer :: j(2) = [42, 2]
end type
-! ERROR: Distinct default component initializations of equivalenced objects affect 'o1' more than once
type (t0) :: O1
-! ERROR: Distinct default component initializations of equivalenced objects affect 'a%i(1_8)' more than once
+! ERROR: Default component initializations of equivalenced objects affect 'a%i(1_8)' more than once, distinctly
type (t1) :: A
-! ERROR: Distinct default component initializations of equivalenced objects affect 'b%j(1_8)' more than once
+! ERROR: Default component initializations of equivalenced objects affect 'b%j(1_8)' more than once, distinctly
type (t2) :: B
-! ERROR: Distinct default component initializations of equivalenced objects affect 'x' more than once
-! ERROR: Distinct default component initializations of equivalenced objects affect 'o2(1_8)' more than once
+! ERROR: Default component initializations of equivalenced objects affect 'x' more than once, distinctly
integer :: x, O2(0)
data x/42/
-! ERROR: Distinct default component initializations of equivalenced objects affect 'undeclared' more than once
+! ERROR: Default component initializations of equivalenced objects affect 'undeclared' more than once, distinctly
equivalence (A, B, x, O1, O2, Undeclared)
call p(x)
call s()
@@ -38,12 +36,12 @@ subroutine s()
sequence
integer(kind=8)::d = 2_8
end type
- ! ERROR: Distinct default component initializations of equivalenced objects affect 'c%d' more than once
+ ! ERROR: Default component initializations of equivalenced objects affect 'c%d' more than once, distinctly
type (g1) :: C
- ! ERROR: Distinct default component initializations of equivalenced objects affect 'd%d' more than once
+ ! ERROR: Default component initializations of equivalenced objects affect 'd%d' more than once, distinctly
type (g2) :: D
- ! ERROR: Distinct default component initializations of equivalenced objects affect 'x' more than once
- ! ERROR: Distinct default component initializations of equivalenced objects affect 'y' more than once
+ ! ERROR: Default component initializations of equivalenced objects affect 'x' more than once, distinctly
+ ! ERROR: Default component initializations of equivalenced objects affect 'y' more than once, distinctly
integer :: x, y
data x/1/, y/2/
equivalence (C, x)
More information about the flang-commits
mailing list