https://github.com/cjc25 created
https://github.com/llvm/llvm-project/pull/202837
When a string-literal is used to initialize a sized char array, the template
instantiation code always returned a reference to the string literal AST node.
Therefore modifications to the array bounds applied to all instantiantions.
This change copies the AST node for each template instantiation, so each
template instantiation gets its own string-literal.
After this change, the compilation behavior matches `g++`:
* When the array bounds depend on the template parameter, multiple
copies of the string literal are present in the final binary, even
with `-O3`
* When the array bounds do not depend on the template parameter, only
one copy of the string literal is present in the final binary with
`-O3`.
I did not check where the dedupe occurs, but it appears to work the same way in
both compilers.
Fixes #72738
>From 34ab6eafd7f0a218fc89236234d812bfa9936c93 Mon Sep 17 00:00:00 2001
From: Chris Carlon <[email protected]>
Date: Tue, 9 Jun 2026 22:16:24 -0400
Subject: [PATCH] fix(clang): Fix miscompile for string literals.
When a string-literal is used to initialize a sized char array, the
template instantiation code always returned a reference to the string
literal AST node. Therefore modifications to the array bounds applied to
all instantiantions.
This change copies the AST node for each template instantiation, so each
template instantiation gets its own string-literal.
After this change, the compilation behavior matches `g++`:
* When the array bounds depend on the template parameter, multiple
copies of the string literal are present in the final binary, even
with `-O3`
* When the array bounds do not depend on the template parameter, only
one copy of the string literal is present in the final binary with
`-O3`.
I did not check where the dedupe occurs, but it appears to work the same
way in both compilers.
Fixes #72738
---
clang/lib/Sema/SemaTemplateInstantiate.cpp | 9 +++++++++
clang/test/SemaTemplate/instantiate-init.cpp | 10 ++++++++++
2 files changed, 19 insertions(+)
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp
b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 6df6d5505c61c..ee9d986bca39a 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1340,6 +1340,7 @@ namespace {
ExprResult TransformPredefinedExpr(PredefinedExpr *E);
ExprResult TransformDeclRefExpr(DeclRefExpr *E);
ExprResult TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E);
+ ExprResult TransformStringLiteral(StringLiteral *E);
ExprResult TransformTemplateParmRefExpr(DeclRefExpr *E,
NonTypeTemplateParmDecl *D);
@@ -1916,6 +1917,14 @@
TemplateInstantiator::TransformPredefinedExpr(PredefinedExpr *E) {
return getSema().BuildPredefinedExpr(E->getLocation(), E->getIdentKind());
}
+ExprResult
+TemplateInstantiator::TransformStringLiteral(StringLiteral *E) {
+ return StringLiteral::Create(
+ SemaRef.Context, E->getBytes(), E->getKind(), E->isPascal(),
+ E->getType(),
+ llvm::ArrayRef<SourceLocation>(E->tokloc_begin(), E->tokloc_end()));
+}
+
ExprResult
TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E,
NonTypeTemplateParmDecl *NTTP) {
diff --git a/clang/test/SemaTemplate/instantiate-init.cpp
b/clang/test/SemaTemplate/instantiate-init.cpp
index 5fc3e83114e28..e9c8374559855 100644
--- a/clang/test/SemaTemplate/instantiate-init.cpp
+++ b/clang/test/SemaTemplate/instantiate-init.cpp
@@ -178,3 +178,13 @@ namespace RebuildStdInitList {
template<typename U> void f() { PES({1, 2, 3}); }
void g() { f<int>(); }
}
+
+namespace StringLiteralDefaultInit {
+ template <unsigned L> struct V {
+ char rest[L] = "at least 18 bytes";
+ };
+ void test() {
+ V<100> v1;
+ V<18> v2;
+ }
+}
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits