[clang] [clang-repl] Emit const variables only once (PR #65257)

Jonas Hahnfeld via cfe-commits cfe-commits at lists.llvm.org
Mon Sep 4 05:23:16 PDT 2023


https://github.com/hahnjo created https://github.com/llvm/llvm-project/pull/65257:

Disable internal linkage for const variables if IncrementalExtensions are enabled. Otherwise the variables are emitted multiple times, with multiple constructions at unique memory locations, during every PTU.

>From fcea5762fab68459aef3f8e82e98fc52e04e1598 Mon Sep 17 00:00:00 2001
From: Jonas Hahnfeld <jonas.hahnfeld at cern.ch>
Date: Mon, 4 Sep 2023 13:56:25 +0200
Subject: [PATCH] [clang-repl] Emit const variables only once

Disable internal linkage for const variables if IncrementalExtensions
are enabled. Otherwise the variables are emitted multiple times, with
multiple constructions at unique memory locations, during every PTU.
---
 clang/lib/AST/Decl.cpp           |  1 +
 clang/test/Interpreter/const.cpp | 29 +++++++++++++++++++++++++++++
 2 files changed, 30 insertions(+)
 create mode 100644 clang/test/Interpreter/const.cpp

diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 60c80f2b075336..e019e701196a38 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -651,6 +651,7 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D,
     //     internal linkage
     // (There is no equivalent in C99.)
     if (Context.getLangOpts().CPlusPlus && Var->getType().isConstQualified() &&
+        !Context.getLangOpts().IncrementalExtensions &&
         !Var->getType().isVolatileQualified() && !Var->isInline() &&
         !isDeclaredInModuleInterfaceOrPartition(Var) &&
         !isa<VarTemplateSpecializationDecl>(Var) &&
diff --git a/clang/test/Interpreter/const.cpp b/clang/test/Interpreter/const.cpp
new file mode 100644
index 00000000000000..a4b610f1a19d84
--- /dev/null
+++ b/clang/test/Interpreter/const.cpp
@@ -0,0 +1,29 @@
+// UNSUPPORTED: system-aix
+// RUN: cat %s | clang-repl | FileCheck %s
+// RUN: cat %s | clang-repl -Xcc -O2 | FileCheck %s
+
+extern "C" int printf(const char*, ...);
+
+struct A { int val; A(int v); ~A(); void f() const; };
+A::A(int v) : val(v) { printf("A(%d), this = %p\n", val, this); }
+A::~A() { printf("~A, this = %p, val = %d\n", this, val); }
+void A::f() const { printf("f: this = %p, val = %d\n", this, val); }
+
+const A a(1);
+// CHECK: A(1), this = [[THIS:0x[0-9a-f]+]]
+// The constructor must only be called once!
+// CHECK-NOT: A(1)
+
+a.f();
+// CHECK-NEXT: f: this = [[THIS]], val = 1
+a.f();
+// CHECK-NEXT: f: this = [[THIS]], val = 1
+
+%quit
+// There must still be no other constructor!
+// CHECK-NOT: A(1)
+
+// At the end, we expect exactly one destructor call
+// CHECK: ~A
+// CHECK-SAME: this = [[THIS]], val = 1
+// CHECK-NOT: ~A



More information about the cfe-commits mailing list