[cfe-commits] r149729 - in /cfe/trunk: lib/AST/ExprConstant.cpp lib/Sema/SemaDeclCXX.cpp test/SemaCXX/constexpr-sysheaders.cpp

Richard Smith richard-llvm at metafoo.co.uk
Fri Feb 3 16:33:54 PST 2012


Author: rsmith
Date: Fri Feb  3 18:33:54 2012
New Revision: 149729

URL: http://llvm.org/viewvc/llvm-project?rev=149729&view=rev
Log:
constexpr:
  The recent support for potential constant expressions exposed a bug in the
  implementation of libstdc++4.6, where numeric_limits<int>::min() is defined
  as (int)1 << 31, which isn't a constant expression. Disable the 'constexpr
  function never produces a constant expression' error inside system headers
  to compensate.

Added:
    cfe/trunk/test/SemaCXX/constexpr-sysheaders.cpp
Modified:
    cfe/trunk/lib/AST/ExprConstant.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp

Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=149729&r1=149728&r2=149729&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Fri Feb  3 18:33:54 2012
@@ -575,7 +575,8 @@
 static void describeCall(CallStackFrame *Frame, llvm::raw_ostream &Out) {
   unsigned ArgIndex = 0;
   bool IsMemberCall = isa<CXXMethodDecl>(Frame->Callee) &&
-                      !isa<CXXConstructorDecl>(Frame->Callee);
+                      !isa<CXXConstructorDecl>(Frame->Callee) &&
+                      cast<CXXMethodDecl>(Frame->Callee)->isInstance();
 
   if (!IsMemberCall)
     Out << *Frame->Callee << '(';

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=149729&r1=149728&r2=149729&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Fri Feb  3 18:33:54 2012
@@ -838,13 +838,13 @@
 /// \return true if the body is OK, false if we have diagnosed a problem.
 bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) {
   if (isa<CXXTryStmt>(Body)) {
-    // C++0x [dcl.constexpr]p3:
+    // C++11 [dcl.constexpr]p3:
     //  The definition of a constexpr function shall satisfy the following
     //  constraints: [...]
     // - its function-body shall be = delete, = default, or a
     //   compound-statement
     //
-    // C++0x [dcl.constexpr]p4:
+    // C++11 [dcl.constexpr]p4:
     //  In the definition of a constexpr constructor, [...]
     // - its function-body shall not be a function-try-block;
     Diag(Body->getLocStart(), diag::err_constexpr_function_try_block)
@@ -972,8 +972,23 @@
     }
   }
 
+  // C++11 [dcl.constexpr]p5:
+  //   if no function argument values exist such that the function invocation
+  //   substitution would produce a constant expression, the program is
+  //   ill-formed; no diagnostic required.
+  // C++11 [dcl.constexpr]p3:
+  //   - every constructor call and implicit conversion used in initializing the
+  //     return value shall be one of those allowed in a constant expression.
+  // C++11 [dcl.constexpr]p4:
+  //   - every constructor involved in initializing non-static data members and
+  //     base class sub-objects shall be a constexpr constructor.
+  //
+  // FIXME: We currently disable this check inside system headers, to work
+  // around early STL implementations which contain constexpr functions which
+  // can't produce constant expressions.
   llvm::SmallVector<PartialDiagnosticAt, 8> Diags;
-  if (!Expr::isPotentialConstantExpr(Dcl, Diags)) {
+  if (!Context.getSourceManager().isInSystemHeader(Dcl->getLocation()) &&
+      !Expr::isPotentialConstantExpr(Dcl, Diags)) {
     Diag(Dcl->getLocation(), diag::err_constexpr_function_never_constant_expr)
       << isa<CXXConstructorDecl>(Dcl);
     for (size_t I = 0, N = Diags.size(); I != N; ++I)

Added: cfe/trunk/test/SemaCXX/constexpr-sysheaders.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constexpr-sysheaders.cpp?rev=149729&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/constexpr-sysheaders.cpp (added)
+++ cfe/trunk/test/SemaCXX/constexpr-sysheaders.cpp Fri Feb  3 18:33:54 2012
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify -include %s %s
+
+// libstdc++4.6 has a broken numeric_limits with a non-constant min() for signed
+// integral types. Disable the 'never produces a constant expression' error in
+// system headers to work around it. We still won't treat the function as
+// producing a constant expression, though.
+
+#ifndef INCLUDED_HEADER
+#define INCLUDED_HEADER
+
+#pragma GCC system_header
+
+// An approximation of libstdc++4.6's broken definition of numeric_limits.
+// FIXME: In the -include case, the line numbers are off by one for some reason!
+struct numeric_limits { // expected-note {{value 2147483648 is outside the range}}
+  static constexpr int min() throw() { return (int)1 << (sizeof(int) * 8 - 1); } // no-error
+  // expected-note {{in call to 'min()'}}
+  static constexpr int lowest() throw() { return min(); }
+};
+
+#else
+
+constexpr int k = numeric_limits::lowest(); // expected-error {{constant expression}} expected-note {{in call to 'lowest()'}}
+
+#endif





More information about the cfe-commits mailing list