tbaeder updated this revision to Diff 449199.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D130894/new/
https://reviews.llvm.org/D130894
Files:
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/include/clang/Sema/Sema.h
clang/lib/Sema/SemaDeclCXX.cpp
clang/test/CXX/dcl.decl/dcl.meaning/dcl.array/p3.cpp
clang/test/CXX/drs/dr7xx.cpp
clang/test/CXX/temp/temp.decls/temp.variadic/init-capture.cpp
clang/test/PCH/cxx-templates.cpp
clang/test/Parser/objc-static-assert.mm
clang/test/SemaCXX/static-assert-cxx17.cpp
clang/test/SemaTemplate/instantiate-var-template.cpp
clang/test/SemaTemplate/instantiation-dependence.cpp
Index: clang/test/SemaTemplate/instantiation-dependence.cpp
===================================================================
--- clang/test/SemaTemplate/instantiation-dependence.cpp
+++ clang/test/SemaTemplate/instantiation-dependence.cpp
@@ -68,8 +68,10 @@
struct D : B, C {};
static_assert(trait<A>::specialization == 0);
- static_assert(trait<B>::specialization == 1); // FIXME expected-error {{failed}}
- static_assert(trait<C>::specialization == 2); // FIXME expected-error {{failed}}
+ static_assert(trait<B>::specialization == 1); // FIXME expected-error {{failed}} \
+ // expected-note {{evaluates to '0'}}
+ static_assert(trait<C>::specialization == 2); // FIXME expected-error {{failed}} \
+ // expected-note {{evaluates to '0'}}
static_assert(trait<D>::specialization == 0); // FIXME-error {{ambiguous partial specialization}}
}
Index: clang/test/SemaTemplate/instantiate-var-template.cpp
===================================================================
--- clang/test/SemaTemplate/instantiate-var-template.cpp
+++ clang/test/SemaTemplate/instantiate-var-template.cpp
@@ -31,7 +31,8 @@
static_assert(b<char> == 1, ""); // expected-note {{in instantiation of}} expected-error {{not an integral constant}}
template<typename T> void f() {
- static_assert(a<sizeof(sizeof(f(T())))> == 0, ""); // expected-error {{static assertion failed due to requirement 'a<sizeof (sizeof (f(type-parameter-0-0())))> == 0'}}
+ static_assert(a<sizeof(sizeof(f(T())))> == 0, ""); // expected-error {{static assertion failed due to requirement 'a<sizeof (sizeof (f(type-parameter-0-0())))> == 0'}} \
+ // expected-note {{evaluates to '1'}}
}
}
Index: clang/test/SemaCXX/static-assert-cxx17.cpp
===================================================================
--- clang/test/SemaCXX/static-assert-cxx17.cpp
+++ clang/test/SemaCXX/static-assert-cxx17.cpp
@@ -88,7 +88,8 @@
static_assert(typename T::T(0));
// expected-error@-1{{static assertion failed due to requirement 'int(0)'}}
static_assert(sizeof(X<typename T::T>) == 0);
- // expected-error@-1{{static assertion failed due to requirement 'sizeof(X<int>) == 0'}}
+ // expected-error@-1{{static assertion failed due to requirement 'sizeof(X<int>) == 0'}} \
+ // expected-note@-1 {{evaluates to '8'}}
static_assert((const X<typename T::T> *)nullptr);
// expected-error@-1{{static assertion failed due to requirement '(const X<int> *)nullptr'}}
static_assert(static_cast<const X<typename T::T> *>(nullptr));
@@ -96,7 +97,8 @@
static_assert((const X<typename T::T>[]){} == nullptr);
// expected-error@-1{{static assertion failed due to requirement '(const X<int>[0]){} == nullptr'}}
static_assert(sizeof(X<decltype(X<typename T::T>().X<typename T::T>::~X())>) == 0);
- // expected-error@-1{{static assertion failed due to requirement 'sizeof(X<void>) == 0'}}
+ // expected-error@-1{{static assertion failed due to requirement 'sizeof(X<void>) == 0'}} \
+ // expected-note@-1 {{evaluates to '8'}}
static_assert(constexpr_return_false<typename T::T, typename T::U>());
// expected-error@-1{{static assertion failed due to requirement 'constexpr_return_false<int, float>()'}}
}
Index: clang/test/Parser/objc-static-assert.mm
===================================================================
--- clang/test/Parser/objc-static-assert.mm
+++ clang/test/Parser/objc-static-assert.mm
@@ -26,7 +26,8 @@
static_assert(a, ""); // expected-error {{static assertion expression is not an integral constant expression}}
static_assert(sizeof(a) == 4, "");
- static_assert(sizeof(a) == 3, ""); // expected-error {{static assertion failed}}
+ static_assert(sizeof(a) == 3, ""); // expected-error {{static assertion failed}} \
+ // expected-note {{evaluates to '4'}}
}
static_assert(1, "");
@@ -40,7 +41,8 @@
static_assert(1, "");
_Static_assert(1, "");
static_assert(sizeof(b) == 4, "");
- static_assert(sizeof(b) == 3, ""); // expected-error {{static assertion failed}}
+ static_assert(sizeof(b) == 3, ""); // expected-error {{static assertion failed}} \
+ // expected-note {{evaluates to '4'}}
}
static_assert(1, "");
@@ -56,7 +58,8 @@
@interface B () {
int b;
static_assert(sizeof(b) == 4, "");
- static_assert(sizeof(b) == 3, ""); // expected-error {{static assertion failed}}
+ static_assert(sizeof(b) == 3, ""); // expected-error {{static assertion failed}} \
+ // expected-note {{evaluates to '4'}}
}
@end
Index: clang/test/PCH/cxx-templates.cpp
===================================================================
--- clang/test/PCH/cxx-templates.cpp
+++ clang/test/PCH/cxx-templates.cpp
@@ -167,7 +167,8 @@
// This used to mark 'f' invalid without producing any diagnostic. That's a
// little hard to detect, but we can make sure that constexpr evaluation
// fails when it should.
- static_assert(A<int>().f() == 1); // expected-error {{static assertion failed}}
+ static_assert(A<int>().f() == 1); // expected-error {{static assertion failed}} \
+ // expected-note {{left-hand side of operator '==' evaluates to '0'}}
#endif
}
Index: clang/test/CXX/temp/temp.decls/temp.variadic/init-capture.cpp
===================================================================
--- clang/test/CXX/temp/temp.decls/temp.variadic/init-capture.cpp
+++ clang/test/CXX/temp/temp.decls/temp.variadic/init-capture.cpp
@@ -40,8 +40,10 @@
template<int ...a> constexpr auto x = [...z = a] (auto F) { return F(z...); };
static_assert(x<1,2,3>([](int a, int b, int c) { return 100 * a + 10 * b + c; }) == 123);
-static_assert(x<1,2,3>([](int a, int b, int c) { return 100 * a + 10 * b + c; }) == 124); // expected-error {{failed}}
+static_assert(x<1,2,3>([](int a, int b, int c) { return 100 * a + 10 * b + c; }) == 124); // expected-error {{failed}} \
+ // expected-note {{evaluates to '123'}}
template<int ...a> constexpr auto y = [z = a...] (auto F) { return F(z...); }; // expected-error {{must appear before the name of the capture}}
static_assert(y<1,2,3>([](int a, int b, int c) { return 100 * a + 10 * b + c; }) == 123);
-static_assert(y<1,2,3>([](int a, int b, int c) { return 100 * a + 10 * b + c; }) == 124); // expected-error {{failed}}
+static_assert(y<1,2,3>([](int a, int b, int c) { return 100 * a + 10 * b + c; }) == 124); // expected-error {{failed}} \
+ // expected-note {{evaluates to '123'}}
Index: clang/test/CXX/drs/dr7xx.cpp
===================================================================
--- clang/test/CXX/drs/dr7xx.cpp
+++ clang/test/CXX/drs/dr7xx.cpp
@@ -178,7 +178,8 @@
static_assert(B<0>().v<1> == 3, "");
static_assert(B<0>().v<0> == 4, "");
#if __cplusplus < 201702L
- // expected-error@-2 {{failed}}
+ // expected-error@-2 {{failed}} \
+ // expected-note@-2 {{left-hand side of operator '==' evaluates to '2'}}
#endif
static_assert(B<1>().w<1> == 1, "");
Index: clang/test/CXX/dcl.decl/dcl.meaning/dcl.array/p3.cpp
===================================================================
--- clang/test/CXX/dcl.decl/dcl.meaning/dcl.array/p3.cpp
+++ clang/test/CXX/dcl.decl/dcl.meaning/dcl.array/p3.cpp
@@ -98,7 +98,8 @@
static_assert(sizeof(arr2) == 12, "");
// Use a failing test to ensure the type isn't considered dependent.
- static_assert(sizeof(arr2) == 13, ""); // expected-error {{failed}}
+ static_assert(sizeof(arr2) == 13, ""); // expected-error {{failed}} \
+ // expected-note {{evaluates to '12'}}
}
void g() { f<int[3]>(); } // expected-note {{in instantiation of}}
Index: clang/lib/Sema/SemaDeclCXX.cpp
===================================================================
--- clang/lib/Sema/SemaDeclCXX.cpp
+++ clang/lib/Sema/SemaDeclCXX.cpp
@@ -16554,6 +16554,48 @@
AssertMessage, RParenLoc, false);
}
+/// Try to print more useful information about a failed static_assert
+/// with expression \E
+void Sema::DiagnoseStaticAssertDetails(const Expr *E) {
+ if (const BinaryOperator *Op = dyn_cast_or_null<BinaryOperator>(E)) {
+ unsigned ExprIsRHS = true;
+ const Expr *ExprSide;
+
+ if (isa<IntegerLiteral>(Op->getRHS()->IgnoreParenImpCasts())) {
+ ExprIsRHS = false;
+ ExprSide = Op->getLHS();
+ } else if (isa<IntegerLiteral>(Op->getLHS()->IgnoreParenImpCasts())) {
+ ExprIsRHS = true;
+ ExprSide = Op->getRHS();
+ } else
+ return;
+
+ // We already print enough info about these earlier,
+ // e.g. "requirement '2 == 1' failed" where 2 is
+ // a substituted template parameter.
+ if (isa<SubstNonTypeTemplateParmExpr>(ExprSide))
+ return;
+
+ if (isa<IntegerLiteral>(ExprSide))
+ return;
+
+ // Evaluate the expression again
+ Expr::EvalResult EvalResult;
+ SmallVector<PartialDiagnosticAt, 0> Notes;
+ EvalResult.Diag = &Notes;
+ ExprSide->EvaluateAsRValue(EvalResult, Context, true);
+
+ SmallString<12> ValueString;
+ if (EvalResult.Val.isInt())
+ EvalResult.Val.getInt().toString(ValueString);
+ else
+ return;
+
+ Diag(ExprSide->getExprLoc(), diag::note_bin_op_evaluates)
+ << (unsigned)ExprIsRHS << Op->getOpcodeStr() << ValueString;
+ }
+}
+
Decl *Sema::BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc,
Expr *AssertExpr,
StringLiteral *AssertMessage,
@@ -16612,6 +16654,7 @@
Diag(StaticAssertLoc, diag::err_static_assert_requirement_failed)
<< InnerCondDescription << !AssertMessage
<< Msg.str() << InnerCond->getSourceRange();
+ DiagnoseStaticAssertDetails(InnerCond);
} else {
Diag(StaticAssertLoc, diag::err_static_assert_failed)
<< !AssertMessage << Msg.str() << AssertExpr->getSourceRange();
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -7482,6 +7482,7 @@
StringLiteral *AssertMessageExpr,
SourceLocation RParenLoc,
bool Failed);
+ void DiagnoseStaticAssertDetails(const Expr *E);
FriendDecl *CheckFriendTypeDecl(SourceLocation LocStart,
SourceLocation FriendLoc,
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1532,6 +1532,8 @@
def err_static_assert_failed : Error<"static assertion failed%select{: %1|}0">;
def err_static_assert_requirement_failed : Error<
"static assertion failed due to requirement '%0'%select{: %2|}1">;
+def note_bin_op_evaluates : Note<
+ "%select{left-hand|right-hand}0 side of operator '%1' evaluates to '%2'">;
def warn_consteval_if_always_true : Warning<
"consteval if is always true in an %select{unevaluated|immediate}0 context">,
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits