Correctly handle discrepancy between formal and actual parameters.
authorJustin Seyster <jseyster@cs.sunysb.edu>
Tue, 24 Aug 2010 20:04:27 +0000 (16:04 -0400)
committerJustin Seyster <jseyster@cs.sunysb.edu>
Tue, 24 Aug 2010 20:04:27 +0000 (16:04 -0400)
A long comment in the commit describes the problem in (excruciating)
detail.

src/aop-type.c

index f0b4aefd9ebe7316e38591d6fe14069173ce4d84..bf70f32a0c15638f89fda3b1313dcfbf0b90a2a8 100644 (file)
@@ -57,12 +57,50 @@ static struct aop_type _aop_t_all_pointer = {
   .tag = NULL,
 };
 
+/**
+ * Return a type that will match any standard-sized signed integer
+ * type.
+ *
+ * Standard integer sizes are 1, 2, 4, and 8 bytes.  This type will
+ * not match 16-byte or larger integer types.
+ *
+ * When passing an aop_t_all_signed() value to an advice function (via
+ * aop_insert_advice()) the value is automatically cast to the
+ * (long long int) type, which is guaranteed by the C standard to
+ * be large enough to hold any standard-sized integer.
+ *
+ * Be careful: (long long int) is larger than (int) on most platforms.
+ * We recommend defining advice functions using the ALL_SIGNED_T macro
+ * to avoid confusion.
+ *
+ * \return A type that will match any standard-sized signed integer
+ * type.
+ */
 const struct aop_type *
 aop_t_all_signed ()
 {
   return &_aop_t_all_signed;
 }
 
+/**
+ * Return a type that will match any standard-sized unsigned integer
+ * type.
+ *
+ * Standard integer sizes are 1, 2, 4, and 8 bytes.  This type will
+ * not match 16-byte or larger integer types.
+ *
+ * When passing an aop_t_all_unsigned() value to an advice function
+ * (via aop_insert_advice()) the value is automatically cast to the
+ * (long long unsigned) type, which is guaranteed by the C standard to
+ * be large enough to hold any standard-sized integer.
+ *
+ * Be careful: (long long unsigned) is larger than unsigned (int) on
+ * most platforms.  We recommend defining advice functions using the
+ * ALL_UNSIGNED_T macro to avoid confusion.
+ *
+ * \return A type that will match any standard-sized unsigned integer
+ * type.
+ */
 const struct aop_type *
 aop_t_all_unsigned ()
 {
@@ -81,6 +119,22 @@ aop_t_all_pointer ()
   return &_aop_t_all_pointer;
 }
 
+/* True if this is an integer type (signed or unsigned) between int8
+   and int64. */
+static bool
+is_stdint_type (tree gcc_type)
+{
+  if (TREE_CODE (gcc_type) == INTEGER_TYPE)
+    {
+      HOST_WIDE_INT size = int_size_in_bytes (gcc_type);
+      return (size > 0 && size <= 8);
+    }
+  else
+    {
+      return false;
+    }
+}
+
 /* Match an actual GCC type with an AOP type specification. */
 bool
 does_type_match (tree gcc_type, const struct aop_type *aop_type)
@@ -96,11 +150,9 @@ does_type_match (tree gcc_type, const struct aop_type *aop_type)
       switch (aop_type->kind)
        {
        case ATK_ALL_SIGNED:
-         return (TREE_CODE (gcc_type) == INTEGER_TYPE
-                 && !TYPE_UNSIGNED (gcc_type));
+         return (is_stdint_type (gcc_type) && !TYPE_UNSIGNED (gcc_type));
        case ATK_ALL_UNSIGNED:
-         return (TREE_CODE (gcc_type) == INTEGER_TYPE
-                 && TYPE_UNSIGNED (gcc_type));
+         return (is_stdint_type (gcc_type) && TYPE_UNSIGNED (gcc_type));
        case ATK_ALL_FP:
          return (TREE_CODE (gcc_type) == REAL_TYPE);
        default: