From 3fdff71737d9b016605f63385613575cef58ce3f Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Tue, 3 Dec 2013 17:10:08 +0000 Subject: [PATCH] Issue diagnostic when constructor or destructor return void expression. // rdar://15366494 pr17759. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@196296 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticSemaKinds.td | 2 ++ lib/Sema/SemaStmt.cpp | 20 ++++++++++++++++---- test/SemaCXX/return.cpp | 10 ++++++++++ 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 20cdfdf545..a22df2b1af 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -6426,6 +6426,8 @@ def ext_return_has_void_expr : Extension< def err_return_init_list : Error< "%select{void function|void method|constructor|destructor}1 %0 " "must not return a value">; +def err_ctor_dtor_returns_void : Error< + "%select{constructor|destructor}1 %0 must not return void expression">; def warn_noreturn_function_has_return_expr : Warning< "function %0 declared 'noreturn' should not return">, InGroup; diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 861d5cf240..6bda42deaa 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -2801,8 +2801,14 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { } else if (!RetValExp->isTypeDependent()) { // C99 6.8.6.4p1 (ext_ since GCC warns) unsigned D = diag::ext_return_has_expr; - if (RetValExp->getType()->isVoidType()) - D = diag::ext_return_has_void_expr; + if (RetValExp->getType()->isVoidType()) { + NamedDecl *CurDecl = getCurFunctionOrMethodDecl(); + if (isa(CurDecl) || + isa(CurDecl)) + D = diag::err_ctor_dtor_returns_void; + else + D = diag::ext_return_has_void_expr; + } else { ExprResult Result = Owned(RetValExp); Result = IgnoredValueConversions(Result.take()); @@ -2812,9 +2818,15 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { RetValExp = ImpCastExprToType(RetValExp, Context.VoidTy, CK_ToVoid).take(); } - + // return of void in constructor/destructor is illegal in C++. + if (D == diag::err_ctor_dtor_returns_void) { + NamedDecl *CurDecl = getCurFunctionOrMethodDecl(); + Diag(ReturnLoc, D) + << CurDecl->getDeclName() << isa(CurDecl) + << RetValExp->getSourceRange(); + } // return (some void expression); is legal in C++. - if (D != diag::ext_return_has_void_expr || + else if (D != diag::ext_return_has_void_expr || !getLangOpts().CPlusPlus) { NamedDecl *CurDecl = getCurFunctionOrMethodDecl(); diff --git a/test/SemaCXX/return.cpp b/test/SemaCXX/return.cpp index 580f0a7233..98dbd51f58 100644 --- a/test/SemaCXX/return.cpp +++ b/test/SemaCXX/return.cpp @@ -102,3 +102,13 @@ namespace return_has_expr { } }; } + +// rdar://15366494 +// pr17759 +namespace ctor_returns_void { + void f() {} + struct S { + S() { return f(); }; // expected-error {{constructor 'S' must not return void expression}} + ~S() { return f(); } // expected-error {{destructor '~S' must not return void expression}} + }; +} -- 2.40.0