You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
#include "config.h"
#include "system.h"
tree
cp_expr_size (tree exp)
{
- if (CLASS_TYPE_P (TREE_TYPE (exp)))
+ tree type = TREE_TYPE (exp);
+
+ if (CLASS_TYPE_P (type))
{
/* The backend should not be interested in the size of an expression
of a type with both of these set; all copies of such types must go
through a constructor or assignment op. */
- gcc_assert (!TYPE_HAS_COMPLEX_INIT_REF (TREE_TYPE (exp))
- || !TYPE_HAS_COMPLEX_ASSIGN_REF (TREE_TYPE (exp))
+ gcc_assert (!TYPE_HAS_COMPLEX_INIT_REF (type)
+ || !TYPE_HAS_COMPLEX_ASSIGN_REF (type)
/* But storing a CONSTRUCTOR isn't a copy. */
- || TREE_CODE (exp) == CONSTRUCTOR);
-
+ || TREE_CODE (exp) == CONSTRUCTOR
+ /* And, the gimplifier will sometimes make a copy of
+ an aggregate. In particular, for a case like:
+
+ struct S { S(); };
+ struct X { int a; S s; };
+ X x = { 0 };
+
+ the gimplifier will create a temporary with
+ static storage duration, perform static
+ initialization of the temporary, and then copy
+ the result. Since the "s" subobject is never
+ constructed, this is a valid transformation. */
+ || CP_AGGREGATE_TYPE_P (type));
+
/* This would be wrong for a type with virtual bases, but they are
caught by the assert above. */
- return (is_empty_class (TREE_TYPE (exp))
+ return (is_empty_class (type)
? size_zero_node
- : CLASSTYPE_SIZE_UNIT (TREE_TYPE (exp)));
+ : CLASSTYPE_SIZE_UNIT (type));
}
else
/* Use the default code. */
switch (code)
{
case TINST_LEVEL: return sizeof (struct tinst_level_s);
- case PTRMEM_CST: return sizeof (struct ptrmem_cst);
+ case PTRMEM_CST: return sizeof (struct ptrmem_cst);
case BASELINK: return sizeof (struct tree_baselink);
- case TEMPLATE_PARM_INDEX: return sizeof (template_parm_index);
+ case TEMPLATE_PARM_INDEX: return sizeof (template_parm_index);
case DEFAULT_ARG: return sizeof (struct tree_default_arg);
case OVERLOAD: return sizeof (struct tree_overload);
default:
free (base);
}
+/* This compares two types for equivalence ("compatible" in C-based languages).
+ This routine should only return 1 if it is sure. It should not be used
+ in contexts where erroneously returning 0 causes problems. */
+
+int
+cxx_types_compatible_p (tree x, tree y)
+{
+ if (same_type_ignoring_top_level_qualifiers_p (x, y))
+ return 1;
+
+ /* Once we get to the middle-end, references and pointers are
+ interchangeable. FIXME should we try to replace all references with
+ pointers? */
+ if (POINTER_TYPE_P (x) && POINTER_TYPE_P (y)
+ && TYPE_MODE (x) == TYPE_MODE (y)
+ && TYPE_REF_CAN_ALIAS_ALL (x) == TYPE_REF_CAN_ALIAS_ALL (y)
+ && same_type_p (TREE_TYPE (x), TREE_TYPE (y)))
+ return 1;
+
+ return 0;
+}
+
/* Stubs to keep c-opts.c happy. */
void
push_file_scope (void)