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