jkorous created this revision.
jkorous added reviewers: arphaman, dexonsmith, rsmith, doug.gregor.
jkorous added a project: clang.
Herald added a subscriber: cfe-commits.

C++17 adds form of static_assert without string literal.

  static_assert ( bool_constexpr )

Currently clang produces diagnostics like this:

  assert.cpp:1:1: error: static_assert failed
  static_assert(false);
  ^             ~~~~~
  1 error generated.

This patch adds assert expression to error message in case string literal is 
missing:

  /Users/jkorous/assert.cpp:1:1: error: static_assert failed "false"
  static_assert(false);
  ^             ~~~~~
  1 error generated.

Reasons why printing assert expression in absence of string literal is useful 
are:

1. Serialized diagnostics (--serialize-diagnostics) don't contain code snippet 
and thus error message lack context.
2. No all tools scraping clang diagnostics use caret snippet provided by 
-f-caret-diagnostics.

This patch doesn't address message length limit as currently clang doesn't 
truncate messages anyway but it might be subject of another patch.

rdar://problem/38931241


Repository:
  rC Clang

https://reviews.llvm.org/D46834

Files:
  lib/Parse/ParseDeclCXX.cpp
  lib/Sema/SemaDeclCXX.cpp
  test/SemaCXX/static-assert-cxx17.cpp
  test/SemaCXX/static-assert.cpp


Index: test/SemaCXX/static-assert.cpp
===================================================================
--- test/SemaCXX/static-assert.cpp
+++ test/SemaCXX/static-assert.cpp
@@ -50,7 +50,7 @@
 StaticAssertProtected<X> sap2; // expected-note {{instantiation}}
 
 static_assert(true); // expected-warning {{C++17 extension}}
-static_assert(false); // expected-error-re {{failed{{$}}}} expected-warning 
{{extension}}
+static_assert(false); // expected-error {{static_assert failed "false"}} 
expected-warning {{C++17 extension}}
 
 
 // Diagnostics for static_assert with multiple conditions
Index: test/SemaCXX/static-assert-cxx17.cpp
===================================================================
--- /dev/null
+++ test/SemaCXX/static-assert-cxx17.cpp
@@ -0,0 +1,5 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 %s
+
+static_assert(false, "foo"); // expected-error {{static_assert failed "foo"}}
+static_assert(false == true); // expected-error {{static_assert failed "false 
== true"}}
+static_assert(false, "foo \"bar\" baz"); // expected-error {{static_assert 
failed "foo \"bar\" baz"}}
Index: lib/Sema/SemaDeclCXX.cpp
===================================================================
--- lib/Sema/SemaDeclCXX.cpp
+++ lib/Sema/SemaDeclCXX.cpp
@@ -13736,9 +13736,16 @@
 
     if (!Failed && !Cond) {
       SmallString<256> MsgBuffer;
-      llvm::raw_svector_ostream Msg(MsgBuffer);
-      if (AssertMessage)
-        AssertMessage->printPretty(Msg, nullptr, getPrintingPolicy());
+      {
+        llvm::raw_svector_ostream Msg(MsgBuffer);
+        if (AssertMessage)
+          AssertMessage->printPretty(Msg, nullptr, getPrintingPolicy());
+        else {
+          AssertExpr->printPretty(Msg, nullptr, getPrintingPolicy());
+          MsgBuffer.insert(MsgBuffer.begin(), '\"');
+          MsgBuffer.append(1, '\"');
+        }
+      }
 
       Expr *InnerCond = nullptr;
       std::string InnerCondDescription;
@@ -13747,11 +13754,12 @@
                                    /*AllowTopLevelCond=*/false);
       if (InnerCond) {
         Diag(StaticAssertLoc, diag::err_static_assert_requirement_failed)
-          << InnerCondDescription << !AssertMessage
-          << Msg.str() << InnerCond->getSourceRange();
+          << InnerCondDescription << MsgBuffer.empty() << MsgBuffer.str()
+          << InnerCond->getSourceRange();
       } else {
         Diag(StaticAssertLoc, diag::err_static_assert_failed)
-          << !AssertMessage << Msg.str() << AssertExpr->getSourceRange();
+          << MsgBuffer.empty() << MsgBuffer.str()
+          << AssertExpr->getSourceRange();
       }
       Failed = true;
     }
Index: lib/Parse/ParseDeclCXX.cpp
===================================================================
--- lib/Parse/ParseDeclCXX.cpp
+++ lib/Parse/ParseDeclCXX.cpp
@@ -819,7 +819,10 @@
 
 /// ParseStaticAssertDeclaration - Parse C++0x or C11 
static_assert-declaration.
 ///
-/// [C++0x] static_assert-declaration:
+/// [C++17] static_assert-declaration:
+///           static_assert ( constant-expression  ) ;
+///
+/// [C++11] static_assert-declaration:
 ///           static_assert ( constant-expression  ,  string-literal  ) ;
 ///
 /// [C11]   static_assert-declaration:


Index: test/SemaCXX/static-assert.cpp
===================================================================
--- test/SemaCXX/static-assert.cpp
+++ test/SemaCXX/static-assert.cpp
@@ -50,7 +50,7 @@
 StaticAssertProtected<X> sap2; // expected-note {{instantiation}}
 
 static_assert(true); // expected-warning {{C++17 extension}}
-static_assert(false); // expected-error-re {{failed{{$}}}} expected-warning {{extension}}
+static_assert(false); // expected-error {{static_assert failed "false"}} expected-warning {{C++17 extension}}
 
 
 // Diagnostics for static_assert with multiple conditions
Index: test/SemaCXX/static-assert-cxx17.cpp
===================================================================
--- /dev/null
+++ test/SemaCXX/static-assert-cxx17.cpp
@@ -0,0 +1,5 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 %s
+
+static_assert(false, "foo"); // expected-error {{static_assert failed "foo"}}
+static_assert(false == true); // expected-error {{static_assert failed "false == true"}}
+static_assert(false, "foo \"bar\" baz"); // expected-error {{static_assert failed "foo \"bar\" baz"}}
Index: lib/Sema/SemaDeclCXX.cpp
===================================================================
--- lib/Sema/SemaDeclCXX.cpp
+++ lib/Sema/SemaDeclCXX.cpp
@@ -13736,9 +13736,16 @@
 
     if (!Failed && !Cond) {
       SmallString<256> MsgBuffer;
-      llvm::raw_svector_ostream Msg(MsgBuffer);
-      if (AssertMessage)
-        AssertMessage->printPretty(Msg, nullptr, getPrintingPolicy());
+      {
+        llvm::raw_svector_ostream Msg(MsgBuffer);
+        if (AssertMessage)
+          AssertMessage->printPretty(Msg, nullptr, getPrintingPolicy());
+        else {
+          AssertExpr->printPretty(Msg, nullptr, getPrintingPolicy());
+          MsgBuffer.insert(MsgBuffer.begin(), '\"');
+          MsgBuffer.append(1, '\"');
+        }
+      }
 
       Expr *InnerCond = nullptr;
       std::string InnerCondDescription;
@@ -13747,11 +13754,12 @@
                                    /*AllowTopLevelCond=*/false);
       if (InnerCond) {
         Diag(StaticAssertLoc, diag::err_static_assert_requirement_failed)
-          << InnerCondDescription << !AssertMessage
-          << Msg.str() << InnerCond->getSourceRange();
+          << InnerCondDescription << MsgBuffer.empty() << MsgBuffer.str()
+          << InnerCond->getSourceRange();
       } else {
         Diag(StaticAssertLoc, diag::err_static_assert_failed)
-          << !AssertMessage << Msg.str() << AssertExpr->getSourceRange();
+          << MsgBuffer.empty() << MsgBuffer.str()
+          << AssertExpr->getSourceRange();
       }
       Failed = true;
     }
Index: lib/Parse/ParseDeclCXX.cpp
===================================================================
--- lib/Parse/ParseDeclCXX.cpp
+++ lib/Parse/ParseDeclCXX.cpp
@@ -819,7 +819,10 @@
 
 /// ParseStaticAssertDeclaration - Parse C++0x or C11 static_assert-declaration.
 ///
-/// [C++0x] static_assert-declaration:
+/// [C++17] static_assert-declaration:
+///           static_assert ( constant-expression  ) ;
+///
+/// [C++11] static_assert-declaration:
 ///           static_assert ( constant-expression  ,  string-literal  ) ;
 ///
 /// [C11]   static_assert-declaration:
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D46834: [... Jan Korous via Phabricator via cfe-commits

Reply via email to