[clang] [Clang][WIP] Constant Expressions inside of gcc'asm strings (PR #131003)
@@ -2586,10 +2586,11 @@ static void UpdateAsmCallInst(llvm::CallBase &Result, bool HasSideEffect, // Slap the source location of the inline asm into a !srcloc metadata on the // call. - if (const auto *gccAsmStmt = dyn_cast(&S)) -Result.setMetadata("srcloc", - getAsmSrcLocInfo(gccAsmStmt->getAsmString(), CGF)); - else { + if (const auto *gccAsmStmt = dyn_cast(&S)) { +if (const StringLiteral *SL = +dyn_cast(gccAsmStmt->getAsmStringExpr())) + Result.setMetadata("srcloc", getAsmSrcLocInfo(SL, CGF)); efriedma-quic wrote: What do the diagnostics look like if you get a parse failure inside the inline asm? https://github.com/llvm/llvm-project/pull/131003 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][WIP] Constant Expressions inside of gcc'asm strings (PR #131003)
@@ -17261,33 +17261,50 @@ void Sema::DiagnoseStaticAssertDetails(const Expr *E) { } } -bool Sema::EvaluateStaticAssertMessageAsString(Expr *Message, - std::string &Result, - ASTContext &Ctx, - bool ErrorOnInvalidMessage) { +template +static bool EvaluateAsStringImpl(Sema &SemaRef, Expr *Message, + ResultType &Result, ASTContext &Ctx, + Sema::StringEvaluationContext EvalContext, + bool ErrorOnInvalidMessage) { + assert(Message); assert(!Message->isTypeDependent() && !Message->isValueDependent() && "can't evaluate a dependant static assert message"); if (const auto *SL = dyn_cast(Message)) { assert(SL->isUnevaluated() && "expected an unevaluated string"); -Result.assign(SL->getString().begin(), SL->getString().end()); +if constexpr (std::is_same_v) { + Result = + APValue(APValue::UninitArray{}, SL->getLength(), SL->getLength()); + const ConstantArrayType *CAT = + SemaRef.getASTContext().getAsConstantArrayType(SL->getType()); + assert(CAT && "string literal isn't an array"); + QualType CharType = CAT->getElementType(); + llvm::APSInt Value(SemaRef.getASTContext().getTypeSize(CharType), + CharType->isUnsignedIntegerType()); + for (unsigned I = 0; I < SL->getLength(); I++) { +Value = SL->getCodeUnit(I); +Result.getArrayInitializedElt(I) = APValue(Value); + } +} else { + Result.assign(SL->getString().begin(), SL->getString().end()); +} return true; } SourceLocation Loc = Message->getBeginLoc(); QualType T = Message->getType().getNonReferenceType(); auto *RD = T->getAsCXXRecordDecl(); if (!RD) { -Diag(Loc, diag::err_static_assert_invalid_message); +SemaRef.Diag(Loc, diag::err_user_defined_msg_invalid) << EvalContext; return false; } auto FindMember = [&](StringRef Member, bool &Empty, bool Diag = false) -> std::optional { cor3ntin wrote: It is preexisting, but there was a lot of nonsense here; thanks! https://github.com/llvm/llvm-project/pull/131003 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][WIP] Constant Expressions inside of gcc'asm strings (PR #131003)
@@ -17261,33 +17261,50 @@ void Sema::DiagnoseStaticAssertDetails(const Expr *E) { } } -bool Sema::EvaluateStaticAssertMessageAsString(Expr *Message, - std::string &Result, - ASTContext &Ctx, - bool ErrorOnInvalidMessage) { +template +static bool EvaluateAsStringImpl(Sema &SemaRef, Expr *Message, + ResultType &Result, ASTContext &Ctx, + Sema::StringEvaluationContext EvalContext, + bool ErrorOnInvalidMessage) { + assert(Message); assert(!Message->isTypeDependent() && !Message->isValueDependent() && "can't evaluate a dependant static assert message"); if (const auto *SL = dyn_cast(Message)) { assert(SL->isUnevaluated() && "expected an unevaluated string"); -Result.assign(SL->getString().begin(), SL->getString().end()); +if constexpr (std::is_same_v) { + Result = + APValue(APValue::UninitArray{}, SL->getLength(), SL->getLength()); + const ConstantArrayType *CAT = + SemaRef.getASTContext().getAsConstantArrayType(SL->getType()); + assert(CAT && "string literal isn't an array"); + QualType CharType = CAT->getElementType(); + llvm::APSInt Value(SemaRef.getASTContext().getTypeSize(CharType), + CharType->isUnsignedIntegerType()); + for (unsigned I = 0; I < SL->getLength(); I++) { +Value = SL->getCodeUnit(I); +Result.getArrayInitializedElt(I) = APValue(Value); + } +} else { + Result.assign(SL->getString().begin(), SL->getString().end()); +} return true; } SourceLocation Loc = Message->getBeginLoc(); QualType T = Message->getType().getNonReferenceType(); auto *RD = T->getAsCXXRecordDecl(); if (!RD) { -Diag(Loc, diag::err_static_assert_invalid_message); +SemaRef.Diag(Loc, diag::err_user_defined_msg_invalid) << EvalContext; return false; } auto FindMember = [&](StringRef Member, bool &Empty, bool Diag = false) -> std::optional { erichkeane wrote: `Diag` isn't actually used at all! https://github.com/llvm/llvm-project/pull/131003 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][WIP] Constant Expressions inside of gcc'asm strings (PR #131003)
@@ -609,9 +632,10 @@ int GCCAsmStmt::getNamedOperand(StringRef SymbolicName) const { /// true, otherwise return false. unsigned GCCAsmStmt::AnalyzeAsmString(SmallVectorImpl&Pieces, const ASTContext &C, unsigned &DiagOffs) const { - StringRef Str = getAsmString()->getString(); - const char *StrStart = Str.begin(); - const char *StrEnd = Str.end(); + + std::string Str = getAsmString(); + const char *StrStart = Str.data(); cor3ntin wrote: begin/end are iterators, and some of the arithmetic in this function we do requires pointers https://github.com/llvm/llvm-project/pull/131003 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][WIP] Constant Expressions inside of gcc'asm strings (PR #131003)
llvmbot wrote: @llvm/pr-subscribers-clang Author: cor3ntin (cor3ntin) Changes Implements GCC's constexpr string ASM extension https://gcc.gnu.org/onlinedocs/gcc/Asm-constexprs.html --- Patch is 77.41 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/131003.diff 25 Files Affected: - (modified) clang/docs/LanguageExtensions.rst (+18) - (modified) clang/docs/ReleaseNotes.rst (+9) - (modified) clang/include/clang/AST/Expr.h (+4) - (modified) clang/include/clang/AST/RecursiveASTVisitor.h (+4-4) - (modified) clang/include/clang/AST/Stmt.h (+28-32) - (modified) clang/include/clang/Basic/DiagnosticParseKinds.td (+4-1) - (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+23-13) - (modified) clang/include/clang/Basic/Features.def (+1) - (modified) clang/include/clang/Sema/Sema.h (+17-3) - (modified) clang/lib/AST/ASTImporter.cpp (+6-6) - (modified) clang/lib/AST/ExprConstant.cpp (+40-11) - (modified) clang/lib/AST/Stmt.cpp (+78-48) - (modified) clang/lib/AST/StmtPrinter.cpp (+4-4) - (modified) clang/lib/AST/StmtProfile.cpp (+4-4) - (modified) clang/lib/CodeGen/CGStmt.cpp (+9-8) - (modified) clang/lib/Parse/ParseStmtAsm.cpp (+3-3) - (modified) clang/lib/Parse/Parser.cpp (+27-14) - (modified) clang/lib/Sema/SemaDeclCXX.cpp (+72-34) - (modified) clang/lib/Sema/SemaStmtAsm.cpp (+107-65) - (modified) clang/lib/Sema/TreeTransform.h (+36-13) - (modified) clang/lib/Serialization/ASTReaderStmt.cpp (+5-5) - (modified) clang/lib/Serialization/ASTWriterStmt.cpp (+4-4) - (added) clang/test/CodeGenCXX/gnu-asm-constexpr.cpp (+38) - (modified) clang/test/Parser/asm.cpp (+45) - (added) clang/test/Sema/gnu-asm-constexpr.cpp (+127) ``diff diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index f8d1bc9fe2624..a990eefc8eeac 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -1958,6 +1958,24 @@ references can be used instead of numeric references. return -1; } + +Constexpr strings in GNU ASM statememts +=== + +In C++11 mode (and greater), Clang supports specifying the template, +constraints, and clobber strings with a parenthesized constant expression +producing an object with ``data`` and ``size`` member functions, +such as ``std::string``. + +Query for this feature with ``__has_extension(gnu_asm_constexpr_strings)``. + +.. code-block:: c++ + + int foo() { + asm((std::string_view("nop")) ::: (std::string_view("memory"))); + } + + Objective-C Features diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 48da5558b3f38..c438b9a997ad8 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -74,6 +74,15 @@ What's New in Clang |release|? C++ Language Changes +- Similarly to GCC, Clang now supports constant expressions in + the strings of a GNU ``asm`` statement. + + .. code-block:: c++ + +int foo() { + asm((std::string_view("nop")) ::: (std::string_view("memory"))); +} + C++2c Feature Support ^ diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index cfe49acf20b77..28437b5629b00 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -787,6 +787,10 @@ class Expr : public ValueStmt { const Expr *PtrExpression, ASTContext &Ctx, EvalResult &Status) const; + bool EvaluateCharRangeAsString(APValue &Result, const Expr *SizeExpression, + const Expr *PtrExpression, ASTContext &Ctx, + EvalResult &Status) const; + /// If the current Expr can be evaluated to a pointer to a null-terminated /// constant string, return the constant string (without the terminating /// null). diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index fac4c10987157..87a6c22b35ee8 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -2410,15 +2410,15 @@ DEF_TRAVERSE_DECL(ImplicitConceptSpecializationDecl, { } DEF_TRAVERSE_STMT(GCCAsmStmt, { - TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getAsmString()); + TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getAsmStringExpr()); for (unsigned I = 0, E = S->getNumInputs(); I < E; ++I) { -TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getInputConstraintLiteral(I)); +TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getInputConstraintExpr(I)); } for (unsigned I = 0, E = S->getNumOutputs(); I < E; ++I) { -TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOutputConstraintLiteral(I)); +TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOutputConstraintExpr(I)); } for (unsigned I = 0, E = S->getNumClobbers(); I < E; ++I) { -TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getClobberStringLiteral(I)); +TRY_TO_TRAV
[clang] [Clang][WIP] Constant Expressions inside of gcc'asm strings (PR #131003)
llvmbot wrote: @llvm/pr-subscribers-clang-modules Author: cor3ntin (cor3ntin) Changes Implements GCC's constexpr string ASM extension https://gcc.gnu.org/onlinedocs/gcc/Asm-constexprs.html --- Patch is 77.41 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/131003.diff 25 Files Affected: - (modified) clang/docs/LanguageExtensions.rst (+18) - (modified) clang/docs/ReleaseNotes.rst (+9) - (modified) clang/include/clang/AST/Expr.h (+4) - (modified) clang/include/clang/AST/RecursiveASTVisitor.h (+4-4) - (modified) clang/include/clang/AST/Stmt.h (+28-32) - (modified) clang/include/clang/Basic/DiagnosticParseKinds.td (+4-1) - (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+23-13) - (modified) clang/include/clang/Basic/Features.def (+1) - (modified) clang/include/clang/Sema/Sema.h (+17-3) - (modified) clang/lib/AST/ASTImporter.cpp (+6-6) - (modified) clang/lib/AST/ExprConstant.cpp (+40-11) - (modified) clang/lib/AST/Stmt.cpp (+78-48) - (modified) clang/lib/AST/StmtPrinter.cpp (+4-4) - (modified) clang/lib/AST/StmtProfile.cpp (+4-4) - (modified) clang/lib/CodeGen/CGStmt.cpp (+9-8) - (modified) clang/lib/Parse/ParseStmtAsm.cpp (+3-3) - (modified) clang/lib/Parse/Parser.cpp (+27-14) - (modified) clang/lib/Sema/SemaDeclCXX.cpp (+72-34) - (modified) clang/lib/Sema/SemaStmtAsm.cpp (+107-65) - (modified) clang/lib/Sema/TreeTransform.h (+36-13) - (modified) clang/lib/Serialization/ASTReaderStmt.cpp (+5-5) - (modified) clang/lib/Serialization/ASTWriterStmt.cpp (+4-4) - (added) clang/test/CodeGenCXX/gnu-asm-constexpr.cpp (+38) - (modified) clang/test/Parser/asm.cpp (+45) - (added) clang/test/Sema/gnu-asm-constexpr.cpp (+127) ``diff diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index f8d1bc9fe2624..a990eefc8eeac 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -1958,6 +1958,24 @@ references can be used instead of numeric references. return -1; } + +Constexpr strings in GNU ASM statememts +=== + +In C++11 mode (and greater), Clang supports specifying the template, +constraints, and clobber strings with a parenthesized constant expression +producing an object with ``data`` and ``size`` member functions, +such as ``std::string``. + +Query for this feature with ``__has_extension(gnu_asm_constexpr_strings)``. + +.. code-block:: c++ + + int foo() { + asm((std::string_view("nop")) ::: (std::string_view("memory"))); + } + + Objective-C Features diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 48da5558b3f38..c438b9a997ad8 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -74,6 +74,15 @@ What's New in Clang |release|? C++ Language Changes +- Similarly to GCC, Clang now supports constant expressions in + the strings of a GNU ``asm`` statement. + + .. code-block:: c++ + +int foo() { + asm((std::string_view("nop")) ::: (std::string_view("memory"))); +} + C++2c Feature Support ^ diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index cfe49acf20b77..28437b5629b00 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -787,6 +787,10 @@ class Expr : public ValueStmt { const Expr *PtrExpression, ASTContext &Ctx, EvalResult &Status) const; + bool EvaluateCharRangeAsString(APValue &Result, const Expr *SizeExpression, + const Expr *PtrExpression, ASTContext &Ctx, + EvalResult &Status) const; + /// If the current Expr can be evaluated to a pointer to a null-terminated /// constant string, return the constant string (without the terminating /// null). diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index fac4c10987157..87a6c22b35ee8 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -2410,15 +2410,15 @@ DEF_TRAVERSE_DECL(ImplicitConceptSpecializationDecl, { } DEF_TRAVERSE_STMT(GCCAsmStmt, { - TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getAsmString()); + TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getAsmStringExpr()); for (unsigned I = 0, E = S->getNumInputs(); I < E; ++I) { -TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getInputConstraintLiteral(I)); +TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getInputConstraintExpr(I)); } for (unsigned I = 0, E = S->getNumOutputs(); I < E; ++I) { -TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOutputConstraintLiteral(I)); +TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOutputConstraintExpr(I)); } for (unsigned I = 0, E = S->getNumClobbers(); I < E; ++I) { -TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getClobberStringLiteral(I)); +TRY
[clang] [Clang][WIP] Constant Expressions inside of gcc'asm strings (PR #131003)
llvmbot wrote: @llvm/pr-subscribers-clang-codegen Author: cor3ntin (cor3ntin) Changes Implements GCC's constexpr string ASM extension https://gcc.gnu.org/onlinedocs/gcc/Asm-constexprs.html --- Patch is 77.41 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/131003.diff 25 Files Affected: - (modified) clang/docs/LanguageExtensions.rst (+18) - (modified) clang/docs/ReleaseNotes.rst (+9) - (modified) clang/include/clang/AST/Expr.h (+4) - (modified) clang/include/clang/AST/RecursiveASTVisitor.h (+4-4) - (modified) clang/include/clang/AST/Stmt.h (+28-32) - (modified) clang/include/clang/Basic/DiagnosticParseKinds.td (+4-1) - (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+23-13) - (modified) clang/include/clang/Basic/Features.def (+1) - (modified) clang/include/clang/Sema/Sema.h (+17-3) - (modified) clang/lib/AST/ASTImporter.cpp (+6-6) - (modified) clang/lib/AST/ExprConstant.cpp (+40-11) - (modified) clang/lib/AST/Stmt.cpp (+78-48) - (modified) clang/lib/AST/StmtPrinter.cpp (+4-4) - (modified) clang/lib/AST/StmtProfile.cpp (+4-4) - (modified) clang/lib/CodeGen/CGStmt.cpp (+9-8) - (modified) clang/lib/Parse/ParseStmtAsm.cpp (+3-3) - (modified) clang/lib/Parse/Parser.cpp (+27-14) - (modified) clang/lib/Sema/SemaDeclCXX.cpp (+72-34) - (modified) clang/lib/Sema/SemaStmtAsm.cpp (+107-65) - (modified) clang/lib/Sema/TreeTransform.h (+36-13) - (modified) clang/lib/Serialization/ASTReaderStmt.cpp (+5-5) - (modified) clang/lib/Serialization/ASTWriterStmt.cpp (+4-4) - (added) clang/test/CodeGenCXX/gnu-asm-constexpr.cpp (+38) - (modified) clang/test/Parser/asm.cpp (+45) - (added) clang/test/Sema/gnu-asm-constexpr.cpp (+127) ``diff diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index f8d1bc9fe2624..a990eefc8eeac 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -1958,6 +1958,24 @@ references can be used instead of numeric references. return -1; } + +Constexpr strings in GNU ASM statememts +=== + +In C++11 mode (and greater), Clang supports specifying the template, +constraints, and clobber strings with a parenthesized constant expression +producing an object with ``data`` and ``size`` member functions, +such as ``std::string``. + +Query for this feature with ``__has_extension(gnu_asm_constexpr_strings)``. + +.. code-block:: c++ + + int foo() { + asm((std::string_view("nop")) ::: (std::string_view("memory"))); + } + + Objective-C Features diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 48da5558b3f38..c438b9a997ad8 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -74,6 +74,15 @@ What's New in Clang |release|? C++ Language Changes +- Similarly to GCC, Clang now supports constant expressions in + the strings of a GNU ``asm`` statement. + + .. code-block:: c++ + +int foo() { + asm((std::string_view("nop")) ::: (std::string_view("memory"))); +} + C++2c Feature Support ^ diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index cfe49acf20b77..28437b5629b00 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -787,6 +787,10 @@ class Expr : public ValueStmt { const Expr *PtrExpression, ASTContext &Ctx, EvalResult &Status) const; + bool EvaluateCharRangeAsString(APValue &Result, const Expr *SizeExpression, + const Expr *PtrExpression, ASTContext &Ctx, + EvalResult &Status) const; + /// If the current Expr can be evaluated to a pointer to a null-terminated /// constant string, return the constant string (without the terminating /// null). diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index fac4c10987157..87a6c22b35ee8 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -2410,15 +2410,15 @@ DEF_TRAVERSE_DECL(ImplicitConceptSpecializationDecl, { } DEF_TRAVERSE_STMT(GCCAsmStmt, { - TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getAsmString()); + TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getAsmStringExpr()); for (unsigned I = 0, E = S->getNumInputs(); I < E; ++I) { -TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getInputConstraintLiteral(I)); +TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getInputConstraintExpr(I)); } for (unsigned I = 0, E = S->getNumOutputs(); I < E; ++I) { -TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOutputConstraintLiteral(I)); +TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOutputConstraintExpr(I)); } for (unsigned I = 0, E = S->getNumClobbers(); I < E; ++I) { -TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getClobberStringLiteral(I)); +TRY
[clang] [Clang][WIP] Constant Expressions inside of gcc'asm strings (PR #131003)
https://github.com/cor3ntin ready_for_review https://github.com/llvm/llvm-project/pull/131003 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][WIP] Constant Expressions inside of gcc'asm strings (PR #131003)
@@ -17300,7 +17317,8 @@ bool Sema::EvaluateStaticAssertMessageAsString(Expr *Message, std::optional SizeMember = FindMember("size", SizeNotFound); std::optional DataMember = FindMember("data", DataNotFound); if (SizeNotFound || DataNotFound) { erichkeane wrote: Should probably just check the optional. https://github.com/llvm/llvm-project/pull/131003 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][WIP] Constant Expressions inside of gcc'asm strings (PR #131003)
@@ -17261,33 +17261,50 @@ void Sema::DiagnoseStaticAssertDetails(const Expr *E) { } } -bool Sema::EvaluateStaticAssertMessageAsString(Expr *Message, - std::string &Result, - ASTContext &Ctx, - bool ErrorOnInvalidMessage) { +template +static bool EvaluateAsStringImpl(Sema &SemaRef, Expr *Message, + ResultType &Result, ASTContext &Ctx, + Sema::StringEvaluationContext EvalContext, + bool ErrorOnInvalidMessage) { + assert(Message); assert(!Message->isTypeDependent() && !Message->isValueDependent() && "can't evaluate a dependant static assert message"); if (const auto *SL = dyn_cast(Message)) { assert(SL->isUnevaluated() && "expected an unevaluated string"); -Result.assign(SL->getString().begin(), SL->getString().end()); +if constexpr (std::is_same_v) { + Result = + APValue(APValue::UninitArray{}, SL->getLength(), SL->getLength()); + const ConstantArrayType *CAT = + SemaRef.getASTContext().getAsConstantArrayType(SL->getType()); + assert(CAT && "string literal isn't an array"); + QualType CharType = CAT->getElementType(); + llvm::APSInt Value(SemaRef.getASTContext().getTypeSize(CharType), + CharType->isUnsignedIntegerType()); + for (unsigned I = 0; I < SL->getLength(); I++) { +Value = SL->getCodeUnit(I); +Result.getArrayInitializedElt(I) = APValue(Value); + } +} else { + Result.assign(SL->getString().begin(), SL->getString().end()); +} return true; } SourceLocation Loc = Message->getBeginLoc(); QualType T = Message->getType().getNonReferenceType(); auto *RD = T->getAsCXXRecordDecl(); if (!RD) { -Diag(Loc, diag::err_static_assert_invalid_message); +SemaRef.Diag(Loc, diag::err_user_defined_msg_invalid) << EvalContext; return false; } auto FindMember = [&](StringRef Member, bool &Empty, bool Diag = false) -> std::optional { -DeclarationName DN = PP.getIdentifierInfo(Member); -LookupResult MemberLookup(*this, DN, Loc, Sema::LookupMemberName); -LookupQualifiedName(MemberLookup, RD); +DeclarationName DN = SemaRef.PP.getIdentifierInfo(Member); +LookupResult MemberLookup(SemaRef, DN, Loc, Sema::LookupMemberName); +SemaRef.LookupQualifiedName(MemberLookup, RD); Empty = MemberLookup.empty(); erichkeane wrote: Whats hte point of `Empty` if we are returning an optional? https://github.com/llvm/llvm-project/pull/131003 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][WIP] Constant Expressions inside of gcc'asm strings (PR #131003)
@@ -15328,6 +15338,15 @@ void Sema::PragmaStack::Act(SourceLocation PragmaLocation, PragmaMsStackAction Action, llvm::StringRef StackSlotLabel, AlignPackInfo Value); + +inline +const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB, +Sema::StringEvaluationContext Ctx) { + DB << llvm::to_underlying(Ctx); cor3ntin wrote: As discussed offline, this is just to pass a number for `%select{}` https://github.com/llvm/llvm-project/pull/131003 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][WIP] Constant Expressions inside of gcc'asm strings (PR #131003)
@@ -609,9 +632,10 @@ int GCCAsmStmt::getNamedOperand(StringRef SymbolicName) const { /// true, otherwise return false. unsigned GCCAsmStmt::AnalyzeAsmString(SmallVectorImpl&Pieces, const ASTContext &C, unsigned &DiagOffs) const { - StringRef Str = getAsmString()->getString(); - const char *StrStart = Str.begin(); - const char *StrEnd = Str.end(); + + std::string Str = getAsmString(); + const char *StrStart = Str.data(); cor3ntin wrote: not necessarily depending on your standard library! (for example `__gnu_cxx::__normal_iterator`) https://github.com/llvm/llvm-project/pull/131003 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][WIP] Constant Expressions inside of gcc'asm strings (PR #131003)
@@ -3193,7 +3193,7 @@ class AsmStmt : public Stmt { /// getOutputConstraint - Return the constraint string for the specified /// output operand. All output constraints are known to be non-empty (either /// '=' or '+'). - StringRef getOutputConstraint(unsigned i) const; + std::string getOutputConstraint(unsigned i) const; cor3ntin wrote: As discussed offline, std::string is better at interface boundaries https://llvm.org/docs/ProgrammersManual.html#string-like-containers https://github.com/llvm/llvm-project/pull/131003 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][WIP] Constant Expressions inside of gcc'asm strings (PR #131003)
@@ -17928,43 +17928,70 @@ std::optional Expr::tryEvaluateString(ASTContext &Ctx) const { return {}; } -bool Expr::EvaluateCharRangeAsString(std::string &Result, - const Expr *SizeExpression, - const Expr *PtrExpression, ASTContext &Ctx, - EvalResult &Status) const { - LValue String; - EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpression); - Info.InConstantContext = true; +template +static bool EvaluateCharRangeAsStringImpl(const Expr*, T& Result, + const Expr *SizeExpression, + const Expr *PtrExpression, ASTContext &Ctx, + Expr::EvalResult &Status) { +LValue String; +EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpression); +Info.InConstantContext = true; - FullExpressionRAII Scope(Info); - APSInt SizeValue; - if (!::EvaluateInteger(SizeExpression, SizeValue, Info)) -return false; +FullExpressionRAII Scope(Info); cor3ntin wrote: fixed https://github.com/llvm/llvm-project/pull/131003 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][WIP] Constant Expressions inside of gcc'asm strings (PR #131003)
@@ -328,20 +328,20 @@ void StmtProfiler::VisitGCCAsmStmt(const GCCAsmStmt *S) { VisitStmt(S); ID.AddBoolean(S->isVolatile()); ID.AddBoolean(S->isSimple()); - VisitStringLiteral(S->getAsmString()); + VisitExpr(S->getAsmStringExpr()); cor3ntin wrote: I was able to revert! https://github.com/llvm/llvm-project/pull/131003 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][WIP] Constant Expressions inside of gcc'asm strings (PR #131003)
@@ -609,9 +632,10 @@ int GCCAsmStmt::getNamedOperand(StringRef SymbolicName) const { /// true, otherwise return false. unsigned GCCAsmStmt::AnalyzeAsmString(SmallVectorImpl&Pieces, const ASTContext &C, unsigned &DiagOffs) const { - StringRef Str = getAsmString()->getString(); - const char *StrStart = Str.begin(); - const char *StrEnd = Str.end(); + + std::string Str = getAsmString(); + const char *StrStart = Str.data(); erichkeane wrote: Isn't the type of the iterators `const char*`? https://github.com/llvm/llvm-project/pull/131003 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][WIP] Constant Expressions inside of gcc'asm strings (PR #131003)
@@ -328,20 +328,20 @@ void StmtProfiler::VisitGCCAsmStmt(const GCCAsmStmt *S) { VisitStmt(S); ID.AddBoolean(S->isVolatile()); ID.AddBoolean(S->isSimple()); - VisitStringLiteral(S->getAsmString()); + VisitExpr(S->getAsmStringExpr()); erichkeane wrote: Are these necessary? I would expect the `children` definition of the statement should instead print these. It'll change how the ast-dump works, but for the better IMO. Though perhaps we like how these look... https://github.com/llvm/llvm-project/pull/131003 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][WIP] Constant Expressions inside of gcc'asm strings (PR #131003)
cor3ntin wrote: @ojhunt @erichkeane @AaronBallman I'm looking for early feedback at this point. Obviously this has no tests yes This - Generalize our ability to evaluate string expression outside of static assert (which will be otherwise useful for https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3423r1.html ) - Implement GCC's constexpr string in ASM - Once strings are evaluated, they are cached in a ConstantExpr (but we still need to go from APValue -> std::string everytime, which seems reasonable - Because the strings can be arbitrary expressions they can be dependent. If any string is a dependent expression all of sema is skipped until instantiation. It's a slightly big hammer but honestly I'm not sure that we can improve or that it would be worth it. - [ ] Tests - [ ] Doc / Changelog - [ ] cxx_features https://github.com/llvm/llvm-project/pull/131003 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][WIP] Constant Expressions inside of gcc'asm strings (PR #131003)
@@ -17928,43 +17928,70 @@ std::optional Expr::tryEvaluateString(ASTContext &Ctx) const { return {}; } -bool Expr::EvaluateCharRangeAsString(std::string &Result, - const Expr *SizeExpression, - const Expr *PtrExpression, ASTContext &Ctx, - EvalResult &Status) const { - LValue String; - EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpression); - Info.InConstantContext = true; +template +static bool EvaluateCharRangeAsStringImpl(const Expr*, T& Result, + const Expr *SizeExpression, + const Expr *PtrExpression, ASTContext &Ctx, + Expr::EvalResult &Status) { +LValue String; +EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpression); +Info.InConstantContext = true; - FullExpressionRAII Scope(Info); - APSInt SizeValue; - if (!::EvaluateInteger(SizeExpression, SizeValue, Info)) -return false; +FullExpressionRAII Scope(Info); erichkeane wrote: What weirdness is going on with the formatting here? https://github.com/llvm/llvm-project/pull/131003 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][WIP] Constant Expressions inside of gcc'asm strings (PR #131003)
@@ -17928,43 +17928,70 @@ std::optional Expr::tryEvaluateString(ASTContext &Ctx) const { return {}; } -bool Expr::EvaluateCharRangeAsString(std::string &Result, - const Expr *SizeExpression, - const Expr *PtrExpression, ASTContext &Ctx, - EvalResult &Status) const { - LValue String; - EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpression); - Info.InConstantContext = true; +template +static bool EvaluateCharRangeAsStringImpl(const Expr*, T& Result, + const Expr *SizeExpression, + const Expr *PtrExpression, ASTContext &Ctx, + Expr::EvalResult &Status) { +LValue String; +EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpression); +Info.InConstantContext = true; - FullExpressionRAII Scope(Info); - APSInt SizeValue; - if (!::EvaluateInteger(SizeExpression, SizeValue, Info)) -return false; +FullExpressionRAII Scope(Info); +APSInt SizeValue; +if (!::EvaluateInteger(SizeExpression, SizeValue, Info)) + return false; - uint64_t Size = SizeValue.getZExtValue(); +uint64_t Size = SizeValue.getZExtValue(); - if (!::EvaluatePointer(PtrExpression, String, Info)) -return false; +if constexpr(std::is_same_v) +Result = APValue(APValue::UninitArray{}, Size, Size); +//else +//Result.reserve(Size); - QualType CharTy = PtrExpression->getType()->getPointeeType(); - for (uint64_t I = 0; I < Size; ++I) { -APValue Char; -if (!handleLValueToRValueConversion(Info, PtrExpression, CharTy, String, -Char)) +if (!::EvaluatePointer(PtrExpression, String, Info)) + return false; + +QualType CharTy = PtrExpression->getType()->getPointeeType(); +for (uint64_t I = 0; I < Size; ++I) { + APValue Char; + if (!handleLValueToRValueConversion(Info, PtrExpression, CharTy, String, + Char)) +return false; + + if constexpr(std::is_same_v) { + Result.getArrayInitializedElt(I) = std::move(Char); + } + else { + APSInt C = Char.getInt(); + Result.push_back(static_cast(C.getExtValue())); + } + + if (!HandleLValueArrayAdjustment(Info, PtrExpression, String, CharTy, 1)) +return false; +} +if (!Scope.destroy()) return false; -APSInt C = Char.getInt(); -Result.push_back(static_cast(C.getExtValue())); -if (!HandleLValueArrayAdjustment(Info, PtrExpression, String, CharTy, 1)) +if (!CheckMemoryLeaks(Info)) erichkeane wrote: This looks like a `if (!X) return false; return true;` here :) https://github.com/llvm/llvm-project/pull/131003 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][WIP] Constant Expressions inside of gcc'asm strings (PR #131003)
@@ -497,6 +497,19 @@ void StmtPrinter::VisitReturnStmt(ReturnStmt *Node) { if (Policy.IncludeNewlines) OS << NL; } +static void PrintGCCAsmString(raw_ostream &OS, Expr*E) { + if(E->getDependence()) { +OS << "<>"; +return; + } + + std::string Str = GCCAsmStmt::ExtractStringFromGCCAsmStmtComponent(E); erichkeane wrote: Do we really want to do this instead of printing the expression? Seems weird that `-ast-print` would be changing the value here. https://github.com/llvm/llvm-project/pull/131003 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][WIP] Constant Expressions inside of gcc'asm strings (PR #131003)
@@ -17928,43 +17928,70 @@ std::optional Expr::tryEvaluateString(ASTContext &Ctx) const { return {}; } -bool Expr::EvaluateCharRangeAsString(std::string &Result, - const Expr *SizeExpression, - const Expr *PtrExpression, ASTContext &Ctx, - EvalResult &Status) const { - LValue String; - EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpression); - Info.InConstantContext = true; +template +static bool EvaluateCharRangeAsStringImpl(const Expr*, T& Result, + const Expr *SizeExpression, + const Expr *PtrExpression, ASTContext &Ctx, + Expr::EvalResult &Status) { +LValue String; +EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpression); +Info.InConstantContext = true; - FullExpressionRAII Scope(Info); - APSInt SizeValue; - if (!::EvaluateInteger(SizeExpression, SizeValue, Info)) -return false; +FullExpressionRAII Scope(Info); +APSInt SizeValue; +if (!::EvaluateInteger(SizeExpression, SizeValue, Info)) + return false; - uint64_t Size = SizeValue.getZExtValue(); +uint64_t Size = SizeValue.getZExtValue(); - if (!::EvaluatePointer(PtrExpression, String, Info)) -return false; +if constexpr(std::is_same_v) +Result = APValue(APValue::UninitArray{}, Size, Size); +//else +//Result.reserve(Size); - QualType CharTy = PtrExpression->getType()->getPointeeType(); - for (uint64_t I = 0; I < Size; ++I) { -APValue Char; -if (!handleLValueToRValueConversion(Info, PtrExpression, CharTy, String, -Char)) +if (!::EvaluatePointer(PtrExpression, String, Info)) + return false; + +QualType CharTy = PtrExpression->getType()->getPointeeType(); +for (uint64_t I = 0; I < Size; ++I) { + APValue Char; + if (!handleLValueToRValueConversion(Info, PtrExpression, CharTy, String, + Char)) +return false; + + if constexpr(std::is_same_v) { + Result.getArrayInitializedElt(I) = std::move(Char); + } + else { + APSInt C = Char.getInt(); + Result.push_back(static_cast(C.getExtValue())); erichkeane wrote: Should we do some range checking before the cast? I would expect based on `CharTy` that we could expect `C` here to have a bitwidth of 8, right? https://github.com/llvm/llvm-project/pull/131003 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][WIP] Constant Expressions inside of gcc'asm strings (PR #131003)
@@ -17928,43 +17928,70 @@ std::optional Expr::tryEvaluateString(ASTContext &Ctx) const { return {}; } -bool Expr::EvaluateCharRangeAsString(std::string &Result, - const Expr *SizeExpression, - const Expr *PtrExpression, ASTContext &Ctx, - EvalResult &Status) const { - LValue String; - EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpression); - Info.InConstantContext = true; +template +static bool EvaluateCharRangeAsStringImpl(const Expr*, T& Result, + const Expr *SizeExpression, + const Expr *PtrExpression, ASTContext &Ctx, + Expr::EvalResult &Status) { +LValue String; +EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpression); +Info.InConstantContext = true; - FullExpressionRAII Scope(Info); - APSInt SizeValue; - if (!::EvaluateInteger(SizeExpression, SizeValue, Info)) -return false; +FullExpressionRAII Scope(Info); +APSInt SizeValue; +if (!::EvaluateInteger(SizeExpression, SizeValue, Info)) + return false; - uint64_t Size = SizeValue.getZExtValue(); +uint64_t Size = SizeValue.getZExtValue(); - if (!::EvaluatePointer(PtrExpression, String, Info)) -return false; +if constexpr(std::is_same_v) +Result = APValue(APValue::UninitArray{}, Size, Size); +//else erichkeane wrote: Eh? https://github.com/llvm/llvm-project/pull/131003 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][WIP] Constant Expressions inside of gcc'asm strings (PR #131003)
@@ -8552,25 +8552,39 @@ template StmtResult TreeTransform::TransformGCCAsmStmt(GCCAsmStmt *S) { + SmallVector Constraints; SmallVector Exprs; SmallVector Names; - ExprResult AsmString; SmallVector Clobbers; bool ExprsChanged = false; + auto RebuildString = [&] (Expr* E) { + ExprResult Result = getDerived().TransformExpr(E); + if (Result.isInvalid()) erichkeane wrote: ```suggestion if (!Result.isUsable()) ``` https://github.com/llvm/llvm-project/pull/131003 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][WIP] Constant Expressions inside of gcc'asm strings (PR #131003)
@@ -3193,7 +3193,7 @@ class AsmStmt : public Stmt { /// getOutputConstraint - Return the constraint string for the specified /// output operand. All output constraints are known to be non-empty (either /// '=' or '+'). - StringRef getOutputConstraint(unsigned i) const; + std::string getOutputConstraint(unsigned i) const; erichkeane wrote: should these be llvm::SmallString? https://github.com/llvm/llvm-project/pull/131003 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][WIP] Constant Expressions inside of gcc'asm strings (PR #131003)
@@ -609,9 +632,10 @@ int GCCAsmStmt::getNamedOperand(StringRef SymbolicName) const { /// true, otherwise return false. unsigned GCCAsmStmt::AnalyzeAsmString(SmallVectorImpl&Pieces, const ASTContext &C, unsigned &DiagOffs) const { - StringRef Str = getAsmString()->getString(); - const char *StrStart = Str.begin(); - const char *StrEnd = Str.end(); + + std::string Str = getAsmString(); + const char *StrStart = Str.data(); erichkeane wrote: Curious why data/data+size instead of just begin/end? https://github.com/llvm/llvm-project/pull/131003 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][WIP] Constant Expressions inside of gcc'asm strings (PR #131003)
@@ -8552,25 +8552,39 @@ template StmtResult TreeTransform::TransformGCCAsmStmt(GCCAsmStmt *S) { + SmallVector Constraints; SmallVector Exprs; SmallVector Names; - ExprResult AsmString; SmallVector Clobbers; bool ExprsChanged = false; + auto RebuildString = [&] (Expr* E) { + ExprResult Result = getDerived().TransformExpr(E); + if (Result.isInvalid()) +return Result; + if(!Result.isInvalid() && Result.get() != E) { erichkeane wrote: ```suggestion if(Result.get() != E) { ``` https://github.com/llvm/llvm-project/pull/131003 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][WIP] Constant Expressions inside of gcc'asm strings (PR #131003)
@@ -15328,6 +15338,15 @@ void Sema::PragmaStack::Act(SourceLocation PragmaLocation, PragmaMsStackAction Action, llvm::StringRef StackSlotLabel, AlignPackInfo Value); + +inline +const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB, +Sema::StringEvaluationContext Ctx) { + DB << llvm::to_underlying(Ctx); erichkeane wrote: This is a shame... an-inverse-string-switch here would be nice. https://github.com/llvm/llvm-project/pull/131003 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][WIP] Constant Expressions inside of gcc'asm strings (PR #131003)
https://github.com/cor3ntin updated https://github.com/llvm/llvm-project/pull/131003 >From 84508166a9784701dad659881bf75f9764e53f54 Mon Sep 17 00:00:00 2001 From: Corentin Jabot Date: Wed, 12 Mar 2025 12:23:14 +0100 Subject: [PATCH 1/2] [Clang][WIP] Constant Expressions inside of gcc'asm strings Implements GCC's constexpr string ASM extension https://gcc.gnu.org/onlinedocs/gcc/Asm-constexprs.html --- clang/include/clang/AST/Expr.h| 5 + clang/include/clang/AST/RecursiveASTVisitor.h | 8 +- clang/include/clang/AST/Stmt.h| 50 +++--- .../clang/Basic/DiagnosticParseKinds.td | 5 +- .../clang/Basic/DiagnosticSemaKinds.td| 36 +++-- clang/include/clang/Sema/Sema.h | 25 ++- clang/lib/AST/ASTImporter.cpp | 12 +- clang/lib/AST/ExprConstant.cpp| 83 ++ clang/lib/AST/Stmt.cpp| 103 clang/lib/AST/StmtPrinter.cpp | 21 ++- clang/lib/AST/StmtProfile.cpp | 8 +- clang/lib/CodeGen/CGStmt.cpp | 16 +- clang/lib/Parse/ParseStmtAsm.cpp | 2 +- clang/lib/Parse/Parser.cpp| 37 +++-- clang/lib/Sema/SemaDeclCXX.cpp| 99 clang/lib/Sema/SemaStmtAsm.cpp| 147 +++--- clang/lib/Sema/TreeTransform.h| 50 -- clang/lib/Serialization/ASTReaderStmt.cpp | 10 +- clang/lib/Serialization/ASTWriterStmt.cpp | 8 +- 19 files changed, 473 insertions(+), 252 deletions(-) diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index cfe49acf20b77..7f9e50dfe78bd 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -787,6 +787,11 @@ class Expr : public ValueStmt { const Expr *PtrExpression, ASTContext &Ctx, EvalResult &Status) const; + bool EvaluateCharRangeAsString(APValue &Result, + const Expr *SizeExpression, + const Expr *PtrExpression, ASTContext &Ctx, + EvalResult &Status) const; + /// If the current Expr can be evaluated to a pointer to a null-terminated /// constant string, return the constant string (without the terminating /// null). diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index fac4c10987157..87a6c22b35ee8 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -2410,15 +2410,15 @@ DEF_TRAVERSE_DECL(ImplicitConceptSpecializationDecl, { } DEF_TRAVERSE_STMT(GCCAsmStmt, { - TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getAsmString()); + TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getAsmStringExpr()); for (unsigned I = 0, E = S->getNumInputs(); I < E; ++I) { -TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getInputConstraintLiteral(I)); +TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getInputConstraintExpr(I)); } for (unsigned I = 0, E = S->getNumOutputs(); I < E; ++I) { -TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOutputConstraintLiteral(I)); +TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOutputConstraintExpr(I)); } for (unsigned I = 0, E = S->getNumClobbers(); I < E; ++I) { -TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getClobberStringLiteral(I)); +TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getClobberExpr(I)); } // children() iterates over inputExpr and outputExpr. }) diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h index 604ac51d478cf..7bf0a6911c515 100644 --- a/clang/include/clang/AST/Stmt.h +++ b/clang/include/clang/AST/Stmt.h @@ -3193,7 +3193,7 @@ class AsmStmt : public Stmt { /// getOutputConstraint - Return the constraint string for the specified /// output operand. All output constraints are known to be non-empty (either /// '=' or '+'). - StringRef getOutputConstraint(unsigned i) const; + std::string getOutputConstraint(unsigned i) const; /// isOutputPlusConstraint - Return true if the specified output constraint /// is a "+" constraint (which is both an input and an output) or false if it @@ -3214,14 +3214,14 @@ class AsmStmt : public Stmt { /// getInputConstraint - Return the specified input constraint. Unlike output /// constraints, these can be empty. - StringRef getInputConstraint(unsigned i) const; + std::string getInputConstraint(unsigned i) const; const Expr *getInputExpr(unsigned i) const; //===--- Other ---===// unsigned getNumClobbers() const { return NumClobbers; } - StringRef getClobber(unsigned i) const; + std::string getClobber(unsigned i) const; static bool classof(const Stmt *T) { return T->getStmtClass() == GCCAsmStmtClass || @@ -3302,20 +3302,20 @@ class GCCAsmStmt : public AsmStmt { friend class ASTStmtReader; SourceLocation RParenLoc; - StringLiteral *AsmStr
[clang] [Clang][WIP] Constant Expressions inside of gcc'asm strings (PR #131003)
github-actions[bot] wrote: :warning: C/C++ code formatter, clang-format found issues in your code. :warning: You can test this locally with the following command: ``bash git-clang-format --diff 90a08fb4b7e79e79121a563ac9cd8138cfedeb3c 84508166a9784701dad659881bf75f9764e53f54 --extensions cpp,h -- clang/include/clang/AST/Expr.h clang/include/clang/AST/RecursiveASTVisitor.h clang/include/clang/AST/Stmt.h clang/include/clang/Sema/Sema.h clang/lib/AST/ASTImporter.cpp clang/lib/AST/ExprConstant.cpp clang/lib/AST/Stmt.cpp clang/lib/AST/StmtPrinter.cpp clang/lib/AST/StmtProfile.cpp clang/lib/CodeGen/CGStmt.cpp clang/lib/Parse/ParseStmtAsm.cpp clang/lib/Parse/Parser.cpp clang/lib/Sema/SemaDeclCXX.cpp clang/lib/Sema/SemaStmtAsm.cpp clang/lib/Sema/TreeTransform.h clang/lib/Serialization/ASTReaderStmt.cpp clang/lib/Serialization/ASTWriterStmt.cpp `` View the diff from clang-format here. ``diff diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 7f9e50dfe7..28437b5629 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -787,10 +787,9 @@ public: const Expr *PtrExpression, ASTContext &Ctx, EvalResult &Status) const; - bool EvaluateCharRangeAsString(APValue &Result, - const Expr *SizeExpression, - const Expr *PtrExpression, ASTContext &Ctx, - EvalResult &Status) const; + bool EvaluateCharRangeAsString(APValue &Result, const Expr *SizeExpression, + const Expr *PtrExpression, ASTContext &Ctx, + EvalResult &Status) const; /// If the current Expr can be evaluated to a pointer to a null-terminated /// constant string, return the constant string (without the terminating diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h index 7bf0a6911c..88ae3aeefa 100644 --- a/clang/include/clang/AST/Stmt.h +++ b/clang/include/clang/AST/Stmt.h @@ -3314,9 +3314,8 @@ public: GCCAsmStmt(const ASTContext &C, SourceLocation asmloc, bool issimple, bool isvolatile, unsigned numoutputs, unsigned numinputs, IdentifierInfo **names, Expr **constraints, Expr **exprs, - Expr *asmstr, unsigned numclobbers, - Expr **clobbers, unsigned numlabels, - SourceLocation rparenloc); + Expr *asmstr, unsigned numclobbers, Expr **clobbers, + unsigned numlabels, SourceLocation rparenloc); /// Build an empty inline-assembly statement. explicit GCCAsmStmt(EmptyShell Empty) : AsmStmt(GCCAsmStmtClass, Empty) {} @@ -3404,9 +3403,7 @@ public: const Expr *getOutputConstraintExpr(unsigned i) const { return Constraints[i]; } - Expr *getOutputConstraintExpr(unsigned i) { -return Constraints[i]; - } + Expr *getOutputConstraintExpr(unsigned i) { return Constraints[i]; } Expr *getOutputExpr(unsigned i); @@ -3443,7 +3440,7 @@ public: return const_cast(this)->getInputExpr(i); } - static std::string ExtractStringFromGCCAsmStmtComponent(const Expr* E); + static std::string ExtractStringFromGCCAsmStmtComponent(const Expr *E); //===--- Labels ---===// @@ -3493,12 +3490,9 @@ public: private: void setOutputsAndInputsAndClobbers(const ASTContext &C, IdentifierInfo **Names, - Expr **Constraints, - Stmt **Exprs, - unsigned NumOutputs, - unsigned NumInputs, - unsigned NumLabels, - Expr **Clobbers, + Expr **Constraints, Stmt **Exprs, + unsigned NumOutputs, unsigned NumInputs, + unsigned NumLabels, Expr **Clobbers, unsigned NumClobbers); public: @@ -3512,9 +3506,7 @@ public: std::string getClobber(unsigned i) const; Expr *getClobberExpr(unsigned i) { return Clobbers[i]; } - const Expr *getClobberExpr(unsigned i) const { -return Clobbers[i]; - } + const Expr *getClobberExpr(unsigned i) const { return Clobbers[i]; } SourceLocation getBeginLoc() const LLVM_READONLY { return AsmLoc; } SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; } diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index e1b1083675..4043699912 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -5585,10 +5585,7 @@ public: void ActOnFinishDelayedCXXMethodDeclaration(Scope *S, Decl *Method); void ActOnFinishDelayedMemberInitializers(Decl *Record); - enum class StringEvaluationContext { - Sta
[clang] [Clang][WIP] Constant Expressions inside of gcc'asm strings (PR #131003)
https://github.com/cor3ntin created https://github.com/llvm/llvm-project/pull/131003 Implements GCC's constexpr string ASM extension https://gcc.gnu.org/onlinedocs/gcc/Asm-constexprs.html >From 84508166a9784701dad659881bf75f9764e53f54 Mon Sep 17 00:00:00 2001 From: Corentin Jabot Date: Wed, 12 Mar 2025 12:23:14 +0100 Subject: [PATCH] [Clang][WIP] Constant Expressions inside of gcc'asm strings Implements GCC's constexpr string ASM extension https://gcc.gnu.org/onlinedocs/gcc/Asm-constexprs.html --- clang/include/clang/AST/Expr.h| 5 + clang/include/clang/AST/RecursiveASTVisitor.h | 8 +- clang/include/clang/AST/Stmt.h| 50 +++--- .../clang/Basic/DiagnosticParseKinds.td | 5 +- .../clang/Basic/DiagnosticSemaKinds.td| 36 +++-- clang/include/clang/Sema/Sema.h | 25 ++- clang/lib/AST/ASTImporter.cpp | 12 +- clang/lib/AST/ExprConstant.cpp| 83 ++ clang/lib/AST/Stmt.cpp| 103 clang/lib/AST/StmtPrinter.cpp | 21 ++- clang/lib/AST/StmtProfile.cpp | 8 +- clang/lib/CodeGen/CGStmt.cpp | 16 +- clang/lib/Parse/ParseStmtAsm.cpp | 2 +- clang/lib/Parse/Parser.cpp| 37 +++-- clang/lib/Sema/SemaDeclCXX.cpp| 99 clang/lib/Sema/SemaStmtAsm.cpp| 147 +++--- clang/lib/Sema/TreeTransform.h| 50 -- clang/lib/Serialization/ASTReaderStmt.cpp | 10 +- clang/lib/Serialization/ASTWriterStmt.cpp | 8 +- 19 files changed, 473 insertions(+), 252 deletions(-) diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index cfe49acf20b77..7f9e50dfe78bd 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -787,6 +787,11 @@ class Expr : public ValueStmt { const Expr *PtrExpression, ASTContext &Ctx, EvalResult &Status) const; + bool EvaluateCharRangeAsString(APValue &Result, + const Expr *SizeExpression, + const Expr *PtrExpression, ASTContext &Ctx, + EvalResult &Status) const; + /// If the current Expr can be evaluated to a pointer to a null-terminated /// constant string, return the constant string (without the terminating /// null). diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index fac4c10987157..87a6c22b35ee8 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -2410,15 +2410,15 @@ DEF_TRAVERSE_DECL(ImplicitConceptSpecializationDecl, { } DEF_TRAVERSE_STMT(GCCAsmStmt, { - TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getAsmString()); + TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getAsmStringExpr()); for (unsigned I = 0, E = S->getNumInputs(); I < E; ++I) { -TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getInputConstraintLiteral(I)); +TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getInputConstraintExpr(I)); } for (unsigned I = 0, E = S->getNumOutputs(); I < E; ++I) { -TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOutputConstraintLiteral(I)); +TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOutputConstraintExpr(I)); } for (unsigned I = 0, E = S->getNumClobbers(); I < E; ++I) { -TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getClobberStringLiteral(I)); +TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getClobberExpr(I)); } // children() iterates over inputExpr and outputExpr. }) diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h index 604ac51d478cf..7bf0a6911c515 100644 --- a/clang/include/clang/AST/Stmt.h +++ b/clang/include/clang/AST/Stmt.h @@ -3193,7 +3193,7 @@ class AsmStmt : public Stmt { /// getOutputConstraint - Return the constraint string for the specified /// output operand. All output constraints are known to be non-empty (either /// '=' or '+'). - StringRef getOutputConstraint(unsigned i) const; + std::string getOutputConstraint(unsigned i) const; /// isOutputPlusConstraint - Return true if the specified output constraint /// is a "+" constraint (which is both an input and an output) or false if it @@ -3214,14 +3214,14 @@ class AsmStmt : public Stmt { /// getInputConstraint - Return the specified input constraint. Unlike output /// constraints, these can be empty. - StringRef getInputConstraint(unsigned i) const; + std::string getInputConstraint(unsigned i) const; const Expr *getInputExpr(unsigned i) const; //===--- Other ---===// unsigned getNumClobbers() const { return NumClobbers; } - StringRef getClobber(unsigned i) const; + std::string getClobber(unsigned i) const; static bool classof(const Stmt *T) { return T->getStmtClass() == GCCAsmStmtClass || @@ -3302,20 +3302,20 @@ class GCCAsmStmt : publ