On Sun, Jul 21, 2019 at 7:40 AM Richard Smith <rich...@metafoo.co.uk> wrote:
>
> On Sat, 20 Jul 2019 at 09:55, Aaron Ballman via cfe-commits 
> <cfe-commits@lists.llvm.org> wrote:
>>
>> Author: aaronballman
>> Date: Sat Jul 20 00:56:34 2019
>> New Revision: 366626
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=366626&view=rev
>> Log:
>> Implement P1301R4, which allows specifying an optional message on the 
>> [[nodiscard]] attribute.
>>
>> This also bumps the attribute feature test value and introduces the notion 
>> of a C++2a extension warning.
>>
>> Modified:
>>     cfe/trunk/include/clang/Basic/Attr.td
>>     cfe/trunk/include/clang/Basic/AttrDocs.td
>>     cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
>>     cfe/trunk/lib/Sema/SemaDeclAttr.cpp
>>     cfe/trunk/lib/Sema/SemaStmt.cpp
>>     cfe/trunk/test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p1.cpp
>>     cfe/trunk/test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p2.cpp
>>     cfe/trunk/test/Preprocessor/has_attribute.cpp
>>     cfe/trunk/test/Sema/c2x-nodiscard.c
>>     cfe/trunk/test/SemaCXX/cxx11-attr-print.cpp
>>
>> Modified: cfe/trunk/include/clang/Basic/Attr.td
>> URL: 
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=366626&r1=366625&r2=366626&view=diff
>> ==============================================================================
>> --- cfe/trunk/include/clang/Basic/Attr.td (original)
>> +++ cfe/trunk/include/clang/Basic/Attr.td Sat Jul 20 00:56:34 2019
>> @@ -2335,10 +2335,11 @@ def WarnUnused : InheritableAttr {
>>  }
>>
>>  def WarnUnusedResult : InheritableAttr {
>> -  let Spellings = [CXX11<"", "nodiscard", 201603>, C2x<"", "nodiscard">,
>> +  let Spellings = [CXX11<"", "nodiscard", 201907>, C2x<"", "nodiscard">,
>
>
> We shouldn't bump the version until we also implement P1771R1, as this number 
> indicates that both papers are implemented.

Good call. I've switched back to the previous value in r366682. Thanks
for catching this!

~Aaron

>
>>
>>                     CXX11<"clang", "warn_unused_result">,
>>                     GCC<"warn_unused_result">];
>>    let Subjects = SubjectList<[ObjCMethod, Enum, Record, FunctionLike]>;
>> +  let Args = [StringArgument<"Message", 1>];
>>    let Documentation = [WarnUnusedResultsDocs];
>>  }
>>
>>
>> Modified: cfe/trunk/include/clang/Basic/AttrDocs.td
>> URL: 
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/AttrDocs.td?rev=366626&r1=366625&r2=366626&view=diff
>> ==============================================================================
>> --- cfe/trunk/include/clang/Basic/AttrDocs.td (original)
>> +++ cfe/trunk/include/clang/Basic/AttrDocs.td Sat Jul 20 00:56:34 2019
>> @@ -1482,6 +1482,13 @@ generated when a function or its return
>>  potentially-evaluated discarded-value expression that is not explicitly 
>> cast to
>>  `void`.
>>
>> +A string literal may optionally be provided to the attribute, which will be
>> +reproduced in any resulting diagnostics. Redeclarations using different 
>> forms
>> +of the attribute (with or without the string literal or with different 
>> string
>> +literal contents) are allowed. If there are redeclarations of the entity 
>> with
>> +differing string literals, it is unspecified which one will be used by Clang
>> +in any resulting diagnostics.
>> +
>>  .. code-block: c++
>>    struct [[nodiscard]] error_info { /*...*/ };
>>    error_info enable_missile_safety_mode();
>>
>> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
>> URL: 
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=366626&r1=366625&r2=366626&view=diff
>> ==============================================================================
>> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
>> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sat Jul 20 00:56:34 
>> 2019
>> @@ -7436,6 +7436,9 @@ def warn_side_effects_typeid : Warning<
>>  def warn_unused_result : Warning<
>>    "ignoring return value of function declared with %0 attribute">,
>>    InGroup<UnusedResult>;
>> +def warn_unused_result_msg : Warning<
>> +  "ignoring return value of function declared with %0 attribute: %1">,
>> +  InGroup<UnusedResult>;
>>  def warn_unused_volatile : Warning<
>>    "expression result unused; assign into a variable to force a volatile 
>> load">,
>>    InGroup<DiagGroup<"unused-volatile-lvalue">>;
>> @@ -7444,6 +7447,8 @@ def ext_cxx14_attr : Extension<
>>    "use of the %0 attribute is a C++14 extension">, InGroup<CXX14>;
>>  def ext_cxx17_attr : Extension<
>>    "use of the %0 attribute is a C++17 extension">, InGroup<CXX17>;
>> +def ext_cxx2a_attr : Extension<
>> +  "use of the %0 attribute is a C++2a extension">, InGroup<CXX2a>;
>>
>>  def warn_unused_comparison : Warning<
>>    "%select{equality|inequality|relational|three-way}0 comparison result 
>> unused">,
>>
>> Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
>> URL: 
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=366626&r1=366625&r2=366626&view=diff
>> ==============================================================================
>> --- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
>> +++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Sat Jul 20 00:56:34 2019
>> @@ -2841,14 +2841,30 @@ static void handleWarnUnusedResult(Sema
>>        return;
>>      }
>>
>> -  // If this is spelled as the standard C++17 attribute, but not in C++17, 
>> warn
>> -  // about using it as an extension.
>> -  if (!S.getLangOpts().CPlusPlus17 && AL.isCXX11Attribute() &&
>> -      !AL.getScopeName())
>> -    S.Diag(AL.getLoc(), diag::ext_cxx17_attr) << AL;
>> +  StringRef Str;
>> +  if ((AL.isCXX11Attribute() || AL.isC2xAttribute()) && !AL.getScopeName()) 
>> {
>> +    // If this is spelled as the standard C++17 attribute, but not in C++17,
>> +    // warn about using it as an extension. If there are attribute 
>> arguments,
>> +    // then claim it's a C++2a extension instead.
>> +    // FIXME: If WG14 does not seem likely to adopt the same feature, add an
>> +    // extension warning for C2x mode.
>> +    const LangOptions &LO = S.getLangOpts();
>> +    if (AL.getNumArgs() == 1) {
>> +      if (LO.CPlusPlus && !LO.CPlusPlus2a)
>> +        S.Diag(AL.getLoc(), diag::ext_cxx2a_attr) << AL;
>> +
>> +      // Since this this is spelled [[nodiscard]], get the optional string
>> +      // literal. If in C++ mode, but not in C++2a mode, diagnose as an
>> +      // extension.
>> +      // FIXME: C2x should support this feature as well, even as an 
>> extension.
>> +      if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, nullptr))
>> +        return;
>> +    } else if (LO.CPlusPlus && !LO.CPlusPlus17)
>> +      S.Diag(AL.getLoc(), diag::ext_cxx17_attr) << AL;
>> +  }
>>
>>    D->addAttr(::new (S.Context)
>> -             WarnUnusedResultAttr(AL.getRange(), S.Context,
>> +             WarnUnusedResultAttr(AL.getRange(), S.Context, Str,
>>                                    AL.getAttributeSpellingListIndex()));
>>  }
>>
>>
>> Modified: cfe/trunk/lib/Sema/SemaStmt.cpp
>> URL: 
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=366626&r1=366625&r2=366626&view=diff
>> ==============================================================================
>> --- cfe/trunk/lib/Sema/SemaStmt.cpp (original)
>> +++ cfe/trunk/lib/Sema/SemaStmt.cpp Sat Jul 20 00:56:34 2019
>> @@ -258,8 +258,13 @@ void Sema::DiagnoseUnusedExprResult(cons
>>      if (E->getType()->isVoidType())
>>        return;
>>
>> -    if (const Attr *A = CE->getUnusedResultAttr(Context)) {
>> -      Diag(Loc, diag::warn_unused_result) << A << R1 << R2;
>> +    if (const auto *A = cast_or_null<WarnUnusedResultAttr>(
>> +            CE->getUnusedResultAttr(Context))) {
>> +      StringRef Msg = A->getMessage();
>> +      if (!Msg.empty())
>> +        Diag(Loc, diag::warn_unused_result_msg) << A << Msg << R1 << R2;
>> +      else
>> +        Diag(Loc, diag::warn_unused_result) << A << R1 << R2;
>>        return;
>>      }
>>
>> @@ -290,7 +295,11 @@ void Sema::DiagnoseUnusedExprResult(cons
>>      const ObjCMethodDecl *MD = ME->getMethodDecl();
>>      if (MD) {
>>        if (const auto *A = MD->getAttr<WarnUnusedResultAttr>()) {
>> -        Diag(Loc, diag::warn_unused_result) << A << R1 << R2;
>> +        StringRef Msg = A->getMessage();
>> +        if (!Msg.empty())
>> +          Diag(Loc, diag::warn_unused_result_msg) << A << Msg << R1 << R2;
>> +        else
>> +          Diag(Loc, diag::warn_unused_result) << A << R1 << R2;
>>          return;
>>        }
>>      }
>>
>> Modified: cfe/trunk/test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p1.cpp
>> URL: 
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p1.cpp?rev=366626&r1=366625&r2=366626&view=diff
>> ==============================================================================
>> --- cfe/trunk/test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p1.cpp (original)
>> +++ cfe/trunk/test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p1.cpp Sat Jul 20 
>> 00:56:34 2019
>> @@ -1,8 +1,8 @@
>> -// RUN: %clang_cc1 -fsyntax-only -std=c++1z -verify %s
>> +// RUN: %clang_cc1 -fsyntax-only -std=c++2a -verify %s
>>
>>  struct [[nodiscard]] S1 {}; // ok
>>  struct [[nodiscard nodiscard]] S2 {}; // expected-error {{attribute 
>> 'nodiscard' cannot appear multiple times in an attribute specifier}}
>> -struct [[nodiscard("Wrong")]] S3 {}; // expected-error {{'nodiscard' cannot 
>> have an argument list}}
>> +struct [[nodiscard("Wrong")]] S3 {};
>>
>>  [[nodiscard]] int f();
>>  enum [[nodiscard]] E {};
>>
>> Modified: cfe/trunk/test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p2.cpp
>> URL: 
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p2.cpp?rev=366626&r1=366625&r2=366626&view=diff
>> ==============================================================================
>> --- cfe/trunk/test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p2.cpp (original)
>> +++ cfe/trunk/test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p2.cpp Sat Jul 20 
>> 00:56:34 2019
>> @@ -1,5 +1,6 @@
>> +// RUN: %clang_cc1 -fsyntax-only -std=c++2a -verify -Wc++2a-extensions %s
>>  // RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify -Wc++17-extensions %s
>> -// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify -DEXT 
>> -Wc++17-extensions %s
>> +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify -DEXT 
>> -Wc++17-extensions -Wc++2a-extensions %s
>>
>>  struct [[nodiscard]] S {};
>>  S get_s();
>> @@ -61,10 +62,33 @@ void f() {
>>  }
>>  } // namespace PR31526
>>
>> +struct [[nodiscard("reason")]] ReasonStruct {};
>> +struct LaterReason;
>> +struct [[nodiscard("later reason")]] LaterReason {};
>> +
>> +ReasonStruct get_reason();
>> +LaterReason get_later_reason();
>> +[[nodiscard("another reason")]] int another_reason();
>> +
>> +[[nodiscard("conflicting reason")]] int conflicting_reason();
>> +[[nodiscard("special reason")]] int conflicting_reason();
>> +
>> +void cxx2a_use() {
>> +  get_reason(); // expected-warning {{ignoring return value of function 
>> declared with 'nodiscard' attribute: reason}}
>> +  get_later_reason(); // expected-warning {{ignoring return value of 
>> function declared with 'nodiscard' attribute: later reason}}
>> +  another_reason(); // expected-warning {{ignoring return value of function 
>> declared with 'nodiscard' attribute: another reason}}
>> +  conflicting_reason(); // expected-warning {{ignoring return value of 
>> function declared with 'nodiscard' attribute: special reason}}
>> +}
>> +
>>  #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@5 {{use of the 'nodiscard' attribute is a C++17 
>> extension}}
>> +// expected-warning@9 {{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@13 {{use of the 'nodiscard' attribute is a C++17 
>> extension}}
>> +// expected-warning@29 {{use of the 'nodiscard' attribute is a C++17 
>> extension}}
>> +// expected-warning@65 {{use of the 'nodiscard' attribute is a C++2a 
>> extension}}
>> +// expected-warning@67 {{use of the 'nodiscard' attribute is a C++2a 
>> extension}}
>> +// expected-warning@71 {{use of the 'nodiscard' attribute is a C++2a 
>> extension}}
>> +// expected-warning@73 {{use of the 'nodiscard' attribute is a C++2a 
>> extension}}
>> +// expected-warning@74 {{use of the 'nodiscard' attribute is a C++2a 
>> extension}}
>>  #endif
>>
>> Modified: cfe/trunk/test/Preprocessor/has_attribute.cpp
>> URL: 
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Preprocessor/has_attribute.cpp?rev=366626&r1=366625&r2=366626&view=diff
>> ==============================================================================
>> --- cfe/trunk/test/Preprocessor/has_attribute.cpp (original)
>> +++ cfe/trunk/test/Preprocessor/has_attribute.cpp Sat Jul 20 00:56:34 2019
>> @@ -63,7 +63,7 @@ CXX11(unlikely)
>>  // CHECK: maybe_unused: 201603L
>>  // ITANIUM: no_unique_address: 201803L
>>  // WINDOWS: no_unique_address: 0
>> -// CHECK: nodiscard: 201603L
>> +// CHECK: nodiscard: 201907L
>>  // CHECK: noreturn: 200809L
>>  // FIXME(201803L) CHECK: unlikely: 0
>>
>>
>> Modified: cfe/trunk/test/Sema/c2x-nodiscard.c
>> URL: 
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/c2x-nodiscard.c?rev=366626&r1=366625&r2=366626&view=diff
>> ==============================================================================
>> --- cfe/trunk/test/Sema/c2x-nodiscard.c (original)
>> +++ cfe/trunk/test/Sema/c2x-nodiscard.c Sat Jul 20 00:56:34 2019
>> @@ -6,10 +6,12 @@ struct [[nodiscard]] S1 { // ok
>>  struct [[nodiscard nodiscard]] S2 { // expected-error {{attribute 
>> 'nodiscard' cannot appear multiple times in an attribute specifier}}
>>    int i;
>>  };
>> -struct [[nodiscard("Wrong")]] S3 { // expected-error {{'nodiscard' cannot 
>> have an argument list}}
>> +struct [[nodiscard("Wrong")]] S3 { // FIXME: may need an extension warning.
>>    int i;
>>  };
>>
>> +struct S3 get_s3(void);
>> +
>>  [[nodiscard]] int f1(void);
>>  enum [[nodiscard]] E1 { One };
>>
>> @@ -27,11 +29,13 @@ enum E2 get_e(void);
>>
>>  void f2(void) {
>>    get_s(); // expected-warning {{ignoring return value of function declared 
>> with 'nodiscard' attribute}}
>> +  get_s3(); // expected-warning {{ignoring return value of function 
>> declared with 'nodiscard' attribute: Wrong}}
>>    get_i(); // expected-warning {{ignoring return value of function declared 
>> with 'nodiscard' attribute}}
>>    get_e(); // expected-warning {{ignoring return value of function declared 
>> with 'nodiscard' attribute}}
>>
>>    // Okay, warnings are not encouraged
>>    (void)get_s();
>> +  (void)get_s3();
>>    (void)get_i();
>>    (void)get_e();
>>  }
>>
>> Modified: cfe/trunk/test/SemaCXX/cxx11-attr-print.cpp
>> URL: 
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx11-attr-print.cpp?rev=366626&r1=366625&r2=366626&view=diff
>> ==============================================================================
>> --- cfe/trunk/test/SemaCXX/cxx11-attr-print.cpp (original)
>> +++ cfe/trunk/test/SemaCXX/cxx11-attr-print.cpp Sat Jul 20 00:56:34 2019
>> @@ -37,13 +37,15 @@ void foo() __attribute__((const));
>>  // CHECK: void bar() __attribute__((__const));
>>  void bar() __attribute__((__const));
>>
>> -// CHECK: int f1() __attribute__((warn_unused_result));
>> +// FIXME: It's unfortunate that the string literal prints with the below 
>> three
>> +// cases given that the string is only exposed via the [[nodiscard]] 
>> spelling.
>> +// CHECK: int f1() __attribute__((warn_unused_result("")));
>>  int f1() __attribute__((warn_unused_result));
>>
>> -// CHECK: {{\[}}[clang::warn_unused_result]];
>> +// CHECK: {{\[}}[clang::warn_unused_result("")]];
>>  int f2 [[clang::warn_unused_result]] ();
>>
>> -// CHECK: {{\[}}[gnu::warn_unused_result]];
>> +// CHECK: {{\[}}[gnu::warn_unused_result("")]];
>>  int f3 [[gnu::warn_unused_result]] ();
>>
>>  // FIXME: ast-print need to print C++11
>>
>>
>> _______________________________________________
>> cfe-commits mailing list
>> cfe-commits@lists.llvm.org
>> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to