Index: include/clang/AST/NestedNameSpecifier.h =================================================================== --- include/clang/AST/NestedNameSpecifier.h +++ include/clang/AST/NestedNameSpecifier.h @@ -212,12 +212,8 @@ /// parameter pack (for C++11 variadic templates). bool containsUnexpandedParameterPack() const; - /// Print this nested name specifier to the given output stream. If - /// `ResolveTemplateArguments` is true, we'll print actual types, e.g. - /// `ns::SomeTemplate` instead of - /// `ns::SomeTemplate`. - void print(raw_ostream &OS, const PrintingPolicy &Policy, - bool ResolveTemplateArguments = false) const; + /// Print this nested name specifier to the given output stream. + void print(raw_ostream &OS, const PrintingPolicy &Policy) const; void Profile(llvm::FoldingSetNodeID &ID) const { ID.AddPointer(Prefix.getOpaqueValue()); Index: lib/AST/NestedNameSpecifier.cpp =================================================================== --- lib/AST/NestedNameSpecifier.cpp +++ lib/AST/NestedNameSpecifier.cpp @@ -271,8 +271,7 @@ /// Print this nested name specifier to the given output /// stream. -void NestedNameSpecifier::print(raw_ostream &OS, const PrintingPolicy &Policy, - bool ResolveTemplateArguments) const { +void NestedNameSpecifier::print(raw_ostream &OS, const PrintingPolicy &Policy) const { if (getPrefix()) getPrefix()->print(OS, Policy); @@ -305,15 +304,6 @@ LLVM_FALLTHROUGH; case TypeSpec: { - const auto *Record = - dyn_cast_or_null(getAsRecordDecl()); - if (ResolveTemplateArguments && Record) { - // Print the type trait with resolved template parameters. - Record->printName(OS); - printTemplateArgumentList(OS, Record->getTemplateArgs().asArray(), - Policy); - break; - } const Type *T = getAsType(); PrintingPolicy InnerPolicy(Policy); Index: lib/AST/TypePrinter.cpp =================================================================== --- lib/AST/TypePrinter.cpp +++ lib/AST/TypePrinter.cpp @@ -164,9 +164,24 @@ static SplitQualType splitAccordingToPolicy(QualType QT, const PrintingPolicy &Policy) { - if (Policy.PrintCanonicalTypes) - QT = QT.getCanonicalType(); - return QT.split(); + if (!Policy.PrintCanonicalTypes) + return QT.split(); + if (QT.isNull()) + return QT.split(); + // We do not canonicalize a few type classes because this would remove the + // information about whether default template parameters were actually + // written. + switch (QT.getTypePtr()->getTypeClass()) { + case Type::TemplateSpecialization: + case Type::Pointer: + case Type::ConstantArray: + case Type::IncompleteArray: + case Type::VariableArray: + case Type::DependentSizedArray: + return QT.split(); + default: + return QT.getCanonicalType().split(); + } } void TypePrinter::print(QualType t, raw_ostream &OS, StringRef PlaceHolder) { Index: lib/Sema/SemaTemplate.cpp =================================================================== --- lib/Sema/SemaTemplate.cpp +++ lib/Sema/SemaTemplate.cpp @@ -3052,40 +3052,6 @@ 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 &P) - : Policy(P) {} - - bool handledStmt(Stmt *E, raw_ostream &OS) override { - const auto *DR = dyn_cast(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(VD)) { - // This is a template variable, print the expanded template arguments. - printTemplateArgumentList(OS, IV->getTemplateArgs().asArray(), Policy); - } - return true; - } - return false; - } - -private: - const PrintingPolicy Policy; -}; - -} // end anonymous namespace - std::pair Sema::findFailedBooleanCondition(Expr *Cond) { Cond = lookThroughRangesV3Condition(PP, Cond); @@ -3124,8 +3090,7 @@ llvm::raw_string_ostream Out(Description); PrintingPolicy Policy = getPrintingPolicy(); Policy.PrintCanonicalTypes = true; - FailedBooleanConditionPrinterHelper Helper(Policy); - FailedCond->printPretty(Out, &Helper, Policy, 0, "\n", nullptr); + FailedCond->printPretty(Out, nullptr, 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 @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++1z -triple=x86_64-linux-gnu -template +template struct S1 { static constexpr const bool value = false; }; @@ -14,7 +14,7 @@ static inline constexpr bool var = global_inline_var; }; -template +template inline constexpr bool constexpr_return_false() { return false; } @@ -23,6 +23,8 @@ void foo() { static_assert(S1::value); // expected-error@-1{{static_assert failed due to requirement 'S1::value'}} + static_assert(S1::value); + // expected-error@-1{{static_assert failed due to requirement 'S1::value'}} } template void foo(); // expected-note@-1{{in instantiation of function template specialization 'foo' requested here}} @@ -66,7 +68,7 @@ using U = float; }; -template +template struct X { int i = 0; int j = 0; @@ -94,11 +96,41 @@ 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'}} + // expected-error@-1{{static_assert failed due to requirement '(const X [0]){} == nullptr'}} static_assert(sizeof(X().X::~X())>) == 0); // expected-error@-1{{static_assert failed due to requirement 'sizeof(X) == 0'}} - static_assert(constexpr_return_false()); - // expected-error@-1{{static_assert failed due to requirement 'constexpr_return_false()'}} + static_assert(constexpr_return_false()); + // expected-error@-1{{static_assert failed due to requirement 'constexpr_return_false()'}} } template void foo6(); // expected-note@-1{{in instantiation of function template specialization 'foo6' requested here}} + +template +void foo7() { + 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 '(const X [0]){} == nullptr'}} + static_assert(sizeof(X().X::~X()), float>) == 0); + // expected-error@-1{{static_assert failed due to requirement 'sizeof(X) == 0'}} + static_assert(constexpr_return_false()); + // expected-error@-1{{static_assert failed due to requirement 'constexpr_return_false()'}} +} +template void foo7(); +// expected-note@-1{{in instantiation of function template specialization 'foo7' requested here}} Index: test/SemaCXX/static-assert.cpp =================================================================== --- test/SemaCXX/static-assert.cpp +++ test/SemaCXX/static-assert.cpp @@ -127,7 +127,7 @@ 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"}} +// 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");