diff mbox

Fix PR c++/69091 (ICE with operator overload having 'auto' return type)

Message ID 1452882474-6012-1-git-send-email-patrick@parcs.ath.cx
State New
Headers show

Commit Message

Patrick Palka Jan. 15, 2016, 6:27 p.m. UTC
The crux of the problem in this PR is that type_dependent_expression_p
returns true for a FUNCTION_DECL that is not actually type-dependent.
This leads tsubst_decl to attempt to perform template argument
substitution on the template arguments of the FUNCTION_DECL, which
do not necessarily correspond with the current template arguments.

In the test case provided in the PR, the FUNCTION_DECL in question
(which is used in a CALL_EXPR built by build_min_non_dep_op_overload
during processing of the template function f()) is the following:

 <function_decl 0x7ffff6a0d700 operator|
    type <function_type 0x7ffff6a0c738
        type <template_type_parm 0x7ffff6a0c690 auto type_0 type_6 VOID
            align 8 symtab 0 alias set -1 canonical type 0x7ffff6a0c690
           index 0 level 1 orig_level 2
            chain <type_decl 0x7ffff69f1e40 auto>>
        QI
        size <integer_cst 0x7ffff6898f48 constant 8>
        unit size <integer_cst 0x7ffff6898f60 constant 1>
        align 8 symtab 0 alias set -1 canonical type 0x7ffff6a0c738
        arg-types <tree_list 0x7ffff6a09898 value <record_type 0x7ffff69f0b28 Option>
            chain <tree_list 0x7ffff6a09820 value <record_type 0x7ffff6a08888 Option>
                chain <tree_list 0x7ffff68acc80 value <void_type 0x7ffff68be150 void>>>>
        pointer_to_this <pointer_type 0x7ffff6a0c7e0>>
    addressable public external QI file /home/patrick/code/gcc/gcc/testsuite/g++.dg/template/pr69091.C line 8 col 6 align 8 context <translation_unit_decl 0x7ffff68a4168 D.1>
    full-name "auto operator|(Option<ValueType, Value>, OptionsRhs) [with ValueType = canine_t; ValueType Value = (canine_t)0u; OptionsRhs = Option<canine_t, (canine_t)1u>]"
    template-info 0x7ffff69ffcc0>

type_dependent_expression_p returns true for this FUNCTION_DECL because
its TREE_TYPE is 'auto'.

Direct calls to operator| do not have this problem because in such a
case the CALL_EXPR_FN of the CALL_EXPR that's built is an OVERLOAD (to a
TEMPLATE_DECL), which tsubst does not touch.

This patch makes it so that type_dependent_expression_p considers a
FUNCTION_DECL with template info to be type-dependent if and only if any
of its template arguments are dependent, similar to how C++14 variable
templates are handled.  Thus for the above FUNCTION_DECL we would return
false because all of its template arguments are non-dependent:

 <tree_vec 0x7ffff6897c00 length 3
    elt 0 <enumeral_type 0x7ffff69f09d8 canine_t
        ...>
    elt 1 <integer_cst 0x7ffff69fdee8 type <enumeral_type 0x7ffff69f09d8 canine_t> constant 0>
    elt 2 <record_type 0x7ffff6a08888 Option type_5 type_6 QI
        ...>>

Bootstrapped and regtested on x86_64-pc-linux-gnu with no new
regressions, and also tested against Boost.  Is this change OK?

gcc/cp/ChangeLog:

	PR c++/69091
	* pt.c (type_dependent_expression_p): For a function template
	specialization, a type is dependent iff any of its template
	arguments are.

gcc/testsuite/ChangeLog:

	PR c++/69091
	* g++.dg/template/pr69091.C: New test.
---
 gcc/cp/pt.c                             |  8 ++++----
 gcc/testsuite/g++.dg/template/pr69091.C | 25 +++++++++++++++++++++++++
 2 files changed, 29 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/template/pr69091.C

Comments

Jason Merrill Jan. 15, 2016, 8:51 p.m. UTC | #1
OK.

Jason
diff mbox

Patch

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index edec774..403c5ac 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -22759,12 +22759,12 @@  type_dependent_expression_p (tree expression)
 	      || dependent_scope_p (scope));
     }
 
+  /* A function template specialization is type-dependent if it has any
+     dependent template arguments.  */
   if (TREE_CODE (expression) == FUNCTION_DECL
       && DECL_LANG_SPECIFIC (expression)
-      && DECL_TEMPLATE_INFO (expression)
-      && (any_dependent_template_arguments_p
-	  (INNERMOST_TEMPLATE_ARGS (DECL_TI_ARGS (expression)))))
-    return true;
+      && DECL_TEMPLATE_INFO (expression))
+    return any_dependent_template_arguments_p (DECL_TI_ARGS (expression));
 
   if (TREE_CODE (expression) == TEMPLATE_DECL
       && !DECL_TEMPLATE_TEMPLATE_PARM_P (expression))
diff --git a/gcc/testsuite/g++.dg/template/pr69091.C b/gcc/testsuite/g++.dg/template/pr69091.C
new file mode 100644
index 0000000..ec7bb25
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/pr69091.C
@@ -0,0 +1,25 @@ 
+// PR c++/69091
+// { dg-do compile { target c++14 } }
+
+template <class ValueType, ValueType>
+struct Option {};
+
+template <class ValueType, ValueType Value, class OptionsRhs>
+auto operator|(Option<ValueType, Value>, OptionsRhs) {
+  return Value;
+}
+
+enum canine_t { no, yes };
+Option<canine_t, no> cat;
+Option<canine_t, yes> dog;
+
+template <class T>
+void f(T) {
+  cat | dog;
+}
+
+struct A {};
+int main() {
+  f(A{});
+  return 0;
+}