This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C++ PATCH for c++/42013 (decltype of ?: of calls)


Like c++/36628, this is a case where folding a ?: of two calls produces a CALL_EXPR, so decltype handling mistakenly does its special call thing. It occurs to me that within decltype the folding doesn't really do us any good, so rather than try to wrap the folded result to hide the call from decltype we could just use the unfolded version.

Tested x86_64-pc-linux-gnu, applied to trunk.
2009-11-12  Jason Merrill  <jason@redhat.com>

	PR c++/42013
	* call.c (build_conditional_expr): Avoid folding to a CALL_EXPR
	within decltype.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index db609f8..e4a6bca 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -3605,6 +3605,7 @@ build_conditional_expr (tree arg1, tree arg2, tree arg3,
   tree arg2_type;
   tree arg3_type;
   tree result = NULL_TREE;
+  tree result_save;
   tree result_type = NULL_TREE;
   bool lvalue_p = true;
   struct z_candidate *candidates = 0;
@@ -3991,8 +3992,13 @@ build_conditional_expr (tree arg1, tree arg2, tree arg3,
     }
 
  valid_operands:
-  result = fold_if_not_in_template (build3 (COND_EXPR, result_type, arg1,
-					    arg2, arg3));
+  result_save = build3 (COND_EXPR, result_type, arg1, arg2, arg3);
+  result = fold_if_not_in_template (result_save);
+
+  if (cp_unevaluated_operand && TREE_CODE (result) == CALL_EXPR)
+    /* Avoid folding to a CALL_EXPR within decltype (c++/42013).  */
+    result = result_save;
+
   /* We can't use result_type below, as fold might have returned a
      throw_expr.  */
 
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype19.C b/gcc/testsuite/g++.dg/cpp0x/decltype19.C
new file mode 100644
index 0000000..41d602f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype19.C
@@ -0,0 +1,24 @@
+// PR c++/42013
+
+template<typename _Tp>
+  _Tp
+__attribute ((const)) declval();
+
+template<typename _Tp, typename _Up>
+  struct common_type
+  {
+    typedef __decltype(true  ? declval<_Tp>() : declval<_Up>()) typet;
+    typedef __decltype(false ? declval<_Tp>() : declval<_Up>()) typef;
+  };
+
+template<typename, typename> struct is_same;
+
+template<typename _Tp> struct is_same<_Tp, _Tp> { typedef _Tp type; };
+
+void f()
+{
+  typedef common_type<int, const int>::typet typet;
+  typedef common_type<int, const int>::typef typef;
+
+  typedef is_same<typet, typef>::type type;
+}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]