// C++ declarations
def err_static_assert_expression_is_not_constant : Error<
"static_assert expression is not an integral constant expression">;
-def err_static_assert_failed : Error<"static_assert failed %0">;
+def err_static_assert_failed : Error<"static_assert failed%select{ %1|}0">;
+def ext_static_assert_no_message : ExtWarn<
+ "static_assert with no message is a C++1z extension">, InGroup<CXX1z>;
+def warn_cxx1y_compat_static_assert_no_message : Warning<
+ "static_assert with no message is incompatible with C++ standards before C++1z">,
+ DefaultIgnore, InGroup<CXXPre1zCompat>;
def warn_inline_namespace_reopened_noninline : Warning<
"inline namespace cannot be reopened as a non-inline namespace">;
return nullptr;
}
- if (ExpectAndConsume(tok::comma)) {
- SkipUntil(tok::semi);
- return nullptr;
- }
+ ExprResult AssertMessage;
+ if (Tok.is(tok::r_paren)) {
+ Diag(Tok, getLangOpts().CPlusPlus1z
+ ? diag::warn_cxx1y_compat_static_assert_no_message
+ : diag::ext_static_assert_no_message)
+ << (getLangOpts().CPlusPlus1z
+ ? FixItHint()
+ : FixItHint::CreateInsertion(Tok.getLocation(), ", \"\""));
+ } else {
+ if (ExpectAndConsume(tok::comma)) {
+ SkipUntil(tok::semi);
+ return nullptr;
+ }
- if (!isTokenStringLiteral()) {
- Diag(Tok, diag::err_expected_string_literal)
- << /*Source='static_assert'*/1;
- SkipMalformedDecl();
- return nullptr;
- }
+ if (!isTokenStringLiteral()) {
+ Diag(Tok, diag::err_expected_string_literal)
+ << /*Source='static_assert'*/1;
+ SkipMalformedDecl();
+ return nullptr;
+ }
- ExprResult AssertMessage(ParseStringLiteralExpression());
- if (AssertMessage.isInvalid()) {
- SkipMalformedDecl();
- return nullptr;
+ AssertMessage = ParseStringLiteralExpression();
+ if (AssertMessage.isInvalid()) {
+ SkipMalformedDecl();
+ return nullptr;
+ }
}
T.consumeClose();
Expr *AssertExpr,
Expr *AssertMessageExpr,
SourceLocation RParenLoc) {
- StringLiteral *AssertMessage = cast<StringLiteral>(AssertMessageExpr);
+ StringLiteral *AssertMessage =
+ AssertMessageExpr ? cast<StringLiteral>(AssertMessageExpr) : nullptr;
if (DiagnoseUnexpandedParameterPack(AssertExpr, UPPC_StaticAssertExpression))
return nullptr;
StringLiteral *AssertMessage,
SourceLocation RParenLoc,
bool Failed) {
- assert(AssertExpr != nullptr && AssertMessage != nullptr &&
- "Expected non-null Expr's");
+ assert(AssertExpr != nullptr && "Expected non-null condition");
if (!AssertExpr->isTypeDependent() && !AssertExpr->isValueDependent() &&
!Failed) {
// In a static_assert-declaration, the constant-expression shall be a
if (!Failed && !Cond) {
SmallString<256> MsgBuffer;
llvm::raw_svector_ostream Msg(MsgBuffer);
- AssertMessage->printPretty(Msg, nullptr, getPrintingPolicy());
+ if (AssertMessage)
+ AssertMessage->printPretty(Msg, nullptr, getPrintingPolicy());
Diag(StaticAssertLoc, diag::err_static_assert_failed)
- << Msg.str() << AssertExpr->getSourceRange();
+ << !AssertMessage << Msg.str() << AssertExpr->getSourceRange();
Failed = true;
}
}
// RUN: %clang_cc1 -fsyntax-only -std=c++98 -Wc++11-compat -verify %s
-// RUN: %clang_cc1 -fsyntax-only -std=c++1y -Wc++11-compat -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++1z -Wc++11-compat -verify %s
#if __cplusplus < 201103L
#else
auto init_capture = [a(0)] {}; // expected-warning {{initialized lambda captures are incompatible with C++ standards before C++1y}}
+static_assert(true); // expected-warning {{incompatible with C++ standards before C++1z}}
#endif
struct X { ~X(); };
StaticAssertProtected<int> sap1;
StaticAssertProtected<X> sap2; // expected-note {{instantiation}}
+
+static_assert(true); // expected-warning {{C++1z extension}}
+static_assert(false); // expected-error-re {{failed$}} expected-warning {{extension}}