@@ -2248,6 +2248,8 @@ size_t DWARFASTParserClang::ParseChildEnumerators(
2248
2248
return 0 ;
2249
2249
2250
2250
size_t enumerators_added = 0 ;
2251
+ unsigned NumNegativeBits = 0 ;
2252
+ unsigned NumPositiveBits = 0 ;
2251
2253
2252
2254
for (DWARFDIE die : parent_die.children ()) {
2253
2255
const dw_tag_t tag = die.Tag ();
@@ -2299,11 +2301,102 @@ size_t DWARFASTParserClang::ParseChildEnumerators(
2299
2301
}
2300
2302
2301
2303
if (name && name[0 ] && got_value) {
2302
- m_ast.AddEnumerationValueToEnumerationType (
2304
+ auto ECD = m_ast.AddEnumerationValueToEnumerationType (
2303
2305
clang_type, decl, name, enum_value, enumerator_byte_size * 8 );
2304
2306
++enumerators_added;
2307
+
2308
+ llvm::APSInt InitVal = ECD->getInitVal ();
2309
+ // Keep track of the size of positive and negative values.
2310
+ if (InitVal.isUnsigned () || InitVal.isNonNegative ()) {
2311
+ // If the enumerator is zero that should still be counted as a positive
2312
+ // bit since we need a bit to store the value zero.
2313
+ unsigned ActiveBits = InitVal.getActiveBits ();
2314
+ NumPositiveBits = std::max ({NumPositiveBits, ActiveBits, 1u });
2315
+ } else {
2316
+ NumNegativeBits =
2317
+ std::max (NumNegativeBits, (unsigned )InitVal.getSignificantBits ());
2318
+ }
2305
2319
}
2306
2320
}
2321
+
2322
+ // / The following code follows the same logic as in Sema::ActOnEnumBody
2323
+ // / clang/lib/Sema/SemaDecl.cpp
2324
+ // If we have an empty set of enumerators we still need one bit.
2325
+ // From [dcl.enum]p8
2326
+ // If the enumerator-list is empty, the values of the enumeration are as if
2327
+ // the enumeration had a single enumerator with value 0
2328
+ if (!NumPositiveBits && !NumNegativeBits)
2329
+ NumPositiveBits = 1 ;
2330
+
2331
+ clang::QualType qual_type (ClangUtil::GetQualType (clang_type));
2332
+ clang::EnumDecl *enum_decl = qual_type->getAs <clang::EnumType>()->getDecl ();
2333
+ enum_decl->setNumPositiveBits (NumPositiveBits);
2334
+ enum_decl->setNumNegativeBits (NumNegativeBits);
2335
+
2336
+ // C++0x N3000 [conv.prom]p3:
2337
+ // An rvalue of an unscoped enumeration type whose underlying
2338
+ // type is not fixed can be converted to an rvalue of the first
2339
+ // of the following types that can represent all the values of
2340
+ // the enumeration: int, unsigned int, long int, unsigned long
2341
+ // int, long long int, or unsigned long long int.
2342
+ // C99 6.4.4.3p2:
2343
+ // An identifier declared as an enumeration constant has type int.
2344
+ // The C99 rule is modified by C23.
2345
+ clang::QualType BestPromotionType;
2346
+ unsigned BestWidth;
2347
+
2348
+ auto &Context = m_ast.getASTContext ();
2349
+ unsigned LongWidth = Context.getTargetInfo ().getLongWidth ();
2350
+ unsigned IntWidth = Context.getTargetInfo ().getIntWidth ();
2351
+ unsigned CharWidth = Context.getTargetInfo ().getCharWidth ();
2352
+ unsigned ShortWidth = Context.getTargetInfo ().getShortWidth ();
2353
+
2354
+ bool is_cpp = Language::LanguageIsCPlusPlus (
2355
+ SymbolFileDWARF::GetLanguage (*parent_die.GetCU ()));
2356
+
2357
+ if (NumNegativeBits) {
2358
+ // If there is a negative value, figure out the smallest integer type (of
2359
+ // int/long/longlong) that fits.
2360
+ if (NumNegativeBits <= CharWidth && NumPositiveBits < CharWidth) {
2361
+ BestWidth = CharWidth;
2362
+ } else if (NumNegativeBits <= ShortWidth && NumPositiveBits < ShortWidth) {
2363
+ BestWidth = ShortWidth;
2364
+ } else if (NumNegativeBits <= IntWidth && NumPositiveBits < IntWidth) {
2365
+ BestWidth = IntWidth;
2366
+ } else if (NumNegativeBits <= LongWidth && NumPositiveBits < LongWidth) {
2367
+ BestWidth = LongWidth;
2368
+ } else {
2369
+ BestWidth = Context.getTargetInfo ().getLongLongWidth ();
2370
+ }
2371
+ BestPromotionType = (BestWidth <= IntWidth ? Context.IntTy : qual_type);
2372
+ } else {
2373
+ // If there is no negative value, figure out the smallest type that fits
2374
+ // all of the enumerator values.
2375
+ if (NumPositiveBits <= CharWidth) {
2376
+ BestPromotionType = Context.IntTy ;
2377
+ BestWidth = CharWidth;
2378
+ } else if (NumPositiveBits <= ShortWidth) {
2379
+ BestPromotionType = Context.IntTy ;
2380
+ BestWidth = ShortWidth;
2381
+ } else if (NumPositiveBits <= IntWidth) {
2382
+ BestWidth = IntWidth;
2383
+ BestPromotionType = (NumPositiveBits == BestWidth || !is_cpp)
2384
+ ? Context.UnsignedIntTy
2385
+ : Context.IntTy ;
2386
+ } else if (NumPositiveBits <= LongWidth) {
2387
+ BestWidth = LongWidth;
2388
+ BestPromotionType = (NumPositiveBits == BestWidth || !is_cpp)
2389
+ ? Context.UnsignedLongTy
2390
+ : Context.LongTy ;
2391
+ } else {
2392
+ BestWidth = Context.getTargetInfo ().getLongLongWidth ();
2393
+ BestPromotionType = (NumPositiveBits == BestWidth || !is_cpp)
2394
+ ? Context.UnsignedLongLongTy
2395
+ : Context.LongLongTy ;
2396
+ }
2397
+ }
2398
+ enum_decl->setPromotionType (BestPromotionType);
2399
+
2307
2400
return enumerators_added;
2308
2401
}
2309
2402
0 commit comments