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