[clang] [Clang][WIP] Constant Expressions inside of gcc'asm strings (PR #131003)

2025-03-13 Thread Eli Friedman via cfe-commits


@@ -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)

2025-03-13 Thread via cfe-commits


@@ -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)

2025-03-13 Thread Erich Keane via cfe-commits


@@ -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)

2025-03-13 Thread via cfe-commits


@@ -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)

2025-03-13 Thread via cfe-commits

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)

2025-03-13 Thread via cfe-commits

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)

2025-03-13 Thread via cfe-commits

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)

2025-03-13 Thread via cfe-commits

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)

2025-03-13 Thread Erich Keane via cfe-commits


@@ -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)

2025-03-13 Thread Erich Keane via cfe-commits


@@ -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)

2025-03-13 Thread via cfe-commits


@@ -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)

2025-03-13 Thread via cfe-commits


@@ -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)

2025-03-13 Thread via cfe-commits


@@ -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)

2025-03-13 Thread via cfe-commits


@@ -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)

2025-03-13 Thread via cfe-commits


@@ -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)

2025-03-13 Thread Erich Keane via cfe-commits


@@ -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)

2025-03-12 Thread Erich Keane via cfe-commits


@@ -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)

2025-03-12 Thread via cfe-commits

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)

2025-03-12 Thread Erich Keane via cfe-commits


@@ -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)

2025-03-12 Thread Erich Keane via cfe-commits


@@ -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)

2025-03-12 Thread Erich Keane via cfe-commits


@@ -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)

2025-03-12 Thread Erich Keane via cfe-commits


@@ -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)

2025-03-12 Thread Erich Keane via cfe-commits


@@ -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)

2025-03-12 Thread Erich Keane via cfe-commits


@@ -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)

2025-03-12 Thread Erich Keane via cfe-commits


@@ -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)

2025-03-12 Thread Erich Keane via cfe-commits


@@ -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)

2025-03-12 Thread Erich Keane via cfe-commits


@@ -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)

2025-03-12 Thread Erich Keane via cfe-commits


@@ -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)

2025-03-12 Thread via cfe-commits

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)

2025-03-12 Thread via cfe-commits

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)

2025-03-12 Thread via cfe-commits

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