[flang-commits] [flang] 813bdb1 - [flang][test] Fix ASAN error in unit tests (#218917)
via flang-commits
flang-commits at lists.llvm.org
Wed Sep 2 02:55:42 PDT 2026
Author: David Spickett
Date: 2026-09-02T10:55:35+01:00
New Revision: 813bdb184af716091bb927070063a3e065124d33
URL: https://github.com/llvm/llvm-project/commit/813bdb184af716091bb927070063a3e065124d33
DIFF: https://github.com/llvm/llvm-project/commit/813bdb184af716091bb927070063a3e065124d33.diff
LOG: [flang][test] Fix ASAN error in unit tests (#218917)
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.
Added:
Modified:
flang/include/flang/Frontend/CompilerInstance.h
flang/lib/Frontend/CompilerInstance.cpp
flang/unittests/Frontend/CodeGenActionTest.cpp
flang/unittests/Frontend/CompilerInstanceTest.cpp
flang/unittests/Frontend/FrontendActionTest.cpp
flang/unittests/Semantics/OpenMPUtils.cpp
Removed:
################################################################################
diff --git a/flang/include/flang/Frontend/CompilerInstance.h b/flang/include/flang/Frontend/CompilerInstance.h
index c0acd57cdc9ee..3909e7bf37bba 100644
--- a/flang/include/flang/Frontend/CompilerInstance.h
+++ b/flang/include/flang/Frontend/CompilerInstance.h
@@ -111,20 +111,15 @@ class CompilerInstance {
/// @}
public:
- explicit CompilerInstance();
+ explicit CompilerInstance(std::shared_ptr<CompilerInvocation> invocation =
+ std::make_shared<CompilerInvocation>());
~CompilerInstance();
/// @name Compiler Invocation
/// {
- CompilerInvocation &getInvocation() {
- assert(invocation && "Compiler instance has no invocation!");
- return *invocation;
- };
-
- /// Replace the current invocation.
- void setInvocation(std::shared_ptr<CompilerInvocation> value);
+ CompilerInvocation &getInvocation() { return *invocation; };
/// }
/// @name File manager
diff --git a/flang/lib/Frontend/CompilerInstance.cpp b/flang/lib/Frontend/CompilerInstance.cpp
index 2416d3b593481..d35f549701282 100644
--- a/flang/lib/Frontend/CompilerInstance.cpp
+++ b/flang/lib/Frontend/CompilerInstance.cpp
@@ -33,11 +33,13 @@
using namespace Fortran::frontend;
-CompilerInstance::CompilerInstance()
- : invocation(new CompilerInvocation()),
+CompilerInstance::CompilerInstance(
+ std::shared_ptr<CompilerInvocation> invocation)
+ : invocation(std::move(invocation)),
allSources(new Fortran::parser::AllSources()),
allCookedSources(new Fortran::parser::AllCookedSources(*allSources)),
parsing(new Fortran::parser::Parsing(*allCookedSources)) {
+ assert(this->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 +49,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..60ef29c53c28d 100644
--- a/flang/unittests/Frontend/CompilerInstanceTest.cpp
+++ b/flang/unittests/Frontend/CompilerInstanceTest.cpp
@@ -103,15 +103,12 @@ TEST(CompilerInstance,
OpenAccDefaultNoneScalarsStrictDisableOptionUsesDriverTable) {
CompilerInstance compInst;
compInst.createDiagnostics();
-
- auto invocation = std::make_shared<CompilerInvocation>();
- invocation->getTargetOpts().triple =
+ compInst.getInvocation().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..ec9682e27b312 100644
--- a/flang/unittests/Frontend/FrontendActionTest.cpp
+++ b/flang/unittests/Frontend/FrontendActionTest.cpp
@@ -38,7 +38,6 @@ class FrontendActionTest : public ::testing::Test {
std::error_code ec;
CompilerInstance compInst;
- std::shared_ptr<CompilerInvocation> invoc;
void SetUp() override {
// Generate a unique test file name.
@@ -60,18 +59,14 @@ 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 =
+ compInst.getInvocation().getTargetOpts().triple =
llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple());
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 aee4b452ec87f..3bdbb7f3f6f03 100644
--- a/flang/unittests/Semantics/OpenMPUtils.cpp
+++ b/flang/unittests/Semantics/OpenMPUtils.cpp
@@ -46,7 +46,6 @@ class OpenMPUtilsTest : public ::testing::Test {
std::error_code ec;
CompilerInstance compInst;
- std::shared_ptr<CompilerInvocation> invoc;
void SetUp() override {
// Generate a unique test file name.
@@ -68,19 +67,15 @@ 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 =
+ compInst.getInvocation().getTargetOpts().triple =
llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple());
- invoc->getLangOpts().OpenMPVersion = 60;
+ compInst.getInvocation().getLangOpts().OpenMPVersion = 60;
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);
More information about the flang-commits
mailing list