@@ -2248,6 +2248,8 @@ size_t DWARFASTParserClang::ParseChildEnumerators(
22482248 return 0 ;
22492249
22502250 size_t enumerators_added = 0 ;
2251+ unsigned NumNegativeBits = 0 ;
2252+ unsigned NumPositiveBits = 0 ;
22512253
22522254 for (DWARFDIE die : parent_die.children ()) {
22532255 const dw_tag_t tag = die.Tag ();
@@ -2299,11 +2301,102 @@ size_t DWARFASTParserClang::ParseChildEnumerators(
22992301 }
23002302
23012303 if (name && name[0 ] && got_value) {
2302- m_ast.AddEnumerationValueToEnumerationType (
2304+ auto ECD = m_ast.AddEnumerationValueToEnumerationType (
23032305 clang_type, decl, name, enum_value, enumerator_byte_size * 8 );
23042306 ++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+ }
23052319 }
23062320 }
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+
23072400 return enumerators_added;
23082401}
23092402
0 commit comments