[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