static Optional<uint64_t> GetCFNumberSize(ASTContext &Ctx, uint64_t i) { static const unsigned char FixedSize[] = { 8, 16, 32, 64, 32, 64 }; if (i < kCFNumberCharType) return FixedSize[i-1]; QualType T; switch (i) { case kCFNumberCharType: T = Ctx.CharTy; break; case kCFNumberShortType: T = Ctx.ShortTy; break; case kCFNumberIntType: T = Ctx.IntTy; break; case kCFNumberLongType: T = Ctx.LongTy; break; case kCFNumberLongLongType: T = Ctx.LongLongTy; break; case kCFNumberFloatType: T = Ctx.FloatTy; break; case kCFNumberDoubleType: T = Ctx.DoubleTy; break; case kCFNumberCFIndexType: case kCFNumberNSIntegerType: case kCFNumberCGFloatType: // FIXME: We need a way to map from names to Type*. default: return None; } return Ctx.getTypeSize(T); }
static bool isHigherOrderRawPtr(QualType T, ASTContext &C) { bool foundPointer = false; while (1) { const PointerType *PT = T->getAs<PointerType>(); if (!PT) { if (!foundPointer) return false; // intptr_t* or intptr_t**, etc? if (T->isIntegerType() && C.getTypeSize(T) == C.getTypeSize(C.VoidPtrTy)) return true; QualType X = C.getCanonicalType(T).getUnqualifiedType(); return X == C.VoidTy; } foundPointer = true; T = PT->getPointeeType(); } }
/// Get the number of possible values that can be switched on for the type T. /// /// \return - 0 if bitcount could not be determined /// - numeric_limits<std::size_t>::max() when overflow appeared due to /// more than 64 bits type size. static std::size_t getNumberOfPossibleValues(QualType T, const ASTContext &Context) { // `isBooleanType` must come first because `bool` is an integral type as well // and would not return 2 as result. if (T->isBooleanType()) return 2; else if (T->isIntegralType(Context)) return twoPow(Context.getTypeSize(T)); else return 1; }
/// Returns true if ValueType is allowed to fold into InitType, i.e. if: /// static_cast<InitType>(ValueType{some_value}) /// does not result in trucation. static bool isValidBuiltinFold(const BuiltinType &ValueType, const BuiltinType &InitType, const ASTContext &Context) { const auto ValueTypeSize = Context.getTypeSize(&ValueType); const auto InitTypeSize = Context.getTypeSize(&InitType); // It's OK to fold a float into a float of bigger or equal size, but not OK to // fold into an int. if (ValueType.isFloatingPoint()) return InitType.isFloatingPoint() && InitTypeSize >= ValueTypeSize; // It's OK to fold an int into: // - an int of the same size and signedness. // - a bigger int, regardless of signedness. // - FIXME: should it be a warning to fold into floating point? if (ValueType.isInteger()) { if (InitType.isInteger()) { if (InitType.isSignedInteger() == ValueType.isSignedInteger()) return InitTypeSize >= ValueTypeSize; return InitTypeSize > ValueTypeSize; } if (InitType.isFloatingPoint()) return InitTypeSize >= ValueTypeSize; } return false; }
static uint64_t CalculateCookiePadding(ASTContext &Ctx, const CXXNewExpr *E) { if (!E->isArray()) return 0; QualType T = E->getAllocatedType(); const RecordType *RT = T->getAs<RecordType>(); if (!RT) return 0; const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl()); if (!RD) return 0; // Check if the class has a trivial destructor. if (RD->hasTrivialDestructor()) { // FIXME: Check for a two-argument delete. return 0; } // Padding is the maximum of sizeof(size_t) and alignof(T) return std::max(Ctx.getTypeSize(Ctx.getSizeType()), static_cast<uint64_t>(Ctx.getTypeAlign(T))) / 8; }