eandrews created this revision.
eandrews added reviewers: rnk, erichkeane.

Clang currently crashes for switch statements inside a template when the 
condition is non-integer and instantiation dependent. This is because 
contextual implicit conversion is skipped while acting on switch condition but 
this conversion is checked in an assert when acting on case statement.

This patch delays checks for dependent expressions till instantiation. Behavior 
now matches GCC.

Patch fixes Bug 40982.


https://reviews.llvm.org/D61023

Files:
  lib/Sema/SemaStmt.cpp
  test/SemaTemplate/non-integral-switch-cond.cpp


Index: test/SemaTemplate/non-integral-switch-cond.cpp
===================================================================
--- /dev/null
+++ test/SemaTemplate/non-integral-switch-cond.cpp
@@ -0,0 +1,19 @@
+// 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;
+    }
+  }
+};
+
+int main() {
+  foo<int> instance;
+  instance.run(); // expected-note {{in instantiation of member function 
'foo<int>::run' requested here}}
+}
Index: lib/Sema/SemaStmt.cpp
===================================================================
--- lib/Sema/SemaStmt.cpp
+++ lib/Sema/SemaStmt.cpp
@@ -404,7 +404,8 @@
     QualType CondType = CondExpr->getType();
 
     auto CheckAndFinish = [&](Expr *E) {
-      if (CondType->isDependentType() || E->isTypeDependent())
+      if (CondType->isDependentType() || CondExpr->isInstantiationDependent() 
||
+          E->isTypeDependent())
         return ExprResult(E);
 
       if (getLangOpts().CPlusPlus11) {
@@ -695,7 +696,8 @@
   Expr *CondExpr = Cond.get().second;
   assert((Cond.isInvalid() || CondExpr) && "switch with no condition");
 
-  if (CondExpr && !CondExpr->isTypeDependent()) {
+  if (CondExpr && !CondExpr->isTypeDependent() &&
+      !CondExpr->isInstantiationDependent()) {
     // We have already converted the expression to an integral or enumeration
     // type, when we parsed the switch condition. If we don't have an
     // appropriate type now, enter the switch scope but remember that it's


Index: test/SemaTemplate/non-integral-switch-cond.cpp
===================================================================
--- /dev/null
+++ test/SemaTemplate/non-integral-switch-cond.cpp
@@ -0,0 +1,19 @@
+// 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;
+    }
+  }
+};
+
+int main() {
+  foo<int> instance;
+  instance.run(); // expected-note {{in instantiation of member function 'foo<int>::run' requested here}}
+}
Index: lib/Sema/SemaStmt.cpp
===================================================================
--- lib/Sema/SemaStmt.cpp
+++ lib/Sema/SemaStmt.cpp
@@ -404,7 +404,8 @@
     QualType CondType = CondExpr->getType();
 
     auto CheckAndFinish = [&](Expr *E) {
-      if (CondType->isDependentType() || E->isTypeDependent())
+      if (CondType->isDependentType() || CondExpr->isInstantiationDependent() ||
+          E->isTypeDependent())
         return ExprResult(E);
 
       if (getLangOpts().CPlusPlus11) {
@@ -695,7 +696,8 @@
   Expr *CondExpr = Cond.get().second;
   assert((Cond.isInvalid() || CondExpr) && "switch with no condition");
 
-  if (CondExpr && !CondExpr->isTypeDependent()) {
+  if (CondExpr && !CondExpr->isTypeDependent() &&
+      !CondExpr->isInstantiationDependent()) {
     // We have already converted the expression to an integral or enumeration
     // type, when we parsed the switch condition. If we don't have an
     // appropriate type now, enter the switch scope but remember that it's
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to