Skip to content

Commit 8634ef1

Browse files
authored
Add [[nodiscard]] attribute (#8462)
This PR adds support for the `[[nodiscard]]` attribute so that diagnostics can be easily issued for cases where return types of functions should not be discarded. This came up in feedback about the `Matrix::Fill` function in the linear algebra specification.
1 parent 14696d1 commit 8634ef1

7 files changed

Lines changed: 56 additions & 8 deletions

File tree

tools/clang/include/clang/AST/Decl.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2079,6 +2079,10 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
20792079
/// operators.
20802080
bool hasUnusedResultAttr() const;
20812081

2082+
// HLSL Change Begin - Add support for nodiscard attribute.
2083+
Attr *getNoDiscardAttr() const;
2084+
// HLSL Change Ends
2085+
20822086
/// \brief Returns the storage class as written in the source. For the
20832087
/// computed linkage of symbol, see getLinkage.
20842088
StorageClass getStorageClass() const { return StorageClass(SClass); }

tools/clang/include/clang/Basic/Attr.td

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2470,13 +2470,15 @@ def WarnUnused : InheritableAttr {
24702470
let Documentation = [Undocumented];
24712471
}
24722472

2473+
// HLSL Change Begin - add C++11 spelling.
24732474
def WarnUnusedResult : InheritableAttr {
2474-
let Spellings = [GCC<"warn_unused_result">,
2475+
let Spellings = [CXX11<"", "nodiscard", 2017>, GCC<"warn_unused_result">,
24752476
CXX11<"clang", "warn_unused_result">];
24762477
let Subjects = SubjectList<[ObjCMethod, CXXRecord, FunctionLike], WarnDiag,
24772478
"ExpectedFunctionMethodOrClass">;
24782479
let Documentation = [Undocumented];
24792480
}
2481+
// HLSL Change End - add C++11 spelling.
24802482

24812483
def Weak : InheritableAttr {
24822484
let Spellings = [GCC<"weak">];

tools/clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6368,9 +6368,11 @@ def warn_side_effects_unevaluated_context : Warning<
63686368
def warn_side_effects_typeid : Warning<
63696369
"expression with side effects will be evaluated despite being used as an "
63706370
"operand to 'typeid'">, InGroup<PotentiallyEvaluatedExpression>;
6371-
def warn_unused_result : Warning<
6372-
"ignoring return value of function declared with warn_unused_result "
6373-
"attribute">, InGroup<DiagGroup<"unused-result">>;
6371+
// HLSL Change Begin - allow attribute spelling to come in.
6372+
def warn_unused_result
6373+
: Warning<"ignoring return value of function declared with %0 attribute">,
6374+
InGroup<DiagGroup<"unused-result">>;
6375+
// HLSL Change End
63746376
def warn_unused_volatile : Warning<
63756377
"expression result unused; assign into a variable to force a volatile load">,
63766378
InGroup<DiagGroup<"unused-volatile-lvalue">>;

tools/clang/lib/AST/Decl.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2884,6 +2884,20 @@ bool FunctionDecl::hasUnusedResultAttr() const {
28842884
return hasAttr<WarnUnusedResultAttr>();
28852885
}
28862886

2887+
// HLSL Change Begin - support nodiscard attr.
2888+
Attr *FunctionDecl::getNoDiscardAttr() const {
2889+
QualType RetType = getReturnType();
2890+
if (RetType->isRecordType()) {
2891+
const CXXRecordDecl *Ret = RetType->getAsCXXRecordDecl();
2892+
const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(this);
2893+
if (Ret && Ret->hasAttr<WarnUnusedResultAttr>() &&
2894+
!(MD && MD->getCorrespondingMethodInClass(Ret, true)))
2895+
return Ret->getAttr<WarnUnusedResultAttr>();
2896+
}
2897+
return getAttr<WarnUnusedResultAttr>();
2898+
}
2899+
// HLSL Change End
2900+
28872901
/// \brief For an inline function definition in C, or for a gnu_inline function
28882902
/// in C++, determine whether the definition will be externally visible.
28892903
///

tools/clang/lib/Headers/hlsl/dx/linalg.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -289,8 +289,9 @@ class Matrix {
289289
}
290290

291291
template <typename T>
292-
static typename hlsl::enable_if<hlsl::is_arithmetic<T>::value, Matrix>::type
293-
Splat(T Val) {
292+
[[nodiscard]] static
293+
typename hlsl::enable_if<hlsl::is_arithmetic<T>::value, Matrix>::type
294+
Splat(T Val) {
294295
Matrix Result;
295296
__builtin_LinAlg_FillMatrix(Result.__handle, Val);
296297
return Result;

tools/clang/lib/Sema/SemaStmt.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,11 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
245245
const FunctionDecl *Func = dyn_cast<FunctionDecl>(FD);
246246
if (Func ? Func->hasUnusedResultAttr()
247247
: FD->hasAttr<WarnUnusedResultAttr>()) {
248-
Diag(Loc, diag::warn_unused_result) << R1 << R2;
248+
// HLSL Change Begin - allow attribute spelling to come in.
249+
Attr *NoDiscardAttr = Func ? Func->getNoDiscardAttr()
250+
: FD->getAttr<WarnUnusedResultAttr>();
251+
Diag(Loc, diag::warn_unused_result) << NoDiscardAttr << R1 << R2;
252+
// HLSL Change End
249253
return;
250254
}
251255
if (ShouldSuppress)
@@ -270,7 +274,10 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
270274
const ObjCMethodDecl *MD = ME->getMethodDecl();
271275
if (MD) {
272276
if (MD->hasAttr<WarnUnusedResultAttr>()) {
273-
Diag(Loc, diag::warn_unused_result) << R1 << R2;
277+
// HLSL Change Begin - allow attribute spelling to come in.
278+
Diag(Loc, diag::warn_unused_result)
279+
<< MD->getAttr<WarnUnusedResultAttr>() << R1 << R2;
280+
// HLSL Change End
274281
return;
275282
}
276283
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// RUN: %dxc -I %hlsl_headers -T cs_6_10 -verify %s
2+
3+
#include <dx/linalg.h>
4+
using namespace dx::linalg;
5+
6+
using MatrixATy = Matrix<ComponentType::F32, 4, 4, MatrixUse::A, MatrixScope::Wave>;
7+
8+
[nodiscard] int fn() { return 42; }
9+
[[nodiscard]] int fn2() { return 42; }
10+
11+
[numthreads(4, 4, 4)]
12+
void main(uint ID : SV_GroupID)
13+
{
14+
MatrixATy MatA1;
15+
MatA1.Splat(1.0f); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
16+
fn(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
17+
fn2(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
18+
}

0 commit comments

Comments
 (0)