]> granicus.if.org Git - clang/commitdiff
Issue diagnostic when constructor or destructor
authorFariborz Jahanian <fjahanian@apple.com>
Tue, 3 Dec 2013 17:10:08 +0000 (17:10 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Tue, 3 Dec 2013 17:10:08 +0000 (17:10 +0000)
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
lib/Sema/SemaStmt.cpp
test/SemaCXX/return.cpp

index 20cdfdf545f57b5365d35569dbe604843bbcad9b..a22df2b1af69e2f40758e6748b89b970771d5466 100644 (file)
@@ -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<InvalidNoreturn>;
index 861d5cf240c81f648f4de1d2d58965d6dc80d8a7..6bda42deaa29b8dccfb0eeb94bb89123ede7e932 100644 (file)
@@ -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<CXXConstructorDecl>(CurDecl) ||
+              isa<CXXDestructorDecl>(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<CXXDestructorDecl>(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();
 
index 580f0a7233e2cafe804a02f3abdea0cab2713d43..98dbd51f58068419c3f76b334a36d2ee51d490ad 100644 (file)
@@ -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}}
+  };
+}