rsmith added you to the CC list for the revision "FixIt for constexpr 
initializer_list errors".

Hi rsmith,

This patch adds a different diagnostic for auto-deduced constexpr
std::initializer_list instances, suggesting the addition of 'static' to
the declaration. We take the form:

  void foo() {
    constexpr auto x = { 1, 2, 3 };
  }

and suggest the FixIt:

  void foo() {
    static constexpr auto x = { 1, 2, 3 };
  }

http://llvm-reviews.chandlerc.com/D2855

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/Sema/SemaDecl.cpp

Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -1703,6 +1703,9 @@
   "constexpr variable cannot have non-literal type %0">;
 def err_constexpr_var_requires_const_init : Error<
   "constexpr variable %0 must be initialized by a constant expression">;
+def err_constexpr_initializer_list_requires_static : Error<
+  "local constexpr initializer list %0 must be initialized by a constant "
+  "expression; did you intend to make it static?">;
 def err_constexpr_redecl_mismatch : Error<
   "%select{non-constexpr declaration of %0 follows constexpr declaration"
   "|constexpr declaration of %0 follows non-constexpr declaration}1">;
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -8888,8 +8888,28 @@
           DiagLoc = Notes[0].first;
           Notes.clear();
         }
-        Diag(DiagLoc, diag::err_constexpr_var_requires_const_init)
-          << var << Init->getSourceRange();
+
+       // If we're initializing a std::initializer_list we might want to also
+       // suggest making it static, because most of the time this is probably
+       // what the user wanted.
+       CXXRecordDecl *RD =
+         baseType.withoutLocalFastQualifiers()->getAsCXXRecordDecl();
+       if (RD && RD->getName().startswith("initializer_list")) {
+         SourceLocation initStart = var->getLocStart();
+         SourceLocation initEnd = Lexer::getLocForEndOfToken(
+             var->getLocEnd(), 0, getSourceManager(), LangOptions());
+         std::string expression(
+             getSourceManager().getCharacterData(initStart),
+             getSourceManager().getCharacterData(initEnd) -
+             getSourceManager().getCharacterData(initStart));
+         Diag(DiagLoc, diag::err_constexpr_initializer_list_requires_static)
+           << var << baseType << Init->getSourceRange()
+           << FixItHint::CreateReplacement(var->getSourceRange(),
+                                           "static " + expression);
+       } else {
+         Diag(DiagLoc, diag::err_constexpr_var_requires_const_init)
+           << var << Init->getSourceRange();
+       }
         for (unsigned I = 0, N = Notes.size(); I != N; ++I)
           Diag(Notes[I].first, Notes[I].second);
       }
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -1703,6 +1703,9 @@
   "constexpr variable cannot have non-literal type %0">;
 def err_constexpr_var_requires_const_init : Error<
   "constexpr variable %0 must be initialized by a constant expression">;
+def err_constexpr_initializer_list_requires_static : Error<
+  "local constexpr initializer list %0 must be initialized by a constant "
+  "expression; did you intend to make it static?">;
 def err_constexpr_redecl_mismatch : Error<
   "%select{non-constexpr declaration of %0 follows constexpr declaration"
   "|constexpr declaration of %0 follows non-constexpr declaration}1">;
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -8888,8 +8888,28 @@
           DiagLoc = Notes[0].first;
           Notes.clear();
         }
-        Diag(DiagLoc, diag::err_constexpr_var_requires_const_init)
-          << var << Init->getSourceRange();
+
+	// If we're initializing a std::initializer_list we might want to also
+	// suggest making it static, because most of the time this is probably
+	// what the user wanted.
+	CXXRecordDecl *RD =
+	  baseType.withoutLocalFastQualifiers()->getAsCXXRecordDecl();
+	if (RD && RD->getName().startswith("initializer_list")) {
+	  SourceLocation initStart = var->getLocStart();
+	  SourceLocation initEnd = Lexer::getLocForEndOfToken(
+	      var->getLocEnd(), 0, getSourceManager(), LangOptions());
+	  std::string expression(
+	      getSourceManager().getCharacterData(initStart),
+	      getSourceManager().getCharacterData(initEnd) -
+	      getSourceManager().getCharacterData(initStart));
+	  Diag(DiagLoc, diag::err_constexpr_initializer_list_requires_static)
+	    << var << baseType << Init->getSourceRange()
+	    << FixItHint::CreateReplacement(var->getSourceRange(),
+					    "static " + expression);
+	} else {
+	  Diag(DiagLoc, diag::err_constexpr_var_requires_const_init)
+	    << var << Init->getSourceRange();
+	}
         for (unsigned I = 0, N = Notes.size(); I != N; ++I)
           Diag(Notes[I].first, Notes[I].second);
       }
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to