Index: cfe/trunk/include/clang/AST/PrettyPrinter.h =================================================================== --- cfe/trunk/include/clang/AST/PrettyPrinter.h +++ cfe/trunk/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: cfe/trunk/include/clang/AST/Type.h =================================================================== --- cfe/trunk/include/clang/AST/Type.h +++ cfe/trunk/include/clang/AST/Type.h @@ -980,9 +980,7 @@ 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, @@ -996,9 +994,7 @@ 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) { Index: cfe/trunk/lib/AST/TypePrinter.cpp =================================================================== --- cfe/trunk/lib/AST/TypePrinter.cpp +++ cfe/trunk/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 QT, + const PrintingPolicy &Policy) { + if (Policy.PrintCanonicalTypes) + QT = QT.getCanonicalType(); + return QT.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,12 @@ return buffer; } +void QualType::print(raw_ostream &OS, const PrintingPolicy &Policy, + const Twine &PlaceHolder, unsigned Indentation) const { + print(splitAccordingToPolicy(*this, Policy), 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 +1839,12 @@ TypePrinter(policy, Indentation).print(ty, qs, OS, PH); } +void QualType::getAsStringInternal(std::string &Str, + const PrintingPolicy &Policy) const { + return getAsStringInternal(splitAccordingToPolicy(*this, Policy), Str, + Policy); +} + void QualType::getAsStringInternal(const Type *ty, Qualifiers qs, std::string &buffer, const PrintingPolicy &policy) { Index: cfe/trunk/lib/Sema/SemaTemplate.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaTemplate.cpp +++ cfe/trunk/lib/Sema/SemaTemplate.cpp @@ -3122,8 +3122,10 @@ std::string Description; { llvm::raw_string_ostream Out(Description); - FailedBooleanConditionPrinterHelper Helper(getPrintingPolicy()); - FailedCond->printPretty(Out, &Helper, getPrintingPolicy()); + PrintingPolicy Policy = getPrintingPolicy(); + Policy.PrintCanonicalTypes = true; + FailedBooleanConditionPrinterHelper Helper(Policy); + FailedCond->printPretty(Out, &Helper, Policy, 0, "\n", nullptr); } return { FailedCond, Description }; } Index: cfe/trunk/test/SemaCXX/static-assert-cxx17.cpp =================================================================== --- cfe/trunk/test/SemaCXX/static-assert-cxx17.cpp +++ cfe/trunk/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: cfe/trunk/test/SemaCXX/static-assert.cpp =================================================================== --- cfe/trunk/test/SemaCXX/static-assert.cpp +++ cfe/trunk/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 {};