From: Kaelyn Uhrain Date: Mon, 12 Nov 2012 23:48:05 +0000 (+0000) Subject: Enable C++11 attribute syntax for warn_unused_result and allow it to be X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=51ceb7bab599ea7d39d290ff5e88e4a1f0f5bc5c;p=clang Enable C++11 attribute syntax for warn_unused_result and allow it to be applied to CXXRecordDecls, where functions with that return type will inherit the warn_unused_result attribute. Also includes a tiny fix (with no discernable behavior change for existing code) to re-sync AttributeDeclKind enum and err_attribute_wrong_decl_type with warn_attribute_wrong_decl_type since the enum is used with both diagnostic messages to chose the correct description. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@167783 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index bfe8093079..72f02a8c8c 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -699,7 +699,7 @@ def VecReturn : InheritableAttr { } def WarnUnusedResult : InheritableAttr { - let Spellings = [GNU<"warn_unused_result">]; + let Spellings = [GNU<"warn_unused_result">, CXX11<"","warn_unused_result">]; } def Weak : InheritableAttr { diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 9110fa36fd..09f80fd45e 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1773,17 +1773,18 @@ def err_alias_not_supported_on_darwin : Error < def warn_attribute_wrong_decl_type : Warning< "%0 attribute only applies to %select{functions|unions|" "variables and functions|functions and methods|parameters|" - "functions, methods and blocks|functions, methods, and parameters|" - "classes|variables|methods|variables, functions and labels|" - "fields and global variables|structs|" + "functions, methods and blocks|functions, methods, and classes|" + "functions, methods, and parameters|classes|variables|methods|" + "variables, functions and labels|fields and global variables|structs|" "variables, functions and tag types|thread-local variables}1">, InGroup; def err_attribute_wrong_decl_type : Error< "%0 attribute only applies to %select{functions|unions|" "variables and functions|functions and methods|parameters|" - "functions, methods and blocks|functions, methods, and parameters|" - "classes|variables|methods|variables, functions and labels|" - "fields and global variables|structs|thread-local variables}1">; + "functions, methods and blocks|functions, methods, and classes|" + "functions, methods, and parameters|classes|variables|methods|" + "variables, functions and labels|fields and global variables|structs|" + "variables, functions and tag types|thread-local variables}1">; def warn_function_attribute_wrong_type : Warning< "'%0' only applies to function types; type here is %1">, InGroup; diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 0092d5dab1..f2e840494f 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -5691,6 +5691,14 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, ProcessDeclAttributes(S, NewFD, D, /*NonInheritable=*/false, /*Inheritable=*/true); + QualType RetType = NewFD->getResultType(); + const CXXRecordDecl *Ret = RetType->isRecordType() ? + RetType->getAsCXXRecordDecl() : RetType->getPointeeCXXRecordDecl(); + if (!NewFD->isInvalidDecl() && !NewFD->hasAttr() && + Ret && Ret->hasAttr()) { + NewFD->addAttr(new (Context) WarnUnusedResultAttr(SourceRange(), Context)); + } + if (!getLangOpts().CPlusPlus) { // Perform semantic checking on the function declaration. bool isExplicitSpecialization=false; diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index e326a20c87..70bc019a74 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -37,6 +37,7 @@ enum AttributeDeclKind { ExpectedFunctionOrMethod, ExpectedParameter, ExpectedFunctionMethodOrBlock, + ExpectedFunctionMethodOrClass, ExpectedFunctionMethodOrParameter, ExpectedClass, ExpectedVariable, @@ -44,6 +45,7 @@ enum AttributeDeclKind { ExpectedVariableFunctionOrLabel, ExpectedFieldOrGlobalVar, ExpectedStruct, + ExpectedVariableFunctionOrTag, ExpectedTLSVar }; @@ -2445,7 +2447,7 @@ static void handleWarnUnusedResult(Sema &S, Decl *D, const AttributeList &Attr) if (!checkAttributeNumArgs(S, Attr, 0)) return; - if (!isFunction(D) && !isa(D)) { + if (!isFunction(D) && !isa(D) && !isa(D)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << Attr.getName() << ExpectedFunctionOrMethod; return; diff --git a/test/SemaCXX/warn-unused-result.cpp b/test/SemaCXX/warn-unused-result.cpp index d14fdf9833..459e5ae9cb 100644 --- a/test/SemaCXX/warn-unused-result.cpp +++ b/test/SemaCXX/warn-unused-result.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s int f() __attribute__((warn_unused_result)); @@ -42,3 +42,33 @@ void bah() { x.foo(); // expected-warning {{ignoring return value}} x2->foo(); // expected-warning {{ignoring return value}} } + +namespace warn_unused_CXX11 { +struct [[warn_unused_result]] Status { + bool ok() const; +}; +Status DoSomething(); +Status& DoSomethingElse(); +Status* DoAnotherThing(); +Status** DoYetAnotherThing(); +void lazy() { + Status s = DoSomething(); + if (!s.ok()) return; + Status &rs = DoSomethingElse(); + if (!rs.ok()) return; + Status *ps = DoAnotherThing(); + if (!ps->ok()) return; + Status **pps = DoYetAnotherThing(); + if (!(*pps)->ok()) return; + + (void)DoSomething(); + (void)DoSomethingElse(); + (void)DoAnotherThing(); + (void)DoYetAnotherThing(); + + DoSomething(); // expected-warning {{ignoring return value}} + DoSomethingElse(); // expected-warning {{ignoring return value}} + DoAnotherThing(); // expected-warning {{ignoring return value}} + DoYetAnotherThing(); +} +}