eandrews created this revision.
eandrews added reviewers: rnk, gribozavr, gribozavr2, Szelethus, erichkeane, 
riccibruno.

This patch reapplies D61027 <https://reviews.llvm.org/D61027>. When D61027 
<https://reviews.llvm.org/D61027> was previously committed (76945821b9cad3), 
buildbots failed due to clang-tidy test fails. The test fails are because some 
errors in templates are now diagnosed earlier (does not wait till 
instantiation).  I have modified the tests to add checks for these 
diagnostics/prevent these diagnostics.

Since I have not worked on clang-tidy in the past, I am hoping someone with 
more familiarity in this area can take a look and review my changes. There are 
no code changes in this second attempt (compared to D61027 
<https://reviews.llvm.org/D61027>). I have only modified failing tests.

Summary of code changes (pasted from D61027 <https://reviews.llvm.org/D61027>) 
is below -

Clang currently crashes for switch statements inside a template when the 
condition is a non-integer field member because contextual implicit conversion 
is skipped when parsing the condition. This conversion is however later checked 
in an assert when the case statement is handled. The conversion is skipped when 
parsing the condition because the field member is set as type-dependent based 
on its containing class. This patch sets the type dependency based on the 
field's type instead. This patch fixes Bug 40982.


https://reviews.llvm.org/D69950

Files:
  
clang-tools-extra/test/clang-tidy/checkers/bugprone-string-integer-assignment.cpp
  clang-tools-extra/test/clang-tidy/checkers/misc-unused-parameters.cpp
  clang/lib/AST/Expr.cpp
  clang/lib/Sema/SemaChecking.cpp
  clang/test/SemaCXX/constant-expression-cxx2a.cpp
  clang/test/SemaTemplate/dependent-names.cpp
  clang/test/SemaTemplate/enum-argument.cpp
  clang/test/SemaTemplate/member-access-expr.cpp
  clang/test/SemaTemplate/non-integral-switch-cond.cpp

Index: clang/test/SemaTemplate/non-integral-switch-cond.cpp
===================================================================
--- /dev/null
+++ clang/test/SemaTemplate/non-integral-switch-cond.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+struct NOT_AN_INTEGRAL_TYPE {};
+
+template <typename T>
+struct foo {
+  NOT_AN_INTEGRAL_TYPE Bad;
+  void run() {
+    switch (Bad) { // expected-error {{statement requires expression of integer type ('NOT_AN_INTEGRAL_TYPE' invalid)}}
+    case 0:
+      break;
+    }
+  }
+};
Index: clang/test/SemaTemplate/member-access-expr.cpp
===================================================================
--- clang/test/SemaTemplate/member-access-expr.cpp
+++ clang/test/SemaTemplate/member-access-expr.cpp
@@ -156,7 +156,7 @@
     void get(B **ptr) {
       // It's okay if at some point we figure out how to diagnose this
       // at instantiation time.
-      *ptr = field;
+      *ptr = field; // expected-error {{assigning to 'test6::B *' from incompatible type 'test6::A *}}
     }
   };
 }
Index: clang/test/SemaTemplate/enum-argument.cpp
===================================================================
--- clang/test/SemaTemplate/enum-argument.cpp
+++ clang/test/SemaTemplate/enum-argument.cpp
@@ -1,5 +1,4 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
-// expected-no-diagnostics
 
 enum Enum { val = 1 };
 template <Enum v> struct C {
@@ -31,7 +30,7 @@
     unsigned long long bitfield : e0;
 
     void f(int j) {
-      bitfield + j;
+      bitfield + j; // expected-warning {{expression result unused}}
     }
   };
 }
Index: clang/test/SemaTemplate/dependent-names.cpp
===================================================================
--- clang/test/SemaTemplate/dependent-names.cpp
+++ clang/test/SemaTemplate/dependent-names.cpp
@@ -273,9 +273,6 @@
       }
       int e[10];
     };
-    void g() {
-      S<int>().f(); // expected-note {{here}}
-    }
   }
 
   namespace A2 {
Index: clang/test/SemaCXX/constant-expression-cxx2a.cpp
===================================================================
--- clang/test/SemaCXX/constant-expression-cxx2a.cpp
+++ clang/test/SemaCXX/constant-expression-cxx2a.cpp
@@ -18,6 +18,7 @@
 [[nodiscard]] void *operator new(std::size_t, std::align_val_t, const std::nothrow_t&) noexcept;
 [[nodiscard]] void *operator new[](std::size_t, const std::nothrow_t&) noexcept;
 [[nodiscard]] void *operator new[](std::size_t, std::align_val_t, const std::nothrow_t&) noexcept;
+[[nodiscard]] void *operator new[](std::size_t, std::align_val_t);
 void operator delete(void*, const std::nothrow_t&) noexcept;
 void operator delete(void*, std::align_val_t, const std::nothrow_t&) noexcept;
 void operator delete[](void*, const std::nothrow_t&) noexcept;
@@ -1050,7 +1051,7 @@
     // Ensure that we don't try to evaluate these for overflow and crash. These
     // are all value-dependent expressions.
     p = new char[n];
-    p = new (n) char[n];
+    p = new ((std::align_val_t)n) char[n];
     p = new char(n);
   }
 }
Index: clang/lib/Sema/SemaChecking.cpp
===================================================================
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -14682,6 +14682,8 @@
   bool AnyIsPacked = false;
   do {
     QualType BaseType = ME->getBase()->getType();
+    if (BaseType->isDependentType())
+      return;
     if (ME->isArrow())
       BaseType = BaseType->getPointeeType();
     RecordDecl *RD = BaseType->castAs<RecordType>()->getDecl();
Index: clang/lib/AST/Expr.cpp
===================================================================
--- clang/lib/AST/Expr.cpp
+++ clang/lib/AST/Expr.cpp
@@ -1675,6 +1675,15 @@
   MemberExpr *E = new (Mem) MemberExpr(Base, IsArrow, OperatorLoc, MemberDecl,
                                        NameInfo, T, VK, OK, NOUR);
 
+  if (FieldDecl *Field = dyn_cast<FieldDecl>(MemberDecl)) {
+    DeclContext *DC = MemberDecl->getDeclContext();
+    // dyn_cast_or_null is used to handle objC variables which do not
+    // have a declaration context.
+    CXXRecordDecl *RD = dyn_cast_or_null<CXXRecordDecl>(DC);
+    if (RD && RD->isDependentContext() && RD->isCurrentInstantiation(DC))
+      E->setTypeDependent(T->isDependentType());
+  }
+
   if (HasQualOrFound) {
     // FIXME: Wrong. We should be looking at the member declaration we found.
     if (QualifierLoc && QualifierLoc.getNestedNameSpecifier()->isDependent()) {
Index: clang-tools-extra/test/clang-tidy/checkers/misc-unused-parameters.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/misc-unused-parameters.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/misc-unused-parameters.cpp
@@ -233,7 +233,7 @@
 template <class>
 class d {
   a e;
-  void f() { e.b(); }
+  void f() { e.b(0); }
 };
 }  // namespace
 }  // namespace PR38055
Index: clang-tools-extra/test/clang-tidy/checkers/bugprone-string-integer-assignment.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/bugprone-string-integer-assignment.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/bugprone-string-integer-assignment.cpp
@@ -103,6 +103,8 @@
   static constexpr T t = 0x8000;
   std::string s;
   void f(char c) { s += c | static_cast<int>(t); }
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: an integer is interpreted as a chara
+  // CHECK-FIXES: {{^}}  void f(char c) { s += std::to_string(c | static_cast<int>(t)); } 
 };
 
 template S<int>;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to