[clang] fix(clang): Fix miscompile for string literals. (PR #202837)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Jun 10 05:58:42 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Chris Carlon (cjc25)
<details>
<summary>Changes</summary>
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
---
Full diff: https://github.com/llvm/llvm-project/pull/202837.diff
2 Files Affected:
- (modified) clang/lib/Sema/SemaTemplateInstantiate.cpp (+7)
- (modified) clang/test/SemaTemplate/instantiate-init.cpp (+10)
``````````diff
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 6df6d5505c61c..cede8fc255b16 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,12 @@ 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;
+ }
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/202837
More information about the cfe-commits
mailing list