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

via cfe-commits cfe-commits at lists.llvm.org
Wed Mar 12 12:26:53 PDT 2025


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 <corentinjabot at gmail.com>
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;
+  Expr *AsmStr;
 
   // FIXME: If we wanted to, we could allocate all of these in one big array.
-  StringLiteral **Constraints = nullptr;
-  StringLiteral **Clobbers = nullptr;
+  Expr **Constraints = nullptr;
+  Expr **Clobbers = nullptr;
   IdentifierInfo **Names = nullptr;
   unsigned NumLabels = 0;
 
 public:
   GCCAsmStmt(const ASTContext &C, SourceLocation asmloc, bool issimple,
              bool isvolatile, unsigned numoutputs, unsigned numinputs,
-             IdentifierInfo **names, StringLiteral **constraints, Expr **exprs,
-             StringLiteral *asmstr, unsigned numclobbers,
-             StringLiteral **clobbers, unsigned numlabels,
+             IdentifierInfo **names, Expr **constraints, Expr **exprs,
+             Expr *asmstr, unsigned numclobbers,
+             Expr **clobbers, unsigned numlabels,
              SourceLocation rparenloc);
 
   /// Build an empty inline-assembly statement.
@@ -3326,9 +3326,11 @@ class GCCAsmStmt : public AsmStmt {
 
   //===--- Asm String Analysis ---===//
 
-  const StringLiteral *getAsmString() const { return AsmStr; }
-  StringLiteral *getAsmString() { return AsmStr; }
-  void setAsmString(StringLiteral *E) { AsmStr = E; }
+  const Expr *getAsmStringExpr() const { return AsmStr; }
+  Expr *getAsmStringExpr() { return AsmStr; }
+  void setAsmString(Expr *E) { AsmStr = E; }
+
+  std::string getAsmString() const;
 
   /// AsmStringPiece - this is part of a decomposed asm string specification
   /// (for use with the AnalyzeAsmString function below).  An asm string is
@@ -3397,12 +3399,12 @@ class GCCAsmStmt : public AsmStmt {
     return {};
   }
 
-  StringRef getOutputConstraint(unsigned i) const;
+  std::string getOutputConstraint(unsigned i) const;
 
-  const StringLiteral *getOutputConstraintLiteral(unsigned i) const {
+  const Expr *getOutputConstraintExpr(unsigned i) const {
     return Constraints[i];
   }
-  StringLiteral *getOutputConstraintLiteral(unsigned i) {
+  Expr *getOutputConstraintExpr(unsigned i) {
     return Constraints[i];
   }
 
@@ -3425,12 +3427,12 @@ class GCCAsmStmt : public AsmStmt {
     return {};
   }
 
-  StringRef getInputConstraint(unsigned i) const;
+  std::string getInputConstraint(unsigned i) const;
 
-  const StringLiteral *getInputConstraintLiteral(unsigned i) const {
+  const Expr *getInputConstraintExpr(unsigned i) const {
     return Constraints[i + NumOutputs];
   }
-  StringLiteral *getInputConstraintLiteral(unsigned i) {
+  Expr *getInputConstraintExpr(unsigned i) {
     return Constraints[i + NumOutputs];
   }
 
@@ -3441,6 +3443,8 @@ class GCCAsmStmt : public AsmStmt {
     return const_cast<GCCAsmStmt*>(this)->getInputExpr(i);
   }
 
+  static std::string ExtractStringFromGCCAsmStmtComponent(const Expr* E);
+
   //===--- Labels ---===//
 
   bool isAsmGoto() const {
@@ -3489,12 +3493,12 @@ class GCCAsmStmt : public AsmStmt {
 private:
   void setOutputsAndInputsAndClobbers(const ASTContext &C,
                                       IdentifierInfo **Names,
-                                      StringLiteral **Constraints,
+                                      Expr **Constraints,
                                       Stmt **Exprs,
                                       unsigned NumOutputs,
                                       unsigned NumInputs,
                                       unsigned NumLabels,
-                                      StringLiteral **Clobbers,
+                                      Expr **Clobbers,
                                       unsigned NumClobbers);
 
 public:
@@ -3505,10 +3509,10 @@ class GCCAsmStmt : public AsmStmt {
   /// This returns -1 if the operand name is invalid.
   int getNamedOperand(StringRef SymbolicName) const;
 
-  StringRef getClobber(unsigned i) const;
+  std::string getClobber(unsigned i) const;
 
-  StringLiteral *getClobberStringLiteral(unsigned i) { return Clobbers[i]; }
-  const StringLiteral *getClobberStringLiteral(unsigned i) const {
+  Expr *getClobberExpr(unsigned i) { return Clobbers[i]; }
+  const Expr *getClobberExpr(unsigned i) const {
     return Clobbers[i];
   }
 
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 092a55f9e9e0c..4dc956f7ae6f7 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -336,7 +336,10 @@ def warn_cxx20_compat_label_end_of_compound_statement : Warning<
 def err_address_of_label_outside_fn : Error<
   "use of address-of-label extension outside of a function body">;
 def err_asm_operand_wide_string_literal : Error<
-  "cannot use %select{unicode|wide|an empty}0 string literal in 'asm'">;
+  "cannot use %select{unicode|wide}0 string literal in 'asm'">;
+
+def err_asm_expected_string : Error<
+  "expected string literal %select{or parenthesized constant expression |}0in 'asm'">;
 def err_expected_selector_for_method : Error<
   "expected selector for Objective-C method">;
 def err_expected_property_name : Error<"expected property name">;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 4bdbb797c2b86..2e8db1a2249e4 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1663,23 +1663,30 @@ def err_static_assert_requirement_failed : Error<
   "static assertion failed due to requirement '%0'%select{: %2|}1">;
 def note_expr_evaluates_to : Note<
   "expression evaluates to '%0 %1 %2'">;
-def err_static_assert_invalid_message : Error<
-  "the message in a static assertion must be a string literal or an "
+
+
+def subst_user_defined_msg : TextSubstitution<
+  "%select{the message|the expression}0 in "
+  "%select{a static assertion|this asm operand}0">;
+
+def err_user_defined_msg_invalid : Error<
+  "%sub{subst_user_defined_msg}0 must be a string literal or an "
   "object with 'data()' and 'size()' member functions">;
-def err_static_assert_missing_member_function : Error<
-  "the message object in this static assertion is missing %select{"
+def err_user_defined_msg_missing_member_function : Error<
+  "the %select{message|string}0 object in "
+  "%select{this static assertion|this asm operand}0 is missing %select{"
   "a 'size()' member function|"
   "a 'data()' member function|"
-  "'data()' and 'size()' member functions}0">;
-def err_static_assert_invalid_mem_fn_ret_ty : Error<
-  "the message in a static assertion must have a '%select{size|data}0()' member "
-  "function returning an object convertible to '%select{std::size_t|const char *}0'">;
-def warn_static_assert_message_constexpr : Warning<
-  "the message in this static assertion is not a "
-  "constant expression">,
+  "'data()' and 'size()' member functions}1">;
+def err_user_defined_msg_invalid_mem_fn_ret_ty : Error<
+  "%sub{subst_user_defined_msg}0 must have a '%select{size|data}1()' member "
+  "function returning an object convertible to '%select{std::size_t|const char *}1'">;
+def warn_user_defined_msg_constexpr : Warning<
+  "%select{the message|the expression}0 in "
+  "%select{this static assertion|this asm operand}0 is not a constant expression">,
   DefaultError, InGroup<DiagGroup<"invalid-static-assert-message">>;
-def err_static_assert_message_constexpr : Error<
-  "the message in a static assertion must be produced by a "
+def err_user_defined_msg_constexpr : Error<
+  "%sub{subst_user_defined_msg}0 must be produced by a "
   "constant expression">;
 
 def warn_consteval_if_always_true : Warning<
@@ -9514,6 +9521,9 @@ def warn_redefine_extname_not_applied : Warning<
 
 // inline asm.
 let CategoryName = "Inline Assembly Issue" in {
+  def err_asm_operand_empty_string : Error<
+     "cannot use an empty string literal in 'asm'">;
+
   def err_asm_pmf_through_constraint_not_permitted
     : Error<"cannot pass a pointer-to-member through register-constrained "
             "inline assembly parameter">;
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index c034de0e633da..e1b1083675612 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -5585,9 +5585,18 @@ class Sema final : public SemaBase {
   void ActOnFinishDelayedCXXMethodDeclaration(Scope *S, Decl *Method);
   void ActOnFinishDelayedMemberInitializers(Decl *Record);
 
-  bool EvaluateStaticAssertMessageAsString(Expr *Message, std::string &Result,
-                                           ASTContext &Ctx,
-                                           bool ErrorOnInvalidMessage);
+  enum class StringEvaluationContext {
+      StaticAssert = 0,
+      Asm = 1
+  };
+
+  bool EvaluateAsString(Expr *Message, APValue &Result, ASTContext &Ctx,
+                        StringEvaluationContext EvalContext,
+                        bool ErrorOnInvalidMessage);
+  bool EvaluateAsString(Expr *Message, std::string &Result, ASTContext &Ctx,
+                        StringEvaluationContext EvalContext,
+                        bool ErrorOnInvalidMessage);
+
   Decl *ActOnStaticAssertDeclaration(SourceLocation StaticAssertLoc,
                                      Expr *AssertExpr, Expr *AssertMessageExpr,
                                      SourceLocation RParenLoc);
@@ -11040,6 +11049,7 @@ class Sema final : public SemaBase {
   ///@{
 
 public:
+  ExprResult ActOnGCCAsmStmtString(Expr* Stm, bool ForAsmLabel);
   StmtResult ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
                              bool IsVolatile, unsigned NumOutputs,
                              unsigned NumInputs, IdentifierInfo **Names,
@@ -15328,6 +15338,15 @@ void Sema::PragmaStack<Sema::AlignPackInfo>::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);
+  return DB;
+}
+
+
 } // end namespace clang
 
 #endif
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 82180486f3c7c..1b507761ddf70 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -6821,25 +6821,25 @@ ExpectedStmt ASTNodeImporter::VisitGCCAsmStmt(GCCAsmStmt *S) {
     Names.push_back(ToII);
   }
 
-  SmallVector<StringLiteral *, 4> Clobbers;
+  SmallVector<Expr *, 4> Clobbers;
   for (unsigned I = 0, E = S->getNumClobbers(); I != E; I++) {
-    if (auto ClobberOrErr = import(S->getClobberStringLiteral(I)))
+    if (auto ClobberOrErr = import(S->getClobberExpr(I)))
       Clobbers.push_back(*ClobberOrErr);
     else
       return ClobberOrErr.takeError();
 
   }
 
-  SmallVector<StringLiteral *, 4> Constraints;
+  SmallVector<Expr *, 4> Constraints;
   for (unsigned I = 0, E = S->getNumOutputs(); I != E; I++) {
-    if (auto OutputOrErr = import(S->getOutputConstraintLiteral(I)))
+    if (auto OutputOrErr = import(S->getOutputConstraintExpr(I)))
       Constraints.push_back(*OutputOrErr);
     else
       return OutputOrErr.takeError();
   }
 
   for (unsigned I = 0, E = S->getNumInputs(); I != E; I++) {
-    if (auto InputOrErr = import(S->getInputConstraintLiteral(I)))
+    if (auto InputOrErr = import(S->getInputConstraintExpr(I)))
       Constraints.push_back(*InputOrErr);
     else
       return InputOrErr.takeError();
@@ -6861,7 +6861,7 @@ ExpectedStmt ASTNodeImporter::VisitGCCAsmStmt(GCCAsmStmt *S) {
   ExpectedSLoc AsmLocOrErr = import(S->getAsmLoc());
   if (!AsmLocOrErr)
     return AsmLocOrErr.takeError();
-  auto AsmStrOrErr = import(S->getAsmString());
+  auto AsmStrOrErr = import(S->getAsmStringExpr());
   if (!AsmStrOrErr)
     return AsmStrOrErr.takeError();
   ExpectedSLoc RParenLocOrErr = import(S->getRParenLoc());
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index f8e8aaddbfdbd..86fe8554cba85 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -17928,43 +17928,70 @@ std::optional<std::string> 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 <typename T>
+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<APValue, T>)
+        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<APValue, T>) {
+          Result.getArrayInitializedElt(I) = std::move(Char);
+      }
+      else {
+          APSInt C = Char.getInt();
+          Result.push_back(static_cast<char>(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<char>(C.getExtValue()));
-    if (!HandleLValueArrayAdjustment(Info, PtrExpression, String, CharTy, 1))
+    if (!CheckMemoryLeaks(Info))
       return false;
-  }
-  if (!Scope.destroy())
-    return false;
 
-  if (!CheckMemoryLeaks(Info))
-    return false;
+    return true;
+}
 
-  return true;
+
+bool Expr::EvaluateCharRangeAsString(std::string &Result,
+                                     const Expr *SizeExpression,
+                                     const Expr *PtrExpression, ASTContext &Ctx,
+                                     EvalResult &Status) const {
+    return EvaluateCharRangeAsStringImpl(this, Result, SizeExpression, PtrExpression, Ctx, Status);
+}
+
+bool Expr::EvaluateCharRangeAsString(APValue &Result,
+                               const Expr *SizeExpression,
+                               const Expr *PtrExpression, ASTContext &Ctx,
+                                EvalResult &Status) const {
+    return EvaluateCharRangeAsStringImpl(this, Result, SizeExpression, PtrExpression, Ctx, Status);
 }
 
 bool Expr::tryEvaluateStrLen(uint64_t &Result, ASTContext &Ctx) const {
diff --git a/clang/lib/AST/Stmt.cpp b/clang/lib/AST/Stmt.cpp
index c8ff2ecea20cc..6e0d95714b641 100644
--- a/clang/lib/AST/Stmt.cpp
+++ b/clang/lib/AST/Stmt.cpp
@@ -455,11 +455,11 @@ std::string AsmStmt::generateAsmString(const ASTContext &C) const {
   llvm_unreachable("unknown asm statement kind!");
 }
 
-StringRef AsmStmt::getOutputConstraint(unsigned i) const {
+std::string AsmStmt::getOutputConstraint(unsigned i) const {
   if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
     return gccAsmStmt->getOutputConstraint(i);
   if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this))
-    return msAsmStmt->getOutputConstraint(i);
+    return msAsmStmt->getOutputConstraint(i).str();
   llvm_unreachable("unknown asm statement kind!");
 }
 
@@ -471,11 +471,11 @@ const Expr *AsmStmt::getOutputExpr(unsigned i) const {
   llvm_unreachable("unknown asm statement kind!");
 }
 
-StringRef AsmStmt::getInputConstraint(unsigned i) const {
+std::string AsmStmt::getInputConstraint(unsigned i) const {
   if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
     return gccAsmStmt->getInputConstraint(i);
   if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this))
-    return msAsmStmt->getInputConstraint(i);
+    return msAsmStmt->getInputConstraint(i).str();
   llvm_unreachable("unknown asm statement kind!");
 }
 
@@ -487,11 +487,11 @@ const Expr *AsmStmt::getInputExpr(unsigned i) const {
   llvm_unreachable("unknown asm statement kind!");
 }
 
-StringRef AsmStmt::getClobber(unsigned i) const {
+std::string AsmStmt::getClobber(unsigned i) const {
   if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
     return gccAsmStmt->getClobber(i);
   if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this))
-    return msAsmStmt->getClobber(i);
+    return msAsmStmt->getClobber(i).str();
   llvm_unreachable("unknown asm statement kind!");
 }
 
@@ -510,8 +510,31 @@ char GCCAsmStmt::AsmStringPiece::getModifier() const {
   return isLetter(Str[0]) ? Str[0] : '\0';
 }
 
-StringRef GCCAsmStmt::getClobber(unsigned i) const {
-  return getClobberStringLiteral(i)->getString();
+std::string GCCAsmStmt::ExtractStringFromGCCAsmStmtComponent(const Expr* E) {
+  if(auto* SL = llvm::dyn_cast<StringLiteral>(E))
+    return SL->getString().str();
+  assert(E->getDependence() == ExprDependence::None && "cannot extract a string from a dependent expression");
+  auto* CE = cast<ConstantExpr>(E);
+  APValue Res = CE->getAPValueResult();
+  assert(Res.isArray() && "expected an array");
+
+  std::string Out;
+  Out.reserve(Res.getArraySize());
+  for(unsigned I = 0; I < Res.getArraySize(); ++I) {
+    APValue C = Res.getArrayInitializedElt(I);
+    assert(C.isInt());
+    auto Ch = static_cast<char>(C.getInt().getExtValue());
+    Out.push_back(Ch);
+  }
+  return Out;
+}
+
+std::string GCCAsmStmt::getAsmString() const {
+  return ExtractStringFromGCCAsmStmtComponent(getAsmStringExpr());
+}
+
+std::string GCCAsmStmt::getClobber(unsigned i) const {
+  return ExtractStringFromGCCAsmStmtComponent(getClobberExpr(i));
 }
 
 Expr *GCCAsmStmt::getOutputExpr(unsigned i) {
@@ -521,8 +544,8 @@ Expr *GCCAsmStmt::getOutputExpr(unsigned i) {
 /// getOutputConstraint - Return the constraint string for the specified
 /// output operand.  All output constraints are known to be non-empty (either
 /// '=' or '+').
-StringRef GCCAsmStmt::getOutputConstraint(unsigned i) const {
-  return getOutputConstraintLiteral(i)->getString();
+std::string GCCAsmStmt::getOutputConstraint(unsigned i) const {
+  return ExtractStringFromGCCAsmStmtComponent(getOutputConstraintExpr(i));
 }
 
 Expr *GCCAsmStmt::getInputExpr(unsigned i) {
@@ -543,18 +566,18 @@ StringRef GCCAsmStmt::getLabelName(unsigned i) const {
 
 /// getInputConstraint - Return the specified input constraint.  Unlike output
 /// constraints, these can be empty.
-StringRef GCCAsmStmt::getInputConstraint(unsigned i) const {
-  return getInputConstraintLiteral(i)->getString();
+std::string GCCAsmStmt::getInputConstraint(unsigned i) const {
+  return ExtractStringFromGCCAsmStmtComponent(getInputConstraintExpr(i));
 }
 
 void GCCAsmStmt::setOutputsAndInputsAndClobbers(const ASTContext &C,
                                                 IdentifierInfo **Names,
-                                                StringLiteral **Constraints,
+                                                Expr **Constraints,
                                                 Stmt **Exprs,
                                                 unsigned NumOutputs,
                                                 unsigned NumInputs,
                                                 unsigned NumLabels,
-                                                StringLiteral **Clobbers,
+                                                Expr **Clobbers,
                                                 unsigned NumClobbers) {
   this->NumOutputs = NumOutputs;
   this->NumInputs = NumInputs;
@@ -573,11 +596,11 @@ void GCCAsmStmt::setOutputsAndInputsAndClobbers(const ASTContext &C,
 
   unsigned NumConstraints = NumOutputs + NumInputs;
   C.Deallocate(this->Constraints);
-  this->Constraints = new (C) StringLiteral*[NumConstraints];
+  this->Constraints = new (C) Expr*[NumConstraints];
   std::copy(Constraints, Constraints + NumConstraints, this->Constraints);
 
   C.Deallocate(this->Clobbers);
-  this->Clobbers = new (C) StringLiteral*[NumClobbers];
+  this->Clobbers = new (C) Expr*[NumClobbers];
   std::copy(Clobbers, Clobbers + NumClobbers, this->Clobbers);
 }
 
@@ -609,9 +632,10 @@ int GCCAsmStmt::getNamedOperand(StringRef SymbolicName) const {
 /// true, otherwise return false.
 unsigned GCCAsmStmt::AnalyzeAsmString(SmallVectorImpl<AsmStringPiece>&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();
+  const char *StrEnd = Str.data() + Str.size();
   const char *CurPtr = StrStart;
 
   // "Simple" inline asms have no constraints or operands, just convert the asm
@@ -739,15 +763,21 @@ unsigned GCCAsmStmt::AnalyzeAsmString(SmallVectorImpl<AsmStringPiece>&Pieces,
 
       // Str contains "x4" (Operand without the leading %).
       std::string Str(Begin, CurPtr - Begin);
-
       // (BeginLoc, EndLoc) represents the range of the operand we are currently
       // processing. Unlike Str, the range includes the leading '%'.
-      SourceLocation BeginLoc = getAsmString()->getLocationOfByte(
-          Percent - StrStart, SM, LO, TI, &LastAsmStringToken,
-          &LastAsmStringOffset);
-      SourceLocation EndLoc = getAsmString()->getLocationOfByte(
-          CurPtr - StrStart, SM, LO, TI, &LastAsmStringToken,
-          &LastAsmStringOffset);
+      SourceLocation BeginLoc, EndLoc;
+      if(auto* SL = dyn_cast<StringLiteral>(getAsmStringExpr())) {
+        BeginLoc = SL->getLocationOfByte(
+            Percent - StrStart, SM, LO, TI, &LastAsmStringToken,
+            &LastAsmStringOffset);
+        EndLoc = SL->getLocationOfByte(
+            CurPtr - StrStart, SM, LO, TI, &LastAsmStringToken,
+            &LastAsmStringOffset);
+      }
+      else {
+        BeginLoc = getAsmStringExpr()->getBeginLoc();
+        EndLoc = getAsmStringExpr()->getEndLoc();
+      }
 
       Pieces.emplace_back(N, std::move(Str), BeginLoc, EndLoc);
       continue;
@@ -778,12 +808,19 @@ unsigned GCCAsmStmt::AnalyzeAsmString(SmallVectorImpl<AsmStringPiece>&Pieces,
 
       // (BeginLoc, EndLoc) represents the range of the operand we are currently
       // processing. Unlike Str, the range includes the leading '%'.
-      SourceLocation BeginLoc = getAsmString()->getLocationOfByte(
+      SourceLocation BeginLoc, EndLoc;
+      if(auto* SL = dyn_cast<StringLiteral>(getAsmStringExpr())) {
+        BeginLoc = SL->getLocationOfByte(
           Percent - StrStart, SM, LO, TI, &LastAsmStringToken,
           &LastAsmStringOffset);
-      SourceLocation EndLoc = getAsmString()->getLocationOfByte(
+        EndLoc = SL->getLocationOfByte(
           NameEnd + 1 - StrStart, SM, LO, TI, &LastAsmStringToken,
           &LastAsmStringOffset);
+      }
+      else {
+        BeginLoc = getAsmStringExpr()->getBeginLoc();
+        EndLoc = getAsmStringExpr()->getEndLoc();
+      }
 
       Pieces.emplace_back(N, std::move(Str), BeginLoc, EndLoc);
 
@@ -863,9 +900,9 @@ void MSAsmStmt::setInputExpr(unsigned i, Expr *E) {
 GCCAsmStmt::GCCAsmStmt(const ASTContext &C, SourceLocation asmloc,
                        bool issimple, bool isvolatile, unsigned numoutputs,
                        unsigned numinputs, IdentifierInfo **names,
-                       StringLiteral **constraints, Expr **exprs,
-                       StringLiteral *asmstr, unsigned numclobbers,
-                       StringLiteral **clobbers, unsigned numlabels,
+                       Expr **constraints, Expr **exprs,
+                       Expr *asmstr, unsigned numclobbers,
+                       Expr **clobbers, unsigned numlabels,
                        SourceLocation rparenloc)
     : AsmStmt(GCCAsmStmtClass, asmloc, issimple, isvolatile, numoutputs,
               numinputs, numclobbers),
@@ -879,10 +916,10 @@ GCCAsmStmt::GCCAsmStmt(const ASTContext &C, SourceLocation asmloc,
   std::copy(exprs, exprs + NumExprs, Exprs);
 
   unsigned NumConstraints = NumOutputs + NumInputs;
-  Constraints = new (C) StringLiteral*[NumConstraints];
+  Constraints = new (C) Expr*[NumConstraints];
   std::copy(constraints, constraints + NumConstraints, Constraints);
 
-  Clobbers = new (C) StringLiteral*[NumClobbers];
+  Clobbers = new (C) Expr*[NumClobbers];
   std::copy(clobbers, clobbers + NumClobbers, Clobbers);
 }
 
diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index e0063ec5f25eb..c8623225b486c 100644
--- a/clang/lib/AST/StmtPrinter.cpp
+++ b/clang/lib/AST/StmtPrinter.cpp
@@ -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 << "<<dependent expr>>";
+    return;
+  }
+
+  std::string Str = GCCAsmStmt::ExtractStringFromGCCAsmStmtComponent(E);
+  llvm::SmallVector<char> Out;
+  // FIXME: Unify with StringLiteral::outputString
+  EscapeStringForDiagnostic(Str, Out);
+  OS << '"' << Out << '"';
+}
+
 void StmtPrinter::VisitGCCAsmStmt(GCCAsmStmt *Node) {
   Indent() << "asm ";
 
@@ -507,7 +520,7 @@ void StmtPrinter::VisitGCCAsmStmt(GCCAsmStmt *Node) {
     OS << "goto ";
 
   OS << "(";
-  VisitStringLiteral(Node->getAsmString());
+  PrintGCCAsmString(OS, Node->getAsmStringExpr());
 
   // Outputs
   if (Node->getNumOutputs() != 0 || Node->getNumInputs() != 0 ||
@@ -524,7 +537,7 @@ void StmtPrinter::VisitGCCAsmStmt(GCCAsmStmt *Node) {
       OS << "] ";
     }
 
-    VisitStringLiteral(Node->getOutputConstraintLiteral(i));
+    PrintGCCAsmString(OS, Node->getOutputConstraintExpr(i));
     OS << " (";
     Visit(Node->getOutputExpr(i));
     OS << ")";
@@ -545,7 +558,7 @@ void StmtPrinter::VisitGCCAsmStmt(GCCAsmStmt *Node) {
       OS << "] ";
     }
 
-    VisitStringLiteral(Node->getInputConstraintLiteral(i));
+    PrintGCCAsmString(OS, Node->getInputConstraintExpr(i));
     OS << " (";
     Visit(Node->getInputExpr(i));
     OS << ")";
@@ -559,7 +572,7 @@ void StmtPrinter::VisitGCCAsmStmt(GCCAsmStmt *Node) {
     if (i != 0)
       OS << ", ";
 
-    VisitStringLiteral(Node->getClobberStringLiteral(i));
+    PrintGCCAsmString(OS, Node->getClobberExpr(i));
   }
 
   // Labels
diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp
index bf72de3854f4b..96852858b3b9e 100644
--- a/clang/lib/AST/StmtProfile.cpp
+++ b/clang/lib/AST/StmtProfile.cpp
@@ -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());
   ID.AddInteger(S->getNumOutputs());
   for (unsigned I = 0, N = S->getNumOutputs(); I != N; ++I) {
     ID.AddString(S->getOutputName(I));
-    VisitStringLiteral(S->getOutputConstraintLiteral(I));
+    VisitExpr(S->getOutputConstraintExpr(I));
   }
   ID.AddInteger(S->getNumInputs());
   for (unsigned I = 0, N = S->getNumInputs(); I != N; ++I) {
     ID.AddString(S->getInputName(I));
-    VisitStringLiteral(S->getInputConstraintLiteral(I));
+    VisitExpr(S->getInputConstraintExpr(I));
   }
   ID.AddInteger(S->getNumClobbers());
   for (unsigned I = 0, N = S->getNumClobbers(); I != N; ++I)
-    VisitStringLiteral(S->getClobberStringLiteral(I));
+    VisitExpr(S->getClobberExpr(I));
   ID.AddInteger(S->getNumLabels());
   for (auto *L : S->labels())
     VisitDecl(L->getLabel());
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index 99b6f563d7c82..6ef9625f75118 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -2586,9 +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<GCCAsmStmt>(&S))
-    Result.setMetadata("srcloc",
-                       getAsmSrcLocInfo(gccAsmStmt->getAsmString(), CGF));
+  if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(&S)) {
+    if(const StringLiteral* SL = dyn_cast<StringLiteral>(gccAsmStmt->getAsmStringExpr()))
+      Result.setMetadata("srcloc",
+                         getAsmSrcLocInfo(SL, CGF));
+  }
   else {
     // At least put the line number on MS inline asm blobs.
     llvm::Constant *Loc =
@@ -2705,9 +2707,9 @@ static void EmitHipStdParUnsupportedAsm(CodeGenFunction *CGF,
                                         const AsmStmt &S) {
   constexpr auto Name = "__ASM__hipstdpar_unsupported";
 
-  StringRef Asm;
+  std::string Asm;
   if (auto GCCAsm = dyn_cast<GCCAsmStmt>(&S))
-    Asm = GCCAsm->getAsmString()->getString();
+    Asm = GCCAsm->getAsmString();
 
   auto &Ctx = CGF->CGM.getLLVMContext();
 
@@ -3050,7 +3052,7 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
 
   // Clobbers
   for (unsigned i = 0, e = S.getNumClobbers(); i != e; i++) {
-    StringRef Clobber = S.getClobber(i);
+    std::string Clobber = S.getClobber(i);
 
     if (Clobber == "memory")
       ReadOnly = ReadNone = false;
@@ -3071,7 +3073,7 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
         if (Constraints.find("=&A") != std::string::npos)
           continue;
         std::string::size_type position1 =
-            Constraints.find("={" + Clobber.str() + "}");
+            Constraints.find("={" + Clobber + "}");
         if (position1 != std::string::npos) {
           Constraints.insert(position1 + 1, "&");
           continue;
diff --git a/clang/lib/Parse/ParseStmtAsm.cpp b/clang/lib/Parse/ParseStmtAsm.cpp
index 04c3a8700c10c..94144225ff406 100644
--- a/clang/lib/Parse/ParseStmtAsm.cpp
+++ b/clang/lib/Parse/ParseStmtAsm.cpp
@@ -809,7 +809,7 @@ StmtResult Parser::ParseAsmStatement(bool &msAsm) {
       ConsumeToken();
     }
     // Parse the asm-string list for clobbers if present.
-    if (!AteExtraColon && isTokenStringLiteral()) {
+    if (!AteExtraColon && (isTokenStringLiteral() || Tok.is(tok::l_paren))) {
       while (true) {
         ExprResult Clobber(ParseAsmStringLiteral(/*ForAsmLabel*/ false));
 
diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp
index 0710542f5e938..baf264c808820 100644
--- a/clang/lib/Parse/Parser.cpp
+++ b/clang/lib/Parse/Parser.cpp
@@ -1668,28 +1668,37 @@ void Parser::ParseKNRParamDeclarations(Declarator &D) {
 ///         string-literal
 ///
 ExprResult Parser::ParseAsmStringLiteral(bool ForAsmLabel) {
-  if (!isTokenStringLiteral()) {
-    Diag(Tok, diag::err_expected_string_literal)
-      << /*Source='in...'*/0 << "'asm'";
-    return ExprError();
-  }
 
-  ExprResult AsmString(ParseStringLiteralExpression());
-  if (!AsmString.isInvalid()) {
+  ExprResult AsmString;
+  if(isTokenStringLiteral()) {
+    AsmString = ParseStringLiteralExpression();
+    if(AsmString.isInvalid())
+      return AsmString;
+
     const auto *SL = cast<StringLiteral>(AsmString.get());
     if (!SL->isOrdinary()) {
       Diag(Tok, diag::err_asm_operand_wide_string_literal)
-        << SL->isWide()
-        << SL->getSourceRange();
+      << SL->isWide()
+      << SL->getSourceRange();
       return ExprError();
     }
-    if (ForAsmLabel && SL->getString().empty()) {
-      Diag(Tok, diag::err_asm_operand_wide_string_literal)
-          << 2 /* an empty */ << SL->getSourceRange();
+  }
+  else if(!ForAsmLabel && getLangOpts().CPlusPlus11 && Tok.is(tok::l_paren)) {
+    ParenParseOption ExprType = SimpleExpr;
+    SourceLocation   RParenLoc;
+    ParsedType CastTy;
+
+    AsmString = ParseParenExpression(ExprType, true/*stopIfCastExpr*/,
+                                   false, CastTy, RParenLoc);
+    if(!AsmString.isUsable())
       return ExprError();
-    }
   }
-  return AsmString;
+  else {
+    Diag(Tok, diag::err_asm_expected_string)
+      << /*and expression=*/(getLangOpts().CPlusPlus11? 0 : 1);
+  }
+
+  return Actions.ActOnGCCAsmStmtString(AsmString.get(), ForAsmLabel);
 }
 
 /// ParseSimpleAsm
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 96aac7871db1e..332099bbbd437 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -17261,17 +17261,34 @@ void Sema::DiagnoseStaticAssertDetails(const Expr *E) {
   }
 }
 
-bool Sema::EvaluateStaticAssertMessageAsString(Expr *Message,
-                                               std::string &Result,
-                                               ASTContext &Ctx,
-                                               bool ErrorOnInvalidMessage) {
+template <typename ResultType>
+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<StringLiteral>(Message)) {
     assert(SL->isUnevaluated() && "expected an unevaluated string");
-    Result.assign(SL->getString().begin(), SL->getString().end());
+    if constexpr(std::is_same_v<APValue, ResultType>) {
+        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;
   }
 
@@ -17279,15 +17296,15 @@ bool Sema::EvaluateStaticAssertMessageAsString(Expr *Message,
   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<LookupResult> {
-    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();
     OverloadCandidateSet Candidates(MemberLookup.getNameLoc(),
                                     OverloadCandidateSet::CSK_Normal);
@@ -17300,7 +17317,8 @@ bool Sema::EvaluateStaticAssertMessageAsString(Expr *Message,
   std::optional<LookupResult> SizeMember = FindMember("size", SizeNotFound);
   std::optional<LookupResult> DataMember = FindMember("data", DataNotFound);
   if (SizeNotFound || DataNotFound) {
-    Diag(Loc, diag::err_static_assert_missing_member_function)
+    SemaRef.Diag(Loc, diag::err_user_defined_msg_missing_member_function)
+        << EvalContext
         << ((SizeNotFound && DataNotFound) ? 2
             : SizeNotFound                 ? 0
                                            : 1);
@@ -17316,47 +17334,49 @@ bool Sema::EvaluateStaticAssertMessageAsString(Expr *Message,
   }
 
   auto BuildExpr = [&](LookupResult &LR) {
-    ExprResult Res = BuildMemberReferenceExpr(
+    ExprResult Res = SemaRef.BuildMemberReferenceExpr(
         Message, Message->getType(), Message->getBeginLoc(), false,
         CXXScopeSpec(), SourceLocation(), nullptr, LR, nullptr, nullptr);
     if (Res.isInvalid())
       return ExprError();
-    Res = BuildCallExpr(nullptr, Res.get(), Loc, {}, Loc, nullptr, false, true);
+    Res = SemaRef.BuildCallExpr(nullptr, Res.get(), Loc, {}, Loc, nullptr, false, true);
     if (Res.isInvalid())
       return ExprError();
     if (Res.get()->isTypeDependent() || Res.get()->isValueDependent())
       return ExprError();
-    return TemporaryMaterializationConversion(Res.get());
+    return SemaRef.TemporaryMaterializationConversion(Res.get());
   };
 
   ExprResult SizeE = BuildExpr(*SizeMember);
   ExprResult DataE = BuildExpr(*DataMember);
 
-  QualType SizeT = Context.getSizeType();
+  QualType SizeT = SemaRef.Context.getSizeType();
   QualType ConstCharPtr =
-      Context.getPointerType(Context.getConstType(Context.CharTy));
+      SemaRef.Context.getPointerType(SemaRef.Context.getConstType(SemaRef.Context.CharTy));
 
   ExprResult EvaluatedSize =
       SizeE.isInvalid() ? ExprError()
-                        : BuildConvertedConstantExpression(
-                              SizeE.get(), SizeT, CCEK_StaticAssertMessageSize);
+                        : SemaRef.BuildConvertedConstantExpression(
+                              SizeE.get(), SizeT, Sema::CCEK_StaticAssertMessageSize);
   if (EvaluatedSize.isInvalid()) {
-    Diag(Loc, diag::err_static_assert_invalid_mem_fn_ret_ty) << /*size*/ 0;
+    SemaRef.Diag(Loc, diag::err_user_defined_msg_invalid_mem_fn_ret_ty)
+            << EvalContext << /*size*/ 0;
     return false;
   }
 
   ExprResult EvaluatedData =
       DataE.isInvalid()
           ? ExprError()
-          : BuildConvertedConstantExpression(DataE.get(), ConstCharPtr,
-                                             CCEK_StaticAssertMessageData);
+          : SemaRef.BuildConvertedConstantExpression(DataE.get(), ConstCharPtr,
+                                             Sema::CCEK_StaticAssertMessageData);
   if (EvaluatedData.isInvalid()) {
-    Diag(Loc, diag::err_static_assert_invalid_mem_fn_ret_ty) << /*data*/ 1;
+    SemaRef.Diag(Loc, diag::err_user_defined_msg_invalid_mem_fn_ret_ty)
+            << EvalContext << /*data*/ 1;
     return false;
   }
 
   if (!ErrorOnInvalidMessage &&
-      Diags.isIgnored(diag::warn_static_assert_message_constexpr, Loc))
+      SemaRef.Diags.isIgnored(diag::warn_user_defined_msg_constexpr, Loc))
     return true;
 
   Expr::EvalResult Status;
@@ -17365,16 +17385,30 @@ bool Sema::EvaluateStaticAssertMessageAsString(Expr *Message,
   if (!Message->EvaluateCharRangeAsString(Result, EvaluatedSize.get(),
                                           EvaluatedData.get(), Ctx, Status) ||
       !Notes.empty()) {
-    Diag(Message->getBeginLoc(),
-         ErrorOnInvalidMessage ? diag::err_static_assert_message_constexpr
-                               : diag::warn_static_assert_message_constexpr);
+    SemaRef.Diag(Message->getBeginLoc(),
+         ErrorOnInvalidMessage ? diag::err_user_defined_msg_constexpr
+                               : diag::warn_user_defined_msg_constexpr)
+            << EvalContext;
     for (const auto &Note : Notes)
-      Diag(Note.first, Note.second);
+      SemaRef.Diag(Note.first, Note.second);
     return !ErrorOnInvalidMessage;
   }
   return true;
 }
 
+bool Sema::EvaluateAsString(Expr *Message, APValue &Result, ASTContext &Ctx,
+                            StringEvaluationContext EvalContext,
+                            bool ErrorOnInvalidMessage) {
+    return EvaluateAsStringImpl(*this, Message, Result, Ctx, EvalContext, ErrorOnInvalidMessage);
+
+}
+
+bool Sema::EvaluateAsString(Expr *Message, std::string &Result, ASTContext &Ctx,
+                            StringEvaluationContext EvalContext,
+                            bool ErrorOnInvalidMessage) {
+    return EvaluateAsStringImpl(*this, Message, Result, Ctx, EvalContext, ErrorOnInvalidMessage);
+}
+
 Decl *Sema::BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc,
                                          Expr *AssertExpr, Expr *AssertMessage,
                                          SourceLocation RParenLoc,
@@ -17420,8 +17454,9 @@ Decl *Sema::BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc,
     // the message is grammatically valid without evaluating it.
     if (!Failed && AssertMessage && Cond.getBoolValue()) {
       std::string Str;
-      EvaluateStaticAssertMessageAsString(AssertMessage, Str, Context,
-                                          /*ErrorOnInvalidMessage=*/false);
+      EvaluateAsString(AssertMessage, Str, Context,
+                        StringEvaluationContext::StaticAssert,
+                       /*ErrorOnInvalidMessage=*/false);
     }
 
     // CWG2518
@@ -17436,10 +17471,10 @@ Decl *Sema::BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc,
       bool HasMessage = AssertMessage;
       if (AssertMessage) {
         std::string Str;
-        HasMessage =
-            EvaluateStaticAssertMessageAsString(
-                AssertMessage, Str, Context, /*ErrorOnInvalidMessage=*/true) ||
-            !Str.empty();
+        HasMessage = EvaluateAsString(AssertMessage, Str, Context,
+                                      StringEvaluationContext::StaticAssert,
+                                      /*ErrorOnInvalidMessage=*/true) ||
+                     !Str.empty();
         Msg << Str;
       }
       Expr *InnerCond = nullptr;
diff --git a/clang/lib/Sema/SemaStmtAsm.cpp b/clang/lib/Sema/SemaStmtAsm.cpp
index a0b203fbdfec2..e168f57f8f303 100644
--- a/clang/lib/Sema/SemaStmtAsm.cpp
+++ b/clang/lib/Sema/SemaStmtAsm.cpp
@@ -17,6 +17,7 @@
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Sema/Initialization.h"
 #include "clang/Sema/Lookup.h"
+#include "clang/Sema/Ownership.h"
 #include "clang/Sema/Scope.h"
 #include "clang/Sema/ScopeInfo.h"
 #include "llvm/ADT/ArrayRef.h"
@@ -203,15 +204,15 @@ static StringRef extractRegisterName(const Expr *Expression,
 // clobbers list. If there's a conflict, returns the location of the
 // conflicted clobber, else returns nullptr
 static SourceLocation
-getClobberConflictLocation(MultiExprArg Exprs, StringLiteral **Constraints,
-                           StringLiteral **Clobbers, int NumClobbers,
+getClobberConflictLocation(MultiExprArg Exprs, Expr **Constraints,
+                           Expr **Clobbers, int NumClobbers,
                            unsigned NumLabels,
                            const TargetInfo &Target, ASTContext &Cont) {
   llvm::StringSet<> InOutVars;
   // Collect all the input and output registers from the extended asm
   // statement in order to check for conflicts with the clobber list
   for (unsigned int i = 0; i < Exprs.size() - NumLabels; ++i) {
-    StringRef Constraint = Constraints[i]->getString();
+    std::string Constraint = GCCAsmStmt::ExtractStringFromGCCAsmStmtComponent(Constraints[i]);
     StringRef InOutReg = Target.getConstraintRegister(
         Constraint, extractRegisterName(Exprs[i], Target));
     if (InOutReg != "")
@@ -220,7 +221,7 @@ getClobberConflictLocation(MultiExprArg Exprs, StringLiteral **Constraints,
   // Check for each item in the clobber list if it conflicts with the input
   // or output
   for (int i = 0; i < NumClobbers; ++i) {
-    StringRef Clobber = Clobbers[i]->getString();
+    std::string Clobber = GCCAsmStmt::ExtractStringFromGCCAsmStmtComponent(Clobbers[i]);
     // We only check registers, therefore we don't check cc and memory
     // clobbers
     if (Clobber == "cc" || Clobber == "memory" || Clobber == "unwind")
@@ -233,6 +234,36 @@ getClobberConflictLocation(MultiExprArg Exprs, StringLiteral **Constraints,
   return SourceLocation();
 }
 
+ExprResult Sema::ActOnGCCAsmStmtString(Expr* Expr, bool ForAsmLabel) {
+  if(!Expr)
+    return ExprError();
+
+  if(auto* SL = dyn_cast<StringLiteral>(Expr)) {
+    assert(SL->isOrdinary());
+    if (ForAsmLabel && SL->getString().empty()) {
+      Diag(Expr->getBeginLoc(), diag::err_asm_operand_empty_string)
+        << SL->getSourceRange();
+    }
+    return SL;
+  }
+  if(DiagnoseUnexpandedParameterPack(Expr))
+    return ExprError();
+  if(Expr->getDependence() != ExprDependence::None)
+    return Expr;
+  APValue V;
+  if(!EvaluateAsString(Expr, V, getASTContext(), StringEvaluationContext::Asm,
+                        /*ErrorOnInvalid=*/true))
+    return ExprError();
+
+  if (ForAsmLabel && V.getArrayInitializedElts() == 0) {
+    Diag(Expr->getBeginLoc(), diag::err_asm_operand_empty_string);
+  }
+
+  ConstantExpr* Res = ConstantExpr::Create(getASTContext(), Expr, ConstantResultStorageKind::APValue);
+  Res->SetResult(V, getASTContext());
+  return Res;
+}
+
 StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
                                  bool IsVolatile, unsigned NumOutputs,
                                  unsigned NumInputs, IdentifierInfo **Names,
@@ -241,38 +272,44 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
                                  unsigned NumLabels,
                                  SourceLocation RParenLoc) {
   unsigned NumClobbers = clobbers.size();
-  StringLiteral **Constraints =
-    reinterpret_cast<StringLiteral**>(constraints.data());
-  StringLiteral *AsmString = cast<StringLiteral>(asmString);
-  StringLiteral **Clobbers = reinterpret_cast<StringLiteral**>(clobbers.data());
 
   SmallVector<TargetInfo::ConstraintInfo, 4> OutputConstraintInfos;
 
-  // The parser verifies that there is a string literal here.
-  assert(AsmString->isOrdinary());
-
   FunctionDecl *FD = dyn_cast<FunctionDecl>(getCurLexicalContext());
   llvm::StringMap<bool> FeatureMap;
   Context.getFunctionFeatureMap(FeatureMap, FD);
 
-  for (unsigned i = 0; i != NumOutputs; i++) {
-    StringLiteral *Literal = Constraints[i];
-    assert(Literal->isOrdinary());
+  auto CreateGCCAsmStmt = [&] {
+    return new (Context)
+    GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs,
+               NumInputs, Names, constraints.data(), Exprs.data(), asmString,
+               NumClobbers, clobbers.data(), NumLabels, RParenLoc);
+  };
+
+  if(asmString->getDependence() != ExprDependence::None
+     || llvm::any_of(constraints, [] (Expr* E) {
+        return E->getDependence() != ExprDependence::None;
+      })
+     || llvm::any_of(clobbers, [] (Expr* E) {
+        return E->getDependence() != ExprDependence::None;
+     }))
+  return CreateGCCAsmStmt();
 
+  for (unsigned i = 0; i != NumOutputs; i++) {
+    Expr* Constraint = constraints[i];
     StringRef OutputName;
     if (Names[i])
       OutputName = Names[i]->getName();
 
-    TargetInfo::ConstraintInfo Info(Literal->getString(), OutputName);
+    std::string ConstraintStr = GCCAsmStmt::ExtractStringFromGCCAsmStmtComponent(Constraint);
+
+    TargetInfo::ConstraintInfo Info(ConstraintStr, OutputName);
     if (!Context.getTargetInfo().validateOutputConstraint(Info) &&
         !(LangOpts.HIPStdPar && LangOpts.CUDAIsDevice)) {
-      targetDiag(Literal->getBeginLoc(),
+      targetDiag(Constraint->getBeginLoc(),
                  diag::err_asm_invalid_output_constraint)
           << Info.getConstraintStr();
-      return new (Context)
-          GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs,
-                     NumInputs, Names, Constraints, Exprs.data(), AsmString,
-                     NumClobbers, Clobbers, NumLabels, RParenLoc);
+      return CreateGCCAsmStmt();
     }
 
     ExprResult ER = CheckPlaceholderExpr(Exprs[i]);
@@ -335,35 +372,30 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
 
     unsigned Size = Context.getTypeSize(OutputExpr->getType());
     if (!Context.getTargetInfo().validateOutputSize(
-            FeatureMap, Literal->getString(), Size)) {
+            FeatureMap,  GCCAsmStmt::ExtractStringFromGCCAsmStmtComponent(Constraint), Size)) {
       targetDiag(OutputExpr->getBeginLoc(), diag::err_asm_invalid_output_size)
           << Info.getConstraintStr();
-      return new (Context)
-          GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs,
-                     NumInputs, Names, Constraints, Exprs.data(), AsmString,
-                     NumClobbers, Clobbers, NumLabels, RParenLoc);
+      return CreateGCCAsmStmt();
     }
   }
 
   SmallVector<TargetInfo::ConstraintInfo, 4> InputConstraintInfos;
 
   for (unsigned i = NumOutputs, e = NumOutputs + NumInputs; i != e; i++) {
-    StringLiteral *Literal = Constraints[i];
-    assert(Literal->isOrdinary());
+    Expr *Constraint = constraints[i];
 
     StringRef InputName;
     if (Names[i])
       InputName = Names[i]->getName();
 
-    TargetInfo::ConstraintInfo Info(Literal->getString(), InputName);
+    std::string ConstraintStr = GCCAsmStmt::ExtractStringFromGCCAsmStmtComponent(Constraint);
+
+    TargetInfo::ConstraintInfo Info(ConstraintStr, InputName);
     if (!Context.getTargetInfo().validateInputConstraint(OutputConstraintInfos,
                                                          Info)) {
-      targetDiag(Literal->getBeginLoc(), diag::err_asm_invalid_input_constraint)
+      targetDiag(Constraint->getBeginLoc(), diag::err_asm_invalid_input_constraint)
           << Info.getConstraintStr();
-      return new (Context)
-          GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs,
-                     NumInputs, Names, Constraints, Exprs.data(), AsmString,
-                     NumClobbers, Clobbers, NumLabels, RParenLoc);
+      return CreateGCCAsmStmt();
     }
 
     ExprResult ER = CheckPlaceholderExpr(Exprs[i]);
@@ -449,7 +481,7 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
 
     unsigned Size = Context.getTypeSize(Ty);
     if (!Context.getTargetInfo().validateInputSize(FeatureMap,
-                                                   Literal->getString(), Size))
+                                                   ConstraintStr, Size))
       return targetDiag(InputExpr->getBeginLoc(),
                         diag::err_asm_invalid_input_size)
              << Info.getConstraintStr();
@@ -459,46 +491,45 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
 
   // Check that the clobbers are valid.
   for (unsigned i = 0; i != NumClobbers; i++) {
-    StringLiteral *Literal = Clobbers[i];
-    assert(Literal->isOrdinary());
+    Expr *ClobberExpr = clobbers[i];
 
-    StringRef Clobber = Literal->getString();
+    std::string Clobber = GCCAsmStmt::ExtractStringFromGCCAsmStmtComponent(ClobberExpr);
 
     if (!Context.getTargetInfo().isValidClobber(Clobber)) {
-      targetDiag(Literal->getBeginLoc(), diag::err_asm_unknown_register_name)
+      targetDiag(ClobberExpr->getBeginLoc(), diag::err_asm_unknown_register_name)
           << Clobber;
       return new (Context)
           GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs,
-                     NumInputs, Names, Constraints, Exprs.data(), AsmString,
-                     NumClobbers, Clobbers, NumLabels, RParenLoc);
+                     NumInputs, Names, constraints.data(), Exprs.data(), asmString,
+                     NumClobbers, clobbers.data(), NumLabels, RParenLoc);
     }
 
     if (Clobber == "unwind") {
-      UnwindClobberLoc = Literal->getBeginLoc();
+      UnwindClobberLoc = ClobberExpr->getBeginLoc();
     }
   }
 
   // Using unwind clobber and asm-goto together is not supported right now.
   if (UnwindClobberLoc && NumLabels > 0) {
     targetDiag(*UnwindClobberLoc, diag::err_asm_unwind_and_goto);
-    return new (Context)
-        GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs, NumInputs,
-                   Names, Constraints, Exprs.data(), AsmString, NumClobbers,
-                   Clobbers, NumLabels, RParenLoc);
+    return CreateGCCAsmStmt();
   }
 
-  GCCAsmStmt *NS =
-    new (Context) GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs,
-                             NumInputs, Names, Constraints, Exprs.data(),
-                             AsmString, NumClobbers, Clobbers, NumLabels,
-                             RParenLoc);
+  GCCAsmStmt *NS = CreateGCCAsmStmt();
   // Validate the asm string, ensuring it makes sense given the operands we
   // have.
+
+  auto GetLocation = [this](const Expr* Str, unsigned Offset) {
+    if(auto* SL = dyn_cast<StringLiteral>(Str))
+      return getLocationOfStringLiteralByte(SL, Offset);
+    return Str->getBeginLoc();
+  };
+
   SmallVector<GCCAsmStmt::AsmStringPiece, 8> Pieces;
   unsigned DiagOffs;
   if (unsigned DiagID = NS->AnalyzeAsmString(Pieces, Context, DiagOffs)) {
-    targetDiag(getLocationOfStringLiteralByte(AsmString, DiagOffs), DiagID)
-        << AsmString->getSourceRange();
+    targetDiag(GetLocation(asmString, DiagOffs), DiagID)
+        << asmString->getSourceRange();
     return NS;
   }
 
@@ -529,7 +560,7 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
     }
 
     // Now that we have the right indexes go ahead and check.
-    StringLiteral *Literal = Constraints[ConstraintIdx];
+    Expr *Constraint = constraints[ConstraintIdx];
     const Type *Ty = Exprs[ConstraintIdx]->getType().getTypePtr();
     if (Ty->isDependentType() || Ty->isIncompleteType())
       continue;
@@ -537,7 +568,7 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
     unsigned Size = Context.getTypeSize(Ty);
     std::string SuggestedModifier;
     if (!Context.getTargetInfo().validateConstraintModifier(
-            Literal->getString(), Piece.getModifier(), Size,
+            GCCAsmStmt::ExtractStringFromGCCAsmStmtComponent(Constraint), Piece.getModifier(), Size,
             SuggestedModifier)) {
       targetDiag(Exprs[ConstraintIdx]->getBeginLoc(),
                  diag::warn_asm_mismatched_size_modifier);
@@ -546,8 +577,10 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
         auto B = targetDiag(Piece.getRange().getBegin(),
                             diag::note_asm_missing_constraint_modifier)
                  << SuggestedModifier;
-        SuggestedModifier = "%" + SuggestedModifier + Piece.getString();
-        B << FixItHint::CreateReplacement(Piece.getRange(), SuggestedModifier);
+        if(isa<StringLiteral>(Constraint)) {
+          SuggestedModifier = "%" + SuggestedModifier + Piece.getString();
+          B << FixItHint::CreateReplacement(Piece.getRange(), SuggestedModifier);
+        }
       }
     }
   }
@@ -708,7 +741,7 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
 
   // Check for conflicts between clobber list and input or output lists
   SourceLocation ConstraintLoc =
-      getClobberConflictLocation(Exprs, Constraints, Clobbers, NumClobbers,
+      getClobberConflictLocation(Exprs, constraints.data(), clobbers.data(), NumClobbers,
                                  NumLabels,
                                  Context.getTargetInfo(), Context);
   if (ConstraintLoc.isValid())
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index a09f623ff8fbf..06d41a8154ca3 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -8552,25 +8552,39 @@ template<typename Derived>
 StmtResult
 TreeTransform<Derived>::TransformGCCAsmStmt(GCCAsmStmt *S) {
 
+
   SmallVector<Expr*, 8> Constraints;
   SmallVector<Expr*, 8> Exprs;
   SmallVector<IdentifierInfo *, 4> Names;
 
-  ExprResult AsmString;
   SmallVector<Expr*, 8> Clobbers;
 
   bool ExprsChanged = false;
 
+  auto RebuildString = [&] (Expr* E) {
+      ExprResult Result = getDerived().TransformExpr(E);
+      if (Result.isInvalid())
+        return Result;
+      if(!Result.isInvalid() && Result.get() != E) {
+          ExprsChanged = true;
+          Result = SemaRef.ActOnGCCAsmStmtString(Result.get(), /*ForLabel=*/false);
+      }
+      return Result;
+  };
+
   // Go through the outputs.
   for (unsigned I = 0, E = S->getNumOutputs(); I != E; ++I) {
     Names.push_back(S->getOutputIdentifier(I));
 
-    // No need to transform the constraint literal.
-    Constraints.push_back(S->getOutputConstraintLiteral(I));
+    ExprResult Result = RebuildString(S->getOutputConstraintExpr(I));
+    if (Result.isInvalid())
+      return StmtError();
+
+    Constraints.push_back(Result.get());
 
     // Transform the output expr.
     Expr *OutputExpr = S->getOutputExpr(I);
-    ExprResult Result = getDerived().TransformExpr(OutputExpr);
+    Result = getDerived().TransformExpr(OutputExpr);
     if (Result.isInvalid())
       return StmtError();
 
@@ -8583,12 +8597,15 @@ TreeTransform<Derived>::TransformGCCAsmStmt(GCCAsmStmt *S) {
   for (unsigned I = 0, E = S->getNumInputs(); I != E; ++I) {
     Names.push_back(S->getInputIdentifier(I));
 
-    // No need to transform the constraint literal.
-    Constraints.push_back(S->getInputConstraintLiteral(I));
+    ExprResult Result = RebuildString(S->getInputConstraintExpr(I));
+    if (Result.isInvalid())
+      return StmtError();
+
+    Constraints.push_back(Result.get());
 
     // Transform the input expr.
     Expr *InputExpr = S->getInputExpr(I);
-    ExprResult Result = getDerived().TransformExpr(InputExpr);
+    Result = getDerived().TransformExpr(InputExpr);
     if (Result.isInvalid())
       return StmtError();
 
@@ -8607,15 +8624,22 @@ TreeTransform<Derived>::TransformGCCAsmStmt(GCCAsmStmt *S) {
     ExprsChanged |= Result.get() != S->getLabelExpr(I);
     Exprs.push_back(Result.get());
   }
-  if (!getDerived().AlwaysRebuild() && !ExprsChanged)
-    return S;
 
   // Go through the clobbers.
-  for (unsigned I = 0, E = S->getNumClobbers(); I != E; ++I)
-    Clobbers.push_back(S->getClobberStringLiteral(I));
+  for (unsigned I = 0, E = S->getNumClobbers(); I != E; ++I) {
+      ExprResult Result = RebuildString(S->getClobberExpr(I));
+      if (Result.isInvalid())
+        return StmtError();
+      Clobbers.push_back(Result.get());
+  }
+
+  ExprResult AsmString = RebuildString(S->getAsmStringExpr());
+  if (AsmString.isInvalid())
+    return StmtError();
+
+  if (!getDerived().AlwaysRebuild() && !ExprsChanged)
+    return S;
 
-  // No need to transform the asm string literal.
-  AsmString = S->getAsmString();
   return getDerived().RebuildGCCAsmStmt(S->getAsmLoc(), S->isSimple(),
                                         S->isVolatile(), S->getNumOutputs(),
                                         S->getNumInputs(), Names.data(),
diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp
index 48f9f89bd6e4c..7ad1216cb53e2 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -381,7 +381,7 @@ void ASTStmtReader::VisitGCCAsmStmt(GCCAsmStmt *S) {
   VisitAsmStmt(S);
   S->NumLabels = Record.readInt();
   S->setRParenLoc(readSourceLocation());
-  S->setAsmString(cast_or_null<StringLiteral>(Record.readSubStmt()));
+  S->setAsmString(cast_or_null<Expr>(Record.readSubStmt()));
 
   unsigned NumOutputs = S->getNumOutputs();
   unsigned NumInputs = S->getNumInputs();
@@ -390,18 +390,18 @@ void ASTStmtReader::VisitGCCAsmStmt(GCCAsmStmt *S) {
 
   // Outputs and inputs
   SmallVector<IdentifierInfo *, 16> Names;
-  SmallVector<StringLiteral*, 16> Constraints;
+  SmallVector<Expr*, 16> Constraints;
   SmallVector<Stmt*, 16> Exprs;
   for (unsigned I = 0, N = NumOutputs + NumInputs; I != N; ++I) {
     Names.push_back(Record.readIdentifier());
-    Constraints.push_back(cast_or_null<StringLiteral>(Record.readSubStmt()));
+    Constraints.push_back(cast_or_null<Expr>(Record.readSubStmt()));
     Exprs.push_back(Record.readSubStmt());
   }
 
   // Constraints
-  SmallVector<StringLiteral*, 16> Clobbers;
+  SmallVector<Expr*, 16> Clobbers;
   for (unsigned I = 0; I != NumClobbers; ++I)
-    Clobbers.push_back(cast_or_null<StringLiteral>(Record.readSubStmt()));
+    Clobbers.push_back(cast_or_null<Expr>(Record.readSubStmt()));
 
   // Labels
   for (unsigned I = 0, N = NumLabels; I != N; ++I) {
diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp
index aa5a7854394a0..32211ced4ff15 100644
--- a/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -361,25 +361,25 @@ void ASTStmtWriter::VisitGCCAsmStmt(GCCAsmStmt *S) {
   VisitAsmStmt(S);
   Record.push_back(S->getNumLabels());
   Record.AddSourceLocation(S->getRParenLoc());
-  Record.AddStmt(S->getAsmString());
+  Record.AddStmt(S->getAsmStringExpr());
 
   // Outputs
   for (unsigned I = 0, N = S->getNumOutputs(); I != N; ++I) {
     Record.AddIdentifierRef(S->getOutputIdentifier(I));
-    Record.AddStmt(S->getOutputConstraintLiteral(I));
+    Record.AddStmt(S->getOutputConstraintExpr(I));
     Record.AddStmt(S->getOutputExpr(I));
   }
 
   // Inputs
   for (unsigned I = 0, N = S->getNumInputs(); I != N; ++I) {
     Record.AddIdentifierRef(S->getInputIdentifier(I));
-    Record.AddStmt(S->getInputConstraintLiteral(I));
+    Record.AddStmt(S->getInputConstraintExpr(I));
     Record.AddStmt(S->getInputExpr(I));
   }
 
   // Clobbers
   for (unsigned I = 0, N = S->getNumClobbers(); I != N; ++I)
-    Record.AddStmt(S->getClobberStringLiteral(I));
+    Record.AddStmt(S->getClobberExpr(I));
 
   // Labels
   for (unsigned I = 0, N = S->getNumLabels(); I != N; ++I) {

>From 6e535f3499d5ae3c9a0f906a418f8faa10975efd Mon Sep 17 00:00:00 2001
From: Corentin Jabot <corentinjabot at gmail.com>
Date: Wed, 12 Mar 2025 19:42:22 +0100
Subject: [PATCH 2/2] format

---
 clang/include/clang/AST/Expr.h            |  7 +-
 clang/include/clang/AST/Stmt.h            | 24 ++----
 clang/include/clang/Sema/Sema.h           | 13 +--
 clang/lib/AST/ExprConstant.cpp            | 85 +++++++++----------
 clang/lib/AST/Stmt.cpp                    | 75 ++++++++---------
 clang/lib/AST/StmtPrinter.cpp             |  4 +-
 clang/lib/CodeGen/CGStmt.cpp              |  9 +--
 clang/lib/Parse/Parser.cpp                | 27 ++++---
 clang/lib/Sema/SemaDeclCXX.cpp            | 75 ++++++++---------
 clang/lib/Sema/SemaStmtAsm.cpp            | 99 ++++++++++++-----------
 clang/lib/Sema/TreeTransform.h            | 25 +++---
 clang/lib/Serialization/ASTReaderStmt.cpp |  4 +-
 12 files changed, 219 insertions(+), 228 deletions(-)

diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 7f9e50dfe78bd..28437b5629b00 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -787,10 +787,9 @@ 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;
+  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 7bf0a6911c515..88ae3aeefa869 100644
--- a/clang/include/clang/AST/Stmt.h
+++ b/clang/include/clang/AST/Stmt.h
@@ -3314,9 +3314,8 @@ class GCCAsmStmt : public AsmStmt {
   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 @@ class GCCAsmStmt : public AsmStmt {
   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 @@ class GCCAsmStmt : public AsmStmt {
     return const_cast<GCCAsmStmt*>(this)->getInputExpr(i);
   }
 
-  static std::string ExtractStringFromGCCAsmStmtComponent(const Expr* E);
+  static std::string ExtractStringFromGCCAsmStmtComponent(const Expr *E);
 
   //===--- Labels ---===//
 
@@ -3493,12 +3490,9 @@ class GCCAsmStmt : public AsmStmt {
 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 @@ class GCCAsmStmt : public AsmStmt {
   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 e1b1083675612..4043699912423 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -5585,10 +5585,7 @@ class Sema final : public SemaBase {
   void ActOnFinishDelayedCXXMethodDeclaration(Scope *S, Decl *Method);
   void ActOnFinishDelayedMemberInitializers(Decl *Record);
 
-  enum class StringEvaluationContext {
-      StaticAssert = 0,
-      Asm = 1
-  };
+  enum class StringEvaluationContext { StaticAssert = 0, Asm = 1 };
 
   bool EvaluateAsString(Expr *Message, APValue &Result, ASTContext &Ctx,
                         StringEvaluationContext EvalContext,
@@ -11049,7 +11046,7 @@ class Sema final : public SemaBase {
   ///@{
 
 public:
-  ExprResult ActOnGCCAsmStmtString(Expr* Stm, bool ForAsmLabel);
+  ExprResult ActOnGCCAsmStmtString(Expr *Stm, bool ForAsmLabel);
   StmtResult ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
                              bool IsVolatile, unsigned NumOutputs,
                              unsigned NumInputs, IdentifierInfo **Names,
@@ -15339,14 +15336,12 @@ void Sema::PragmaStack<Sema::AlignPackInfo>::Act(SourceLocation PragmaLocation,
                                                  llvm::StringRef StackSlotLabel,
                                                  AlignPackInfo Value);
 
-inline
-const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
-                                    Sema::StringEvaluationContext Ctx) {
+inline const StreamingDiagnostic &
+operator<<(const StreamingDiagnostic &DB, Sema::StringEvaluationContext Ctx) {
   DB << llvm::to_underlying(Ctx);
   return DB;
 }
 
-
 } // end namespace clang
 
 #endif
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 86fe8554cba85..70f3531524620 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -17929,69 +17929,70 @@ std::optional<std::string> Expr::tryEvaluateString(ASTContext &Ctx) const {
 }
 
 template <typename T>
-static bool EvaluateCharRangeAsStringImpl(const Expr*, T& Result,
+static bool EvaluateCharRangeAsStringImpl(const Expr *, T &Result,
                                           const Expr *SizeExpression,
-                                          const Expr *PtrExpression, ASTContext &Ctx,
+                                          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;
+  LValue String;
+  EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpression);
+  Info.InConstantContext = true;
 
-    uint64_t Size = SizeValue.getZExtValue();
+  FullExpressionRAII Scope(Info);
+  APSInt SizeValue;
+  if (!::EvaluateInteger(SizeExpression, SizeValue, Info))
+    return false;
 
-    if constexpr(std::is_same_v<APValue, T>)
-        Result = APValue(APValue::UninitArray{}, Size, Size);
-    //else
-    //    Result.reserve(Size);
+  uint64_t Size = SizeValue.getZExtValue();
 
-    if (!::EvaluatePointer(PtrExpression, String, Info))
-      return false;
+  if constexpr (std::is_same_v<APValue, T>)
+    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))
-        return false;
+  if (!::EvaluatePointer(PtrExpression, String, Info))
+    return false;
 
-      if constexpr(std::is_same_v<APValue, T>) {
-          Result.getArrayInitializedElt(I) = std::move(Char);
-      }
-      else {
-          APSInt C = Char.getInt();
-          Result.push_back(static_cast<char>(C.getExtValue()));
-      }
+  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 (!HandleLValueArrayAdjustment(Info, PtrExpression, String, CharTy, 1))
-        return false;
+    if constexpr (std::is_same_v<APValue, T>) {
+      Result.getArrayInitializedElt(I) = std::move(Char);
+    } else {
+      APSInt C = Char.getInt();
+      Result.push_back(static_cast<char>(C.getExtValue()));
     }
-    if (!Scope.destroy())
-      return false;
 
-    if (!CheckMemoryLeaks(Info))
+    if (!HandleLValueArrayAdjustment(Info, PtrExpression, String, CharTy, 1))
       return false;
+  }
+  if (!Scope.destroy())
+    return false;
 
-    return true;
-}
+  if (!CheckMemoryLeaks(Info))
+    return false;
 
+  return true;
+}
 
 bool Expr::EvaluateCharRangeAsString(std::string &Result,
                                      const Expr *SizeExpression,
                                      const Expr *PtrExpression, ASTContext &Ctx,
                                      EvalResult &Status) const {
-    return EvaluateCharRangeAsStringImpl(this, Result, SizeExpression, PtrExpression, Ctx, Status);
+  return EvaluateCharRangeAsStringImpl(this, Result, SizeExpression,
+                                       PtrExpression, Ctx, Status);
 }
 
 bool Expr::EvaluateCharRangeAsString(APValue &Result,
-                               const Expr *SizeExpression,
-                               const Expr *PtrExpression, ASTContext &Ctx,
-                                EvalResult &Status) const {
-    return EvaluateCharRangeAsStringImpl(this, Result, SizeExpression, PtrExpression, Ctx, Status);
+                                     const Expr *SizeExpression,
+                                     const Expr *PtrExpression, ASTContext &Ctx,
+                                     EvalResult &Status) const {
+  return EvaluateCharRangeAsStringImpl(this, Result, SizeExpression,
+                                       PtrExpression, Ctx, Status);
 }
 
 bool Expr::tryEvaluateStrLen(uint64_t &Result, ASTContext &Ctx) const {
diff --git a/clang/lib/AST/Stmt.cpp b/clang/lib/AST/Stmt.cpp
index 6e0d95714b641..be4ba6878bf0c 100644
--- a/clang/lib/AST/Stmt.cpp
+++ b/clang/lib/AST/Stmt.cpp
@@ -510,17 +510,18 @@ char GCCAsmStmt::AsmStringPiece::getModifier() const {
   return isLetter(Str[0]) ? Str[0] : '\0';
 }
 
-std::string GCCAsmStmt::ExtractStringFromGCCAsmStmtComponent(const Expr* E) {
-  if(auto* SL = llvm::dyn_cast<StringLiteral>(E))
+std::string GCCAsmStmt::ExtractStringFromGCCAsmStmtComponent(const Expr *E) {
+  if (auto *SL = llvm::dyn_cast<StringLiteral>(E))
     return SL->getString().str();
-  assert(E->getDependence() == ExprDependence::None && "cannot extract a string from a dependent expression");
-  auto* CE = cast<ConstantExpr>(E);
+  assert(E->getDependence() == ExprDependence::None &&
+         "cannot extract a string from a dependent expression");
+  auto *CE = cast<ConstantExpr>(E);
   APValue Res = CE->getAPValueResult();
   assert(Res.isArray() && "expected an array");
 
   std::string Out;
   Out.reserve(Res.getArraySize());
-  for(unsigned I = 0; I < Res.getArraySize(); ++I) {
+  for (unsigned I = 0; I < Res.getArraySize(); ++I) {
     APValue C = Res.getArrayInitializedElt(I);
     assert(C.isInt());
     auto Ch = static_cast<char>(C.getInt().getExtValue());
@@ -570,15 +571,10 @@ std::string GCCAsmStmt::getInputConstraint(unsigned i) const {
   return ExtractStringFromGCCAsmStmtComponent(getInputConstraintExpr(i));
 }
 
-void GCCAsmStmt::setOutputsAndInputsAndClobbers(const ASTContext &C,
-                                                IdentifierInfo **Names,
-                                                Expr **Constraints,
-                                                Stmt **Exprs,
-                                                unsigned NumOutputs,
-                                                unsigned NumInputs,
-                                                unsigned NumLabels,
-                                                Expr **Clobbers,
-                                                unsigned NumClobbers) {
+void GCCAsmStmt::setOutputsAndInputsAndClobbers(
+    const ASTContext &C, IdentifierInfo **Names, Expr **Constraints,
+    Stmt **Exprs, unsigned NumOutputs, unsigned NumInputs, unsigned NumLabels,
+    Expr **Clobbers, unsigned NumClobbers) {
   this->NumOutputs = NumOutputs;
   this->NumInputs = NumInputs;
   this->NumClobbers = NumClobbers;
@@ -596,11 +592,11 @@ void GCCAsmStmt::setOutputsAndInputsAndClobbers(const ASTContext &C,
 
   unsigned NumConstraints = NumOutputs + NumInputs;
   C.Deallocate(this->Constraints);
-  this->Constraints = new (C) Expr*[NumConstraints];
+  this->Constraints = new (C) Expr *[NumConstraints];
   std::copy(Constraints, Constraints + NumConstraints, this->Constraints);
 
   C.Deallocate(this->Clobbers);
-  this->Clobbers = new (C) Expr*[NumClobbers];
+  this->Clobbers = new (C) Expr *[NumClobbers];
   std::copy(Clobbers, Clobbers + NumClobbers, this->Clobbers);
 }
 
@@ -766,15 +762,14 @@ unsigned GCCAsmStmt::AnalyzeAsmString(SmallVectorImpl<AsmStringPiece>&Pieces,
       // (BeginLoc, EndLoc) represents the range of the operand we are currently
       // processing. Unlike Str, the range includes the leading '%'.
       SourceLocation BeginLoc, EndLoc;
-      if(auto* SL = dyn_cast<StringLiteral>(getAsmStringExpr())) {
-        BeginLoc = SL->getLocationOfByte(
-            Percent - StrStart, SM, LO, TI, &LastAsmStringToken,
-            &LastAsmStringOffset);
-        EndLoc = SL->getLocationOfByte(
-            CurPtr - StrStart, SM, LO, TI, &LastAsmStringToken,
-            &LastAsmStringOffset);
-      }
-      else {
+      if (auto *SL = dyn_cast<StringLiteral>(getAsmStringExpr())) {
+        BeginLoc =
+            SL->getLocationOfByte(Percent - StrStart, SM, LO, TI,
+                                  &LastAsmStringToken, &LastAsmStringOffset);
+        EndLoc =
+            SL->getLocationOfByte(CurPtr - StrStart, SM, LO, TI,
+                                  &LastAsmStringToken, &LastAsmStringOffset);
+      } else {
         BeginLoc = getAsmStringExpr()->getBeginLoc();
         EndLoc = getAsmStringExpr()->getEndLoc();
       }
@@ -809,15 +804,14 @@ unsigned GCCAsmStmt::AnalyzeAsmString(SmallVectorImpl<AsmStringPiece>&Pieces,
       // (BeginLoc, EndLoc) represents the range of the operand we are currently
       // processing. Unlike Str, the range includes the leading '%'.
       SourceLocation BeginLoc, EndLoc;
-      if(auto* SL = dyn_cast<StringLiteral>(getAsmStringExpr())) {
-        BeginLoc = SL->getLocationOfByte(
-          Percent - StrStart, SM, LO, TI, &LastAsmStringToken,
-          &LastAsmStringOffset);
-        EndLoc = SL->getLocationOfByte(
-          NameEnd + 1 - StrStart, SM, LO, TI, &LastAsmStringToken,
-          &LastAsmStringOffset);
-      }
-      else {
+      if (auto *SL = dyn_cast<StringLiteral>(getAsmStringExpr())) {
+        BeginLoc =
+            SL->getLocationOfByte(Percent - StrStart, SM, LO, TI,
+                                  &LastAsmStringToken, &LastAsmStringOffset);
+        EndLoc =
+            SL->getLocationOfByte(NameEnd + 1 - StrStart, SM, LO, TI,
+                                  &LastAsmStringToken, &LastAsmStringOffset);
+      } else {
         BeginLoc = getAsmStringExpr()->getBeginLoc();
         EndLoc = getAsmStringExpr()->getEndLoc();
       }
@@ -900,13 +894,12 @@ void MSAsmStmt::setInputExpr(unsigned i, Expr *E) {
 GCCAsmStmt::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 **constraints, Expr **exprs, Expr *asmstr,
+                       unsigned numclobbers, Expr **clobbers,
+                       unsigned numlabels, SourceLocation rparenloc)
     : AsmStmt(GCCAsmStmtClass, asmloc, issimple, isvolatile, numoutputs,
               numinputs, numclobbers),
-              RParenLoc(rparenloc), AsmStr(asmstr), NumLabels(numlabels) {
+      RParenLoc(rparenloc), AsmStr(asmstr), NumLabels(numlabels) {
   unsigned NumExprs = NumOutputs + NumInputs + NumLabels;
 
   Names = new (C) IdentifierInfo*[NumExprs];
@@ -916,10 +909,10 @@ GCCAsmStmt::GCCAsmStmt(const ASTContext &C, SourceLocation asmloc,
   std::copy(exprs, exprs + NumExprs, Exprs);
 
   unsigned NumConstraints = NumOutputs + NumInputs;
-  Constraints = new (C) Expr*[NumConstraints];
+  Constraints = new (C) Expr *[NumConstraints];
   std::copy(constraints, constraints + NumConstraints, Constraints);
 
-  Clobbers = new (C) Expr*[NumClobbers];
+  Clobbers = new (C) Expr *[NumClobbers];
   std::copy(clobbers, clobbers + NumClobbers, Clobbers);
 }
 
diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index c8623225b486c..bceab177a6aa3 100644
--- a/clang/lib/AST/StmtPrinter.cpp
+++ b/clang/lib/AST/StmtPrinter.cpp
@@ -497,8 +497,8 @@ void StmtPrinter::VisitReturnStmt(ReturnStmt *Node) {
   if (Policy.IncludeNewlines) OS << NL;
 }
 
-static void PrintGCCAsmString(raw_ostream &OS, Expr*E) {
-  if(E->getDependence()) {
+static void PrintGCCAsmString(raw_ostream &OS, Expr *E) {
+  if (E->getDependence()) {
     OS << "<<dependent expr>>";
     return;
   }
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index 6ef9625f75118..c243d5c98239b 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -2587,11 +2587,10 @@ 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<GCCAsmStmt>(&S)) {
-    if(const StringLiteral* SL = dyn_cast<StringLiteral>(gccAsmStmt->getAsmStringExpr()))
-      Result.setMetadata("srcloc",
-                         getAsmSrcLocInfo(SL, CGF));
-  }
-  else {
+    if (const StringLiteral *SL =
+            dyn_cast<StringLiteral>(gccAsmStmt->getAsmStringExpr()))
+      Result.setMetadata("srcloc", getAsmSrcLocInfo(SL, CGF));
+  } else {
     // At least put the line number on MS inline asm blobs.
     llvm::Constant *Loc =
         llvm::ConstantInt::get(CGF.Int64Ty, S.getAsmLoc().getRawEncoding());
diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp
index baf264c808820..66d2e3238317e 100644
--- a/clang/lib/Parse/Parser.cpp
+++ b/clang/lib/Parse/Parser.cpp
@@ -1670,32 +1670,33 @@ void Parser::ParseKNRParamDeclarations(Declarator &D) {
 ExprResult Parser::ParseAsmStringLiteral(bool ForAsmLabel) {
 
   ExprResult AsmString;
-  if(isTokenStringLiteral()) {
+  if (isTokenStringLiteral()) {
     AsmString = ParseStringLiteralExpression();
-    if(AsmString.isInvalid())
+    if (AsmString.isInvalid())
       return AsmString;
 
     const auto *SL = cast<StringLiteral>(AsmString.get());
     if (!SL->isOrdinary()) {
       Diag(Tok, diag::err_asm_operand_wide_string_literal)
-      << SL->isWide()
-      << SL->getSourceRange();
+          << SL->isWide() << SL->getSourceRange();
       return ExprError();
     }
-  }
-  else if(!ForAsmLabel && getLangOpts().CPlusPlus11 && Tok.is(tok::l_paren)) {
+  } else if (!ForAsmLabel && getLangOpts().CPlusPlus11 &&
+             Tok.is(tok::l_paren)) {
     ParenParseOption ExprType = SimpleExpr;
-    SourceLocation   RParenLoc;
+    SourceLocation RParenLoc;
     ParsedType CastTy;
 
-    AsmString = ParseParenExpression(ExprType, true/*stopIfCastExpr*/,
-                                   false, CastTy, RParenLoc);
-    if(!AsmString.isUsable())
+    Sema::ExpressionEvaluationContext Context =
+        Sema::ExpressionEvaluationContext::ConstantEvaluated;
+
+    AsmString = ParseParenExpression(ExprType, true /*stopIfCastExpr*/, false,
+                                     CastTy, RParenLoc);
+    if (!AsmString.isUsable())
       return ExprError();
-  }
-  else {
+  } else {
     Diag(Tok, diag::err_asm_expected_string)
-      << /*and expression=*/(getLangOpts().CPlusPlus11? 0 : 1);
+        << /*and expression=*/(getLangOpts().CPlusPlus11 ? 0 : 1);
   }
 
   return Actions.ActOnGCCAsmStmtString(AsmString.get(), ForAsmLabel);
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 332099bbbd437..dcd249e7a19dd 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -17262,11 +17262,10 @@ void Sema::DiagnoseStaticAssertDetails(const Expr *E) {
 }
 
 template <typename ResultType>
-static bool EvaluateAsStringImpl(Sema & SemaRef,
-                            Expr *Message,
-                            ResultType &Result, ASTContext &Ctx,
-                            Sema::StringEvaluationContext EvalContext,
-                            bool ErrorOnInvalidMessage) {
+static bool EvaluateAsStringImpl(Sema &SemaRef, Expr *Message,
+                                 ResultType &Result, ASTContext &Ctx,
+                                 Sema::StringEvaluationContext EvalContext,
+                                 bool ErrorOnInvalidMessage) {
 
   assert(Message);
   assert(!Message->isTypeDependent() && !Message->isValueDependent() &&
@@ -17274,20 +17273,21 @@ static bool EvaluateAsStringImpl(Sema & SemaRef,
 
   if (const auto *SL = dyn_cast<StringLiteral>(Message)) {
     assert(SL->isUnevaluated() && "expected an unevaluated string");
-    if constexpr(std::is_same_v<APValue, ResultType>) {
-        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());
+    if constexpr (std::is_same_v<APValue, ResultType>) {
+      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;
   }
@@ -17339,7 +17339,8 @@ static bool EvaluateAsStringImpl(Sema & SemaRef,
         CXXScopeSpec(), SourceLocation(), nullptr, LR, nullptr, nullptr);
     if (Res.isInvalid())
       return ExprError();
-    Res = SemaRef.BuildCallExpr(nullptr, Res.get(), Loc, {}, Loc, nullptr, false, true);
+    Res = SemaRef.BuildCallExpr(nullptr, Res.get(), Loc, {}, Loc, nullptr,
+                                false, true);
     if (Res.isInvalid())
       return ExprError();
     if (Res.get()->isTypeDependent() || Res.get()->isValueDependent())
@@ -17351,27 +17352,28 @@ static bool EvaluateAsStringImpl(Sema & SemaRef,
   ExprResult DataE = BuildExpr(*DataMember);
 
   QualType SizeT = SemaRef.Context.getSizeType();
-  QualType ConstCharPtr =
-      SemaRef.Context.getPointerType(SemaRef.Context.getConstType(SemaRef.Context.CharTy));
+  QualType ConstCharPtr = SemaRef.Context.getPointerType(
+      SemaRef.Context.getConstType(SemaRef.Context.CharTy));
 
   ExprResult EvaluatedSize =
-      SizeE.isInvalid() ? ExprError()
-                        : SemaRef.BuildConvertedConstantExpression(
-                              SizeE.get(), SizeT, Sema::CCEK_StaticAssertMessageSize);
+      SizeE.isInvalid()
+          ? ExprError()
+          : SemaRef.BuildConvertedConstantExpression(
+                SizeE.get(), SizeT, Sema::CCEK_StaticAssertMessageSize);
   if (EvaluatedSize.isInvalid()) {
     SemaRef.Diag(Loc, diag::err_user_defined_msg_invalid_mem_fn_ret_ty)
-            << EvalContext << /*size*/ 0;
+        << EvalContext << /*size*/ 0;
     return false;
   }
 
   ExprResult EvaluatedData =
       DataE.isInvalid()
           ? ExprError()
-          : SemaRef.BuildConvertedConstantExpression(DataE.get(), ConstCharPtr,
-                                             Sema::CCEK_StaticAssertMessageData);
+          : SemaRef.BuildConvertedConstantExpression(
+                DataE.get(), ConstCharPtr, Sema::CCEK_StaticAssertMessageData);
   if (EvaluatedData.isInvalid()) {
     SemaRef.Diag(Loc, diag::err_user_defined_msg_invalid_mem_fn_ret_ty)
-            << EvalContext << /*data*/ 1;
+        << EvalContext << /*data*/ 1;
     return false;
   }
 
@@ -17386,9 +17388,9 @@ static bool EvaluateAsStringImpl(Sema & SemaRef,
                                           EvaluatedData.get(), Ctx, Status) ||
       !Notes.empty()) {
     SemaRef.Diag(Message->getBeginLoc(),
-         ErrorOnInvalidMessage ? diag::err_user_defined_msg_constexpr
-                               : diag::warn_user_defined_msg_constexpr)
-            << EvalContext;
+                 ErrorOnInvalidMessage ? diag::err_user_defined_msg_constexpr
+                                       : diag::warn_user_defined_msg_constexpr)
+        << EvalContext;
     for (const auto &Note : Notes)
       SemaRef.Diag(Note.first, Note.second);
     return !ErrorOnInvalidMessage;
@@ -17399,14 +17401,15 @@ static bool EvaluateAsStringImpl(Sema & SemaRef,
 bool Sema::EvaluateAsString(Expr *Message, APValue &Result, ASTContext &Ctx,
                             StringEvaluationContext EvalContext,
                             bool ErrorOnInvalidMessage) {
-    return EvaluateAsStringImpl(*this, Message, Result, Ctx, EvalContext, ErrorOnInvalidMessage);
-
+  return EvaluateAsStringImpl(*this, Message, Result, Ctx, EvalContext,
+                              ErrorOnInvalidMessage);
 }
 
 bool Sema::EvaluateAsString(Expr *Message, std::string &Result, ASTContext &Ctx,
                             StringEvaluationContext EvalContext,
                             bool ErrorOnInvalidMessage) {
-    return EvaluateAsStringImpl(*this, Message, Result, Ctx, EvalContext, ErrorOnInvalidMessage);
+  return EvaluateAsStringImpl(*this, Message, Result, Ctx, EvalContext,
+                              ErrorOnInvalidMessage);
 }
 
 Decl *Sema::BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc,
@@ -17455,7 +17458,7 @@ Decl *Sema::BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc,
     if (!Failed && AssertMessage && Cond.getBoolValue()) {
       std::string Str;
       EvaluateAsString(AssertMessage, Str, Context,
-                        StringEvaluationContext::StaticAssert,
+                       StringEvaluationContext::StaticAssert,
                        /*ErrorOnInvalidMessage=*/false);
     }
 
diff --git a/clang/lib/Sema/SemaStmtAsm.cpp b/clang/lib/Sema/SemaStmtAsm.cpp
index e168f57f8f303..4507a21a4c111 100644
--- a/clang/lib/Sema/SemaStmtAsm.cpp
+++ b/clang/lib/Sema/SemaStmtAsm.cpp
@@ -205,14 +205,14 @@ static StringRef extractRegisterName(const Expr *Expression,
 // conflicted clobber, else returns nullptr
 static SourceLocation
 getClobberConflictLocation(MultiExprArg Exprs, Expr **Constraints,
-                           Expr **Clobbers, int NumClobbers,
-                           unsigned NumLabels,
+                           Expr **Clobbers, int NumClobbers, unsigned NumLabels,
                            const TargetInfo &Target, ASTContext &Cont) {
   llvm::StringSet<> InOutVars;
   // Collect all the input and output registers from the extended asm
   // statement in order to check for conflicts with the clobber list
   for (unsigned int i = 0; i < Exprs.size() - NumLabels; ++i) {
-    std::string Constraint = GCCAsmStmt::ExtractStringFromGCCAsmStmtComponent(Constraints[i]);
+    std::string Constraint =
+        GCCAsmStmt::ExtractStringFromGCCAsmStmtComponent(Constraints[i]);
     StringRef InOutReg = Target.getConstraintRegister(
         Constraint, extractRegisterName(Exprs[i], Target));
     if (InOutReg != "")
@@ -221,7 +221,8 @@ getClobberConflictLocation(MultiExprArg Exprs, Expr **Constraints,
   // Check for each item in the clobber list if it conflicts with the input
   // or output
   for (int i = 0; i < NumClobbers; ++i) {
-    std::string Clobber = GCCAsmStmt::ExtractStringFromGCCAsmStmtComponent(Clobbers[i]);
+    std::string Clobber =
+        GCCAsmStmt::ExtractStringFromGCCAsmStmtComponent(Clobbers[i]);
     // We only check registers, therefore we don't check cc and memory
     // clobbers
     if (Clobber == "cc" || Clobber == "memory" || Clobber == "unwind")
@@ -234,24 +235,24 @@ getClobberConflictLocation(MultiExprArg Exprs, Expr **Constraints,
   return SourceLocation();
 }
 
-ExprResult Sema::ActOnGCCAsmStmtString(Expr* Expr, bool ForAsmLabel) {
-  if(!Expr)
+ExprResult Sema::ActOnGCCAsmStmtString(Expr *Expr, bool ForAsmLabel) {
+  if (!Expr)
     return ExprError();
 
-  if(auto* SL = dyn_cast<StringLiteral>(Expr)) {
+  if (auto *SL = dyn_cast<StringLiteral>(Expr)) {
     assert(SL->isOrdinary());
     if (ForAsmLabel && SL->getString().empty()) {
       Diag(Expr->getBeginLoc(), diag::err_asm_operand_empty_string)
-        << SL->getSourceRange();
+          << SL->getSourceRange();
     }
     return SL;
   }
-  if(DiagnoseUnexpandedParameterPack(Expr))
+  if (DiagnoseUnexpandedParameterPack(Expr))
     return ExprError();
-  if(Expr->getDependence() != ExprDependence::None)
+  if (Expr->getDependence() != ExprDependence::None)
     return Expr;
   APValue V;
-  if(!EvaluateAsString(Expr, V, getASTContext(), StringEvaluationContext::Asm,
+  if (!EvaluateAsString(Expr, V, getASTContext(), StringEvaluationContext::Asm,
                         /*ErrorOnInvalid=*/true))
     return ExprError();
 
@@ -259,7 +260,8 @@ ExprResult Sema::ActOnGCCAsmStmtString(Expr* Expr, bool ForAsmLabel) {
     Diag(Expr->getBeginLoc(), diag::err_asm_operand_empty_string);
   }
 
-  ConstantExpr* Res = ConstantExpr::Create(getASTContext(), Expr, ConstantResultStorageKind::APValue);
+  ConstantExpr *Res = ConstantExpr::Create(getASTContext(), Expr,
+                                           ConstantResultStorageKind::APValue);
   Res->SetResult(V, getASTContext());
   return Res;
 }
@@ -281,27 +283,28 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
 
   auto CreateGCCAsmStmt = [&] {
     return new (Context)
-    GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs,
-               NumInputs, Names, constraints.data(), Exprs.data(), asmString,
-               NumClobbers, clobbers.data(), NumLabels, RParenLoc);
+        GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs, NumInputs,
+                   Names, constraints.data(), Exprs.data(), asmString,
+                   NumClobbers, clobbers.data(), NumLabels, RParenLoc);
   };
 
-  if(asmString->getDependence() != ExprDependence::None
-     || llvm::any_of(constraints, [] (Expr* E) {
+  if (asmString->getDependence() != ExprDependence::None ||
+      llvm::any_of(
+          constraints,
+          [](Expr *E) { return E->getDependence() != ExprDependence::None; }) ||
+      llvm::any_of(clobbers, [](Expr *E) {
         return E->getDependence() != ExprDependence::None;
-      })
-     || llvm::any_of(clobbers, [] (Expr* E) {
-        return E->getDependence() != ExprDependence::None;
-     }))
-  return CreateGCCAsmStmt();
+      }))
+    return CreateGCCAsmStmt();
 
   for (unsigned i = 0; i != NumOutputs; i++) {
-    Expr* Constraint = constraints[i];
+    Expr *Constraint = constraints[i];
     StringRef OutputName;
     if (Names[i])
       OutputName = Names[i]->getName();
 
-    std::string ConstraintStr = GCCAsmStmt::ExtractStringFromGCCAsmStmtComponent(Constraint);
+    std::string ConstraintStr =
+        GCCAsmStmt::ExtractStringFromGCCAsmStmtComponent(Constraint);
 
     TargetInfo::ConstraintInfo Info(ConstraintStr, OutputName);
     if (!Context.getTargetInfo().validateOutputConstraint(Info) &&
@@ -372,7 +375,9 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
 
     unsigned Size = Context.getTypeSize(OutputExpr->getType());
     if (!Context.getTargetInfo().validateOutputSize(
-            FeatureMap,  GCCAsmStmt::ExtractStringFromGCCAsmStmtComponent(Constraint), Size)) {
+            FeatureMap,
+            GCCAsmStmt::ExtractStringFromGCCAsmStmtComponent(Constraint),
+            Size)) {
       targetDiag(OutputExpr->getBeginLoc(), diag::err_asm_invalid_output_size)
           << Info.getConstraintStr();
       return CreateGCCAsmStmt();
@@ -388,12 +393,14 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
     if (Names[i])
       InputName = Names[i]->getName();
 
-    std::string ConstraintStr = GCCAsmStmt::ExtractStringFromGCCAsmStmtComponent(Constraint);
+    std::string ConstraintStr =
+        GCCAsmStmt::ExtractStringFromGCCAsmStmtComponent(Constraint);
 
     TargetInfo::ConstraintInfo Info(ConstraintStr, InputName);
     if (!Context.getTargetInfo().validateInputConstraint(OutputConstraintInfos,
                                                          Info)) {
-      targetDiag(Constraint->getBeginLoc(), diag::err_asm_invalid_input_constraint)
+      targetDiag(Constraint->getBeginLoc(),
+                 diag::err_asm_invalid_input_constraint)
           << Info.getConstraintStr();
       return CreateGCCAsmStmt();
     }
@@ -480,8 +487,8 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
         return StmtError();
 
     unsigned Size = Context.getTypeSize(Ty);
-    if (!Context.getTargetInfo().validateInputSize(FeatureMap,
-                                                   ConstraintStr, Size))
+    if (!Context.getTargetInfo().validateInputSize(FeatureMap, ConstraintStr,
+                                                   Size))
       return targetDiag(InputExpr->getBeginLoc(),
                         diag::err_asm_invalid_input_size)
              << Info.getConstraintStr();
@@ -493,15 +500,17 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
   for (unsigned i = 0; i != NumClobbers; i++) {
     Expr *ClobberExpr = clobbers[i];
 
-    std::string Clobber = GCCAsmStmt::ExtractStringFromGCCAsmStmtComponent(ClobberExpr);
+    std::string Clobber =
+        GCCAsmStmt::ExtractStringFromGCCAsmStmtComponent(ClobberExpr);
 
     if (!Context.getTargetInfo().isValidClobber(Clobber)) {
-      targetDiag(ClobberExpr->getBeginLoc(), diag::err_asm_unknown_register_name)
+      targetDiag(ClobberExpr->getBeginLoc(),
+                 diag::err_asm_unknown_register_name)
           << Clobber;
-      return new (Context)
-          GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs,
-                     NumInputs, Names, constraints.data(), Exprs.data(), asmString,
-                     NumClobbers, clobbers.data(), NumLabels, RParenLoc);
+      return new (Context) GCCAsmStmt(
+          Context, AsmLoc, IsSimple, IsVolatile, NumOutputs, NumInputs, Names,
+          constraints.data(), Exprs.data(), asmString, NumClobbers,
+          clobbers.data(), NumLabels, RParenLoc);
     }
 
     if (Clobber == "unwind") {
@@ -519,8 +528,8 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
   // Validate the asm string, ensuring it makes sense given the operands we
   // have.
 
-  auto GetLocation = [this](const Expr* Str, unsigned Offset) {
-    if(auto* SL = dyn_cast<StringLiteral>(Str))
+  auto GetLocation = [this](const Expr *Str, unsigned Offset) {
+    if (auto *SL = dyn_cast<StringLiteral>(Str))
       return getLocationOfStringLiteralByte(SL, Offset);
     return Str->getBeginLoc();
   };
@@ -568,8 +577,8 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
     unsigned Size = Context.getTypeSize(Ty);
     std::string SuggestedModifier;
     if (!Context.getTargetInfo().validateConstraintModifier(
-            GCCAsmStmt::ExtractStringFromGCCAsmStmtComponent(Constraint), Piece.getModifier(), Size,
-            SuggestedModifier)) {
+            GCCAsmStmt::ExtractStringFromGCCAsmStmtComponent(Constraint),
+            Piece.getModifier(), Size, SuggestedModifier)) {
       targetDiag(Exprs[ConstraintIdx]->getBeginLoc(),
                  diag::warn_asm_mismatched_size_modifier);
 
@@ -577,9 +586,10 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
         auto B = targetDiag(Piece.getRange().getBegin(),
                             diag::note_asm_missing_constraint_modifier)
                  << SuggestedModifier;
-        if(isa<StringLiteral>(Constraint)) {
+        if (isa<StringLiteral>(Constraint)) {
           SuggestedModifier = "%" + SuggestedModifier + Piece.getString();
-          B << FixItHint::CreateReplacement(Piece.getRange(), SuggestedModifier);
+          B << FixItHint::CreateReplacement(Piece.getRange(),
+                                            SuggestedModifier);
         }
       }
     }
@@ -740,10 +750,9 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
   }
 
   // Check for conflicts between clobber list and input or output lists
-  SourceLocation ConstraintLoc =
-      getClobberConflictLocation(Exprs, constraints.data(), clobbers.data(), NumClobbers,
-                                 NumLabels,
-                                 Context.getTargetInfo(), Context);
+  SourceLocation ConstraintLoc = getClobberConflictLocation(
+      Exprs, constraints.data(), clobbers.data(), NumClobbers, NumLabels,
+      Context.getTargetInfo(), Context);
   if (ConstraintLoc.isValid())
     targetDiag(ConstraintLoc, diag::error_inoutput_conflict_with_clobber);
 
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 06d41a8154ca3..8cf82a4c33782 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -8552,7 +8552,6 @@ template<typename Derived>
 StmtResult
 TreeTransform<Derived>::TransformGCCAsmStmt(GCCAsmStmt *S) {
 
-
   SmallVector<Expr*, 8> Constraints;
   SmallVector<Expr*, 8> Exprs;
   SmallVector<IdentifierInfo *, 4> Names;
@@ -8561,15 +8560,15 @@ TreeTransform<Derived>::TransformGCCAsmStmt(GCCAsmStmt *S) {
 
   bool ExprsChanged = false;
 
-  auto RebuildString = [&] (Expr* E) {
-      ExprResult Result = getDerived().TransformExpr(E);
-      if (Result.isInvalid())
-        return Result;
-      if(!Result.isInvalid() && Result.get() != E) {
-          ExprsChanged = true;
-          Result = SemaRef.ActOnGCCAsmStmtString(Result.get(), /*ForLabel=*/false);
-      }
+  auto RebuildString = [&](Expr *E) {
+    ExprResult Result = getDerived().TransformExpr(E);
+    if (Result.isInvalid())
       return Result;
+    if (!Result.isInvalid() && Result.get() != E) {
+      ExprsChanged = true;
+      Result = SemaRef.ActOnGCCAsmStmtString(Result.get(), /*ForLabel=*/false);
+    }
+    return Result;
   };
 
   // Go through the outputs.
@@ -8627,10 +8626,10 @@ TreeTransform<Derived>::TransformGCCAsmStmt(GCCAsmStmt *S) {
 
   // Go through the clobbers.
   for (unsigned I = 0, E = S->getNumClobbers(); I != E; ++I) {
-      ExprResult Result = RebuildString(S->getClobberExpr(I));
-      if (Result.isInvalid())
-        return StmtError();
-      Clobbers.push_back(Result.get());
+    ExprResult Result = RebuildString(S->getClobberExpr(I));
+    if (Result.isInvalid())
+      return StmtError();
+    Clobbers.push_back(Result.get());
   }
 
   ExprResult AsmString = RebuildString(S->getAsmStringExpr());
diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp
index 7ad1216cb53e2..2db7d9346c463 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -390,7 +390,7 @@ void ASTStmtReader::VisitGCCAsmStmt(GCCAsmStmt *S) {
 
   // Outputs and inputs
   SmallVector<IdentifierInfo *, 16> Names;
-  SmallVector<Expr*, 16> Constraints;
+  SmallVector<Expr *, 16> Constraints;
   SmallVector<Stmt*, 16> Exprs;
   for (unsigned I = 0, N = NumOutputs + NumInputs; I != N; ++I) {
     Names.push_back(Record.readIdentifier());
@@ -399,7 +399,7 @@ void ASTStmtReader::VisitGCCAsmStmt(GCCAsmStmt *S) {
   }
 
   // Constraints
-  SmallVector<Expr*, 16> Clobbers;
+  SmallVector<Expr *, 16> Clobbers;
   for (unsigned I = 0; I != NumClobbers; ++I)
     Clobbers.push_back(cast_or_null<Expr>(Record.readSubStmt()));
 



More information about the cfe-commits mailing list