summaryrefslogtreecommitdiffstats
path: root/utils
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2010-02-02 20:10:50 +0000
committerDouglas Gregor <dgregor@apple.com>2010-02-02 20:10:50 +0000
commitaa74a1e49f7c4b89539830290f76fe2c3e97187f (patch)
tree69a11738333a93c3e6520a549ac3776c2248d09f /utils
parenta78fa2c40fbbe505485e7d120dc68a292ee0c968 (diff)
Implement promotion for enumeration types.
WHAT!?! It turns out that Type::isPromotableIntegerType() was not considering enumeration types to be promotable, so we would never do the promotion despite having properly computed the promotion type when the enum was defined. Various operations on values of enum type just "worked" because we could still compute the integer rank of an enum type; the oddity, however, is that operations such as "add an enum and an unsigned" would often have an enum result type (!). The bug actually showed up as a spurious -Wformat diagnostic (<rdar://problem/7595366>), but in theory it could cause miscompiles. In this commit: - Enum types with a promotion type of "int" or "unsigned int" are promotable. - Tweaked the computation of promotable types for enums - For all of the ABIs, treat enum types the same way as their underlying types (*not* their promotion types) for argument passing and return values - Extend the ABI tester with support for enumeration types git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@95117 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'utils')
-rwxr-xr-xutils/ABITest/ABITestGen.py14
-rw-r--r--utils/ABITest/TypeGen.py83
2 files changed, 96 insertions, 1 deletions
diff --git a/utils/ABITest/ABITestGen.py b/utils/ABITest/ABITestGen.py
index a31f01043c..c45a0c3432 100755
--- a/utils/ABITest/ABITestGen.py
+++ b/utils/ABITest/ABITestGen.py
@@ -207,6 +207,9 @@ class TypePrinter:
yield '(%s) 0'%(t.name,)
yield '(%s) -1'%(t.name,)
yield '(%s) 1'%(t.name,)
+ elif isinstance(t, EnumType):
+ for i in range(0, len(t.enumerators)):
+ yield 'enum%dval%d' % (t.index, i)
elif isinstance(t, RecordType):
nonPadding = [f for f in t.fields
if not f.isPaddingBitField()]
@@ -273,6 +276,8 @@ class TypePrinter:
else:
code = 'p'
print >>output, '%*sprintf("%s: %s = %%%s\\n", %s);'%(indent, '', prefix, name, code, name)
+ elif isinstance(t, EnumType):
+ print >>output, '%*sprintf("%s: %s = %%d\\n", %s);'%(indent, '', prefix, name, name)
elif isinstance(t, RecordType):
if not t.fields:
print >>output, '%*sprintf("%s: %s (empty)\\n");'%(indent, '', prefix, name)
@@ -301,6 +306,8 @@ class TypePrinter:
output = self.output
if isinstance(t, BuiltinType):
print >>output, '%*sassert(%s == %s);' % (indent, '', nameLHS, nameRHS)
+ elif isinstance(t, EnumType):
+ print >>output, '%*sassert(%s == %s);' % (indent, '', nameLHS, nameRHS)
elif isinstance(t, RecordType):
for i,f in enumerate(t.fields):
if f.isPaddingBitField():
@@ -403,6 +410,11 @@ def main():
help="do not generate void* types",
action="store_false", default=True)
+ # Enumerations
+ group.add_option("", "--no-enums", dest="useEnum",
+ help="do not generate enum types",
+ action="store_false", default=True)
+
# Derived types
group.add_option("", "--no-array", dest="useArray",
help="do not generate record types",
@@ -530,6 +542,8 @@ def main():
vTypes.append(ArrayType(i, True, type, count * type.size))
atg.addGenerator(FixedTypeGenerator(vTypes))
+ if opts.useEnum:
+ atg.addGenerator(EnumTypeGenerator([None, '-1', '1', '1u'], 1, 4))
if opts.recordMaxDepth is None:
# Fully recursive, just avoid top-level arrays.
diff --git a/utils/ABITest/TypeGen.py b/utils/ABITest/TypeGen.py
index d5678db6a0..40ea791eb5 100644
--- a/utils/ABITest/TypeGen.py
+++ b/utils/ABITest/TypeGen.py
@@ -46,6 +46,28 @@ class BuiltinType(Type):
def __str__(self):
return self.name
+class EnumType(Type):
+ def __init__(self, index, enumerators):
+ self.index = index
+ self.enumerators = enumerators
+
+ def getEnumerators(self):
+ result = ''
+ for i, init in enumerate(self.enumerators):
+ if i > 0:
+ result = result + ', '
+ result = result + 'enum%dval%d' % (self.index, i)
+ if init:
+ result = result + ' = %s' % (init)
+
+ return result
+
+ def __str__(self):
+ return 'enum { %s }' % (self.getEnumerators())
+
+ def getTypedefDef(self, name, printer):
+ return 'typedef enum %s { %s } %s;'%(name, self.getEnumerators(), name)
+
class RecordType(Type):
def __init__(self, index, isUnion, fields):
self.index = index
@@ -188,6 +210,63 @@ class FixedTypeGenerator(TypeGenerator):
def generateType(self, N):
return self.types[N]
+# Factorial
+def fact(n):
+ result = 1
+ while n > 0:
+ result = result * n
+ n = n - 1
+ return result
+
+# Compute the number of combinations (n choose k)
+def num_combinations(n, k):
+ return fact(n) / (fact(k) * fact(n - k))
+
+# Enumerate the combinations choosing k elements from the list of values
+def combinations(values, k):
+ # From ActiveState Recipe 190465: Generator for permutations,
+ # combinations, selections of a sequence
+ if k==0: yield []
+ else:
+ for i in xrange(len(values)-k+1):
+ for cc in combinations(values[i+1:],k-1):
+ yield [values[i]]+cc
+
+class EnumTypeGenerator(TypeGenerator):
+ def __init__(self, values, minEnumerators, maxEnumerators):
+ TypeGenerator.__init__(self)
+ self.values = values
+ self.minEnumerators = minEnumerators
+ self.maxEnumerators = maxEnumerators
+ self.setCardinality()
+
+ def setCardinality(self):
+ self.cardinality = 0
+ for num in range(self.minEnumerators, self.maxEnumerators + 1):
+ self.cardinality += num_combinations(len(self.values), num)
+
+ def generateType(self, n):
+ # Figure out the number of enumerators in this type
+ numEnumerators = self.minEnumerators
+ valuesCovered = 0
+ while numEnumerators < self.maxEnumerators:
+ comb = num_combinations(len(self.values), numEnumerators)
+ if valuesCovered + comb > n:
+ break
+ numEnumerators = numEnumerators + 1
+ valuesCovered += comb
+
+ # Find the requested combination of enumerators and build a
+ # type from it.
+ i = 0
+ for enumerators in combinations(self.values, numEnumerators):
+ if i == n - valuesCovered:
+ return EnumType(n, enumerators)
+
+ i = i + 1
+
+ assert False
+
class ComplexTypeGenerator(TypeGenerator):
def __init__(self, typeGen):
TypeGenerator.__init__(self)
@@ -363,10 +442,12 @@ def test():
btg = FixedTypeGenerator([BuiltinType('char', 4),
BuiltinType('int', 4)])
-
+ etg = EnumTypeGenerator([None, '-1', '1', '1u'], 0, 3)
+
atg = AnyTypeGenerator()
atg.addGenerator( btg )
atg.addGenerator( RecordTypeGenerator(fields0, False, 4) )
+ atg.addGenerator( etg )
print 'Cardinality:',atg.cardinality
for i in range(100):
if i == atg.cardinality: