r349729 - [Sema] Better static assert diagnostics for expressions involving temporaries/casts/....

Clement Courbet via cfe-commits cfe-commits at lists.llvm.org
Thu Dec 20 01:05:15 PST 2018


Author: courbet
Date: Thu Dec 20 01:05:15 2018
New Revision: 349729

URL: http://llvm.org/viewvc/llvm-project?rev=349729&view=rev
Log:
[Sema] Better static assert diagnostics for expressions involving temporaries/casts/....

Summary:
Handles expressions such as:
 - `std::is_const<T>()`
 - `std::is_const<T>()()`;
 - `std::is_same(decltype(U()), V>::value`;

Reviewers: aaron.ballman, Quuxplusone

Subscribers: cfe-commits, llvm-commits

Differential Revision: https://reviews.llvm.org/D55552

Modified:
    cfe/trunk/include/clang/AST/PrettyPrinter.h
    cfe/trunk/include/clang/AST/Type.h
    cfe/trunk/lib/AST/TypePrinter.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/test/SemaCXX/static-assert-cxx17.cpp
    cfe/trunk/test/SemaCXX/static-assert.cpp

Modified: cfe/trunk/include/clang/AST/PrettyPrinter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/PrettyPrinter.h?rev=349729&r1=349728&r2=349729&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/PrettyPrinter.h (original)
+++ cfe/trunk/include/clang/AST/PrettyPrinter.h Thu Dec 20 01:05:15 2018
@@ -51,7 +51,7 @@ struct PrintingPolicy {
         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 @@ struct PrintingPolicy {
   /// 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<std::string(StringRef)> remapPath;
 };

Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=349729&r1=349728&r2=349729&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Thu Dec 20 01:05:15 2018
@@ -980,9 +980,7 @@ public:
 
   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 @@ public:
                     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) {

Modified: cfe/trunk/lib/AST/TypePrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TypePrinter.cpp?rev=349729&r1=349728&r2=349729&view=diff
==============================================================================
--- cfe/trunk/lib/AST/TypePrinter.cpp (original)
+++ cfe/trunk/lib/AST/TypePrinter.cpp Thu Dec 20 01:05:15 2018
@@ -117,9 +117,7 @@ namespace {
     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 @@ namespace {
     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 @@ void TypePrinter::spaceBeforePlaceHolder
     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 @@ bool TypePrinter::canPrefixQualifiers(co
 }
 
 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::printBefore(const Type
 }
 
 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 @@ std::string QualType::getAsString(const
   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 @@ void QualType::print(const Type *ty, Qua
   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) {

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=349729&r1=349728&r2=349729&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Thu Dec 20 01:05:15 2018
@@ -3122,8 +3122,10 @@ Sema::findFailedBooleanCondition(Expr *C
   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 };
 }

Modified: cfe/trunk/test/SemaCXX/static-assert-cxx17.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/static-assert-cxx17.cpp?rev=349729&r1=349728&r2=349729&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/static-assert-cxx17.cpp (original)
+++ cfe/trunk/test/SemaCXX/static-assert-cxx17.cpp Thu Dec 20 01:05:15 2018
@@ -54,3 +54,44 @@ void foo5() {
 }
 template void foo5<int, float>();
 // expected-note at -1{{in instantiation of function template specialization 'foo5<int, float>' requested here}}
+
+struct ExampleTypes {
+  explicit ExampleTypes(int);
+  using T = int;
+  using U = float;
+};
+
+template <class T>
+struct X {
+  int i = 0;
+  int j = 0;
+  constexpr operator bool() const { return false; }
+};
+
+template <class T>
+void foo6() {
+  static_assert(X<typename T::T>());
+  // expected-error at -1{{static_assert failed due to requirement 'X<int>()'}}
+  static_assert(X<typename T::T>{});
+  // expected-error at -1{{static_assert failed due to requirement 'X<int>{}'}}
+  static_assert(X<typename T::T>{1, 2});
+  // expected-error at -1{{static_assert failed due to requirement 'X<int>{1, 2}'}}
+  static_assert(X<typename T::T>({1, 2}));
+  // expected-error at -1{{static_assert failed due to requirement 'X<int>({1, 2})'}}
+  static_assert(typename T::T{0});
+  // expected-error at -1{{static_assert failed due to requirement 'int{0}'}}
+  static_assert(typename T::T(0));
+  // expected-error at -1{{static_assert failed due to requirement 'int(0)'}}
+  static_assert(sizeof(X<typename T::T>) == 0);
+  // expected-error at -1{{static_assert failed due to requirement 'sizeof(X<int>) == 0'}}
+  static_assert((const X<typename T::T> *)nullptr);
+  // expected-error at -1{{static_assert failed due to requirement '(const X<int> *)nullptr'}}
+  static_assert(static_cast<const X<typename T::T> *>(nullptr));
+  // expected-error at -1{{static_assert failed due to requirement 'static_cast<const X<int> *>(nullptr)'}}
+  static_assert((const X<typename T::T>[]){} == nullptr);
+  // expected-error at -1{{static_assert failed due to requirement '(X<int> const[0]){} == nullptr'}}
+  static_assert(sizeof(X<decltype(X<typename T::T>().X<typename T::T>::~X())>) == 0);
+  // expected-error at -1{{static_assert failed due to requirement 'sizeof(X<void>) == 0'}}
+}
+template void foo6<ExampleTypes>();
+// expected-note at -1{{in instantiation of function template specialization 'foo6<ExampleTypes>' requested here}}

Modified: cfe/trunk/test/SemaCXX/static-assert.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/static-assert.cpp?rev=349729&r1=349728&r2=349729&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/static-assert.cpp (original)
+++ cfe/trunk/test/SemaCXX/static-assert.cpp Thu Dec 20 01:05:15 2018
@@ -76,6 +76,8 @@ struct integral_constant {
   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 <class Tp, Tp v>
@@ -103,6 +105,7 @@ struct is_same<T, T> {
 } // namespace std
 
 struct ExampleTypes {
+  explicit ExampleTypes(int);
   using T = int;
   using U = float;
 };
@@ -119,6 +122,18 @@ static_assert(std::is_const<const Exampl
 // expected-error at -1{{static_assert failed due to requirement 'std::is_const<const int>::value == false' "message"}}
 static_assert(!(std::is_const<const ExampleTypes::T>::value == true), "message");
 // expected-error at -1{{static_assert failed due to requirement '!(std::is_const<const int>::value == true)' "message"}}
+static_assert(std::is_const<ExampleTypes::T>(), "message");
+// expected-error at -1{{static_assert failed due to requirement 'std::is_const<int>()' "message"}}
+static_assert(!(std::is_const<const ExampleTypes::T>()()), "message");
+// expected-error at -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 at -1{{static_assert failed due to requirement 'std::is_same<std::is_const<const int>, int>::value' "message"}}
+static_assert(std::is_const<decltype(ExampleTypes::T(3))>::value, "message");
+// expected-error at -1{{static_assert failed due to requirement 'std::is_const<int>::value' "message"}}
+static_assert(std::is_const<decltype(ExampleTypes::T())>::value, "message");
+// expected-error at -1{{static_assert failed due to requirement 'std::is_const<int>::value' "message"}}
+static_assert(std::is_const<decltype(ExampleTypes(3))>::value, "message");
+// expected-error at -1{{static_assert failed due to requirement 'std::is_const<ExampleTypes>::value' "message"}}
 
 struct BI_tag {};
 struct RAI_tag : BI_tag {};




More information about the cfe-commits mailing list