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
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits