PR14550: If a system header contains a bogus constexpr function definition,
don't mark the function as invalid, since we suppress the error.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@169689 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 399449d..7a529d6 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1538,7 +1538,7 @@
   "%select{function|constructor}1">;
 def err_constexpr_var_declaration : Error<
   "variables cannot be declared in a constexpr %select{function|constructor}0">;
-def err_constexpr_function_never_constant_expr : ExtWarn<
+def ext_constexpr_function_never_constant_expr : ExtWarn<
   "constexpr %select{function|constructor}0 never produces a "
   "constant expression">, InGroup<DiagGroup<"invalid-constexpr">>, DefaultError;
 def err_constexpr_body_no_return : Error<
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 5cca43b..6f1b489 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -994,11 +994,12 @@
   //     base class sub-objects shall be a constexpr constructor.
   llvm::SmallVector<PartialDiagnosticAt, 8> Diags;
   if (!Expr::isPotentialConstantExpr(Dcl, Diags)) {
-    Diag(Dcl->getLocation(), diag::err_constexpr_function_never_constant_expr)
+    Diag(Dcl->getLocation(), diag::ext_constexpr_function_never_constant_expr)
       << isa<CXXConstructorDecl>(Dcl);
     for (size_t I = 0, N = Diags.size(); I != N; ++I)
       Diag(Diags[I].first, Diags[I].second);
-    return false;
+    // Don't return false here: we allow this for compatibility in
+    // system headers.
   }
 
   return true;
diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp
index 3c1152c..bca73ee 100644
--- a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp
+++ b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp
@@ -1,5 +1,5 @@
 // RUN: %clang_cc1 -fsyntax-only -triple x86_64-unknown-unknown -verify -std=c++11 -fcxx-exceptions %s
-// RUN: %clang_cc1 -fsyntax-only -triple x86_64-unknown-unknown -std=c++11 -fcxx-exceptions -Wno-invalid-constexpr %s
+// RUN: %clang_cc1 -fsyntax-only -triple x86_64-unknown-unknown -std=c++11 -fcxx-exceptions -Wno-invalid-constexpr %s -DNO_INVALID_CONSTEXPR
 
 namespace StdExample {
 
@@ -110,3 +110,23 @@
 int y2 = Y<Z>().get(); // ok
 
 }
+
+#ifndef NO_INVALID_CONSTEXPR
+namespace PR14550 {
+  // As an "extension", we allow functions which can't produce constant
+  // expressions to be declared constexpr in system headers (libstdc++
+  // marks some functions as constexpr which use builtins which we don't
+  // support constant folding). Ensure that we don't mark those functions
+  // as invalid after suppressing the diagnostic.
+# 122 "p5.cpp" 1 3
+  int n;
+  struct A {
+    static constexpr int f() { return n; }
+  };
+  template<typename T> struct B {
+    B() { g(T::f()); } // expected-error {{undeclared identifier 'g'}}
+  };
+# 130 "p5.cpp" 2
+  template class B<A>; // expected-note {{here}}
+}
+#endif