@@ -103,22 +103,29 @@ public static Enumeration GetEnumWithMatchingItem(this ASTContext context, strin
103
103
/// as well as all previously discovered <see cref="Enumeration.Items"/>. The intent is to
104
104
/// preserve sign information about the values held in <paramref name="enum"/>.
105
105
/// </remarks>
106
- public static Enumeration . Item GenerateEnumItemFromMacro ( this Enumeration @enum ,
107
- MacroDefinition macro )
106
+ public static bool TryGenerateEnumItemFromMacro ( this Enumeration @enum ,
107
+ MacroDefinition macro , out Enumeration . Item item )
108
108
{
109
- var ( value , type ) = ParseEnumItemMacroExpression ( macro , @enum ) ;
109
+ if ( ! TryParseEnumItemMacroExpression ( macro , @enum , out var result ) )
110
+ {
111
+ item = null ;
112
+ return false ;
113
+ }
114
+
115
+ var ( value , type ) = result ;
110
116
if ( type > @enum . BuiltinType . Type )
111
117
{
112
118
@enum . BuiltinType = new BuiltinType ( type ) ;
113
119
@enum . Type = @enum . BuiltinType ;
114
120
}
115
- return new Enumeration . Item
121
+ item = new Enumeration . Item
116
122
{
117
123
Name = macro . Name ,
118
124
Expression = macro . Expression ,
119
125
Value = value ,
120
126
Namespace = @enum
121
127
} ;
128
+ return true ;
122
129
}
123
130
124
131
static object EvaluateEnumExpression ( string expr , Enumeration @enum )
@@ -154,7 +161,7 @@ static object EvaluateEnumExpression(string expr, Enumeration @enum)
154
161
/// evaluator biases towards returning <see cref="int"/> values: it doesn't attempt to
155
162
/// discover that a value could be stored in a <see cref="byte"/>.
156
163
/// </returns>
157
- static ( ulong value , PrimitiveType type ) ParseEnumItemMacroExpression ( MacroDefinition macro , Enumeration @enum )
164
+ static bool TryParseEnumItemMacroExpression ( MacroDefinition macro , Enumeration @enum , out ( ulong value , PrimitiveType type ) item )
158
165
{
159
166
var expression = macro . Expression ;
160
167
@@ -171,38 +178,40 @@ static object EvaluateEnumExpression(string expr, Enumeration @enum)
171
178
// Verify we have some sort of integer type. Enums can have negative values: record
172
179
// that fact so that we can set the underlying primitive type correctly in the enum
173
180
// item.
174
- switch ( System . Type . GetTypeCode ( eval . GetType ( ) ) )
181
+ item = System . Type . GetTypeCode ( eval . GetType ( ) ) switch
175
182
{
176
183
// Must unbox eval which is typed as object to be able to cast it to a ulong.
177
- case TypeCode . SByte : return ( ( ulong ) ( sbyte ) eval , PrimitiveType . SChar ) ;
178
- case TypeCode . Int16 : return ( ( ulong ) ( short ) eval , PrimitiveType . Short ) ;
179
- case TypeCode . Int32 : return ( ( ulong ) ( int ) eval , PrimitiveType . Int ) ;
180
- case TypeCode . Int64 : return ( ( ulong ) ( long ) eval , PrimitiveType . LongLong ) ;
184
+ TypeCode . SByte => ( ( ulong ) ( sbyte ) eval , PrimitiveType . SChar ) ,
185
+ TypeCode . Int16 => ( ( ulong ) ( short ) eval , PrimitiveType . Short ) ,
186
+ TypeCode . Int32 => ( ( ulong ) ( int ) eval , PrimitiveType . Int ) ,
187
+ TypeCode . Int64 => ( ( ulong ) ( long ) eval , PrimitiveType . LongLong ) ,
181
188
182
- case TypeCode . Byte : return ( ( byte ) eval , PrimitiveType . UChar ) ;
183
- case TypeCode . UInt16 : return ( ( ushort ) eval , PrimitiveType . UShort ) ;
184
- case TypeCode . UInt32 : return ( ( uint ) eval , PrimitiveType . UInt ) ;
185
- case TypeCode . UInt64 : return ( ( ulong ) eval , PrimitiveType . ULongLong ) ;
189
+ TypeCode . Byte => ( ( byte ) eval , PrimitiveType . UChar ) ,
190
+ TypeCode . UInt16 => ( ( ushort ) eval , PrimitiveType . UShort ) ,
191
+ TypeCode . UInt32 => ( ( uint ) eval , PrimitiveType . UInt ) ,
192
+ TypeCode . UInt64 => ( ( ulong ) eval , PrimitiveType . ULongLong ) ,
186
193
187
- case TypeCode . Char : return ( ( char ) eval , PrimitiveType . UShort ) ;
194
+ TypeCode . Char => ( ( char ) eval , PrimitiveType . UShort ) ,
188
195
// C++ allows booleans as enum values - they're translated to 1, 0.
189
- case TypeCode . Boolean : return ( ( bool ) eval ? 1UL : 0UL , PrimitiveType . UChar ) ;
196
+ TypeCode . Boolean => ( ( bool ) eval ? 1UL : 0UL , PrimitiveType . UChar ) ,
190
197
191
- default : throw new Exception ( $ "Expression { expression } is not a valid expression type for an enum") ;
192
- }
198
+ _ => throw new Exception ( $ "Expression { expression } is not a valid expression type for an enum")
199
+ } ;
200
+
201
+ return true ;
193
202
}
194
203
catch ( Exception ex )
195
204
{
196
- // TODO: This should just throw, but we have a pre-existing behavior that expects malformed
197
- // macro expressions to default to 0, see CSharp.h (MY_MACRO_TEST2_0), so do it for now.
205
+ // TODO: There should be a toggle to just throw here instead.
198
206
199
207
// Like other paths, we can however, write a diagnostic message to the console.
200
208
201
209
Diagnostics . PushIndent ( ) ;
202
210
Diagnostics . Warning ( $ "Unable to translate macro '{ macro . Name } ' to en enum value: { ex . Message } ") ;
203
211
Diagnostics . PopIndent ( ) ;
204
212
205
- return ( 0 , PrimitiveType . Int ) ;
213
+ item = default ;
214
+ return false ;
206
215
}
207
216
}
208
217
@@ -311,16 +320,18 @@ TranslationUnit GetUnitFromItems(List<Enumeration.Item> list)
311
320
if ( @enum . Items . Exists ( it => it . Name == macro . Name ) )
312
321
continue ;
313
322
314
- var item = @enum . GenerateEnumItemFromMacro ( macro ) ;
315
- @enum . AddItem ( item ) ;
316
- macro . Enumeration = @enum ;
323
+ if ( @enum . TryGenerateEnumItemFromMacro ( macro , out var item ) )
324
+ {
325
+ @enum . AddItem ( item ) ;
326
+ macro . Enumeration = @enum ;
327
+ }
317
328
}
318
329
319
330
if ( @enum . Items . Count <= 0 )
320
331
return @enum ;
321
332
322
333
// The value of @enum.BuiltinType has been adjusted on the fly via
323
- // GenerateEnumItemFromMacro . However, its notion of PrimitiveType corresponds with
334
+ // TryGenerateEnumItemFromMacro . However, its notion of PrimitiveType corresponds with
324
335
// what the ExpressionEvaluator returns. In particular, the expression "1" will result
325
336
// in PrimitiveType.Int from the expression evaluator. Narrow the type to account for
326
337
// types narrower than int.
0 commit comments