It's another fallout of the scalar-storage-order merge in the form of a tree 
checking failure in reverse_storage_order_for_component_p with UBSan.
The tree generated by UBSan is arguably invalid (it's a COMPONENT_REF of a 
REFERENCE_TYPE) but the code already works around invalid trees generated in 
Fortran (COMPONENT_REF of a VOID_TYPE) and making it more robust is trivial.

Tested on x86_64-suse-linux, applied on the mainline as obvious.


2015-11-09  Eric Botcazou  <ebotca...@adacore.com>

        PR middle-end/68259
        * tree.h (reverse_storage_order_for_component_p) <COMPONENT_REF>:
        Check that the type of the first operand is an aggregate type.


2015-11-09  Eric Botcazou  <ebotca...@adacore.com>

        * g++.dg/ubsan/pr68259.C: New test.

-- 
Eric Botcazou
Index: tree.h
===================================================================
--- tree.h	(revision 230016)
+++ tree.h	(working copy)
@@ -4387,8 +4387,9 @@ reverse_storage_order_for_component_p (t
     {
     case ARRAY_REF:
     case COMPONENT_REF:
-      /* ??? Fortran can take COMPONENT_REF of a void type.  */
-      return !VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (t, 0)))
+      /* ??? Fortran can take COMPONENT_REF of a VOID_TYPE.  */
+      /* ??? UBSan can take COMPONENT_REF of a REFERENCE_TYPE.  */
+      return AGGREGATE_TYPE_P (TREE_TYPE (TREE_OPERAND (t, 0)))
 	     && TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (TREE_OPERAND (t, 0)));
 
     case BIT_FIELD_REF:
// PR middle-end/68259

// { dg-do compile }
// { dg-options "-fsanitize=undefined -w" }

namespace std {
  template < typename _Tp > class allocator { };
    template < typename _Tp, typename _Alloc
= std::allocator < _Tp >
>class vector {
  public:
typedef _Tp value_type;
    void push_back (const value_type & __x) { }
  };
}
class Foo;
class FooBar {
public:
Foo * primitive_context;
  FooBar () { }
  FooBar (const FooBar & pnhp);
};
template < class KEY, class CONTENT > class AVLTreeNode { };
template < class KEY, class CONTENT > class FooTree final
{
  FooBar insertPrimitive ();
public:
AVLTreeNode < KEY, CONTENT > *seek_no_lock (const KEY & key) { }
  void primitive_patterns ( std::vector < FooBar > &patterns);
};
template < class KEY, class CONTENT > void FooTree < KEY,
  CONTENT >::primitive_patterns ( std::vector <FooBar > &patterns)
{
    patterns.push_back (insertPrimitive());
}
template < class KEY, class CONTENT >
FooBar FooTree < KEY, CONTENT >::insertPrimitive ()
{
  FooBar place;
  seek_no_lock (place.primitive_context);
  return place;
}
class ManuverResults { };
class opc_info_t
{
public:
FooTree < Foo *, ManuverResults > *primitivecache;
};
static void
do_optical_prox_corr_tsafe (opc_info_t * opc_info)
{
  std::vector < FooBar > patterns;
  opc_info->primitivecache->primitive_patterns (patterns);
}

Reply via email to