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

Reply via email to