Index: lib/Sema/SemaTemplate.cpp =================================================================== --- lib/Sema/SemaTemplate.cpp +++ lib/Sema/SemaTemplate.cpp @@ -3059,8 +3059,9 @@ // for actual types. class FailedBooleanConditionPrinterHelper : public PrinterHelper { public: - explicit FailedBooleanConditionPrinterHelper(const PrintingPolicy &P) - : Policy(P) {} + FailedBooleanConditionPrinterHelper(const ASTContext &Context, + const PrintingPolicy &P) + : Context(Context), Policy(P) {} bool handledStmt(Stmt *E, raw_ostream &OS) override { const auto *DR = dyn_cast(E); @@ -3077,10 +3078,38 @@ } return true; } + if (auto *Node = dyn_cast(E)) { + Node->getType().getCanonicalType().print(OS, Policy); + if (Node->isStdInitListInitialization()) + /* Nothing to do; braces are part of creating the std::initializer_list. + */ + ; + else if (Node->isListInitialization()) + OS << "{"; + else + OS << "("; + for (CXXTemporaryObjectExpr::arg_iterator Arg = Node->arg_begin(), + ArgEnd = Node->arg_end(); + Arg != ArgEnd; ++Arg) { + if ((*Arg)->isDefaultArgument()) + break; + if (Arg != Node->arg_begin()) + OS << ", "; + (*Arg)->printPretty(OS, this, Policy); + } + if (Node->isStdInitListInitialization()) + /* See above. */; + else if (Node->isListInitialization()) + OS << "}"; + else + OS << ")"; + return true; + } return false; } private: + const ASTContext &Context; const PrintingPolicy Policy; }; @@ -3122,7 +3151,7 @@ std::string Description; { llvm::raw_string_ostream Out(Description); - FailedBooleanConditionPrinterHelper Helper(getPrintingPolicy()); + FailedBooleanConditionPrinterHelper Helper(Context, getPrintingPolicy()); FailedCond->printPretty(Out, &Helper, getPrintingPolicy()); } return { FailedCond, Description }; Index: test/SemaCXX/static-assert.cpp =================================================================== --- test/SemaCXX/static-assert.cpp +++ test/SemaCXX/static-assert.cpp @@ -76,6 +76,8 @@ static const Tp value = v; typedef Tp value_type; typedef integral_constant type; + constexpr operator value_type() const noexcept { return value; } + constexpr value_type operator()() const noexcept { return value; } }; template @@ -103,6 +105,7 @@ } // namespace std struct ExampleTypes { + explicit ExampleTypes(int); using T = int; using U = float; }; @@ -119,6 +122,18 @@ // expected-error@-1{{static_assert failed due to requirement 'std::is_const::value == false' "message"}} static_assert(!(std::is_const::value == true), "message"); // expected-error@-1{{static_assert failed due to requirement '!(std::is_const::value == true)' "message"}} +static_assert(std::is_const(), "message"); +// expected-error@-1{{static_assert failed due to requirement 'std::is_const()' "message"}} +static_assert(!(std::is_const()()), "message"); +// expected-error@-1{{static_assert failed due to requirement '!(std::is_const()())' "message"}} +static_assert(std::is_same()), int>::value, "message"); +// expected-error@-1{{static_assert failed due to requirement 'std::is_same, int>::value' "message"}} +static_assert(std::is_const::value, "message"); +// expected-error@-1{{static_assert failed due to requirement 'std::is_const::value' "message"}} +static_assert(std::is_const::value, "message"); +// expected-error@-1{{static_assert failed due to requirement 'std::is_const::value' "message"}} +static_assert(std::is_const::value, "message"); +// expected-error@-1{{static_assert failed due to requirement 'std::is_const::value' "message"}} struct BI_tag {}; struct RAI_tag : BI_tag {};