Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -7426,6 +7426,9 @@ def warn_unused_call : Warning< "ignoring return value of function declared with %0 attribute">, InGroup; +def warn_unused_constructor : Warning< + "ignoring temporary created by a constructor declared with %0 attribute">, + InGroup; def warn_side_effects_unevaluated_context : Warning< "expression with side effects has no effect in an unevaluated context">, InGroup; Index: clang/lib/AST/Expr.cpp =================================================================== --- clang/lib/AST/Expr.cpp +++ clang/lib/AST/Expr.cpp @@ -2563,13 +2563,30 @@ case CXXTemporaryObjectExprClass: case CXXConstructExprClass: { if (const CXXRecordDecl *Type = getType()->getAsCXXRecordDecl()) { - if (Type->hasAttr()) { + if (Type->hasAttr() || + Type->hasAttr()) { WarnE = this; Loc = getBeginLoc(); R1 = getSourceRange(); return true; } } + + const auto *CE = cast(this); + if (const CXXConstructorDecl *Ctor = CE->getConstructor()) { + if (Ctor->hasAttr() || Ctor->hasAttr() || + Ctor->hasAttr()) { + WarnE = this; + Loc = getBeginLoc(); + R1 = getSourceRange(); + + if (unsigned NumArgs = CE->getNumArgs()) + R2 = SourceRange(CE->getArg(0)->getBeginLoc(), + CE->getArg(NumArgs - 1)->getEndLoc()); + return true; + } + } + return false; } Index: clang/lib/Sema/SemaDeclAttr.cpp =================================================================== --- clang/lib/Sema/SemaDeclAttr.cpp +++ clang/lib/Sema/SemaDeclAttr.cpp @@ -2831,7 +2831,8 @@ static void handleWarnUnusedResult(Sema &S, Decl *D, const ParsedAttr &AL) { if (D->getFunctionType() && - D->getFunctionType()->getReturnType()->isVoidType()) { + D->getFunctionType()->getReturnType()->isVoidType() && + !isa(D)) { S.Diag(AL.getLoc(), diag::warn_attribute_void_function_method) << AL << 0; return; } Index: clang/lib/Sema/SemaStmt.cpp =================================================================== --- clang/lib/Sema/SemaStmt.cpp +++ clang/lib/Sema/SemaStmt.cpp @@ -279,6 +279,21 @@ return; } } + } else if (const auto *CE = dyn_cast(E)) { + if (const CXXConstructorDecl *Ctor = CE->getConstructor()) { + if (const Attr *A = Ctor->getAttr()) { + Diag(Loc, diag::warn_unused_constructor) << A << R1 << R2; + return; + } + if (const Attr *A = Ctor->getAttr()) { + Diag(Loc, diag::warn_unused_constructor) << A << R1 << R2; + return; + } + if (const Attr *A = Ctor->getAttr()) { + Diag(Loc, diag::warn_unused_constructor) << A << R1 << R2; + return; + } + } } else if (ShouldSuppress) return; Index: clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p2.cpp =================================================================== --- clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p2.cpp +++ clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p2.cpp @@ -61,10 +61,27 @@ } } // namespace PR31526 +namespace p1771 { + struct S { + [[nodiscard]] S(); + [[gnu::pure]] S(int); + [[gnu::const]] S(double); + }; + struct [[nodiscard]]Y{}; + void usage() { + S(); // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}} + S(1); // expected-warning {{ignoring temporary created by a constructor declared with 'pure' attribute}} + S(2.2); // expected-warning {{ignoring temporary created by a constructor declared with 'const' attribute}} + Y(); // expected-warning {{expression result unused}} + } +}; // namespace p1771 + #ifdef EXT // expected-warning@4 {{use of the 'nodiscard' attribute is a C++17 extension}} // expected-warning@8 {{use of the 'nodiscard' attribute is a C++17 extension}} // expected-warning@11 {{use of the 'nodiscard' attribute is a C++17 extension}} // expected-warning@12 {{use of the 'nodiscard' attribute is a C++17 extension}} // expected-warning@28 {{use of the 'nodiscard' attribute is a C++17 extension}} +// expected-warning@66 {{use of the 'nodiscard' attribute is a C++17 extension}} +// expected-warning@70 {{use of the 'nodiscard' attribute is a C++17 extension}} #endif