[flang-commits] [flang] [flang][test] Fix ASAN error in unit tests (PR #218917)
David Spickett via flang-commits
flang-commits at lists.llvm.org
Tue Sep 1 08:17:08 PDT 2026
https://github.com/DavidSpickett updated https://github.com/llvm/llvm-project/pull/218917
>From fc9c48c85031cea2242fcb2016982840f030aa25 Mon Sep 17 00:00:00 2001
From: David Spickett <david.spickett at arm.com>
Date: Wed, 26 Aug 2026 12:56:07 +0000
Subject: [PATCH 1/6] [flang][test] Fix ASAN error in unit tests
When flang is built with ASAN, one of the unit tests fails:
[ RUN ] FrontendActionTest.ParseSyntaxOnly
=================================================================
==94036==ERROR: AddressSanitizer: heap-use-after-free on address 0xef60299e1268 at pc 0xbf00842915d0 bp 0xffffcc819e50 sp 0xffffcc819e48
READ of size 2 at 0xef60299e1268 thread T0
#0 0xbf00842915cc in getShowColors /home/davspi01/llvm-project/llvm/../clang/include/clang/Basic/DiagnosticOptions.def:68:14
#1 0xbf00842915cc in showColors /home/davspi01/llvm-project/llvm/../clang/include/clang/Basic/DiagnosticOptions.h:159:13
#2 0xbf00842915cc in Fortran::frontend::TextDiagnosticPrinter::HandleDiagnostic(clang::DiagnosticsEngine::Level, clang::Diagnostic const&) /home/davspi01/llvm-project/flang/lib/Frontend/TextDiagnosticPrinter.cpp:116:27
#3 0xbf0088f08ef0 in clang::DiagnosticsEngine::Report(clang::DiagnosticsEngine::Level, clang::Diagnostic const&) /home/davspi01/llvm-project/clang/lib/Basic/Diagnostic.cpp:625:11
#4 0xbf0088f09584 in clang::DiagnosticsEngine::ProcessDiag(clang::DiagnosticBuilder const&) /home/davspi01/llvm-project/clang/lib/Basic/Diagnostic.cpp:705:3
#5 0xbf0088f099ac in clang::DiagnosticsEngine::EmitDiagnostic(clang::DiagnosticBuilder const&, bool) /home/davspi01/llvm-project/clang/lib/Basic/Diagnostic.cpp:727:15
#6 0xbf0082d78778 in Emit /home/davspi01/llvm-project/llvm/../clang/include/clang/Basic/Diagnostic.h:1332:28
#7 0xbf0082d78778 in clang::DiagnosticBuilder::~DiagnosticBuilder() /home/davspi01/llvm-project/llvm/../clang/include/clang/Basic/Diagnostic.h:1367:26
#8 0xbf0083dacd7c in Fortran::frontend::FrontendAction::reportFatalSemanticErrors() /home/davspi01/llvm-project/flang/lib/Frontend/FrontendAction.cpp:310:5
<...>
* CompilerInstance is defaut constructed, which means it has
a default constructed CompilerInvocation.
* CompilerInstance::createDiagnostics is called.
* It makes a clang::DiagnosticsEngine and gives it a reference
to whatever getDiagnosticOpts() returns.
* That returns invocation->getDiagnosticOpts().
* CompilerInstance::setInvocation is called with a new invocation,
replacing the original invocation.
* The clang::DiagnosticsEngine now has a dangling reference
to the options in the original invocation.
To fix this, I have implemented the same thing that
b69dcb873476cd8e7d3f6f9ffd5b6d0bbe1a3a17 did for Clang.
Pass the invocation to the CompilerInstance constructor,
and remove the setInvocation method. So that you cannot
mix up the order.
---
flang/include/flang/Frontend/CompilerInstance.h | 7 ++-----
flang/lib/Frontend/CompilerInstance.cpp | 12 ++++--------
flang/unittests/Frontend/CodeGenActionTest.cpp | 3 +--
flang/unittests/Frontend/CompilerInstanceTest.cpp | 6 ++----
flang/unittests/Frontend/FrontendActionTest.cpp | 11 ++++-------
flang/unittests/Semantics/OpenMPUtils.cpp | 11 ++++-------
6 files changed, 17 insertions(+), 33 deletions(-)
diff --git a/flang/include/flang/Frontend/CompilerInstance.h b/flang/include/flang/Frontend/CompilerInstance.h
index c0acd57cdc9ee..9dc1701f290fc 100644
--- a/flang/include/flang/Frontend/CompilerInstance.h
+++ b/flang/include/flang/Frontend/CompilerInstance.h
@@ -111,7 +111,8 @@ class CompilerInstance {
/// @}
public:
- explicit CompilerInstance();
+ explicit CompilerInstance(std::shared_ptr<CompilerInvocation> invocation =
+ std::make_shared<CompilerInvocation>());
~CompilerInstance();
@@ -119,13 +120,9 @@ class CompilerInstance {
/// {
CompilerInvocation &getInvocation() {
- assert(invocation && "Compiler instance has no invocation!");
return *invocation;
};
- /// Replace the current invocation.
- void setInvocation(std::shared_ptr<CompilerInvocation> value);
-
/// }
/// @name File manager
/// {
diff --git a/flang/lib/Frontend/CompilerInstance.cpp b/flang/lib/Frontend/CompilerInstance.cpp
index 2416d3b593481..caeb58d9f8fdc 100644
--- a/flang/lib/Frontend/CompilerInstance.cpp
+++ b/flang/lib/Frontend/CompilerInstance.cpp
@@ -33,11 +33,12 @@
using namespace Fortran::frontend;
-CompilerInstance::CompilerInstance()
- : invocation(new CompilerInvocation()),
- allSources(new Fortran::parser::AllSources()),
+CompilerInstance::CompilerInstance(
+ std::shared_ptr<CompilerInvocation> invocation)
+ : invocation(invocation), allSources(new Fortran::parser::AllSources()),
allCookedSources(new Fortran::parser::AllCookedSources(*allSources)),
parsing(new Fortran::parser::Parsing(*allCookedSources)) {
+ assert(invocation && "Invocation must not be null.");
// TODO: This is a good default during development, but ultimately we should
// give the user the opportunity to specify this.
allSources->set_encoding(Fortran::parser::Encoding::UTF_8);
@@ -47,11 +48,6 @@ CompilerInstance::~CompilerInstance() {
assert(outputFiles.empty() && "Still output files in flight?");
}
-void CompilerInstance::setInvocation(
- std::shared_ptr<CompilerInvocation> value) {
- invocation = std::move(value);
-}
-
void CompilerInstance::setSemaOutputStream(raw_ostream &value) {
ownedSemaOutputStream.release();
semaOutputStream = &value;
diff --git a/flang/unittests/Frontend/CodeGenActionTest.cpp b/flang/unittests/Frontend/CodeGenActionTest.cpp
index e606456663eec..2d1aa1cf188e4 100644
--- a/flang/unittests/Frontend/CodeGenActionTest.cpp
+++ b/flang/unittests/Frontend/CodeGenActionTest.cpp
@@ -99,9 +99,8 @@ TEST(CodeGenAction, GracefullyHandleLLVMConversionFailure) {
auto diagPrinter = std::make_unique<Fortran::frontend::TextDiagnosticPrinter>(
diagnosticsOS, diagOpts);
- CompilerInstance ci;
+ CompilerInstance ci(std::make_shared<CompilerInvocation>());
ci.createDiagnostics(diagPrinter.get(), /*ShouldOwnClient=*/false);
- ci.setInvocation(std::make_shared<CompilerInvocation>());
ci.setOutputStream(std::make_unique<llvm::raw_null_ostream>());
ci.getInvocation().getCodeGenOpts().OptimizationLevel = 0;
diff --git a/flang/unittests/Frontend/CompilerInstanceTest.cpp b/flang/unittests/Frontend/CompilerInstanceTest.cpp
index 5cd360e7a2828..98953531acb4e 100644
--- a/flang/unittests/Frontend/CompilerInstanceTest.cpp
+++ b/flang/unittests/Frontend/CompilerInstanceTest.cpp
@@ -101,17 +101,15 @@ TEST(CompilerInstance, AllowDiagnosticLogWithUnownedDiagnosticConsumer) {
TEST(CompilerInstance,
OpenAccDefaultNoneScalarsStrictDisableOptionUsesDriverTable) {
- CompilerInstance compInst;
- compInst.createDiagnostics();
-
auto invocation = std::make_shared<CompilerInvocation>();
+ CompilerInstance compInst(invocation);
+ compInst.createDiagnostics();
invocation->getTargetOpts().triple =
llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple());
llvm::InitializeAllTargets();
llvm::InitializeAllTargetMCs();
- compInst.setInvocation(std::move(invocation));
ASSERT_TRUE(compInst.setUpTargetMachine());
auto &context = compInst.createNewSemanticsContext();
diff --git a/flang/unittests/Frontend/FrontendActionTest.cpp b/flang/unittests/Frontend/FrontendActionTest.cpp
index bdf5a23fdbf6a..ef14149d539fa 100644
--- a/flang/unittests/Frontend/FrontendActionTest.cpp
+++ b/flang/unittests/Frontend/FrontendActionTest.cpp
@@ -37,8 +37,9 @@ class FrontendActionTest : public ::testing::Test {
std::error_code ec;
- CompilerInstance compInst;
- std::shared_ptr<CompilerInvocation> invoc;
+ std::shared_ptr<CompilerInvocation> invoc =
+ std::make_shared<CompilerInvocation>();
+ CompilerInstance compInst{invoc};
void SetUp() override {
// Generate a unique test file name.
@@ -60,10 +61,6 @@ class FrontendActionTest : public ::testing::Test {
inputFilePath = cwd.c_str();
inputFilePath += "/" + inputFileName;
- // Prepare the compiler (CompilerInvocation + CompilerInstance)
- compInst.createDiagnostics();
- invoc = std::make_shared<CompilerInvocation>();
-
// Set-up default target triple and initialize LLVM Targets so that the
// target data layout can be passed to the frontend.
invoc->getTargetOpts().triple =
@@ -71,7 +68,7 @@ class FrontendActionTest : public ::testing::Test {
llvm::InitializeAllTargets();
llvm::InitializeAllTargetMCs();
- compInst.setInvocation(std::move(invoc));
+ compInst.createDiagnostics();
compInst.getFrontendOpts().inputs.push_back(
FrontendInputFile(inputFilePath, Language::Fortran));
}
diff --git a/flang/unittests/Semantics/OpenMPUtils.cpp b/flang/unittests/Semantics/OpenMPUtils.cpp
index 7b003d8fa4af8..9a662b108005e 100644
--- a/flang/unittests/Semantics/OpenMPUtils.cpp
+++ b/flang/unittests/Semantics/OpenMPUtils.cpp
@@ -45,8 +45,9 @@ class OpenMPUtilsTest : public ::testing::Test {
std::error_code ec;
- CompilerInstance compInst;
- std::shared_ptr<CompilerInvocation> invoc;
+ std::shared_ptr<CompilerInvocation> invoc =
+ std::make_shared<CompilerInvocation>();
+ CompilerInstance compInst{invoc};
void SetUp() override {
// Generate a unique test file name.
@@ -68,10 +69,6 @@ class OpenMPUtilsTest : public ::testing::Test {
inputFilePath = cwd.c_str();
inputFilePath += "/" + inputFileName;
- // Prepare the compiler (CompilerInvocation + CompilerInstance)
- compInst.createDiagnostics();
- invoc = std::make_shared<CompilerInvocation>();
-
// Set-up default target triple and initialize LLVM Targets so that the
// target data layout can be passed to the frontend.
invoc->getTargetOpts().triple =
@@ -80,7 +77,7 @@ class OpenMPUtilsTest : public ::testing::Test {
llvm::InitializeAllTargets();
llvm::InitializeAllTargetMCs();
- compInst.setInvocation(std::move(invoc));
+ compInst.createDiagnostics();
compInst.getFrontendOpts().inputs.push_back(
FrontendInputFile(inputFilePath, Language::Fortran));
compInst.getFrontendOpts().features.Enable(common::LanguageFeature::OpenMP);
>From 9498d0d72d5550bd8ff833dc0afa7cc42a186a84 Mon Sep 17 00:00:00 2001
From: David Spickett <david.spickett at arm.com>
Date: Wed, 26 Aug 2026 13:06:04 +0000
Subject: [PATCH 2/6] use normal constructor
---
flang/unittests/Frontend/FrontendActionTest.cpp | 2 +-
flang/unittests/Semantics/OpenMPUtils.cpp | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/flang/unittests/Frontend/FrontendActionTest.cpp b/flang/unittests/Frontend/FrontendActionTest.cpp
index ef14149d539fa..ec8233d7fd34b 100644
--- a/flang/unittests/Frontend/FrontendActionTest.cpp
+++ b/flang/unittests/Frontend/FrontendActionTest.cpp
@@ -39,7 +39,7 @@ class FrontendActionTest : public ::testing::Test {
std::shared_ptr<CompilerInvocation> invoc =
std::make_shared<CompilerInvocation>();
- CompilerInstance compInst{invoc};
+ CompilerInstance compInst(invoc);
void SetUp() override {
// Generate a unique test file name.
diff --git a/flang/unittests/Semantics/OpenMPUtils.cpp b/flang/unittests/Semantics/OpenMPUtils.cpp
index 9a662b108005e..18bbea512e6d1 100644
--- a/flang/unittests/Semantics/OpenMPUtils.cpp
+++ b/flang/unittests/Semantics/OpenMPUtils.cpp
@@ -47,7 +47,7 @@ class OpenMPUtilsTest : public ::testing::Test {
std::shared_ptr<CompilerInvocation> invoc =
std::make_shared<CompilerInvocation>();
- CompilerInstance compInst{invoc};
+ CompilerInstance compInst(invoc);
void SetUp() override {
// Generate a unique test file name.
>From f37b96bb4a8b43bc6c3b3c348347b6dc6f6b99c5 Mon Sep 17 00:00:00 2001
From: David Spickett <david.spickett at arm.com>
Date: Wed, 26 Aug 2026 13:07:26 +0000
Subject: [PATCH 3/6] format
---
flang/include/flang/Frontend/CompilerInstance.h | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/flang/include/flang/Frontend/CompilerInstance.h b/flang/include/flang/Frontend/CompilerInstance.h
index 9dc1701f290fc..3909e7bf37bba 100644
--- a/flang/include/flang/Frontend/CompilerInstance.h
+++ b/flang/include/flang/Frontend/CompilerInstance.h
@@ -119,9 +119,7 @@ class CompilerInstance {
/// @name Compiler Invocation
/// {
- CompilerInvocation &getInvocation() {
- return *invocation;
- };
+ CompilerInvocation &getInvocation() { return *invocation; };
/// }
/// @name File manager
>From 5e51466e8f0db0a55f5c87492bb646cdbec904e7 Mon Sep 17 00:00:00 2001
From: David Spickett <david.spickett at arm.com>
Date: Wed, 26 Aug 2026 13:16:27 +0000
Subject: [PATCH 4/6] use getInvocation
---
flang/unittests/Frontend/FrontendActionTest.cpp | 6 ++----
flang/unittests/Semantics/OpenMPUtils.cpp | 8 +++-----
2 files changed, 5 insertions(+), 9 deletions(-)
diff --git a/flang/unittests/Frontend/FrontendActionTest.cpp b/flang/unittests/Frontend/FrontendActionTest.cpp
index ec8233d7fd34b..ec9682e27b312 100644
--- a/flang/unittests/Frontend/FrontendActionTest.cpp
+++ b/flang/unittests/Frontend/FrontendActionTest.cpp
@@ -37,9 +37,7 @@ class FrontendActionTest : public ::testing::Test {
std::error_code ec;
- std::shared_ptr<CompilerInvocation> invoc =
- std::make_shared<CompilerInvocation>();
- CompilerInstance compInst(invoc);
+ CompilerInstance compInst;
void SetUp() override {
// Generate a unique test file name.
@@ -63,7 +61,7 @@ class FrontendActionTest : public ::testing::Test {
// Set-up default target triple and initialize LLVM Targets so that the
// target data layout can be passed to the frontend.
- invoc->getTargetOpts().triple =
+ compInst.getInvocation().getTargetOpts().triple =
llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple());
llvm::InitializeAllTargets();
llvm::InitializeAllTargetMCs();
diff --git a/flang/unittests/Semantics/OpenMPUtils.cpp b/flang/unittests/Semantics/OpenMPUtils.cpp
index 18bbea512e6d1..d2b56e28143ca 100644
--- a/flang/unittests/Semantics/OpenMPUtils.cpp
+++ b/flang/unittests/Semantics/OpenMPUtils.cpp
@@ -45,9 +45,7 @@ class OpenMPUtilsTest : public ::testing::Test {
std::error_code ec;
- std::shared_ptr<CompilerInvocation> invoc =
- std::make_shared<CompilerInvocation>();
- CompilerInstance compInst(invoc);
+ CompilerInstance compInst;
void SetUp() override {
// Generate a unique test file name.
@@ -71,9 +69,9 @@ class OpenMPUtilsTest : public ::testing::Test {
// Set-up default target triple and initialize LLVM Targets so that the
// target data layout can be passed to the frontend.
- invoc->getTargetOpts().triple =
+ compInst.getInvocation().getTargetOpts().triple =
llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple());
- invoc->getLangOpts().OpenMPVersion = 60;
+ compInst.getInvocation().getLangOpts().OpenMPVersion = 60;
llvm::InitializeAllTargets();
llvm::InitializeAllTargetMCs();
>From 10259a000d2e262cb2e9f0c51648ff6c9b7edd50 Mon Sep 17 00:00:00 2001
From: David Spickett <david.spickett at arm.com>
Date: Wed, 26 Aug 2026 13:18:46 +0000
Subject: [PATCH 5/6] another getInvocation
---
flang/unittests/Frontend/CompilerInstanceTest.cpp | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/flang/unittests/Frontend/CompilerInstanceTest.cpp b/flang/unittests/Frontend/CompilerInstanceTest.cpp
index 98953531acb4e..60ef29c53c28d 100644
--- a/flang/unittests/Frontend/CompilerInstanceTest.cpp
+++ b/flang/unittests/Frontend/CompilerInstanceTest.cpp
@@ -101,10 +101,9 @@ TEST(CompilerInstance, AllowDiagnosticLogWithUnownedDiagnosticConsumer) {
TEST(CompilerInstance,
OpenAccDefaultNoneScalarsStrictDisableOptionUsesDriverTable) {
- auto invocation = std::make_shared<CompilerInvocation>();
- CompilerInstance compInst(invocation);
+ CompilerInstance compInst;
compInst.createDiagnostics();
- invocation->getTargetOpts().triple =
+ compInst.getInvocation().getTargetOpts().triple =
llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple());
llvm::InitializeAllTargets();
>From fbf69284c364c5ad33d8c04c45026aaa8f02f899 Mon Sep 17 00:00:00 2001
From: David Spickett <david.spickett at arm.com>
Date: Tue, 1 Sep 2026 15:14:41 +0000
Subject: [PATCH 6/6] use move
---
flang/lib/Frontend/CompilerInstance.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/flang/lib/Frontend/CompilerInstance.cpp b/flang/lib/Frontend/CompilerInstance.cpp
index caeb58d9f8fdc..72f157b5e2002 100644
--- a/flang/lib/Frontend/CompilerInstance.cpp
+++ b/flang/lib/Frontend/CompilerInstance.cpp
@@ -35,7 +35,8 @@ using namespace Fortran::frontend;
CompilerInstance::CompilerInstance(
std::shared_ptr<CompilerInvocation> invocation)
- : invocation(invocation), allSources(new Fortran::parser::AllSources()),
+ : invocation(std::move(invocation)),
+ allSources(new Fortran::parser::AllSources()),
allCookedSources(new Fortran::parser::AllCookedSources(*allSources)),
parsing(new Fortran::parser::Parsing(*allCookedSources)) {
assert(invocation && "Invocation must not be null.");
More information about the flang-commits
mailing list