Index: include/clang/AST/Stmt.h =================================================================== --- include/clang/AST/Stmt.h +++ include/clang/AST/Stmt.h @@ -843,7 +843,8 @@ void printPretty(raw_ostream &OS, PrinterHelper *Helper, const PrintingPolicy &Policy, unsigned Indentation = 0, StringRef NewlineSymbol = "\n", - const ASTContext *Context = nullptr) const; + const ASTContext *Context = nullptr, + bool PrintCanonicalTypes = false) const; /// viewAST - Visualize an AST rooted at this Stmt* using GraphViz. Only /// works on systems with GraphViz (Mac OS X) or dot+gv installed. Index: lib/AST/StmtPrinter.cpp =================================================================== --- lib/AST/StmtPrinter.cpp +++ lib/AST/StmtPrinter.cpp @@ -71,14 +71,15 @@ PrintingPolicy Policy; std::string NL; const ASTContext *Context; + const bool PrintCanonicalTypes; public: StmtPrinter(raw_ostream &os, PrinterHelper *helper, - const PrintingPolicy &Policy, unsigned Indentation = 0, - StringRef NL = "\n", - const ASTContext *Context = nullptr) + const PrintingPolicy &Policy, unsigned Indentation, + StringRef NL, const ASTContext *Context, + bool PrintCanonicalTypes) : OS(os), IndentLevel(Indentation), Helper(helper), Policy(Policy), - NL(NL), Context(Context) {} + NL(NL), Context(Context), PrintCanonicalTypes(PrintCanonicalTypes) {} void PrintStmt(Stmt *S) { PrintStmt(S, Policy.Indentation); @@ -165,6 +166,14 @@ #define STMT(CLASS, PARENT) \ void Visit##CLASS(CLASS *Node); #include "clang/AST/StmtNodes.inc" + + private: + void PrintType(const QualType &T) const { + if (PrintCanonicalTypes) + T.getCanonicalType().print(OS, Policy); + else + T.print(OS, Policy); + } }; } // namespace @@ -1194,7 +1203,7 @@ void StmtPrinter::VisitOffsetOfExpr(OffsetOfExpr *Node) { OS << "__builtin_offsetof("; - Node->getTypeSourceInfo()->getType().print(OS, Policy); + PrintType(Node->getTypeSourceInfo()->getType()); OS << ", "; bool PrintedSomething = false; for (unsigned i = 0, n = Node->getNumComponents(); i < n; ++i) { @@ -1251,7 +1260,7 @@ } if (Node->isArgumentType()) { OS << '('; - Node->getArgumentType().print(OS, Policy); + PrintType(Node->getArgumentType()); OS << ')'; } else { OS << " "; @@ -1268,7 +1277,7 @@ if (T.isNull()) OS << "default"; else - T.print(OS, Policy); + PrintType(T); OS << ": "; PrintExpr(Node->getAssocExpr(i)); } @@ -1359,14 +1368,14 @@ void StmtPrinter::VisitCStyleCastExpr(CStyleCastExpr *Node) { OS << '('; - Node->getTypeAsWritten().print(OS, Policy); + PrintType(Node->getTypeAsWritten()); OS << ')'; PrintExpr(Node->getSubExpr()); } void StmtPrinter::VisitCompoundLiteralExpr(CompoundLiteralExpr *Node) { OS << '('; - Node->getType().print(OS, Policy); + PrintType(Node->getType()); OS << ')'; PrintExpr(Node->getInitializer()); } @@ -1442,7 +1451,7 @@ OS << "__builtin_convertvector("; PrintExpr(Node->getSrcExpr()); OS << ", "; - Node->getType().print(OS, Policy); + PrintType(Node->getType()); OS << ")"; } @@ -1535,11 +1544,11 @@ void StmtPrinter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *Node) { if (Node->getType()->getAsCXXRecordDecl()) { OS << "/*implicit*/"; - Node->getType().print(OS, Policy); + PrintType(Node->getType()); OS << "()"; } else { OS << "/*implicit*/("; - Node->getType().print(OS, Policy); + PrintType(Node->getType()); OS << ')'; if (Node->getType()->isRecordType()) OS << "{}"; @@ -1552,7 +1561,7 @@ OS << "__builtin_va_arg("; PrintExpr(Node->getSubExpr()); OS << ", "; - Node->getType().print(OS, Policy); + PrintType(Node->getType()); OS << ")"; } @@ -1670,7 +1679,7 @@ void StmtPrinter::VisitCXXNamedCastExpr(CXXNamedCastExpr *Node) { OS << Node->getCastName() << '<'; - Node->getTypeAsWritten().print(OS, Policy); + PrintType(Node->getTypeAsWritten()); OS << ">("; PrintExpr(Node->getSubExpr()); OS << ")"; @@ -1695,7 +1704,7 @@ void StmtPrinter::VisitCXXTypeidExpr(CXXTypeidExpr *Node) { OS << "typeid("; if (Node->isTypeOperand()) { - Node->getTypeOperandSourceInfo()->getType().print(OS, Policy); + PrintType(Node->getTypeOperandSourceInfo()->getType()); } else { PrintExpr(Node->getExprOperand()); } @@ -1705,7 +1714,7 @@ void StmtPrinter::VisitCXXUuidofExpr(CXXUuidofExpr *Node) { OS << "__uuidof("; if (Node->isTypeOperand()) { - Node->getTypeOperandSourceInfo()->getType().print(OS, Policy); + PrintType(Node->getTypeOperandSourceInfo()->getType()); } else { PrintExpr(Node->getExprOperand()); } @@ -1806,7 +1815,7 @@ } void StmtPrinter::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *Node) { - Node->getType().print(OS, Policy); + PrintType(Node->getType()); // If there are no parens, this is list-initialization, and the braces are // part of the syntax of the inner construct. if (Node->getLParenLoc().isValid()) @@ -1821,7 +1830,7 @@ } void StmtPrinter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *Node) { - Node->getType().print(OS, Policy); + PrintType(Node->getType()); if (Node->isStdInitListInitialization()) /* Nothing to do; braces are part of creating the std::initializer_list. */; else if (Node->isListInitialization()) @@ -1932,7 +1941,7 @@ // Print the trailing return type if it was specified in the source. if (Node->hasExplicitResultType()) { OS << " -> "; - Proto->getReturnType().print(OS, Policy); + PrintType(Proto->getReturnType()); } } @@ -1944,9 +1953,9 @@ void StmtPrinter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *Node) { if (TypeSourceInfo *TSInfo = Node->getTypeSourceInfo()) - TSInfo->getType().print(OS, Policy); + PrintType(TSInfo->getType()); else - Node->getType().print(OS, Policy); + PrintType(Node->getType()); OS << "()"; } @@ -2011,7 +2020,7 @@ if (IdentifierInfo *II = E->getDestroyedTypeIdentifier()) OS << II->getName(); else - E->getDestroyedType().print(OS, Policy); + PrintType(E->getDestroyedType()); } void StmtPrinter::VisitCXXConstructExpr(CXXConstructExpr *E) { @@ -2049,7 +2058,7 @@ void StmtPrinter::VisitCXXUnresolvedConstructExpr( CXXUnresolvedConstructExpr *Node) { - Node->getTypeAsWritten().print(OS, Policy); + PrintType(Node->getTypeAsWritten()); OS << "("; for (CXXUnresolvedConstructExpr::arg_iterator Arg = Node->arg_begin(), ArgEnd = Node->arg_end(); @@ -2124,14 +2133,14 @@ for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) { if (I > 0) OS << ", "; - E->getArg(I)->getType().print(OS, Policy); + PrintType(E->getArg(I)->getType()); } OS << ")"; } void StmtPrinter::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) { OS << getTypeTraitName(E->getTrait()) << '('; - E->getQueriedType().print(OS, Policy); + PrintType(E->getQueriedType()); OS << ')'; } @@ -2259,7 +2268,7 @@ void StmtPrinter::VisitObjCEncodeExpr(ObjCEncodeExpr *Node) { OS << "@encode("; - Node->getEncodedType().print(OS, Policy); + PrintType(Node->getEncodedType()); OS << ')'; } @@ -2281,7 +2290,7 @@ break; case ObjCMessageExpr::Class: - Mess->getClassReceiver().print(OS, Policy); + PrintType(Mess->getClassReceiver()); break; case ObjCMessageExpr::SuperInstance: @@ -2323,7 +2332,7 @@ void StmtPrinter::VisitObjCBridgedCastExpr(ObjCBridgedCastExpr *E) { OS << '(' << E->getBridgeKindName(); - E->getType().print(OS, Policy); + PrintType(E->getType()); OS << ')'; PrintExpr(E->getSubExpr()); } @@ -2368,7 +2377,7 @@ OS << "__builtin_astype("; PrintExpr(Node->getSrcExpr()); OS << ", "; - Node->getType().print(OS, Policy); + PrintType(Node->getType()); OS << ")"; } @@ -2382,9 +2391,10 @@ void Stmt::printPretty(raw_ostream &OS, PrinterHelper *Helper, const PrintingPolicy &Policy, unsigned Indentation, - StringRef NL, - const ASTContext *Context) const { - StmtPrinter P(OS, Helper, Policy, Indentation, NL, Context); + StringRef NL, const ASTContext *Context, + bool PrintCanonicalTypes) const { + StmtPrinter P(OS, Helper, Policy, Indentation, NL, Context, + PrintCanonicalTypes); P.Visit(const_cast(this)); } 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); @@ -3081,6 +3082,7 @@ } private: + const ASTContext &Context; const PrintingPolicy Policy; }; @@ -3122,8 +3124,9 @@ std::string Description; { llvm::raw_string_ostream Out(Description); - FailedBooleanConditionPrinterHelper Helper(getPrintingPolicy()); - FailedCond->printPretty(Out, &Helper, getPrintingPolicy()); + FailedBooleanConditionPrinterHelper Helper(Context, getPrintingPolicy()); + FailedCond->printPretty(Out, &Helper, getPrintingPolicy(), 0, "\n", nullptr, + true); } return { FailedCond, Description }; } Index: test/SemaCXX/static-assert-cxx17.cpp =================================================================== --- test/SemaCXX/static-assert-cxx17.cpp +++ test/SemaCXX/static-assert-cxx17.cpp @@ -54,3 +54,44 @@ } template void foo5(); // expected-note@-1{{in instantiation of function template specialization 'foo5' requested here}} + +struct ExampleTypes { + explicit ExampleTypes(int); + using T = int; + using U = float; +}; + +template +struct X { + int i = 0; + int j = 0; + constexpr operator bool() const { return false; } +}; + +template +void foo6() { + static_assert(X()); + // expected-error@-1{{static_assert failed due to requirement 'X()'}} + static_assert(X{}); + // expected-error@-1{{static_assert failed due to requirement 'X{}'}} + static_assert(X{1, 2}); + // expected-error@-1{{static_assert failed due to requirement 'X{1, 2}'}} + static_assert(X({1, 2})); + // expected-error@-1{{static_assert failed due to requirement 'X({1, 2})'}} + static_assert(typename T::T{0}); + // expected-error@-1{{static_assert failed due to requirement 'int{0}'}} + static_assert(typename T::T(0)); + // expected-error@-1{{static_assert failed due to requirement 'int(0)'}} + static_assert(sizeof(X) == 0); + // expected-error@-1{{static_assert failed due to requirement 'sizeof(X) == 0'}} + static_assert((const X *)nullptr); + // expected-error@-1{{static_assert failed due to requirement '(const X *)nullptr'}} + static_assert(static_cast *>(nullptr)); + // expected-error@-1{{static_assert failed due to requirement 'static_cast *>(nullptr)'}} + static_assert((const X[]){} == nullptr); + // expected-error@-1{{static_assert failed due to requirement '(X const[0]){} == nullptr'}} + static_assert(sizeof(X().X::~X())>) == 0); + // expected-error@-1{{static_assert failed due to requirement 'sizeof(X) == 0'}} +} +template void foo6(); +// expected-note@-1{{in instantiation of function template specialization 'foo6' requested here}} 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 {};