Skip to content

Commit ad7727e

Browse files
author
z1.cciauto
committed
merge main into amd-staging
2 parents 71c8c00 + 297f6d9 commit ad7727e

File tree

226 files changed

+62063
-1435
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

226 files changed

+62063
-1435
lines changed

clang-tools-extra/clang-tidy/bugprone/UncheckedOptionalAccessCheck.cpp

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
namespace clang::tidy::bugprone {
2020
using ast_matchers::MatchFinder;
2121
using dataflow::UncheckedOptionalAccessDiagnoser;
22+
using dataflow::UncheckedOptionalAccessDiagnostic;
2223
using dataflow::UncheckedOptionalAccessModel;
2324

2425
static constexpr llvm::StringLiteral FuncID("fun");
@@ -52,14 +53,16 @@ void UncheckedOptionalAccessCheck::check(
5253
UncheckedOptionalAccessDiagnoser Diagnoser(ModelOptions);
5354
// FIXME: Allow user to set the (defaulted) SAT iterations max for
5455
// `diagnoseFunction` with config options.
55-
if (llvm::Expected<llvm::SmallVector<SourceLocation>> Locs =
56-
dataflow::diagnoseFunction<UncheckedOptionalAccessModel,
57-
SourceLocation>(*FuncDecl, *Result.Context,
58-
Diagnoser))
59-
for (const SourceLocation &Loc : *Locs)
60-
diag(Loc, "unchecked access to optional value");
56+
if (llvm::Expected<llvm::SmallVector<UncheckedOptionalAccessDiagnostic>>
57+
Diags = dataflow::diagnoseFunction<UncheckedOptionalAccessModel,
58+
UncheckedOptionalAccessDiagnostic>(
59+
*FuncDecl, *Result.Context, Diagnoser))
60+
for (const UncheckedOptionalAccessDiagnostic &Diag : *Diags) {
61+
diag(Diag.Range.getBegin(), "unchecked access to optional value")
62+
<< Diag.Range;
63+
}
6164
else
62-
llvm::consumeError(Locs.takeError());
65+
llvm::consumeError(Diags.takeError());
6366
}
6467

6568
} // namespace clang::tidy::bugprone

clang/docs/LanguageExtensions.rst

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1959,6 +1959,32 @@ references can be used instead of numeric references.
19591959
return -1;
19601960
}
19611961

1962+
1963+
Constexpr strings in GNU ASM statememts
1964+
=======================================
1965+
1966+
In C++11 mode (and greater), Clang supports specifying the template,
1967+
constraints, and clobber strings with a parenthesized constant expression
1968+
producing an object with the following member functions
1969+
1970+
.. code-block:: c++
1971+
1972+
constexpr const char* data() const;
1973+
constexpr size_t size() const;
1974+
1975+
such as ``std::string``, ``std::string_view``, ``std::vector<char>``.
1976+
This mechanism follow the same rules as ``static_assert`` messages in
1977+
C++26, see ``[dcl.pre]/p12``.
1978+
1979+
Query for this feature with ``__has_extension(gnu_asm_constexpr_strings)``.
1980+
1981+
.. code-block:: c++
1982+
1983+
int foo() {
1984+
asm((std::string_view("nop")) ::: (std::string_view("memory")));
1985+
}
1986+
1987+
19621988
Objective-C Features
19631989
====================
19641990

clang/docs/ReleaseNotes.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,15 @@ What's New in Clang |release|?
7474
C++ Language Changes
7575
--------------------
7676

77+
- Similarly to GCC, Clang now supports constant expressions in
78+
the strings of a GNU ``asm`` statement.
79+
80+
.. code-block:: c++
81+
82+
int foo() {
83+
asm((std::string_view("nop")) ::: (std::string_view("memory")));
84+
}
85+
7786
C++2c Feature Support
7887
^^^^^^^^^^^^^^^^^^^^^
7988

clang/include/clang/AST/Expr.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -787,6 +787,10 @@ class Expr : public ValueStmt {
787787
const Expr *PtrExpression, ASTContext &Ctx,
788788
EvalResult &Status) const;
789789

790+
bool EvaluateCharRangeAsString(APValue &Result, const Expr *SizeExpression,
791+
const Expr *PtrExpression, ASTContext &Ctx,
792+
EvalResult &Status) const;
793+
790794
/// If the current Expr can be evaluated to a pointer to a null-terminated
791795
/// constant string, return the constant string (without the terminating
792796
/// null).

clang/include/clang/AST/RecursiveASTVisitor.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2410,15 +2410,15 @@ DEF_TRAVERSE_DECL(ImplicitConceptSpecializationDecl, {
24102410
}
24112411

24122412
DEF_TRAVERSE_STMT(GCCAsmStmt, {
2413-
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getAsmString());
2413+
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getAsmStringExpr());
24142414
for (unsigned I = 0, E = S->getNumInputs(); I < E; ++I) {
2415-
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getInputConstraintLiteral(I));
2415+
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getInputConstraintExpr(I));
24162416
}
24172417
for (unsigned I = 0, E = S->getNumOutputs(); I < E; ++I) {
2418-
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOutputConstraintLiteral(I));
2418+
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOutputConstraintExpr(I));
24192419
}
24202420
for (unsigned I = 0, E = S->getNumClobbers(); I < E; ++I) {
2421-
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getClobberStringLiteral(I));
2421+
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getClobberExpr(I));
24222422
}
24232423
// children() iterates over inputExpr and outputExpr.
24242424
})

clang/include/clang/AST/Stmt.h

Lines changed: 28 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3193,7 +3193,7 @@ class AsmStmt : public Stmt {
31933193
/// getOutputConstraint - Return the constraint string for the specified
31943194
/// output operand. All output constraints are known to be non-empty (either
31953195
/// '=' or '+').
3196-
StringRef getOutputConstraint(unsigned i) const;
3196+
std::string getOutputConstraint(unsigned i) const;
31973197

31983198
/// isOutputPlusConstraint - Return true if the specified output constraint
31993199
/// is a "+" constraint (which is both an input and an output) or false if it
@@ -3214,14 +3214,14 @@ class AsmStmt : public Stmt {
32143214

32153215
/// getInputConstraint - Return the specified input constraint. Unlike output
32163216
/// constraints, these can be empty.
3217-
StringRef getInputConstraint(unsigned i) const;
3217+
std::string getInputConstraint(unsigned i) const;
32183218

32193219
const Expr *getInputExpr(unsigned i) const;
32203220

32213221
//===--- Other ---===//
32223222

32233223
unsigned getNumClobbers() const { return NumClobbers; }
3224-
StringRef getClobber(unsigned i) const;
3224+
std::string getClobber(unsigned i) const;
32253225

32263226
static bool classof(const Stmt *T) {
32273227
return T->getStmtClass() == GCCAsmStmtClass ||
@@ -3302,21 +3302,20 @@ class GCCAsmStmt : public AsmStmt {
33023302
friend class ASTStmtReader;
33033303

33043304
SourceLocation RParenLoc;
3305-
StringLiteral *AsmStr;
3305+
Expr *AsmStr;
33063306

33073307
// FIXME: If we wanted to, we could allocate all of these in one big array.
3308-
StringLiteral **Constraints = nullptr;
3309-
StringLiteral **Clobbers = nullptr;
3308+
Expr **Constraints = nullptr;
3309+
Expr **Clobbers = nullptr;
33103310
IdentifierInfo **Names = nullptr;
33113311
unsigned NumLabels = 0;
33123312

33133313
public:
33143314
GCCAsmStmt(const ASTContext &C, SourceLocation asmloc, bool issimple,
33153315
bool isvolatile, unsigned numoutputs, unsigned numinputs,
3316-
IdentifierInfo **names, StringLiteral **constraints, Expr **exprs,
3317-
StringLiteral *asmstr, unsigned numclobbers,
3318-
StringLiteral **clobbers, unsigned numlabels,
3319-
SourceLocation rparenloc);
3316+
IdentifierInfo **names, Expr **constraints, Expr **exprs,
3317+
Expr *asmstr, unsigned numclobbers, Expr **clobbers,
3318+
unsigned numlabels, SourceLocation rparenloc);
33203319

33213320
/// Build an empty inline-assembly statement.
33223321
explicit GCCAsmStmt(EmptyShell Empty) : AsmStmt(GCCAsmStmtClass, Empty) {}
@@ -3326,9 +3325,11 @@ class GCCAsmStmt : public AsmStmt {
33263325

33273326
//===--- Asm String Analysis ---===//
33283327

3329-
const StringLiteral *getAsmString() const { return AsmStr; }
3330-
StringLiteral *getAsmString() { return AsmStr; }
3331-
void setAsmString(StringLiteral *E) { AsmStr = E; }
3328+
const Expr *getAsmStringExpr() const { return AsmStr; }
3329+
Expr *getAsmStringExpr() { return AsmStr; }
3330+
void setAsmStringExpr(Expr *E) { AsmStr = E; }
3331+
3332+
std::string getAsmString() const;
33323333

33333334
/// AsmStringPiece - this is part of a decomposed asm string specification
33343335
/// (for use with the AnalyzeAsmString function below). An asm string is
@@ -3397,14 +3398,12 @@ class GCCAsmStmt : public AsmStmt {
33973398
return {};
33983399
}
33993400

3400-
StringRef getOutputConstraint(unsigned i) const;
3401+
std::string getOutputConstraint(unsigned i) const;
34013402

3402-
const StringLiteral *getOutputConstraintLiteral(unsigned i) const {
3403-
return Constraints[i];
3404-
}
3405-
StringLiteral *getOutputConstraintLiteral(unsigned i) {
3403+
const Expr *getOutputConstraintExpr(unsigned i) const {
34063404
return Constraints[i];
34073405
}
3406+
Expr *getOutputConstraintExpr(unsigned i) { return Constraints[i]; }
34083407

34093408
Expr *getOutputExpr(unsigned i);
34103409

@@ -3425,12 +3424,12 @@ class GCCAsmStmt : public AsmStmt {
34253424
return {};
34263425
}
34273426

3428-
StringRef getInputConstraint(unsigned i) const;
3427+
std::string getInputConstraint(unsigned i) const;
34293428

3430-
const StringLiteral *getInputConstraintLiteral(unsigned i) const {
3429+
const Expr *getInputConstraintExpr(unsigned i) const {
34313430
return Constraints[i + NumOutputs];
34323431
}
3433-
StringLiteral *getInputConstraintLiteral(unsigned i) {
3432+
Expr *getInputConstraintExpr(unsigned i) {
34343433
return Constraints[i + NumOutputs];
34353434
}
34363435

@@ -3441,6 +3440,8 @@ class GCCAsmStmt : public AsmStmt {
34413440
return const_cast<GCCAsmStmt*>(this)->getInputExpr(i);
34423441
}
34433442

3443+
static std::string ExtractStringFromGCCAsmStmtComponent(const Expr *E);
3444+
34443445
//===--- Labels ---===//
34453446

34463447
bool isAsmGoto() const {
@@ -3489,12 +3490,9 @@ class GCCAsmStmt : public AsmStmt {
34893490
private:
34903491
void setOutputsAndInputsAndClobbers(const ASTContext &C,
34913492
IdentifierInfo **Names,
3492-
StringLiteral **Constraints,
3493-
Stmt **Exprs,
3494-
unsigned NumOutputs,
3495-
unsigned NumInputs,
3496-
unsigned NumLabels,
3497-
StringLiteral **Clobbers,
3493+
Expr **Constraints, Stmt **Exprs,
3494+
unsigned NumOutputs, unsigned NumInputs,
3495+
unsigned NumLabels, Expr **Clobbers,
34983496
unsigned NumClobbers);
34993497

35003498
public:
@@ -3505,12 +3503,10 @@ class GCCAsmStmt : public AsmStmt {
35053503
/// This returns -1 if the operand name is invalid.
35063504
int getNamedOperand(StringRef SymbolicName) const;
35073505

3508-
StringRef getClobber(unsigned i) const;
3506+
std::string getClobber(unsigned i) const;
35093507

3510-
StringLiteral *getClobberStringLiteral(unsigned i) { return Clobbers[i]; }
3511-
const StringLiteral *getClobberStringLiteral(unsigned i) const {
3512-
return Clobbers[i];
3513-
}
3508+
Expr *getClobberExpr(unsigned i) { return Clobbers[i]; }
3509+
const Expr *getClobberExpr(unsigned i) const { return Clobbers[i]; }
35143510

35153511
SourceLocation getBeginLoc() const LLVM_READONLY { return AsmLoc; }
35163512
SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; }

clang/include/clang/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "clang/Analysis/FlowSensitive/CachedConstAccessorsLattice.h"
2121
#include "clang/Analysis/FlowSensitive/DataflowAnalysis.h"
2222
#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
23+
#include "clang/Analysis/FlowSensitive/MatchSwitch.h"
2324
#include "clang/Analysis/FlowSensitive/NoopLattice.h"
2425
#include "clang/Basic/SourceLocation.h"
2526
#include "llvm/ADT/SmallVector.h"
@@ -71,20 +72,26 @@ class UncheckedOptionalAccessModel
7172
TransferMatchSwitch;
7273
};
7374

75+
/// Diagnostic information for an unchecked optional access.
76+
struct UncheckedOptionalAccessDiagnostic {
77+
CharSourceRange Range;
78+
};
79+
7480
class UncheckedOptionalAccessDiagnoser {
7581
public:
7682
UncheckedOptionalAccessDiagnoser(
7783
UncheckedOptionalAccessModelOptions Options = {});
7884

79-
llvm::SmallVector<SourceLocation>
85+
llvm::SmallVector<UncheckedOptionalAccessDiagnostic>
8086
operator()(const CFGElement &Elt, ASTContext &Ctx,
8187
const TransferStateForDiagnostics<UncheckedOptionalAccessLattice>
8288
&State) {
8389
return DiagnoseMatchSwitch(Elt, Ctx, State.Env);
8490
}
8591

8692
private:
87-
CFGMatchSwitch<const Environment, llvm::SmallVector<SourceLocation>>
93+
CFGMatchSwitch<const Environment,
94+
llvm::SmallVector<UncheckedOptionalAccessDiagnostic>>
8895
DiagnoseMatchSwitch;
8996
};
9097

clang/include/clang/Basic/DiagnosticParseKinds.td

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,10 @@ def warn_cxx20_compat_label_end_of_compound_statement : Warning<
336336
def err_address_of_label_outside_fn : Error<
337337
"use of address-of-label extension outside of a function body">;
338338
def err_asm_operand_wide_string_literal : Error<
339-
"cannot use %select{unicode|wide|an empty}0 string literal in 'asm'">;
339+
"cannot use %select{unicode|wide}0 string literal in 'asm'">;
340+
341+
def err_asm_expected_string : Error<
342+
"expected string literal %select{or parenthesized constant expression |}0in 'asm'">;
340343
def err_expected_selector_for_method : Error<
341344
"expected selector for Objective-C method">;
342345
def err_expected_property_name : Error<"expected property name">;

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1663,23 +1663,30 @@ def err_static_assert_requirement_failed : Error<
16631663
"static assertion failed due to requirement '%0'%select{: %2|}1">;
16641664
def note_expr_evaluates_to : Note<
16651665
"expression evaluates to '%0 %1 %2'">;
1666-
def err_static_assert_invalid_message : Error<
1667-
"the message in a static assertion must be a string literal or an "
1666+
1667+
1668+
def subst_user_defined_msg : TextSubstitution<
1669+
"%select{the message|the expression}0 in "
1670+
"%select{a static assertion|this asm operand}0">;
1671+
1672+
def err_user_defined_msg_invalid : Error<
1673+
"%sub{subst_user_defined_msg}0 must be a string literal or an "
16681674
"object with 'data()' and 'size()' member functions">;
1669-
def err_static_assert_missing_member_function : Error<
1670-
"the message object in this static assertion is missing %select{"
1675+
def err_user_defined_msg_missing_member_function : Error<
1676+
"the %select{message|string}0 object in "
1677+
"%select{this static assertion|this asm operand}0 is missing %select{"
16711678
"a 'size()' member function|"
16721679
"a 'data()' member function|"
1673-
"'data()' and 'size()' member functions}0">;
1674-
def err_static_assert_invalid_mem_fn_ret_ty : Error<
1675-
"the message in a static assertion must have a '%select{size|data}0()' member "
1676-
"function returning an object convertible to '%select{std::size_t|const char *}0'">;
1677-
def warn_static_assert_message_constexpr : Warning<
1678-
"the message in this static assertion is not a "
1679-
"constant expression">,
1680+
"'data()' and 'size()' member functions}1">;
1681+
def err_user_defined_msg_invalid_mem_fn_ret_ty : Error<
1682+
"%sub{subst_user_defined_msg}0 must have a '%select{size|data}1()' member "
1683+
"function returning an object convertible to '%select{std::size_t|const char *}1'">;
1684+
def warn_user_defined_msg_constexpr : Warning<
1685+
"%select{the message|the expression}0 in "
1686+
"%select{this static assertion|this asm operand}0 is not a constant expression">,
16801687
DefaultError, InGroup<DiagGroup<"invalid-static-assert-message">>;
1681-
def err_static_assert_message_constexpr : Error<
1682-
"the message in a static assertion must be produced by a "
1688+
def err_user_defined_msg_constexpr : Error<
1689+
"%sub{subst_user_defined_msg}0 must be produced by a "
16831690
"constant expression">;
16841691

16851692
def warn_consteval_if_always_true : Warning<
@@ -9520,6 +9527,9 @@ def warn_redefine_extname_not_applied : Warning<
95209527

95219528
// inline asm.
95229529
let CategoryName = "Inline Assembly Issue" in {
9530+
def err_asm_operand_empty_string : Error<
9531+
"cannot use an empty string literal in 'asm'">;
9532+
95239533
def err_asm_pmf_through_constraint_not_permitted
95249534
: Error<"cannot pass a pointer-to-member through register-constrained "
95259535
"inline assembly parameter">;

clang/include/clang/Basic/Features.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,7 @@ EXTENSION(statement_attributes_with_gnu_syntax, true)
306306
EXTENSION(gnu_asm, LangOpts.GNUAsm)
307307
EXTENSION(gnu_asm_goto_with_outputs, LangOpts.GNUAsm)
308308
EXTENSION(gnu_asm_goto_with_outputs_full, LangOpts.GNUAsm)
309+
EXTENSION(gnu_asm_constexpr_strings, LangOpts.GNUAsm && LangOpts.CPlusPlus11)
309310
EXTENSION(matrix_types, LangOpts.MatrixTypes)
310311
EXTENSION(matrix_types_scalar_division, true)
311312
EXTENSION(cxx_attributes_on_using_declarations, LangOpts.CPlusPlus11)

0 commit comments

Comments
 (0)