courbet created this revision. courbet added reviewers: aaron.ballman, Quuxplusone.
As a followup to D55270 <https://reviews.llvm.org/D55270>. Repository: rC Clang https://reviews.llvm.org/D55933 Files: include/clang/AST/NestedNameSpecifier.h lib/AST/NestedNameSpecifier.cpp lib/AST/TypePrinter.cpp lib/Sema/SemaTemplate.cpp test/SemaCXX/static-assert-cxx17.cpp test/SemaCXX/static-assert.cpp
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<const ExampleTypes::T>()()), "message"); // expected-error@-1{{static_assert failed due to requirement '!(std::is_const<const int>()())' "message"}} static_assert(std::is_same<decltype(std::is_const<const ExampleTypes::T>()), int>::value, "message"); -// expected-error@-1{{static_assert failed due to requirement 'std::is_same<std::is_const<const int>, int>::value' "message"}} +// expected-error@-1{{static_assert failed due to requirement 'std::is_same<is_const<const int>, int>::value' "message"}} static_assert(std::is_const<decltype(ExampleTypes::T(3))>::value, "message"); // expected-error@-1{{static_assert failed due to requirement 'std::is_const<int>::value' "message"}} static_assert(std::is_const<decltype(ExampleTypes::T())>::value, "message"); 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 <typename U, typename V> +template <typename U, typename V = U> struct S1 { static constexpr const bool value = false; }; @@ -14,7 +14,7 @@ static inline constexpr bool var = global_inline_var<U, V>; }; -template <typename U, typename V> +template <typename U, typename V = double> inline constexpr bool constexpr_return_false() { return false; } @@ -23,6 +23,8 @@ void foo() { static_assert(S1<U, V>::value); // expected-error@-1{{static_assert failed due to requirement 'S1<int, float>::value'}} + static_assert(S1<U>::value); + // expected-error@-1{{static_assert failed due to requirement 'S1<int>::value'}} } template void foo<int, float>(); // expected-note@-1{{in instantiation of function template specialization 'foo<int, float>' requested here}} @@ -66,7 +68,7 @@ using U = float; }; -template <class T> +template <class T, class U = double> struct X { int i = 0; int j = 0; @@ -94,11 +96,41 @@ static_assert(static_cast<const X<typename T::T> *>(nullptr)); // expected-error@-1{{static_assert failed due to requirement 'static_cast<const X<int> *>(nullptr)'}} static_assert((const X<typename T::T>[]){} == nullptr); - // expected-error@-1{{static_assert failed due to requirement '(X<int> const[0]){} == nullptr'}} + // expected-error@-1{{static_assert failed due to requirement '(const X<int> [0]){} == nullptr'}} static_assert(sizeof(X<decltype(X<typename T::T>().X<typename T::T>::~X())>) == 0); // expected-error@-1{{static_assert failed due to requirement 'sizeof(X<void>) == 0'}} - static_assert(constexpr_return_false<typename T::T, typename T::U>()); - // expected-error@-1{{static_assert failed due to requirement 'constexpr_return_false<int, float>()'}} + static_assert(constexpr_return_false<typename T::T>()); + // expected-error@-1{{static_assert failed due to requirement 'constexpr_return_false<int>()'}} } template void foo6<ExampleTypes>(); // expected-note@-1{{in instantiation of function template specialization 'foo6<ExampleTypes>' requested here}} + +template <class T, class U> +void foo7() { + static_assert(X<typename T::T, U>()); + // expected-error@-1{{static_assert failed due to requirement 'X<int, float>()'}} + static_assert(X<typename T::T, U>{}); + // expected-error@-1{{static_assert failed due to requirement 'X<int, float>{}'}} + static_assert(X<typename T::T, U>{1, 2}); + // expected-error@-1{{static_assert failed due to requirement 'X<int, float>{1, 2}'}} + static_assert(X<typename T::T, U>({1, 2})); + // expected-error@-1{{static_assert failed due to requirement 'X<int, float>({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<typename T::T, U>) == 0); + // expected-error@-1{{static_assert failed due to requirement 'sizeof(X<int, float>) == 0'}} + static_assert((const X<typename T::T, U> *)nullptr); + // expected-error@-1{{static_assert failed due to requirement '(const X<int, float> *)nullptr'}} + static_assert(static_cast<const X<typename T::T, U> *>(nullptr)); + // expected-error@-1{{static_assert failed due to requirement 'static_cast<const X<int, float> *>(nullptr)'}} + static_assert((const X<typename T::T, U>[]){} == nullptr); + // expected-error@-1{{static_assert failed due to requirement '(const X<int, float> [0]){} == nullptr'}} + static_assert(sizeof(X<decltype(X<typename T::T, U>().X<typename T::T, U>::~X()), float>) == 0); + // expected-error@-1{{static_assert failed due to requirement 'sizeof(X<void, float>) == 0'}} + static_assert(constexpr_return_false<typename T::T, typename T::U>()); + // expected-error@-1{{static_assert failed due to requirement 'constexpr_return_false<int, float>()'}} +} +template void foo7<ExampleTypes, float>(); +// expected-note@-1{{in instantiation of function template specialization 'foo7<ExampleTypes, float>' requested here}} 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<DeclRefExpr>(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<VarTemplateSpecializationDecl>(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<Expr *, std::string> 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: 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/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<ClassTemplateSpecializationDecl>(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: 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<int, MyClass>` instead of - /// `ns::SomeTemplate<Container::value_type, T>`. - 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());
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits