]> granicus.if.org Git - clang/commitdiff
PR18746: If a constexpr function has a dependent return type and no return
authorRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 22 Apr 2014 23:14:23 +0000 (23:14 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 22 Apr 2014 23:14:23 +0000 (23:14 +0000)
statements, don't diagnose; the return type might end up being 'void'.

Patch by Rahul Jain! Tiny tweaks by me.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@206929 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaDeclCXX.cpp
test/SemaCXX/cxx1y-deduced-return-type.cpp

index 96c636011485101296b0750fe4a87a79fb05eb00..197518f99efcd2d898e75cccd8648963cce76963 100644 (file)
@@ -1175,10 +1175,12 @@ bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) {
   } else {
     if (ReturnStmts.empty()) {
       // C++1y doesn't require constexpr functions to contain a 'return'
-      // statement. We still do, unless the return type is void, because
+      // statement. We still do, unless the return type might be void, because
       // otherwise if there's no return statement, the function cannot
       // be used in a core constant expression.
-      bool OK = getLangOpts().CPlusPlus1y && Dcl->getReturnType()->isVoidType();
+      bool OK = getLangOpts().CPlusPlus1y &&
+                (Dcl->getReturnType()->isVoidType() ||
+                 Dcl->getReturnType()->isDependentType());
       Diag(Dcl->getLocation(),
            OK ? diag::warn_cxx11_compat_constexpr_body_no_return
               : diag::err_constexpr_body_no_return);
index d3308b3fd50bfd8924703ceddee828ab37ced381..60864165954addcc90253a472b8304c176aeaf4f 100644 (file)
@@ -261,6 +261,13 @@ namespace DefaultedMethods {
 
 namespace Constexpr {
   constexpr auto f1(int n) { return n; }
+  template<typename T> struct X { constexpr auto f() {} }; // PR18746
+  template<typename T> struct Y { constexpr T f() {} }; // expected-note {{control reached end of constexpr function}}
+  void f() {
+    X<int>().f();
+    Y<void>().f();
+    constexpr int q = Y<int>().f(); // expected-error {{must be initialized by a constant expression}} expected-note {{in call to '&Y<int>()->f()'}}
+  }
   struct NonLiteral { ~NonLiteral(); } nl; // expected-note {{user-provided destructor}}
   constexpr auto f2(int n) { return nl; } // expected-error {{return type 'Constexpr::NonLiteral' is not a literal type}}
 }