diff options
Diffstat (limited to 'clang/lib/Sema/SemaTemplate.cpp')
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 77 |
1 files changed, 36 insertions, 41 deletions
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index c7d67cde112..56302d62484 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -3052,42 +3052,30 @@ static Expr *lookThroughRangesV3Condition(Preprocessor &PP, Expr *Cond) { return Cond; } -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; +// 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); } - return false; + return; } - -private: - const PrintingPolicy &Policy; -}; - -} // end anonymous namespace + FailedCond->printPretty(OS, nullptr, Policy); +} std::pair<Expr *, std::string> -Sema::findFailedBooleanCondition(Expr *Cond) { +Sema::findFailedBooleanCondition(Expr *Cond, bool AllowTopLevelCond) { Cond = lookThroughRangesV3Condition(PP, Cond); // Separate out all of the terms in a conjunction. @@ -3099,6 +3087,11 @@ Sema::findFailedBooleanCondition(Expr *Cond) { 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( @@ -3111,18 +3104,18 @@ Sema::findFailedBooleanCondition(Expr *Cond) { break; } } - if (!FailedCond) - FailedCond = Cond->IgnoreParenImpCasts(); - // Literals are uninteresting. - if (isa<CXXBoolLiteralExpr>(FailedCond) || isa<IntegerLiteral>(FailedCond)) - return {nullptr, ""}; + if (!FailedCond) { + if (!AllowTopLevelCond) + return { nullptr, "" }; + + FailedCond = Cond->IgnoreParenImpCasts(); + } std::string Description; { llvm::raw_string_ostream Out(Description); - FailedBooleanConditionPrinterHelper Helper(getPrintingPolicy()); - FailedCond->printPretty(Out, &Helper, getPrintingPolicy()); + prettyPrintFailedBooleanCondition(Out, FailedCond, getPrintingPolicy()); } return { FailedCond, Description }; } @@ -3206,7 +3199,9 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, Expr *FailedCond; std::string FailedDescription; std::tie(FailedCond, FailedDescription) = - findFailedBooleanCondition(TemplateArgs[0].getSourceExpression()); + findFailedBooleanCondition( + TemplateArgs[0].getSourceExpression(), + /*AllowTopLevelCond=*/true); // Remove the old SFINAE diagnostic. PartialDiagnosticAt OldDiag = @@ -9654,7 +9649,7 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, Expr *FailedCond; std::string FailedDescription; std::tie(FailedCond, FailedDescription) = - findFailedBooleanCondition(Cond); + findFailedBooleanCondition(Cond, /*AllowTopLevelCond=*/true); Diag(FailedCond->getExprLoc(), diag::err_typename_nested_not_found_requirement) |