diff --git a/src/il.c b/src/il.c index 11db2ca050..f45f06c880 100644 --- a/src/il.c +++ b/src/il.c @@ -8665,19 +8665,22 @@ are done. } /* if */ if (!identical_types_full(node1->type, node2->type, itf_options)) { eq = FALSE; - } else if ((options & CC_EXACT_EQUIVALENCE) && - (node1->extra.rescan_info != NULL) != - (node2->extra.rescan_info != NULL)) { - /* The two expressions are equivalent, but one has associated rescan - information and the other not. With the given option, the two - should not be considered equivalent because it could cause the - version with rescan information to be replaced by the other version, - thereby causing spurious rescan failures. (If the two nodes have - associated rescan information, that information can be assumed to - be equivalent since the expressions are equivalent.) */ - eq = FALSE; } /* if */ } /* if */ + if (eq && (options & CC_EXACT_EQUIVALENCE) && + (node1->extra.rescan_info != NULL) != + (node2->extra.rescan_info != NULL)) { + /* The two expressions are equivalent, but one has associated rescan + information and the other not. With the given option, the two + should not be considered equivalent because it could cause the + version with rescan information to be replaced by the other version, + thereby causing spurious rescan failures. (If the two nodes have + associated rescan information, that information can be assumed to + be equivalent since the expressions are equivalent.) This check is + done even when the type comparison is skipped (e.g., for variable + references). */ + eq = FALSE; + } /* if */ } /* if */ done: #if DEBUG diff --git a/src/pending_changes/ctad-missing-rescan-info.txt b/src/pending_changes/ctad-missing-rescan-info.txt new file mode 100644 index 0000000000..d90b834015 --- /dev/null +++ b/src/pending_changes/ctad-missing-rescan-info.txt @@ -0,0 +1,17 @@ +[GH #335] +Fix CTAD rescan info for reused specializations + +An internal error ("missing default rescan info") could occur when building +an implicit deduction guide for a constructor whose parameter type is a +class template specialization with a nontype template argument referring to +a dependent static data member, if that same specialization was already used +earlier in the class (e.g., in a member declaration). For example, with +--c++17: + + template struct P {}; + template struct A { + static constexpr bool b = sizeof(T) == 1; + P m; + A(T, P); + }; + void g() { A{char{}, {}}; } // Previously caused an internal error. diff --git a/tests/tests/regressions/.ctad-dependent-member-template-arg-reuse.rto/default.1.1.txt b/tests/tests/regressions/.ctad-dependent-member-template-arg-reuse.rto/default.1.1.txt new file mode 100644 index 0000000000..43bb995b7b --- /dev/null +++ b/tests/tests/regressions/.ctad-dependent-member-template-arg-reuse.rto/default.1.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=1 --c++17 Test_name.c diff --git a/tests/tests/regressions/ctad-dependent-member-template-arg-reuse.sft.cpp b/tests/tests/regressions/ctad-dependent-member-template-arg-reuse.sft.cpp new file mode 100644 index 0000000000..d26cab8579 --- /dev/null +++ b/tests/tests/regressions/ctad-dependent-member-template-arg-reuse.sft.cpp @@ -0,0 +1,31 @@ +//type:fp +//options_all:--c++17 + +// A class template specialization whose nontype template argument refers to +// a dependent static data member (P below) was first created by a member +// declaration and later reused for the same specialization in a constructor +// parameter type. The first argument expression lacked the information +// needed to redo semantic analysis, so building the implicit deduction guide +// for class template argument deduction caused an internal error ("missing +// default rescan info"). + +template constexpr bool f() { return true; } + +template struct P {}; + +template struct A { + static constexpr bool b = f(); + P m; + A(T, P); +}; + +template struct B { + static constexpr bool b = sizeof(T) == 1; + P m; + B(T, P); +}; + +void g() { + A{char{}, {}}; + B{char{}, {}}; +}