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.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@149729 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index a45aea9..701e9cc 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -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 << '(';
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index d52ee12..7a64893 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -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)
diff --git a/test/SemaCXX/constexpr-sysheaders.cpp b/test/SemaCXX/constexpr-sysheaders.cpp
new file mode 100644
index 0000000..5f9a712
--- /dev/null
+++ b/test/SemaCXX/constexpr-sysheaders.cpp
@@ -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