[clang] [clang] Fix handling of asm string literals (PR #169803)
Abhina Sree via cfe-commits
cfe-commits at lists.llvm.org
Wed Oct 7 07:58:00 PDT 2026
https://github.com/abhina-sree updated https://github.com/llvm/llvm-project/pull/169803
>From 5142bd699c604228bb8ef2be06d928fe3cd5e933 Mon Sep 17 00:00:00 2001
From: Abhina Sreeskantharajan <Abhina.Sreeskantharajan at ibm.com>
Date: Fri, 8 May 2026 12:17:22 -0400
Subject: [PATCH 01/10] add ParserConversionAction, do not translate
unevaluated strings
---
clang/include/clang/Parse/Parser.h | 1 +
clang/include/clang/Sema/Sema.h | 4 +++-
clang/lib/Parse/ParseDecl.cpp | 9 +++++++++
clang/lib/Parse/ParseExpr.cpp | 6 +++---
clang/lib/Parse/Parser.cpp | 4 ++++
clang/lib/Sema/SemaExpr.cpp | 8 ++++----
clang/test/CodeGen/systemz-charset-diag.cpp | 8 ++++++++
clang/test/CodeGen/systemz-charset.c | 5 +++++
8 files changed, 37 insertions(+), 8 deletions(-)
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index 163aa483a84e3..824c97d048df1 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -5716,6 +5716,7 @@ class Parser : public CodeCompletionHandler {
bool Finished;
};
ObjCImplParsingDataRAII *CurParsedObjCImpl;
+ ConversionAction ParserConversionAction;
/// StashAwayMethodOrFunctionBodyTokens - Consume the tokens and store them
/// for later parsing.
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index b1d2488d2163b..8ff9cba3ead47 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -54,6 +54,7 @@
#include "clang/Basic/StackExhaustionHandler.h"
#include "clang/Basic/TemplateKinds.h"
#include "clang/Basic/TokenKinds.h"
+#include "clang/Lex/TextEncoding.h"
#include "clang/Sema/AnalysisBasedWarnings.h"
#include "clang/Sema/Attr.h"
#include "clang/Sema/CleanupInfo.h"
@@ -7397,7 +7398,8 @@ class Sema final : public SemaBase {
/// from multiple tokens. However, the common case is that StringToks points
/// to one string.
ExprResult ActOnStringLiteral(ArrayRef<Token> StringToks,
- Scope *UDLScope = nullptr);
+ Scope *UDLScope = nullptr,
+ ConversionAction Action = CA_ToLiteralEncoding);
ExprResult ActOnUnevaluatedStringLiteral(ArrayRef<Token> StringToks);
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 2bbc76fc7c4df..8475143c69b36 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -565,6 +565,9 @@ unsigned Parser::ParseAttributeArgsCommon(
nullptr,
Sema::ExpressionEvaluationContextRecord::EK_AttrArgument);
+ SaveAndRestore<ConversionAction> SavedTranslationState(
+ ParserConversionAction, CA_NoConversion);
+
ExprResult ArgExpr = ParseAssignmentExpression();
if (ArgExpr.isInvalid()) {
SkipUntil(tok::r_paren, StopAtSemi);
@@ -645,6 +648,9 @@ void Parser::ParseGNUAttributeArgs(
ParsedAttr::Kind AttrKind =
ParsedAttr::getParsedKind(AttrName, ScopeName, Form.getSyntax());
+ SaveAndRestore<ConversionAction> SavedTranslationState(ParserConversionAction,
+ CA_NoConversion);
+
if (AttrKind == ParsedAttr::AT_Availability) {
ParseAvailabilityAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
ScopeLoc, Form);
@@ -724,6 +730,9 @@ unsigned Parser::ParseClangAttributeArgs(
ParsedAttr::Kind AttrKind =
ParsedAttr::getParsedKind(AttrName, ScopeName, Form.getSyntax());
+ SaveAndRestore<ConversionAction> SavedTranslationState(ParserConversionAction,
+ CA_NoConversion);
+
switch (AttrKind) {
default:
return ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc,
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 87cd7a01451cf..06482f6b65426 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -3041,9 +3041,9 @@ ExprResult Parser::ParseStringLiteralExpression(bool AllowUserDefinedLiteral,
}
// Pass the set of string tokens, ready for concatenation, to the actions.
- return Actions.ActOnStringLiteral(StringToks,
- AllowUserDefinedLiteral ? getCurScope()
- : nullptr);
+ return Actions.ActOnStringLiteral(
+ StringToks, AllowUserDefinedLiteral ? getCurScope() : nullptr,
+ ParserConversionAction);
}
ExprResult Parser::ParseGenericSelectionExpression() {
diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp
index d83b75072f844..72c6808d51716 100644
--- a/clang/lib/Parse/Parser.cpp
+++ b/clang/lib/Parse/Parser.cpp
@@ -70,6 +70,8 @@ Parser::Parser(Preprocessor &pp, Sema &actions, bool skipFunctionBodies)
NumCachedScopes = 0;
CurParsedObjCImpl = nullptr;
+ ParserConversionAction = CA_ToLiteralEncoding;
+
// Add #pragma handlers. These are removed and destroyed in the
// destructor.
initializePragmaHandlers();
@@ -1552,6 +1554,8 @@ void Parser::ParseKNRParamDeclarations(Declarator &D) {
}
ExprResult Parser::ParseAsmStringLiteral(bool ForAsmLabel) {
+ SaveAndRestore<ConversionAction> SavedTranslationState(ParserConversionAction,
+ CA_NoConversion);
ExprResult AsmString;
if (isTokenStringLiteral()) {
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 90e360e2b05fc..c02b8b1d3643d 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -2259,8 +2259,8 @@ Sema::ExpandFunctionLocalPredefinedMacros(ArrayRef<Token> Toks) {
return ExpandedToks;
}
-ExprResult
-Sema::ActOnStringLiteral(ArrayRef<Token> StringToks, Scope *UDLScope) {
+ExprResult Sema::ActOnStringLiteral(ArrayRef<Token> StringToks, Scope *UDLScope,
+ ConversionAction Action) {
assert(!StringToks.empty() && "Must have at least one string!");
// StringToks needs backing storage as it doesn't hold array elements itself
@@ -2268,8 +2268,8 @@ Sema::ActOnStringLiteral(ArrayRef<Token> StringToks, Scope *UDLScope) {
if (getLangOpts().MicrosoftExt)
StringToks = ExpandedToks = ExpandFunctionLocalPredefinedMacros(StringToks);
- StringLiteralParser Literal(
- StringToks, PP, StringLiteralEvalMethod::Evaluated, CA_ToLiteralEncoding);
+ StringLiteralParser Literal(StringToks, PP,
+ StringLiteralEvalMethod::Evaluated, Action);
if (Literal.hadError)
return ExprError();
diff --git a/clang/test/CodeGen/systemz-charset-diag.cpp b/clang/test/CodeGen/systemz-charset-diag.cpp
index 4ed94810150a3..ad08e1f391214 100644
--- a/clang/test/CodeGen/systemz-charset-diag.cpp
+++ b/clang/test/CodeGen/systemz-charset-diag.cpp
@@ -1,3 +1,11 @@
// RUN: %clang_cc1 -triple s390x-none-zos -fexec-charset IBM-1047 %s -std=c++17 -emit-llvm -o - -verify
const char* Computer = "🖥️"; // expected-error-re {{conversion to literal encoding failed: {{.*}}}}
+
+static_assert(false, "Error string"); // expected-error {{static assertion failed: Error string}}
+
+[[deprecated("message")]] void test_deprecated() {return;} // expected-note {{'test_deprecated' has been explicitly marked deprecated here}}
+
+int main() {
+ test_deprecated(); // expected-warning {{'test_deprecated' is deprecated: message}}
+}
diff --git a/clang/test/CodeGen/systemz-charset.c b/clang/test/CodeGen/systemz-charset.c
index 766b6a83f00ff..e0d1736bf853f 100644
--- a/clang/test/CodeGen/systemz-charset.c
+++ b/clang/test/CodeGen/systemz-charset.c
@@ -66,3 +66,8 @@ const char* hello_macro = HELLO;
const char* preprocessor_concatenation = HELLO_WORLD;
//CHECK: c"\C8\85\93\93\96@\E6\96\99\93\84Z\00"
//CHECK-UTF8: c"Hello World!\00"
+
+void asm_labeled_fn(void) __asm__("asm_sym");
+void asm_labeled_fn(void) {}
+//CHECK: define{{.*}} void @asm_sym(
+//CHECK-UTF8: define{{.*}} void @asm_sym(
>From e1e45679032c206172b0e650be5939519fb43a8a Mon Sep 17 00:00:00 2001
From: Abhina Sreeskantharajan <Abhina.Sreeskantharajan at ibm.com>
Date: Fri, 3 Jul 2026 14:52:22 -0400
Subject: [PATCH 02/10] remove unnecessary changes
---
clang/lib/Parse/ParseDecl.cpp | 9 ---------
1 file changed, 9 deletions(-)
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 8475143c69b36..2bbc76fc7c4df 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -565,9 +565,6 @@ unsigned Parser::ParseAttributeArgsCommon(
nullptr,
Sema::ExpressionEvaluationContextRecord::EK_AttrArgument);
- SaveAndRestore<ConversionAction> SavedTranslationState(
- ParserConversionAction, CA_NoConversion);
-
ExprResult ArgExpr = ParseAssignmentExpression();
if (ArgExpr.isInvalid()) {
SkipUntil(tok::r_paren, StopAtSemi);
@@ -648,9 +645,6 @@ void Parser::ParseGNUAttributeArgs(
ParsedAttr::Kind AttrKind =
ParsedAttr::getParsedKind(AttrName, ScopeName, Form.getSyntax());
- SaveAndRestore<ConversionAction> SavedTranslationState(ParserConversionAction,
- CA_NoConversion);
-
if (AttrKind == ParsedAttr::AT_Availability) {
ParseAvailabilityAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
ScopeLoc, Form);
@@ -730,9 +724,6 @@ unsigned Parser::ParseClangAttributeArgs(
ParsedAttr::Kind AttrKind =
ParsedAttr::getParsedKind(AttrName, ScopeName, Form.getSyntax());
- SaveAndRestore<ConversionAction> SavedTranslationState(ParserConversionAction,
- CA_NoConversion);
-
switch (AttrKind) {
default:
return ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc,
>From 19dbec5de802b7d47b2dab358a180dc91640cb54 Mon Sep 17 00:00:00 2001
From: Abhina Sreeskantharajan <Abhina.Sreeskantharajan at ibm.com>
Date: Thu, 9 Jul 2026 13:25:39 -0400
Subject: [PATCH 03/10] remove ParserConversionAction, add paramter to
ParseStringLiteralExpression instead, add conversion to SystemCharset then
back to UTF8 to handle escape sequences in system encoding
---
clang/include/clang/Basic/TargetInfo.h | 3 ++
clang/include/clang/Lex/TextEncoding.h | 11 ++++++--
clang/include/clang/Parse/Parser.h | 6 ++--
clang/lib/Basic/TargetInfo.cpp | 2 ++
clang/lib/Frontend/CompilerInstance.cpp | 4 +--
clang/lib/Lex/TextEncoding.cpp | 37 +++++++++++++++++++++----
clang/lib/Parse/ParseExpr.cpp | 6 ++--
clang/lib/Parse/Parser.cpp | 8 ++----
clang/lib/Sema/SemaStmtAsm.cpp | 8 ++++++
clang/test/CodeGen/systemz-charset.c | 6 ++--
10 files changed, 67 insertions(+), 24 deletions(-)
diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h
index 6311b6b567a5e..dba50e03cc6d6 100644
--- a/clang/include/clang/Basic/TargetInfo.h
+++ b/clang/include/clang/Basic/TargetInfo.h
@@ -38,6 +38,7 @@
#include "llvm/IR/DerivedTypes.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/Error.h"
+#include "llvm/Support/TextEncoding.h"
#include "llvm/Support/VersionTuple.h"
#include "llvm/TargetParser/Triple.h"
#include <cassert>
@@ -329,6 +330,8 @@ class TargetInfo : public TransferrableTargetInfo,
virtual ~TargetInfo();
+ std::unique_ptr<llvm::TextEncodingConverter> TargetStrConverter;
+
/// Retrieve the target options.
TargetOptions &getTargetOpts() const {
assert(TargetOpts && "Missing target options");
diff --git a/clang/include/clang/Lex/TextEncoding.h b/clang/include/clang/Lex/TextEncoding.h
index 55663cdc072da..02cb16cef9f1b 100644
--- a/clang/include/clang/Lex/TextEncoding.h
+++ b/clang/include/clang/Lex/TextEncoding.h
@@ -10,6 +10,7 @@
#define LLVM_CLANG_LEX_TEXTENCODING_H
#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/StringRef.h"
namespace llvm {
@@ -17,16 +18,22 @@ class TextEncodingConverter;
} // namespace llvm
namespace clang {
-enum ConversionAction { CA_NoConversion, CA_ToLiteralEncoding };
+enum ConversionAction {
+ CA_NoConversion,
+ CA_ToSystemEncoding,
+ CA_ToLiteralEncoding
+};
class TextEncoding {
llvm::StringRef LiteralEncoding;
std::unique_ptr<llvm::TextEncodingConverter> ToLiteralEncodingConverter;
+ std::unique_ptr<llvm::TextEncodingConverter> ToSystemEncodingConverter;
public:
llvm::TextEncodingConverter *getConverter(ConversionAction Action) const;
static std::error_code
- setConvertersFromOptions(TextEncoding &TE, const clang::LangOptions &Opts);
+ setConvertersFromOptions(TextEncoding &TE, const clang::LangOptions &Opts,
+ clang::TargetInfo &TInfo);
llvm::StringRef getLiteralEncoding() { return LiteralEncoding; }
};
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index 824c97d048df1..92c700114420c 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -3867,8 +3867,9 @@ class Parser : public CodeCompletionHandler {
/// associated with the class's definition.
void PopParsingClass(Sema::ParsingClassState);
- ExprResult ParseStringLiteralExpression(bool AllowUserDefinedLiteral,
- bool Unevaluated);
+ ExprResult
+ ParseStringLiteralExpression(bool AllowUserDefinedLiteral, bool Unevaluated,
+ ConversionAction CA = CA_ToLiteralEncoding);
/// This routine is called when the '@' is seen and consumed.
/// Current token is an Identifier and is not a 'try'. This
@@ -5716,7 +5717,6 @@ class Parser : public CodeCompletionHandler {
bool Finished;
};
ObjCImplParsingDataRAII *CurParsedObjCImpl;
- ConversionAction ParserConversionAction;
/// StashAwayMethodOrFunctionBodyTokens - Consume the tokens and store them
/// for later parsing.
diff --git a/clang/lib/Basic/TargetInfo.cpp b/clang/lib/Basic/TargetInfo.cpp
index 1bb0026d8422e..1cc49cf84ce4c 100644
--- a/clang/lib/Basic/TargetInfo.cpp
+++ b/clang/lib/Basic/TargetInfo.cpp
@@ -198,6 +198,8 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : Triple(T) {
MaxOpenCLWorkGroupSize = 1024;
MaxBitIntWidth.reset();
+
+ TargetStrConverter = nullptr;
}
// Out of line virtual dtor for TargetInfo.
diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp
index 66662a786e6fc..5179696041b66 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -563,8 +563,8 @@ void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) {
if (GetDependencyDirectives)
PP->setDependencyDirectivesGetter(*GetDependencyDirectives);
- if (auto EC = TextEncoding::setConvertersFromOptions(PP->getTextEncoding(),
- getLangOpts()))
+ if (auto EC = TextEncoding::setConvertersFromOptions(
+ PP->getTextEncoding(), getLangOpts(), getTarget()))
PP->getDiagnostics().Report(clang::diag::err_fe_text_encoding_config)
<< PP->getTextEncoding().getLiteralEncoding();
}
diff --git a/clang/lib/Lex/TextEncoding.cpp b/clang/lib/Lex/TextEncoding.cpp
index eb4fde8928a68..effd05185faf7 100644
--- a/clang/lib/Lex/TextEncoding.cpp
+++ b/clang/lib/Lex/TextEncoding.cpp
@@ -17,6 +17,8 @@ TextEncoding::getConverter(ConversionAction Action) const {
switch (Action) {
case CA_ToLiteralEncoding:
return ToLiteralEncodingConverter.get();
+ case CA_ToSystemEncoding:
+ return ToSystemEncodingConverter.get();
default:
return nullptr;
}
@@ -24,23 +26,46 @@ TextEncoding::getConverter(ConversionAction Action) const {
std::error_code
TextEncoding::setConvertersFromOptions(TextEncoding &TE,
- const clang::LangOptions &Opts) {
+ const clang::LangOptions &Opts,
+ clang::TargetInfo &TInfo) {
using namespace llvm;
const char *UTF8 = "UTF-8";
TE.LiteralEncoding =
Opts.LiteralEncoding.empty() ? UTF8 : Opts.LiteralEncoding.c_str();
- // Create converter between internal and literal encoding specified
- // in fexec-charset option.
- if (TE.LiteralEncoding == UTF8)
+ if (TE.LiteralEncoding != UTF8) {
+ ErrorOr<TextEncodingConverter> ErrorOrLiteralConverter =
+ llvm::TextEncodingConverter::create(UTF8, TE.LiteralEncoding);
+ if (ErrorOrLiteralConverter)
+ TE.ToLiteralEncodingConverter = std::make_unique<TextEncodingConverter>(
+ std::move(*ErrorOrLiteralConverter));
+ else
+ return ErrorOrLiteralConverter.getError();
+ }
+
+ if (TInfo.getDefaultOrdinaryLiteralEncoding() == UTF8)
return std::error_code();
+
+ // Create converter between internal and default ordinary encoding for the
+ // target
ErrorOr<TextEncodingConverter> ErrorOrConverter =
- llvm::TextEncodingConverter::create(UTF8, TE.LiteralEncoding);
+ llvm::TextEncodingConverter::create(
+ UTF8, TInfo.getDefaultOrdinaryLiteralEncoding());
+ if (ErrorOrConverter)
+ TE.ToSystemEncodingConverter =
+ std::make_unique<TextEncodingConverter>(std::move(*ErrorOrConverter));
+ else
+ return ErrorOrConverter.getError();
+
+ ErrorOrConverter = llvm::TextEncodingConverter::create(
+ TInfo.getDefaultOrdinaryLiteralEncoding(), UTF8);
+
if (ErrorOrConverter)
- TE.ToLiteralEncodingConverter =
+ TInfo.TargetStrConverter =
std::make_unique<TextEncodingConverter>(std::move(*ErrorOrConverter));
else
return ErrorOrConverter.getError();
+
return std::error_code();
}
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 06482f6b65426..e7830c536f7a7 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -3021,7 +3021,8 @@ ExprResult Parser::ParseUnevaluatedStringLiteralExpression() {
}
ExprResult Parser::ParseStringLiteralExpression(bool AllowUserDefinedLiteral,
- bool Unevaluated) {
+ bool Unevaluated,
+ ConversionAction CA) {
assert(tokenIsLikeStringLiteral(Tok, getLangOpts()) &&
"Not a string-literal-like token!");
@@ -3042,8 +3043,7 @@ ExprResult Parser::ParseStringLiteralExpression(bool AllowUserDefinedLiteral,
// Pass the set of string tokens, ready for concatenation, to the actions.
return Actions.ActOnStringLiteral(
- StringToks, AllowUserDefinedLiteral ? getCurScope() : nullptr,
- ParserConversionAction);
+ StringToks, AllowUserDefinedLiteral ? getCurScope() : nullptr, CA);
}
ExprResult Parser::ParseGenericSelectionExpression() {
diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp
index 72c6808d51716..d6856206d900b 100644
--- a/clang/lib/Parse/Parser.cpp
+++ b/clang/lib/Parse/Parser.cpp
@@ -70,8 +70,6 @@ Parser::Parser(Preprocessor &pp, Sema &actions, bool skipFunctionBodies)
NumCachedScopes = 0;
CurParsedObjCImpl = nullptr;
- ParserConversionAction = CA_ToLiteralEncoding;
-
// Add #pragma handlers. These are removed and destroyed in the
// destructor.
initializePragmaHandlers();
@@ -1554,12 +1552,12 @@ void Parser::ParseKNRParamDeclarations(Declarator &D) {
}
ExprResult Parser::ParseAsmStringLiteral(bool ForAsmLabel) {
- SaveAndRestore<ConversionAction> SavedTranslationState(ParserConversionAction,
- CA_NoConversion);
ExprResult AsmString;
if (isTokenStringLiteral()) {
- AsmString = ParseStringLiteralExpression();
+ AsmString = ParseStringLiteralExpression(/*AllowUserDefinedLiteral=*/false,
+ /*Unevaluated=*/false,
+ CA_ToSystemEncoding);
if (AsmString.isInvalid())
return AsmString;
diff --git a/clang/lib/Sema/SemaStmtAsm.cpp b/clang/lib/Sema/SemaStmtAsm.cpp
index 6bf12d9cd98da..f1aab455b4411 100644
--- a/clang/lib/Sema/SemaStmtAsm.cpp
+++ b/clang/lib/Sema/SemaStmtAsm.cpp
@@ -245,6 +245,14 @@ ExprResult Sema::ActOnGCCAsmStmtString(Expr *Expr, bool ForAsmLabel) {
Diag(Expr->getBeginLoc(), diag::err_asm_operand_empty_string)
<< SL->getSourceRange();
}
+ if (Context.getTargetInfo().TargetStrConverter) {
+ SmallString<16> ConvertedAsm;
+ Context.getTargetInfo().TargetStrConverter->convert(SL->getString(),
+ ConvertedAsm);
+ return StringLiteral::Create(Context, ConvertedAsm,
+ StringLiteralKind::Ordinary,
+ /*Pascal*/ false, {}, SL->getBeginLoc());
+ }
return SL;
}
if (DiagnoseUnexpandedParameterPack(Expr))
diff --git a/clang/test/CodeGen/systemz-charset.c b/clang/test/CodeGen/systemz-charset.c
index e0d1736bf853f..f3bb1055ddf5e 100644
--- a/clang/test/CodeGen/systemz-charset.c
+++ b/clang/test/CodeGen/systemz-charset.c
@@ -67,7 +67,7 @@ const char* preprocessor_concatenation = HELLO_WORLD;
//CHECK: c"\C8\85\93\93\96@\E6\96\99\93\84Z\00"
//CHECK-UTF8: c"Hello World!\00"
-void asm_labeled_fn(void) __asm__("asm_sym");
+void asm_labeled_fn(void) __asm__("\174asm_sym");
void asm_labeled_fn(void) {}
-//CHECK: define{{.*}} void @asm_sym(
-//CHECK-UTF8: define{{.*}} void @asm_sym(
+//CHECK: define{{.*}}void @"@asm_sym"(
+//CHECK-UTF8: define{{.*}}void @"@asm_sym"(
>From c9e99a9bfc1dc844e7149b048abb5ef170f76627 Mon Sep 17 00:00:00 2001
From: Abhina Sreeskantharajan <Abhina.Sreeskantharajan at ibm.com>
Date: Fri, 10 Jul 2026 15:07:07 -0400
Subject: [PATCH 04/10] address comments, attempt to fix CI
---
clang/include/clang/Basic/TargetInfo.h | 2 +-
clang/lib/Basic/TargetInfo.cpp | 2 +-
clang/lib/Lex/TextEncoding.cpp | 2 +-
clang/lib/Sema/SemaStmtAsm.cpp | 10 ++++++----
clang/test/CodeGen/systemz-charset.c | 4 ++++
5 files changed, 13 insertions(+), 7 deletions(-)
diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h
index dba50e03cc6d6..0518e8beb5a68 100644
--- a/clang/include/clang/Basic/TargetInfo.h
+++ b/clang/include/clang/Basic/TargetInfo.h
@@ -330,7 +330,7 @@ class TargetInfo : public TransferrableTargetInfo,
virtual ~TargetInfo();
- std::unique_ptr<llvm::TextEncodingConverter> TargetStrConverter;
+ std::unique_ptr<llvm::TextEncodingConverter> FromSystemEncodingConverter;
/// Retrieve the target options.
TargetOptions &getTargetOpts() const {
diff --git a/clang/lib/Basic/TargetInfo.cpp b/clang/lib/Basic/TargetInfo.cpp
index 1cc49cf84ce4c..3cecb1adc6511 100644
--- a/clang/lib/Basic/TargetInfo.cpp
+++ b/clang/lib/Basic/TargetInfo.cpp
@@ -199,7 +199,7 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : Triple(T) {
MaxBitIntWidth.reset();
- TargetStrConverter = nullptr;
+ FromSystemEncodingConverter = nullptr;
}
// Out of line virtual dtor for TargetInfo.
diff --git a/clang/lib/Lex/TextEncoding.cpp b/clang/lib/Lex/TextEncoding.cpp
index effd05185faf7..fd59f3df59bdf 100644
--- a/clang/lib/Lex/TextEncoding.cpp
+++ b/clang/lib/Lex/TextEncoding.cpp
@@ -62,7 +62,7 @@ TextEncoding::setConvertersFromOptions(TextEncoding &TE,
TInfo.getDefaultOrdinaryLiteralEncoding(), UTF8);
if (ErrorOrConverter)
- TInfo.TargetStrConverter =
+ TInfo.FromSystemEncodingConverter =
std::make_unique<TextEncodingConverter>(std::move(*ErrorOrConverter));
else
return ErrorOrConverter.getError();
diff --git a/clang/lib/Sema/SemaStmtAsm.cpp b/clang/lib/Sema/SemaStmtAsm.cpp
index f1aab455b4411..8b61228db3533 100644
--- a/clang/lib/Sema/SemaStmtAsm.cpp
+++ b/clang/lib/Sema/SemaStmtAsm.cpp
@@ -245,13 +245,15 @@ ExprResult Sema::ActOnGCCAsmStmtString(Expr *Expr, bool ForAsmLabel) {
Diag(Expr->getBeginLoc(), diag::err_asm_operand_empty_string)
<< SL->getSourceRange();
}
- if (Context.getTargetInfo().TargetStrConverter) {
+ if (Context.getTargetInfo().FromSystemEncodingConverter) {
SmallString<16> ConvertedAsm;
- Context.getTargetInfo().TargetStrConverter->convert(SL->getString(),
- ConvertedAsm);
+ Context.getTargetInfo().FromSystemEncodingConverter->convert(
+ SL->getString(), ConvertedAsm);
+ QualType StrTy = Context.getStringLiteralArrayType(Context.CharTy,
+ ConvertedAsm.size());
return StringLiteral::Create(Context, ConvertedAsm,
StringLiteralKind::Ordinary,
- /*Pascal*/ false, {}, SL->getBeginLoc());
+ /*Pascal*/ false, StrTy, SL->getBeginLoc());
}
return SL;
}
diff --git a/clang/test/CodeGen/systemz-charset.c b/clang/test/CodeGen/systemz-charset.c
index f3bb1055ddf5e..4ccc9934e4bde 100644
--- a/clang/test/CodeGen/systemz-charset.c
+++ b/clang/test/CodeGen/systemz-charset.c
@@ -71,3 +71,7 @@ void asm_labeled_fn(void) __asm__("\174asm_sym");
void asm_labeled_fn(void) {}
//CHECK: define{{.*}}void @"@asm_sym"(
//CHECK-UTF8: define{{.*}}void @"@asm_sym"(
+
+void asm_stmt_fn(void) { __asm__("\225\226\227nop"); }
+//CHECK: call void asm{{.*}}"nopnop"
+//CHECK-UTF8: call void asm{{.*}}"nopnop"
>From 2931a8a2d84dabc94e20619d69aedbfe54f4989f Mon Sep 17 00:00:00 2001
From: Abhina Sreeskantharajan <Abhina.Sreeskantharajan at ibm.com>
Date: Fri, 17 Jul 2026 14:31:50 -0400
Subject: [PATCH 05/10] check for UTF-8 to avoid conversion codepath if no
conversion is needed
---
clang/lib/Sema/SemaStmtAsm.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/lib/Sema/SemaStmtAsm.cpp b/clang/lib/Sema/SemaStmtAsm.cpp
index 8b61228db3533..e0c3f7c7fd84f 100644
--- a/clang/lib/Sema/SemaStmtAsm.cpp
+++ b/clang/lib/Sema/SemaStmtAsm.cpp
@@ -245,7 +245,7 @@ ExprResult Sema::ActOnGCCAsmStmtString(Expr *Expr, bool ForAsmLabel) {
Diag(Expr->getBeginLoc(), diag::err_asm_operand_empty_string)
<< SL->getSourceRange();
}
- if (Context.getTargetInfo().FromSystemEncodingConverter) {
+ if (Context.getTargetInfo().FromSystemEncodingConverter != nullptr) {
SmallString<16> ConvertedAsm;
Context.getTargetInfo().FromSystemEncodingConverter->convert(
SL->getString(), ConvertedAsm);
>From a18b6d5603ff9c0c1badb2e3a068d9197daa6f5a Mon Sep 17 00:00:00 2001
From: Abhina Sreeskantharajan <Abhina.Sreeskantharajan at ibm.com>
Date: Tue, 11 Aug 2026 09:02:17 -0400
Subject: [PATCH 06/10] Remove unrelated testcases
---
clang/test/CodeGen/systemz-charset-diag.cpp | 8 --------
1 file changed, 8 deletions(-)
diff --git a/clang/test/CodeGen/systemz-charset-diag.cpp b/clang/test/CodeGen/systemz-charset-diag.cpp
index ad08e1f391214..4ed94810150a3 100644
--- a/clang/test/CodeGen/systemz-charset-diag.cpp
+++ b/clang/test/CodeGen/systemz-charset-diag.cpp
@@ -1,11 +1,3 @@
// RUN: %clang_cc1 -triple s390x-none-zos -fexec-charset IBM-1047 %s -std=c++17 -emit-llvm -o - -verify
const char* Computer = "🖥️"; // expected-error-re {{conversion to literal encoding failed: {{.*}}}}
-
-static_assert(false, "Error string"); // expected-error {{static assertion failed: Error string}}
-
-[[deprecated("message")]] void test_deprecated() {return;} // expected-note {{'test_deprecated' has been explicitly marked deprecated here}}
-
-int main() {
- test_deprecated(); // expected-warning {{'test_deprecated' is deprecated: message}}
-}
>From 509257d1de4c50bfc9ea350aee21a3d9c544ab76 Mon Sep 17 00:00:00 2001
From: Abhina Sreeskantharajan <Abhina.Sreeskantharajan at ibm.com>
Date: Thu, 13 Aug 2026 14:18:12 -0400
Subject: [PATCH 07/10] constexpr in asm strings will be in fexec-charset, do
not do backwards conversion for those strings
---
clang/include/clang/Sema/Sema.h | 3 ++-
clang/lib/Parse/Parser.cpp | 5 ++++-
clang/lib/Sema/SemaStmtAsm.cpp | 7 +++++--
clang/test/CodeGen/systemz-charset.cpp | 24 ++++++++++++++++++++++++
4 files changed, 35 insertions(+), 4 deletions(-)
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 8ff9cba3ead47..de87529aa9d9f 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -11429,7 +11429,8 @@ class Sema final : public SemaBase {
///@{
public:
- ExprResult ActOnGCCAsmStmtString(Expr *Stm, bool ForAsmLabel);
+ ExprResult ActOnGCCAsmStmtString(Expr *Stm, bool ForAsmLabel,
+ bool IsConstExpr = false);
StmtResult ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
bool IsVolatile, unsigned NumOutputs,
unsigned NumInputs, IdentifierInfo **Names,
diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp
index d6856206d900b..6d1e006a180de 100644
--- a/clang/lib/Parse/Parser.cpp
+++ b/clang/lib/Parse/Parser.cpp
@@ -1554,6 +1554,7 @@ void Parser::ParseKNRParamDeclarations(Declarator &D) {
ExprResult Parser::ParseAsmStringLiteral(bool ForAsmLabel) {
ExprResult AsmString;
+ bool IsConstExpr = false;
if (isTokenStringLiteral()) {
AsmString = ParseStringLiteralExpression(/*AllowUserDefinedLiteral=*/false,
/*Unevaluated=*/false,
@@ -1569,6 +1570,7 @@ ExprResult Parser::ParseAsmStringLiteral(bool ForAsmLabel) {
}
} else if (!ForAsmLabel && getLangOpts().CPlusPlus11 &&
Tok.is(tok::l_paren)) {
+ IsConstExpr = true;
ParenParseOption ExprType = ParenParseOption::SimpleExpr;
SourceLocation RParenLoc;
ParsedType CastTy;
@@ -1588,7 +1590,8 @@ ExprResult Parser::ParseAsmStringLiteral(bool ForAsmLabel) {
(getLangOpts().CPlusPlus11 && !ForAsmLabel) ? 0 : 1);
}
- return Actions.ActOnGCCAsmStmtString(AsmString.get(), ForAsmLabel);
+ return Actions.ActOnGCCAsmStmtString(AsmString.get(), ForAsmLabel,
+ IsConstExpr);
}
ExprResult Parser::ParseSimpleAsm(bool ForAsmLabel, SourceLocation *EndLoc) {
diff --git a/clang/lib/Sema/SemaStmtAsm.cpp b/clang/lib/Sema/SemaStmtAsm.cpp
index e0c3f7c7fd84f..a4506587f3675 100644
--- a/clang/lib/Sema/SemaStmtAsm.cpp
+++ b/clang/lib/Sema/SemaStmtAsm.cpp
@@ -235,7 +235,8 @@ getClobberConflictLocation(MultiExprArg Exprs, Expr **Constraints,
return SourceLocation();
}
-ExprResult Sema::ActOnGCCAsmStmtString(Expr *Expr, bool ForAsmLabel) {
+ExprResult Sema::ActOnGCCAsmStmtString(Expr *Expr, bool ForAsmLabel,
+ bool IsConstExpr) {
if (!Expr)
return ExprError();
@@ -245,7 +246,8 @@ ExprResult Sema::ActOnGCCAsmStmtString(Expr *Expr, bool ForAsmLabel) {
Diag(Expr->getBeginLoc(), diag::err_asm_operand_empty_string)
<< SL->getSourceRange();
}
- if (Context.getTargetInfo().FromSystemEncodingConverter != nullptr) {
+ if (!IsConstExpr &&
+ Context.getTargetInfo().FromSystemEncodingConverter != nullptr) {
SmallString<16> ConvertedAsm;
Context.getTargetInfo().FromSystemEncodingConverter->convert(
SL->getString(), ConvertedAsm);
@@ -272,6 +274,7 @@ ExprResult Sema::ActOnGCCAsmStmtString(Expr *Expr, bool ForAsmLabel) {
ConstantExpr *Res = ConstantExpr::Create(getASTContext(), Expr,
ConstantResultStorageKind::APValue);
+
Res->SetResult(V, getASTContext());
return Res;
}
diff --git a/clang/test/CodeGen/systemz-charset.cpp b/clang/test/CodeGen/systemz-charset.cpp
index 41674e9c11a64..6348fb72dac9a 100644
--- a/clang/test/CodeGen/systemz-charset.cpp
+++ b/clang/test/CodeGen/systemz-charset.cpp
@@ -72,3 +72,27 @@ const char16_t *UnicodeUCNString16 = u"\u00E2\u00AC\U000000DF";
const char32_t *UnicodeUCNString32 = U"\u00E2\u00AC\U000000DF";
//CHECK: [4 x i32] [i32 226, i32 172, i32 223, i32 0]
//CHECK-UTF8: [4 x i32] [i32 226, i32 172, i32 223, i32 0]
+
+
+struct string_view {
+ int S;
+ const char* D;
+ constexpr string_view() : S(0), D(0){}
+ constexpr string_view(const char* Str) : S(__builtin_strlen(Str)), D(Str) {}
+ constexpr string_view(int Size, const char* Str) : S(Size), D(Str) {}
+ constexpr int size() const {
+ return S;
+ }
+ constexpr const char* data() const {
+ return D;
+ }
+};
+
+constexpr string_view getfoo() { return "\174foo"; }
+
+void function()
+{
+ asm((getfoo()));
+}
+// CHECK: asm{{.*}}|\86\96\96
+// CHECK-UTF8: asm{{.*}}|foo
>From 61b1af4f9ab8f89615a57abcd8202fc8178890ed Mon Sep 17 00:00:00 2001
From: Abhina Sreeskantharajan <Abhina.Sreeskantharajan at ibm.com>
Date: Wed, 30 Sep 2026 11:52:59 -0400
Subject: [PATCH 08/10] rename FromSystemEncodingConverter and move out of
TargetInfo
---
clang/include/clang/Basic/TargetInfo.h | 3 ---
clang/include/clang/Lex/TextEncoding.h | 14 +++++++++++++-
clang/lib/Basic/TargetInfo.cpp | 2 --
clang/lib/Lex/TextEncoding.cpp | 19 +++++++++++++------
clang/lib/Sema/SemaStmtAsm.cpp | 9 +++++----
5 files changed, 31 insertions(+), 16 deletions(-)
diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h
index 0518e8beb5a68..6311b6b567a5e 100644
--- a/clang/include/clang/Basic/TargetInfo.h
+++ b/clang/include/clang/Basic/TargetInfo.h
@@ -38,7 +38,6 @@
#include "llvm/IR/DerivedTypes.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/Error.h"
-#include "llvm/Support/TextEncoding.h"
#include "llvm/Support/VersionTuple.h"
#include "llvm/TargetParser/Triple.h"
#include <cassert>
@@ -330,8 +329,6 @@ class TargetInfo : public TransferrableTargetInfo,
virtual ~TargetInfo();
- std::unique_ptr<llvm::TextEncodingConverter> FromSystemEncodingConverter;
-
/// Retrieve the target options.
TargetOptions &getTargetOpts() const {
assert(TargetOpts && "Missing target options");
diff --git a/clang/include/clang/Lex/TextEncoding.h b/clang/include/clang/Lex/TextEncoding.h
index 02cb16cef9f1b..ec826ec661592 100644
--- a/clang/include/clang/Lex/TextEncoding.h
+++ b/clang/include/clang/Lex/TextEncoding.h
@@ -27,10 +27,22 @@ enum ConversionAction {
class TextEncoding {
llvm::StringRef LiteralEncoding;
std::unique_ptr<llvm::TextEncodingConverter> ToLiteralEncodingConverter;
- std::unique_ptr<llvm::TextEncodingConverter> ToSystemEncodingConverter;
+
+ // Only non-null on z/OS, where the system default encoding is IBM-1047.
+ // This converts UTF-8 to IBM-1047 for asm string literals so that
+ // octal/hex escape sequences are interpreted as IBM-1047 code points,
+ // regardless of -fexec-charset.
+ std::unique_ptr<llvm::TextEncodingConverter> ToIBM1047Converter;
+ std::unique_ptr<llvm::TextEncodingConverter> FromIBM1047Converter;
public:
llvm::TextEncodingConverter *getConverter(ConversionAction Action) const;
+
+ /// Returns the converter from IBM-1047 to UTF-8, or nullptr if not on z/OS.
+ llvm::TextEncodingConverter *getFromIBM1047Converter() const {
+ return FromIBM1047Converter.get();
+ }
+
static std::error_code
setConvertersFromOptions(TextEncoding &TE, const clang::LangOptions &Opts,
clang::TargetInfo &TInfo);
diff --git a/clang/lib/Basic/TargetInfo.cpp b/clang/lib/Basic/TargetInfo.cpp
index 3cecb1adc6511..1bb0026d8422e 100644
--- a/clang/lib/Basic/TargetInfo.cpp
+++ b/clang/lib/Basic/TargetInfo.cpp
@@ -198,8 +198,6 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : Triple(T) {
MaxOpenCLWorkGroupSize = 1024;
MaxBitIntWidth.reset();
-
- FromSystemEncodingConverter = nullptr;
}
// Out of line virtual dtor for TargetInfo.
diff --git a/clang/lib/Lex/TextEncoding.cpp b/clang/lib/Lex/TextEncoding.cpp
index fd59f3df59bdf..6ee6f8a0ef266 100644
--- a/clang/lib/Lex/TextEncoding.cpp
+++ b/clang/lib/Lex/TextEncoding.cpp
@@ -18,7 +18,8 @@ TextEncoding::getConverter(ConversionAction Action) const {
case CA_ToLiteralEncoding:
return ToLiteralEncodingConverter.get();
case CA_ToSystemEncoding:
- return ToSystemEncodingConverter.get();
+ // return null for non-z/OS targets
+ return ToIBM1047Converter.get();
default:
return nullptr;
}
@@ -34,6 +35,8 @@ TextEncoding::setConvertersFromOptions(TextEncoding &TE,
TE.LiteralEncoding =
Opts.LiteralEncoding.empty() ? UTF8 : Opts.LiteralEncoding.c_str();
+ // Create converter between internal and literal encoding specified
+ // in fexec-charset option.
if (TE.LiteralEncoding != UTF8) {
ErrorOr<TextEncodingConverter> ErrorOrLiteralConverter =
llvm::TextEncodingConverter::create(UTF8, TE.LiteralEncoding);
@@ -47,22 +50,26 @@ TextEncoding::setConvertersFromOptions(TextEncoding &TE,
if (TInfo.getDefaultOrdinaryLiteralEncoding() == UTF8)
return std::error_code();
- // Create converter between internal and default ordinary encoding for the
- // target
+ // The IBM-1047 converters are only needed on z/OS, where the system
+ // (assembler/linker) default encoding is IBM-1047 rather than UTF-8.
+ assert((TInfo.getTriple().getOS() == llvm::Triple::ZOS) &&
+ "Non-UTF-8 system encoding is only expected on z/OS");
+
+ // Create a converter from UTF-8 to IBM-1047 for use when parsing asm string
+ // literals on z/OS, where escape sequences are IBM-1047 code points.
ErrorOr<TextEncodingConverter> ErrorOrConverter =
llvm::TextEncodingConverter::create(
UTF8, TInfo.getDefaultOrdinaryLiteralEncoding());
if (ErrorOrConverter)
- TE.ToSystemEncodingConverter =
+ TE.ToIBM1047Converter =
std::make_unique<TextEncodingConverter>(std::move(*ErrorOrConverter));
else
return ErrorOrConverter.getError();
ErrorOrConverter = llvm::TextEncodingConverter::create(
TInfo.getDefaultOrdinaryLiteralEncoding(), UTF8);
-
if (ErrorOrConverter)
- TInfo.FromSystemEncodingConverter =
+ TE.FromIBM1047Converter =
std::make_unique<TextEncodingConverter>(std::move(*ErrorOrConverter));
else
return ErrorOrConverter.getError();
diff --git a/clang/lib/Sema/SemaStmtAsm.cpp b/clang/lib/Sema/SemaStmtAsm.cpp
index a4506587f3675..f8c5e904effb7 100644
--- a/clang/lib/Sema/SemaStmtAsm.cpp
+++ b/clang/lib/Sema/SemaStmtAsm.cpp
@@ -15,6 +15,7 @@
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/TextEncoding.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Ownership.h"
@@ -24,6 +25,7 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/MC/MCParser/MCAsmParser.h"
+#include "llvm/Support/TextEncoding.h"
#include <optional>
using namespace clang;
using namespace sema;
@@ -247,10 +249,10 @@ ExprResult Sema::ActOnGCCAsmStmtString(Expr *Expr, bool ForAsmLabel,
<< SL->getSourceRange();
}
if (!IsConstExpr &&
- Context.getTargetInfo().FromSystemEncodingConverter != nullptr) {
+ PP.getTextEncoding().getFromIBM1047Converter() != nullptr) {
SmallString<16> ConvertedAsm;
- Context.getTargetInfo().FromSystemEncodingConverter->convert(
- SL->getString(), ConvertedAsm);
+ PP.getTextEncoding().getFromIBM1047Converter()->convert(SL->getString(),
+ ConvertedAsm);
QualType StrTy = Context.getStringLiteralArrayType(Context.CharTy,
ConvertedAsm.size());
return StringLiteral::Create(Context, ConvertedAsm,
@@ -274,7 +276,6 @@ ExprResult Sema::ActOnGCCAsmStmtString(Expr *Expr, bool ForAsmLabel,
ConstantExpr *Res = ConstantExpr::Create(getASTContext(), Expr,
ConstantResultStorageKind::APValue);
-
Res->SetResult(V, getASTContext());
return Res;
}
>From 8951bc8e0407db1bf460394636c10b0a3a6b8d0f Mon Sep 17 00:00:00 2001
From: Abhina Sreeskantharajan <Abhina.Sreeskantharajan at ibm.com>
Date: Mon, 5 Oct 2026 10:13:37 -0400
Subject: [PATCH 09/10] rename CA_ToSystemEncoding to
CA_ToLiteralEncodingForAsm
---
clang/include/clang/Lex/TextEncoding.h | 2 +-
clang/lib/Lex/TextEncoding.cpp | 2 +-
clang/lib/Parse/Parser.cpp | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/clang/include/clang/Lex/TextEncoding.h b/clang/include/clang/Lex/TextEncoding.h
index ec826ec661592..46903a5361059 100644
--- a/clang/include/clang/Lex/TextEncoding.h
+++ b/clang/include/clang/Lex/TextEncoding.h
@@ -20,7 +20,7 @@ class TextEncodingConverter;
namespace clang {
enum ConversionAction {
CA_NoConversion,
- CA_ToSystemEncoding,
+ CA_ToLiteralEncodingForAsm, // IBM-1047 on z/OS, UTF-8 on other platforms
CA_ToLiteralEncoding
};
diff --git a/clang/lib/Lex/TextEncoding.cpp b/clang/lib/Lex/TextEncoding.cpp
index 6ee6f8a0ef266..afb5130ece88e 100644
--- a/clang/lib/Lex/TextEncoding.cpp
+++ b/clang/lib/Lex/TextEncoding.cpp
@@ -17,7 +17,7 @@ TextEncoding::getConverter(ConversionAction Action) const {
switch (Action) {
case CA_ToLiteralEncoding:
return ToLiteralEncodingConverter.get();
- case CA_ToSystemEncoding:
+ case CA_ToLiteralEncodingForAsm:
// return null for non-z/OS targets
return ToIBM1047Converter.get();
default:
diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp
index 6d1e006a180de..afebe64d3e66d 100644
--- a/clang/lib/Parse/Parser.cpp
+++ b/clang/lib/Parse/Parser.cpp
@@ -1558,7 +1558,7 @@ ExprResult Parser::ParseAsmStringLiteral(bool ForAsmLabel) {
if (isTokenStringLiteral()) {
AsmString = ParseStringLiteralExpression(/*AllowUserDefinedLiteral=*/false,
/*Unevaluated=*/false,
- CA_ToSystemEncoding);
+ CA_ToLiteralEncodingForAsm);
if (AsmString.isInvalid())
return AsmString;
>From bcd956509f05849dec71f136867ee78376f570b0 Mon Sep 17 00:00:00 2001
From: Abhina Sreeskantharajan <Abhina.Sreeskantharajan at ibm.com>
Date: Wed, 7 Oct 2026 10:56:26 -0400
Subject: [PATCH 10/10] add more testcases, make diagnostic message generic
---
clang/include/clang/Basic/DiagnosticLexKinds.td | 2 +-
clang/test/CodeGen/systemz-charset-diag.cpp | 2 +-
clang/test/CodeGen/systemz-charset.cpp | 8 ++++++--
clang/test/Sema/systemz-charset-asm.cpp | 11 +++++++++++
4 files changed, 19 insertions(+), 4 deletions(-)
create mode 100644 clang/test/Sema/systemz-charset-asm.cpp
diff --git a/clang/include/clang/Basic/DiagnosticLexKinds.td b/clang/include/clang/Basic/DiagnosticLexKinds.td
index f0791ed486a74..bc1518b7995b7 100644
--- a/clang/include/clang/Basic/DiagnosticLexKinds.td
+++ b/clang/include/clang/Basic/DiagnosticLexKinds.td
@@ -292,7 +292,7 @@ def ext_string_too_long : Extension<"string literal of length %0 exceeds "
def err_character_too_large : Error<
"character too large for enclosing character literal type">;
def err_exec_charset_conversion_failed
- : Error<"conversion to literal encoding failed: '%0'">;
+ : Error<"encoding conversion failed: '%0'">;
def warn_c99_compat_unicode_literal : Warning<
"unicode literals are incompatible with C99">,
InGroup<C99Compat>, DefaultIgnore;
diff --git a/clang/test/CodeGen/systemz-charset-diag.cpp b/clang/test/CodeGen/systemz-charset-diag.cpp
index 4ed94810150a3..a59a5ef4f0604 100644
--- a/clang/test/CodeGen/systemz-charset-diag.cpp
+++ b/clang/test/CodeGen/systemz-charset-diag.cpp
@@ -1,3 +1,3 @@
// RUN: %clang_cc1 -triple s390x-none-zos -fexec-charset IBM-1047 %s -std=c++17 -emit-llvm -o - -verify
-const char* Computer = "🖥️"; // expected-error-re {{conversion to literal encoding failed: {{.*}}}}
+const char* Computer = "🖥️"; // expected-error-re {{encoding conversion failed: {{.*}}}}
diff --git a/clang/test/CodeGen/systemz-charset.cpp b/clang/test/CodeGen/systemz-charset.cpp
index 6348fb72dac9a..b6b79842468c1 100644
--- a/clang/test/CodeGen/systemz-charset.cpp
+++ b/clang/test/CodeGen/systemz-charset.cpp
@@ -92,7 +92,11 @@ constexpr string_view getfoo() { return "\174foo"; }
void function()
{
+ asm("\174foo");
+ // CHECK: asm{{.*}}@foo
+ // CHECK-UTF8: asm{{.*}}@foo
asm((getfoo()));
+ // CHECK: asm{{.*}}|\86\96\96
+ // CHECK-UTF8: asm{{.*}}|foo
}
-// CHECK: asm{{.*}}|\86\96\96
-// CHECK-UTF8: asm{{.*}}|foo
+
diff --git a/clang/test/Sema/systemz-charset-asm.cpp b/clang/test/Sema/systemz-charset-asm.cpp
new file mode 100644
index 0000000000000..b3c27cc53638e
--- /dev/null
+++ b/clang/test/Sema/systemz-charset-asm.cpp
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -triple s390x-none-zos -fexec-charset IBM-1047 %s -std=c++23 -fsyntax-only -verify
+// RUN: %clang_cc1 -triple s390x-none-zos -fexec-charset UTF-8 %s -std=c++23 -fsyntax-only -verify
+
+long inline_asm_ucn_named_operand(long a, long b) {
+ // The \N{...} escape encodes to U+0130. IBM-1047 has no code point for
+ // U+0130, so the conversion reports an error.
+ asm("\tLGR %0, %[\N{LATIN CAPITAL LETTER I WITH DOT ABOVE}]\n" // expected-error-re {{encoding conversion failed: {{.*}}}}
+ : "=r"(a)
+ : [\N{LATIN CAPITAL LETTER I WITH DOT ABOVE}] "r"(b));
+ return a;
+}
More information about the cfe-commits
mailing list