From f0130ce81bbe393a9549f59a54d6210243c4880c Mon Sep 17 00:00:00 2001 From: Jonas Hahnfeld Date: Wed, 6 Sep 2023 11:10:05 +0200 Subject: [PATCH] [cling] Emit const variables only once Otherwise they are emitted as internal and we get double-construction and -destruction on the same memory address due to the way we promote interal declarations in KeepLocalGVPass. According to upstream tests, the de-duplication doesn't work on Windows (yet), but I think this problem is severe enough to fix it on the other platforms sooner rather than later. Fixes #13429 --- interpreter/cling/test/CodeGeneration/const.C | 37 +++++++++++++++++++ .../llvm-project/clang/lib/AST/ASTContext.cpp | 9 +++++ interpreter/llvm-project/llvm-project.tag | 2 +- .../llvm/lib/ExecutionEngine/Orc/LLJIT.cpp | 2 +- 4 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 interpreter/cling/test/CodeGeneration/const.C diff --git a/interpreter/cling/test/CodeGeneration/const.C b/interpreter/cling/test/CodeGeneration/const.C new file mode 100644 index 0000000000000..8fe1397be30d8 --- /dev/null +++ b/interpreter/cling/test/CodeGeneration/const.C @@ -0,0 +1,37 @@ +//------------------------------------------------------------------------------ +// CLING - the C++ LLVM-based InterpreterG :) +// +// This file is dual-licensed: you can choose to license it under the University +// of Illinois Open Source License or the GNU Lesser General Public License. See +// LICENSE.TXT for details. +//------------------------------------------------------------------------------ + +// RUN: cat %s | %cling 2>&1 | FileCheck %s + +extern "C" int printf(const char*, ...); + +struct A { + int val; + A(int v) : val(v) { + printf("A(%d), this = %p\n", val, this); + } + ~A() { + printf("~A(%d), this = %p\n", val, this); + } + int getVal() const { return val; } +}; + +const A a(1); +// CHECK: A(1), this = [[PTR:.+]] + +a.val +// CHECK-NEXT: (const int) 1 +a.getVal() +// CHECK-NEXT: (int) 1 +a.val +// CHECK-NEXT: (const int) 1 +a.getVal() +// CHECK-NEXT: (int) 1 + +// CHECK-NEXT: ~A(1), this = [[PTR]] +// CHECK-NOT: ~A diff --git a/interpreter/llvm-project/clang/lib/AST/ASTContext.cpp b/interpreter/llvm-project/clang/lib/AST/ASTContext.cpp index 04370f38f4b6a..50484fcf4d8dd 100644 --- a/interpreter/llvm-project/clang/lib/AST/ASTContext.cpp +++ b/interpreter/llvm-project/clang/lib/AST/ASTContext.cpp @@ -10831,6 +10831,15 @@ GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) const { static GVALinkage basicGVALinkageForVariable(const ASTContext &Context, const VarDecl *VD) { + // As an extension for interactive REPLs, make sure constant variables are + // only emitted once instead of LinkageComputer::getLVForNamespaceScopeDecl + // marking them as internal. + if (Context.getLangOpts().CPlusPlus && + VD->getType().isConstQualified() && + !VD->getType().isVolatileQualified() && !VD->isInline() && + !isa(VD) && !VD->getDescribedVarTemplate()) + return GVA_DiscardableODR; + if (!VD->isExternallyVisible()) return GVA_Internal; diff --git a/interpreter/llvm-project/llvm-project.tag b/interpreter/llvm-project/llvm-project.tag index 2e2e8aebaf613..a9a4e39eccf2c 100644 --- a/interpreter/llvm-project/llvm-project.tag +++ b/interpreter/llvm-project/llvm-project.tag @@ -1 +1 @@ -ROOT-llvm13-20230921-01 +ROOT-llvm13-20231003-01 diff --git a/interpreter/llvm-project/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp b/interpreter/llvm-project/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp index 6c52998dc633b..4d304f7bca7b8 100644 --- a/interpreter/llvm-project/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp +++ b/interpreter/llvm-project/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp @@ -483,7 +483,7 @@ GlobalCtorDtorScraper::operator()(ThreadSafeModule TSM, Inits.push_back(std::make_pair(E.Func, E.Priority)); llvm::sort(Inits, [](const std::pair &LHS, const std::pair &RHS) { - return LHS.first < RHS.first; + return LHS.second < RHS.second; }); auto *EntryBlock = BasicBlock::Create(Ctx, "entry", InitFunc); IRBuilder<> IB(EntryBlock);