summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema
diff options
context:
space:
mode:
authorClement Courbet <courbet@google.com>2018-12-10 08:19:38 +0000
committerClement Courbet <courbet@google.com>2018-12-10 08:19:38 +0000
commit057f7695de385511c042e14542e0d3414109b267 (patch)
treeaca6eeae6c77f70c4c0de2d64156eb95fd2746eb /clang/lib/Sema
parent7b475f3b412506b6fe7b65b389c91ac285dd090d (diff)
downloadbcm5719-llvm-057f7695de385511c042e14542e0d3414109b267.tar.gz
bcm5719-llvm-057f7695de385511c042e14542e0d3414109b267.zip
[Sema] Further improvements to to static_assert diagnostics.
Summary: We're now handling cases like `static_assert(!expr)` and static_assert(!(expr))`. Reviewers: aaron.ballman, Quuxplusone Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D55270 llvm-svn: 348741
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp3
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp77
2 files changed, 42 insertions, 38 deletions
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index e408c043791..831e74a2bf6 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -13878,8 +13878,7 @@ Decl *Sema::BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc,
Expr *InnerCond = nullptr;
std::string InnerCondDescription;
std::tie(InnerCond, InnerCondDescription) =
- findFailedBooleanCondition(Converted.get(),
- /*AllowTopLevelCond=*/false);
+ findFailedBooleanCondition(Converted.get());
if (InnerCond) {
Diag(StaticAssertLoc, diag::err_static_assert_requirement_failed)
<< InnerCondDescription << !AssertMessage
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 56302d62484..c7d67cde112 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -3052,30 +3052,42 @@ static Expr *lookThroughRangesV3Condition(Preprocessor &PP, Expr *Cond) {
return Cond;
}
-// Print a diagnostic for the failing static_assert expression. Defaults to
-// pretty-printing the expression.
-static void prettyPrintFailedBooleanCondition(llvm::raw_string_ostream &OS,
- const Expr *FailedCond,
- const PrintingPolicy &Policy) {
- const auto *DR = dyn_cast<DeclRefExpr>(FailedCond);
- if (DR && DR->getQualifier()) {
- // If this is a qualified name, expand the template arguments in nested
- // qualifiers.
- DR->getQualifier()->print(OS, Policy, true);
- // Then print the decl itself.
- const ValueDecl *VD = DR->getDecl();
- OS << VD->getName();
- if (const auto *IV = dyn_cast<VarTemplateSpecializationDecl>(VD)) {
- // This is a template variable, print the expanded template arguments.
- printTemplateArgumentList(OS, IV->getTemplateArgs().asArray(), Policy);
+namespace {
+
+// A PrinterHelper that prints more helpful diagnostics for some sub-expressions
+// within failing boolean expression, such as substituting template parameters
+// for actual types.
+class FailedBooleanConditionPrinterHelper : public PrinterHelper {
+public:
+ explicit FailedBooleanConditionPrinterHelper(const PrintingPolicy &Policy)
+ : Policy(Policy) {}
+
+ bool handledStmt(Stmt *E, raw_ostream &OS) override {
+ const auto *DR = dyn_cast<DeclRefExpr>(E);
+ if (DR && DR->getQualifier()) {
+ // If this is a qualified name, expand the template arguments in nested
+ // qualifiers.
+ DR->getQualifier()->print(OS, Policy, true);
+ // Then print the decl itself.
+ const ValueDecl *VD = DR->getDecl();
+ OS << VD->getName();
+ if (const auto *IV = dyn_cast<VarTemplateSpecializationDecl>(VD)) {
+ // This is a template variable, print the expanded template arguments.
+ printTemplateArgumentList(OS, IV->getTemplateArgs().asArray(), Policy);
+ }
+ return true;
}
- return;
+ return false;
}
- FailedCond->printPretty(OS, nullptr, Policy);
-}
+
+private:
+ const PrintingPolicy &Policy;
+};
+
+} // end anonymous namespace
std::pair<Expr *, std::string>
-Sema::findFailedBooleanCondition(Expr *Cond, bool AllowTopLevelCond) {
+Sema::findFailedBooleanCondition(Expr *Cond) {
Cond = lookThroughRangesV3Condition(PP, Cond);
// Separate out all of the terms in a conjunction.
@@ -3087,11 +3099,6 @@ Sema::findFailedBooleanCondition(Expr *Cond, bool AllowTopLevelCond) {
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(
@@ -3104,18 +3111,18 @@ Sema::findFailedBooleanCondition(Expr *Cond, bool AllowTopLevelCond) {
break;
}
}
-
- if (!FailedCond) {
- if (!AllowTopLevelCond)
- return { nullptr, "" };
-
+ if (!FailedCond)
FailedCond = Cond->IgnoreParenImpCasts();
- }
+
+ // Literals are uninteresting.
+ if (isa<CXXBoolLiteralExpr>(FailedCond) || isa<IntegerLiteral>(FailedCond))
+ return {nullptr, ""};
std::string Description;
{
llvm::raw_string_ostream Out(Description);
- prettyPrintFailedBooleanCondition(Out, FailedCond, getPrintingPolicy());
+ FailedBooleanConditionPrinterHelper Helper(getPrintingPolicy());
+ FailedCond->printPretty(Out, &Helper, getPrintingPolicy());
}
return { FailedCond, Description };
}
@@ -3199,9 +3206,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
Expr *FailedCond;
std::string FailedDescription;
std::tie(FailedCond, FailedDescription) =
- findFailedBooleanCondition(
- TemplateArgs[0].getSourceExpression(),
- /*AllowTopLevelCond=*/true);
+ findFailedBooleanCondition(TemplateArgs[0].getSourceExpression());
// Remove the old SFINAE diagnostic.
PartialDiagnosticAt OldDiag =
@@ -9649,7 +9654,7 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
Expr *FailedCond;
std::string FailedDescription;
std::tie(FailedCond, FailedDescription) =
- findFailedBooleanCondition(Cond, /*AllowTopLevelCond=*/true);
+ findFailedBooleanCondition(Cond);
Diag(FailedCond->getExprLoc(),
diag::err_typename_nested_not_found_requirement)
OpenPOWER on IntegriCloud