Index: include/clang/AST/PrettyPrinter.h =================================================================== --- include/clang/AST/PrettyPrinter.h +++ include/clang/AST/PrettyPrinter.h @@ -51,7 +51,7 @@ MSWChar(LO.MicrosoftExt && !LO.WChar), IncludeNewlines(true), MSVCFormatting(false), ConstantsAsWritten(false), SuppressImplicitBase(false), FullyQualifiedName(false), - RemapFilePaths(false) {} + RemapFilePaths(false), PrintCanonicalTypes(false) {} /// Adjust this printing policy for cases where it's known that we're /// printing C++ code (for instance, if AST dumping reaches a C++-only @@ -228,6 +228,9 @@ /// Whether to apply -fdebug-prefix-map to any file paths. unsigned RemapFilePaths : 1; + /// Whether to print types as written or canonically. + unsigned PrintCanonicalTypes : 1; + /// When RemapFilePaths is true, this function performs the action. std::function remapPath; }; Index: include/clang/AST/Type.h =================================================================== --- include/clang/AST/Type.h +++ include/clang/AST/Type.h @@ -980,15 +980,11 @@ void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder = Twine(), - unsigned Indentation = 0) const { - print(split(), OS, Policy, PlaceHolder, Indentation); - } + unsigned Indentation = 0) const; static void print(SplitQualType split, raw_ostream &OS, const PrintingPolicy &policy, const Twine &PlaceHolder, - unsigned Indentation = 0) { - return print(split.Ty, split.Quals, OS, policy, PlaceHolder, Indentation); - } + unsigned Indentation = 0); static void print(const Type *ty, Qualifiers qs, raw_ostream &OS, const PrintingPolicy &policy, @@ -996,14 +992,10 @@ unsigned Indentation = 0); void getAsStringInternal(std::string &Str, - const PrintingPolicy &Policy) const { - return getAsStringInternal(split(), Str, Policy); - } + const PrintingPolicy &Policy) const; static void getAsStringInternal(SplitQualType split, std::string &out, - const PrintingPolicy &policy) { - return getAsStringInternal(split.Ty, split.Quals, out, policy); - } + const PrintingPolicy &policy); static void getAsStringInternal(const Type *ty, Qualifiers qs, std::string &out, Index: lib/AST/StmtPrinter.cpp =================================================================== --- lib/AST/StmtPrinter.cpp +++ lib/AST/StmtPrinter.cpp @@ -75,8 +75,7 @@ public: StmtPrinter(raw_ostream &os, PrinterHelper *helper, const PrintingPolicy &Policy, unsigned Indentation = 0, - StringRef NL = "\n", - const ASTContext *Context = nullptr) + StringRef NL = "\n", const ASTContext *Context = nullptr) : OS(os), IndentLevel(Indentation), Helper(helper), Policy(Policy), NL(NL), Context(Context) {} @@ -2382,8 +2381,7 @@ void Stmt::printPretty(raw_ostream &OS, PrinterHelper *Helper, const PrintingPolicy &Policy, unsigned Indentation, - StringRef NL, - const ASTContext *Context) const { + StringRef NL, const ASTContext *Context) const { StmtPrinter P(OS, Helper, Policy, Indentation, NL, Context); P.Visit(const_cast(this)); } Index: lib/AST/TypePrinter.cpp =================================================================== --- lib/AST/TypePrinter.cpp +++ lib/AST/TypePrinter.cpp @@ -117,9 +117,7 @@ void spaceBeforePlaceHolder(raw_ostream &OS); void printTypeSpec(NamedDecl *D, raw_ostream &OS); - void printBefore(const Type *ty, Qualifiers qs, raw_ostream &OS); void printBefore(QualType T, raw_ostream &OS); - void printAfter(const Type *ty, Qualifiers qs, raw_ostream &OS); void printAfter(QualType T, raw_ostream &OS); void AppendScope(DeclContext *DC, raw_ostream &OS); void printTag(TagDecl *T, raw_ostream &OS); @@ -129,6 +127,10 @@ void print##CLASS##Before(const CLASS##Type *T, raw_ostream &OS); \ void print##CLASS##After(const CLASS##Type *T, raw_ostream &OS); #include "clang/AST/TypeNodes.def" + + private: + void printBefore(const Type *ty, Qualifiers qs, raw_ostream &OS); + void printAfter(const Type *ty, Qualifiers qs, raw_ostream &OS); }; } // namespace @@ -160,8 +162,15 @@ OS << ' '; } +static SplitQualType splitAccordingToPolicy(QualType t, + const PrintingPolicy &Policy) { + if (Policy.PrintCanonicalTypes) + t = t.getCanonicalType(); + return t.split(); +} + void TypePrinter::print(QualType t, raw_ostream &OS, StringRef PlaceHolder) { - SplitQualType split = t.split(); + SplitQualType split = splitAccordingToPolicy(t, Policy); print(split.Ty, split.Quals, OS, PlaceHolder); } @@ -260,7 +269,7 @@ } void TypePrinter::printBefore(QualType T, raw_ostream &OS) { - SplitQualType Split = T.split(); + SplitQualType Split = splitAccordingToPolicy(T, Policy); // If we have cv1 T, where T is substituted for cv2 U, only print cv1 - cv2 // at this level. @@ -320,7 +329,7 @@ } void TypePrinter::printAfter(QualType t, raw_ostream &OS) { - SplitQualType split = t.split(); + SplitQualType split = splitAccordingToPolicy(t, Policy); printAfter(split.Ty, split.Quals, OS); } @@ -1815,6 +1824,19 @@ return buffer; } +void QualType::print(raw_ostream &OS, const PrintingPolicy &Policy, + const Twine &PlaceHolder, + unsigned Indentation) const { + SplitQualType split = splitAccordingToPolicy(*this, Policy); + print(split, OS, Policy, PlaceHolder, Indentation); +} + +void QualType::print(SplitQualType split, raw_ostream &OS, + const PrintingPolicy &policy, const Twine &PlaceHolder, + unsigned Indentation) { + return print(split.Ty, split.Quals, OS, policy, PlaceHolder, Indentation); +} + void QualType::print(const Type *ty, Qualifiers qs, raw_ostream &OS, const PrintingPolicy &policy, const Twine &PlaceHolder, unsigned Indentation) { @@ -1824,6 +1846,17 @@ TypePrinter(policy, Indentation).print(ty, qs, OS, PH); } +void QualType::getAsStringInternal(std::string &Str, + const PrintingPolicy &Policy) const { + SplitQualType split = splitAccordingToPolicy(*this, Policy); + return getAsStringInternal(split, Str, Policy); +} + +void QualType::getAsStringInternal(SplitQualType split, std::string &out, + const PrintingPolicy &policy) { + return getAsStringInternal(split.Ty, split.Quals, out, policy); +} + void QualType::getAsStringInternal(const Type *ty, Qualifiers qs, std::string &buffer, const PrintingPolicy &policy) { Index: lib/Sema/SemaTemplate.cpp =================================================================== --- lib/Sema/SemaTemplate.cpp +++ lib/Sema/SemaTemplate.cpp @@ -3059,8 +3059,7 @@ // for actual types. class FailedBooleanConditionPrinterHelper : public PrinterHelper { public: - explicit FailedBooleanConditionPrinterHelper(const PrintingPolicy &P) - : Policy(P) {} + FailedBooleanConditionPrinterHelper(const PrintingPolicy &P) : Policy(P) {} bool handledStmt(Stmt *E, raw_ostream &OS) override { const auto *DR = dyn_cast(E); @@ -3122,8 +3121,10 @@ std::string Description; { llvm::raw_string_ostream Out(Description); - FailedBooleanConditionPrinterHelper Helper(getPrintingPolicy()); - FailedCond->printPretty(Out, &Helper, getPrintingPolicy()); + auto Policy = getPrintingPolicy(); + Policy.PrintCanonicalTypes = true; + FailedBooleanConditionPrinterHelper Helper(Policy); + FailedCond->printPretty(Out, &Helper, Policy, 0, "\n", nullptr); } 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 {};