r313315 - Diagnostic specific failed condition in a static_assert.
Douglas Gregor via cfe-commits
cfe-commits at lists.llvm.org
Thu Sep 14 16:38:42 PDT 2017
Author: dgregor
Date: Thu Sep 14 16:38:42 2017
New Revision: 313315
URL: http://llvm.org/viewvc/llvm-project?rev=313315&view=rev
Log:
Diagnostic specific failed condition in a static_assert.
When a static_assert fails, dig out a specific condition to diagnose,
using the same logic that we use to find the enable_if condition to
diagnose.
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/lib/Sema/SemaTemplate.cpp
cfe/trunk/test/SemaCXX/static-assert.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=313315&r1=313314&r2=313315&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Sep 14 16:38:42 2017
@@ -1219,6 +1219,8 @@ def warn_messaging_unqualified_id : Warn
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%select{ %1|}0">;
+def err_static_assert_requirement_failed : Error<
+ "static_assert failed due to requirement '%0'%select{ %2|}1">;
def ext_static_assert_no_message : ExtWarn<
"static_assert with no message is a C++17 extension">, InGroup<CXX17>;
def warn_cxx14_compat_static_assert_no_message : Warning<
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=313315&r1=313314&r2=313315&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Thu Sep 14 16:38:42 2017
@@ -2783,6 +2783,14 @@ public:
EnableIfAttr *CheckEnableIf(FunctionDecl *Function, ArrayRef<Expr *> Args,
bool MissingImplicitThis = false);
+ /// Find the failed Boolean condition within a given Boolean
+ /// constant expression, and describe it with a string.
+ ///
+ /// \param AllowTopLevelCond Whether to allow the result to be the
+ /// complete top-level condition.
+ std::pair<Expr *, std::string>
+ findFailedBooleanCondition(Expr *Cond, bool AllowTopLevelCond);
+
/// Emit diagnostics for the diagnose_if attributes on Function, ignoring any
/// non-ArgDependent DiagnoseIfAttrs.
///
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=313315&r1=313314&r2=313315&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu Sep 14 16:38:42 2017
@@ -13296,8 +13296,20 @@ Decl *Sema::BuildStaticAssertDeclaration
llvm::raw_svector_ostream Msg(MsgBuffer);
if (AssertMessage)
AssertMessage->printPretty(Msg, nullptr, getPrintingPolicy());
- Diag(StaticAssertLoc, diag::err_static_assert_failed)
- << !AssertMessage << Msg.str() << AssertExpr->getSourceRange();
+
+ Expr *InnerCond = nullptr;
+ std::string InnerCondDescription;
+ std::tie(InnerCond, InnerCondDescription) =
+ findFailedBooleanCondition(Converted.get(),
+ /*AllowTopLevelCond=*/false);
+ if (InnerCond) {
+ Diag(StaticAssertLoc, diag::err_static_assert_requirement_failed)
+ << InnerCondDescription << !AssertMessage
+ << Msg.str() << InnerCond->getSourceRange();
+ } else {
+ Diag(StaticAssertLoc, diag::err_static_assert_failed)
+ << !AssertMessage << Msg.str() << AssertExpr->getSourceRange();
+ }
Failed = true;
}
}
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=313315&r1=313314&r2=313315&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Thu Sep 14 16:38:42 2017
@@ -2863,11 +2863,9 @@ static Expr *lookThroughRangesV3Conditio
return Cond;
}
-/// Find the failed subexpression within enable_if, and describe it
-/// with a string.
-static std::pair<Expr *, std::string>
-findFailedEnableIfCondition(Sema &S, Expr *Cond) {
- Cond = lookThroughRangesV3Condition(S.PP, Cond);
+std::pair<Expr *, std::string>
+Sema::findFailedBooleanCondition(Expr *Cond, bool AllowTopLevelCond) {
+ Cond = lookThroughRangesV3Condition(PP, Cond);
// Separate out all of the terms in a conjunction.
SmallVector<Expr *, 4> Terms;
@@ -2876,27 +2874,37 @@ findFailedEnableIfCondition(Sema &S, Exp
// Determine which term failed.
Expr *FailedCond = nullptr;
for (Expr *Term : Terms) {
+ Expr *TermAsWritten = Term->IgnoreParenImpCasts();
+
+ // Literals are uninteresting.
+ if (isa<CXXBoolLiteralExpr>(TermAsWritten) ||
+ isa<IntegerLiteral>(TermAsWritten))
+ continue;
+
// The initialization of the parameter from the argument is
// a constant-evaluated context.
EnterExpressionEvaluationContext ConstantEvaluated(
- S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
+ *this, Sema::ExpressionEvaluationContext::ConstantEvaluated);
bool Succeeded;
- if (Term->EvaluateAsBooleanCondition(Succeeded, S.Context) &&
+ if (Term->EvaluateAsBooleanCondition(Succeeded, Context) &&
!Succeeded) {
- FailedCond = Term->IgnoreParenImpCasts();
+ FailedCond = TermAsWritten;
break;
}
}
- if (!FailedCond)
+ if (!FailedCond) {
+ if (!AllowTopLevelCond)
+ return { nullptr, "" };
+
FailedCond = Cond->IgnoreParenImpCasts();
+ }
std::string Description;
{
llvm::raw_string_ostream Out(Description);
- FailedCond->printPretty(Out, nullptr,
- PrintingPolicy(S.Context.getLangOpts()));
+ FailedCond->printPretty(Out, nullptr, getPrintingPolicy());
}
return { FailedCond, Description };
}
@@ -2980,8 +2988,9 @@ QualType Sema::CheckTemplateIdType(Templ
Expr *FailedCond;
std::string FailedDescription;
std::tie(FailedCond, FailedDescription) =
- findFailedEnableIfCondition(
- *this, TemplateArgs[0].getSourceExpression());
+ findFailedBooleanCondition(
+ TemplateArgs[0].getSourceExpression(),
+ /*AllowTopLevelCond=*/true);
// Remove the old SFINAE diagnostic.
PartialDiagnosticAt OldDiag =
@@ -9513,7 +9522,7 @@ Sema::CheckTypenameType(ElaboratedTypeKe
Expr *FailedCond;
std::string FailedDescription;
std::tie(FailedCond, FailedDescription) =
- findFailedEnableIfCondition(*this, Cond);
+ findFailedBooleanCondition(Cond, /*AllowTopLevelCond=*/true);
Diag(FailedCond->getExprLoc(),
diag::err_typename_nested_not_found_requirement)
Modified: cfe/trunk/test/SemaCXX/static-assert.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/static-assert.cpp?rev=313315&r1=313314&r2=313315&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/static-assert.cpp (original)
+++ cfe/trunk/test/SemaCXX/static-assert.cpp Thu Sep 14 16:38:42 2017
@@ -51,3 +51,20 @@ StaticAssertProtected<X> sap2; // expect
static_assert(true); // expected-warning {{C++17 extension}}
static_assert(false); // expected-error-re {{failed{{$}}}} expected-warning {{extension}}
+
+
+// Diagnostics for static_assert with multiple conditions
+template<typename T> struct first_trait {
+ static const bool value = false;
+};
+
+template<>
+struct first_trait<X> {
+ static const bool value = true;
+};
+
+template<typename T> struct second_trait {
+ static const bool value = false;
+};
+
+static_assert(first_trait<X>::value && second_trait<X>::value, "message"); // expected-error{{static_assert failed due to requirement 'second_trait<X>::value' "message"}}
More information about the cfe-commits
mailing list