From: Richard Smith Date: Mon, 10 Oct 2011 18:28:20 +0000 (+0000) Subject: Constant expression evaluation refactoring: X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a6b8b2c09610b8bc4330e948ece8b940c2386406;p=clang Constant expression evaluation refactoring: - Remodel Expr::EvaluateAsInt to behave like the other EvaluateAs* functions, and add Expr::EvaluateKnownConstInt to capture the current fold-or-assert behaviour. - Factor out evaluation of bitfield bit widths. - Fix a few places which would evaluate an expression twice: once to determine whether it is a constant expression, then again to get the value. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@141561 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 0f65bfbd35..09eb560f21 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -2084,6 +2084,7 @@ public: Expr *getBitWidth() const { return isBitField() ? InitializerOrBitWidth.getPointer() : 0; } + unsigned getBitWidthValue(const ASTContext &Ctx) const; void setBitWidth(Expr *BW) { assert(!InitializerOrBitWidth.getPointer() && "bit width or initializer already set"); diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 3475562337..882124bfdd 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -453,9 +453,14 @@ public: /// EvaluateAsBooleanCondition - Return true if this is a constant /// which we we can fold and convert to a boolean condition using - /// any crazy technique that we want to. + /// any crazy technique that we want to, even if the expression has + /// side-effects. bool EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx) const; + /// EvaluateAsInt - Return true if this is a constant which we can fold and + /// convert to an integer using any crazy technique that we want to. + bool EvaluateAsInt(llvm::APSInt &Result, const ASTContext &Ctx) const; + /// isEvaluatable - Call Evaluate to see if this expression can be constant /// folded, but discard the result. bool isEvaluatable(const ASTContext &Ctx) const; @@ -466,9 +471,9 @@ public: /// variable read. bool HasSideEffects(const ASTContext &Ctx) const; - /// EvaluateAsInt - Call Evaluate and return the folded integer. This + /// EvaluateKnownConstInt - Call Evaluate and return the folded integer. This /// must be called on an expression that constant folds to an integer. - llvm::APSInt EvaluateAsInt(const ASTContext &Ctx) const; + llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx) const; /// EvaluateAsLValue - Evaluate an expression to see if it's a lvalue /// with link time known address. @@ -3098,7 +3103,7 @@ public: unsigned getShuffleMaskIdx(ASTContext &Ctx, unsigned N) { assert((N < NumExprs - 2) && "Shuffle idx out of range!"); - return getExpr(N+2)->EvaluateAsInt(Ctx).getZExtValue(); + return getExpr(N+2)->EvaluateKnownConstInt(Ctx).getZExtValue(); } // Iterators diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 3377799e3d..b625655e45 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -608,33 +608,33 @@ void ASTContext::setInstantiatedFromUnnamedFieldDecl(FieldDecl *Inst, bool ASTContext::ZeroBitfieldFollowsNonBitfield(const FieldDecl *FD, const FieldDecl *LastFD) const { return (FD->isBitField() && LastFD && !LastFD->isBitField() && - FD->getBitWidth()->EvaluateAsInt(*this).getZExtValue() == 0); + FD->getBitWidthValue(*this) == 0); } bool ASTContext::ZeroBitfieldFollowsBitfield(const FieldDecl *FD, const FieldDecl *LastFD) const { return (FD->isBitField() && LastFD && LastFD->isBitField() && - FD->getBitWidth()->EvaluateAsInt(*this).getZExtValue() == 0 && - LastFD->getBitWidth()->EvaluateAsInt(*this).getZExtValue() != 0); + FD->getBitWidthValue(*this) == 0 && + LastFD->getBitWidthValue(*this) != 0); } bool ASTContext::BitfieldFollowsBitfield(const FieldDecl *FD, const FieldDecl *LastFD) const { return (FD->isBitField() && LastFD && LastFD->isBitField() && - FD->getBitWidth()->EvaluateAsInt(*this).getZExtValue() && - LastFD->getBitWidth()->EvaluateAsInt(*this).getZExtValue()); + FD->getBitWidthValue(*this) && + LastFD->getBitWidthValue(*this)); } bool ASTContext::NonBitfieldFollowsBitfield(const FieldDecl *FD, const FieldDecl *LastFD) const { return (!FD->isBitField() && LastFD && LastFD->isBitField() && - LastFD->getBitWidth()->EvaluateAsInt(*this).getZExtValue()); + LastFD->getBitWidthValue(*this)); } bool ASTContext::BitfieldFollowsNonBitfield(const FieldDecl *FD, const FieldDecl *LastFD) const { return (FD->isBitField() && LastFD && !LastFD->isBitField() && - FD->getBitWidth()->EvaluateAsInt(*this).getZExtValue()); + FD->getBitWidthValue(*this)); } ASTContext::overridden_cxx_method_iterator @@ -3577,8 +3577,7 @@ QualType ASTContext::isPromotableBitField(Expr *E) const { QualType FT = Field->getType(); - llvm::APSInt BitWidthAP = Field->getBitWidth()->EvaluateAsInt(*this); - uint64_t BitWidth = BitWidthAP.getZExtValue(); + uint64_t BitWidth = Field->getBitWidthValue(*this); uint64_t IntSize = getTypeSize(IntTy); // GCC extension compatibility: if the bit-field size is less than or equal // to the size of int, it gets promoted no matter what its type is. @@ -4255,8 +4254,7 @@ static char ObjCEncodingForEnumType(const ASTContext *C, const EnumType *ET) { static void EncodeBitField(const ASTContext *Ctx, std::string& S, QualType T, const FieldDecl *FD) { - const Expr *E = FD->getBitWidth(); - assert(E && "bitfield width not there - getObjCEncodingForTypeImpl"); + assert(FD->isBitField() && "not a bitfield - getObjCEncodingForTypeImpl"); S += 'b'; // The NeXT runtime encodes bit fields as b followed by the number of bits. // The GNU runtime requires more information; bitfields are encoded as b, @@ -4282,8 +4280,7 @@ static void EncodeBitField(const ASTContext *Ctx, std::string& S, else S += ObjCEncodingForPrimitiveKind(Ctx, T); } - unsigned N = E->EvaluateAsInt(*Ctx).getZExtValue(); - S += llvm::utostr(N); + S += llvm::utostr(FD->getBitWidthValue(*Ctx)); } // FIXME: Use SmallString for accumulating string. @@ -4699,7 +4696,7 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl, if (field->isBitField()) { EncodeBitField(this, S, field->getType(), field); - CurOffs += field->getBitWidth()->EvaluateAsInt(*this).getZExtValue(); + CurOffs += field->getBitWidthValue(*this); } else { QualType qt = field->getType(); getLegacyIntegralTypeEncoding(qt); diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 050a9ab2c6..2f7497db66 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -956,43 +956,33 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent) << Context.C2.getTypeDeclType(D2); if (Field1->isBitField()) { - llvm::APSInt Bits; - Field1->getBitWidth()->isIntegerConstantExpr(Bits, Context.C1); Context.Diag1(Field1->getLocation(), diag::note_odr_bit_field) << Field1->getDeclName() << Field1->getType() - << Bits.toString(10, false); + << Field1->getBitWidthValue(Context.C1); Context.Diag2(Field2->getLocation(), diag::note_odr_not_bit_field) << Field2->getDeclName(); } else { - llvm::APSInt Bits; - Field2->getBitWidth()->isIntegerConstantExpr(Bits, Context.C2); Context.Diag2(Field2->getLocation(), diag::note_odr_bit_field) << Field2->getDeclName() << Field2->getType() - << Bits.toString(10, false); - Context.Diag1(Field1->getLocation(), - diag::note_odr_not_bit_field) - << Field1->getDeclName(); + << Field2->getBitWidthValue(Context.C2); + Context.Diag1(Field1->getLocation(), diag::note_odr_not_bit_field) + << Field1->getDeclName(); } return false; } if (Field1->isBitField()) { // Make sure that the bit-fields are the same length. - llvm::APSInt Bits1, Bits2; - if (!Field1->getBitWidth()->isIntegerConstantExpr(Bits1, Context.C1)) - return false; - if (!Field2->getBitWidth()->isIntegerConstantExpr(Bits2, Context.C2)) - return false; + unsigned Bits1 = Field1->getBitWidthValue(Context.C1); + unsigned Bits2 = Field2->getBitWidthValue(Context.C2); - if (!IsSameValue(Bits1, Bits2)) { + if (Bits1 != Bits2) { Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent) << Context.C2.getTypeDeclType(D2); Context.Diag2(Field2->getLocation(), diag::note_odr_bit_field) - << Field2->getDeclName() << Field2->getType() - << Bits2.toString(10, false); + << Field2->getDeclName() << Field2->getType() << Bits2; Context.Diag1(Field1->getLocation(), diag::note_odr_bit_field) - << Field1->getDeclName() << Field1->getType() - << Bits1.toString(10, false); + << Field1->getDeclName() << Field1->getType() << Bits1; return false; } } diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 7d3390f133..5cd98584bf 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -2187,6 +2187,12 @@ bool FieldDecl::isAnonymousStructOrUnion() const { return false; } +unsigned FieldDecl::getBitWidthValue(const ASTContext &Ctx) const { + assert(isBitField() && "not a bitfield"); + Expr *BitWidth = InitializerOrBitWidth.getPointer(); + return BitWidth->EvaluateKnownConstInt(Ctx).getZExtValue(); +} + unsigned FieldDecl::getFieldIndex() const { if (CachedFieldIndex) return CachedFieldIndex - 1; diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index 5dcecb9a11..8f61ea23cd 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -830,15 +830,11 @@ NotASpecialMember:; // If this is not a zero-length bit-field, then the class is not empty. if (data().Empty) { - if (!Field->getBitWidth()) + if (!Field->isBitField() || + (!Field->getBitWidth()->isTypeDependent() && + !Field->getBitWidth()->isValueDependent() && + Field->getBitWidthValue(Context) != 0)) data().Empty = false; - else if (!Field->getBitWidth()->isTypeDependent() && - !Field->getBitWidth()->isValueDependent()) { - llvm::APSInt Bits; - if (Field->getBitWidth()->isIntegerConstantExpr(Bits, Context)) - if (!!Bits) - data().Empty = false; - } } } diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 7cfbd9e2fb..dc37ac9226 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -2955,7 +2955,7 @@ StringRef ObjCBridgedCastExpr::getBridgeKindName() const { } bool ChooseExpr::isConditionTrue(const ASTContext &C) const { - return getCond()->EvaluateAsInt(C) != 0; + return getCond()->EvaluateKnownConstInt(C) != 0; } ShuffleVectorExpr::ShuffleVectorExpr(ASTContext &C, Expr **args, unsigned nexpr, diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 742dcab564..3da744955a 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -1285,7 +1285,7 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { // If evaluating the argument has side-effects we can't determine // the size of the object and lower it to unknown now. if (E->getArg(0)->HasSideEffects(Info.Ctx)) { - if (E->getArg(1)->EvaluateAsInt(Info.Ctx).getZExtValue() <= 1) + if (E->getArg(1)->EvaluateKnownConstInt(Info.Ctx).getZExtValue() <= 1) return Success(-1ULL, E); return Success(0, E); } @@ -1302,7 +1302,7 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { return Success(E->getArg(0)->isEvaluatable(Info.Ctx), E); case Builtin::BI__builtin_eh_return_data_regno: { - int Operand = E->getArg(0)->EvaluateAsInt(Info.Ctx).getZExtValue(); + int Operand = E->getArg(0)->EvaluateKnownConstInt(Info.Ctx).getZExtValue(); Operand = Info.Ctx.getTargetInfo().getEHDataRegisterNumber(Operand); return Success(Operand, E); } @@ -2681,6 +2681,13 @@ bool Expr::EvaluateAsBooleanCondition(bool &Result, return HandleConversionToBool(this, Result, Info); } +bool Expr::EvaluateAsInt(APSInt &Result, const ASTContext &Ctx) const { + EvalResult Scratch; + EvalInfo Info(Ctx, Scratch); + + return EvaluateInteger(this, Result, Info) && !Scratch.HasSideEffects; +} + bool Expr::EvaluateAsLValue(EvalResult &Result, const ASTContext &Ctx) const { EvalInfo Info(Ctx, Result); @@ -2719,7 +2726,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx) const { return HasSideEffect(Info).Visit(this); } -APSInt Expr::EvaluateAsInt(const ASTContext &Ctx) const { +APSInt Expr::EvaluateKnownConstInt(const ASTContext &Ctx) const { EvalResult EvalResult; bool Result = Evaluate(EvalResult, Ctx); (void)Result; @@ -3021,11 +3028,11 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { // Evaluate gives an error for undefined Div/Rem, so make sure // we don't evaluate one. if (LHSResult.Val == 0 && RHSResult.Val == 0) { - llvm::APSInt REval = Exp->getRHS()->EvaluateAsInt(Ctx); + llvm::APSInt REval = Exp->getRHS()->EvaluateKnownConstInt(Ctx); if (REval == 0) return ICEDiag(1, E->getLocStart()); if (REval.isSigned() && REval.isAllOnesValue()) { - llvm::APSInt LEval = Exp->getLHS()->EvaluateAsInt(Ctx); + llvm::APSInt LEval = Exp->getLHS()->EvaluateKnownConstInt(Ctx); if (LEval.isMinSignedValue()) return ICEDiag(1, E->getLocStart()); } @@ -3056,11 +3063,11 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { // evaluated are not considered. if (Ctx.getLangOptions().CPlusPlus0x && LHSResult.Val == 0) { if (Exp->getOpcode() == BO_LAnd && - Exp->getLHS()->EvaluateAsInt(Ctx) == 0) + Exp->getLHS()->EvaluateKnownConstInt(Ctx) == 0) return LHSResult; if (Exp->getOpcode() == BO_LOr && - Exp->getLHS()->EvaluateAsInt(Ctx) != 0) + Exp->getLHS()->EvaluateKnownConstInt(Ctx) != 0) return LHSResult; } @@ -3070,7 +3077,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { // to actually check the condition to see whether the side // with the comma is evaluated. if ((Exp->getOpcode() == BO_LAnd) != - (Exp->getLHS()->EvaluateAsInt(Ctx) == 0)) + (Exp->getLHS()->EvaluateKnownConstInt(Ctx) == 0)) return RHSResult; return NoDiag(); } @@ -3109,7 +3116,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { if (FalseResult.Val == 2) return FalseResult; if (CommonResult.Val == 1) return CommonResult; if (FalseResult.Val == 1 && - Exp->getCommon()->EvaluateAsInt(Ctx) == 0) return NoDiag(); + Exp->getCommon()->EvaluateKnownConstInt(Ctx) == 0) return NoDiag(); return FalseResult; } case Expr::ConditionalOperatorClass: { @@ -3136,7 +3143,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { // subexpressions of [...] conditional (5.16) operations that // are not evaluated are not considered bool TrueBranch = Ctx.getLangOptions().CPlusPlus0x - ? Exp->getCond()->EvaluateAsInt(Ctx) != 0 + ? Exp->getCond()->EvaluateKnownConstInt(Ctx) != 0 : false; ICEDiag TrueResult = NoDiag(); if (!Ctx.getLangOptions().CPlusPlus0x || TrueBranch) @@ -3156,7 +3163,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { // Rare case where the diagnostics depend on which side is evaluated // Note that if we get here, CondResult is 0, and at least one of // TrueResult and FalseResult is non-zero. - if (Exp->getCond()->EvaluateAsInt(Ctx) == 0) { + if (Exp->getCond()->EvaluateKnownConstInt(Ctx) == 0) { return FalseResult; } return TrueResult; diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp index 41cfa6ad01..2b93250fad 100644 --- a/lib/AST/ItaniumMangle.cpp +++ b/lib/AST/ItaniumMangle.cpp @@ -2416,7 +2416,8 @@ recurse: QualType T = (ImplicitlyConvertedToType.isNull() || !ImplicitlyConvertedToType->isIntegerType())? SAE->getType() : ImplicitlyConvertedToType; - mangleIntegerLiteral(T, SAE->EvaluateAsInt(Context.getASTContext())); + llvm::APSInt V = SAE->EvaluateKnownConstInt(Context.getASTContext()); + mangleIntegerLiteral(T, V); break; } diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp index f351d76d76..a3ccbd0850 100644 --- a/lib/AST/RecordLayoutBuilder.cpp +++ b/lib/AST/RecordLayoutBuilder.cpp @@ -1362,7 +1362,7 @@ void RecordLayoutBuilder::LayoutFields(const RecordDecl *D) { if (TypeSizeLastFD != TypeSize) { if (RemainingInAlignment && LastFD && LastFD->isBitField() && - LastFD->getBitWidth()->EvaluateAsInt(Context).getZExtValue()) { + LastFD->getBitWidthValue(Context)) { // If previous field was a bitfield with some remaining unfilled // bits, pad the field so current field starts on its type boundary. uint64_t FieldOffset = @@ -1393,8 +1393,7 @@ void RecordLayoutBuilder::LayoutFields(const RecordDecl *D) { setSize(std::max(getSizeInBits(), getDataSizeInBits())); } if (FD->isBitField()) { - uint64_t FieldSize = - FD->getBitWidth()->EvaluateAsInt(Context).getZExtValue(); + uint64_t FieldSize = FD->getBitWidthValue(Context); assert (FieldSize > 0 && "LayoutFields - ms_struct layout"); if (RemainingInAlignment < FieldSize) RemainingInAlignment = TypeSize - FieldSize; @@ -1403,8 +1402,7 @@ void RecordLayoutBuilder::LayoutFields(const RecordDecl *D) { } } else if (FD->isBitField()) { - uint64_t FieldSize = - FD->getBitWidth()->EvaluateAsInt(Context).getZExtValue(); + uint64_t FieldSize = FD->getBitWidthValue(Context); std::pair FieldInfo = Context.getTypeInfo(FD->getType()); uint64_t TypeSize = FieldInfo.first; @@ -1415,15 +1413,13 @@ void RecordLayoutBuilder::LayoutFields(const RecordDecl *D) { else if (!Context.getTargetInfo().useBitFieldTypeAlignment() && Context.getTargetInfo().useZeroLengthBitfieldAlignment()) { FieldDecl *FD = (*Field); - if (FD->isBitField() && - FD->getBitWidth()->EvaluateAsInt(Context).getZExtValue() == 0) + if (FD->isBitField() && FD->getBitWidthValue(Context) == 0) ZeroLengthBitfield = FD; } LayoutField(*Field); } if (IsMsStruct && RemainingInAlignment && - LastFD && LastFD->isBitField() && - LastFD->getBitWidth()->EvaluateAsInt(Context).getZExtValue()) { + LastFD && LastFD->isBitField() && LastFD->getBitWidthValue(Context)) { // If we ended a bitfield before the full length of the type then // pad the struct out to the full length of the last type. uint64_t FieldOffset = @@ -1504,7 +1500,7 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { bool FieldPacked = Packed || D->hasAttr(); uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastByte; uint64_t FieldOffset = IsUnion ? 0 : UnpaddedFieldOffset; - uint64_t FieldSize = D->getBitWidth()->EvaluateAsInt(Context).getZExtValue(); + uint64_t FieldSize = D->getBitWidthValue(Context); std::pair FieldInfo = Context.getTypeInfo(D->getType()); uint64_t TypeSize = FieldInfo.first; diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 3ec4efef76..f7179befeb 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -548,11 +548,10 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, case Builtin::BI__builtin___memcpy_chk: { // fold __builtin_memcpy_chk(x, y, cst1, cst2) to memset iff cst1<=cst2. - if (!E->getArg(2)->isEvaluatable(CGM.getContext()) || - !E->getArg(3)->isEvaluatable(CGM.getContext())) + llvm::APSInt Size, DstSize; + if (!E->getArg(2)->EvaluateAsInt(Size, CGM.getContext()) || + !E->getArg(3)->EvaluateAsInt(DstSize, CGM.getContext())) break; - llvm::APSInt Size = E->getArg(2)->EvaluateAsInt(CGM.getContext()); - llvm::APSInt DstSize = E->getArg(3)->EvaluateAsInt(CGM.getContext()); if (Size.ugt(DstSize)) break; Value *Dest = EmitScalarExpr(E->getArg(0)); @@ -573,11 +572,10 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, case Builtin::BI__builtin___memmove_chk: { // fold __builtin_memmove_chk(x, y, cst1, cst2) to memset iff cst1<=cst2. - if (!E->getArg(2)->isEvaluatable(CGM.getContext()) || - !E->getArg(3)->isEvaluatable(CGM.getContext())) + llvm::APSInt Size, DstSize; + if (!E->getArg(2)->EvaluateAsInt(Size, CGM.getContext()) || + !E->getArg(3)->EvaluateAsInt(DstSize, CGM.getContext())) break; - llvm::APSInt Size = E->getArg(2)->EvaluateAsInt(CGM.getContext()); - llvm::APSInt DstSize = E->getArg(3)->EvaluateAsInt(CGM.getContext()); if (Size.ugt(DstSize)) break; Value *Dest = EmitScalarExpr(E->getArg(0)); @@ -606,11 +604,10 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, } case Builtin::BI__builtin___memset_chk: { // fold __builtin_memset_chk(x, y, cst1, cst2) to memset iff cst1<=cst2. - if (!E->getArg(2)->isEvaluatable(CGM.getContext()) || - !E->getArg(3)->isEvaluatable(CGM.getContext())) + llvm::APSInt Size, DstSize; + if (!E->getArg(2)->EvaluateAsInt(Size, CGM.getContext()) || + !E->getArg(3)->EvaluateAsInt(DstSize, CGM.getContext())) break; - llvm::APSInt Size = E->getArg(2)->EvaluateAsInt(CGM.getContext()); - llvm::APSInt DstSize = E->getArg(3)->EvaluateAsInt(CGM.getContext()); if (Size.ugt(DstSize)) break; Value *Address = EmitScalarExpr(E->getArg(0)); diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index eda73253b5..313c02dc6f 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -603,7 +603,7 @@ llvm::DIType CGDebugInfo::CreateType(const FunctionType *Ty, llvm::DIType CGDebugInfo::createFieldType(StringRef name, QualType type, - Expr *bitWidth, + uint64_t sizeInBitsOverride, SourceLocation loc, AccessSpecifier AS, uint64_t offsetInBits, @@ -620,8 +620,8 @@ llvm::DIType CGDebugInfo::createFieldType(StringRef name, if (!type->isIncompleteArrayType()) { llvm::tie(sizeInBits, alignInBits) = CGM.getContext().getTypeInfo(type); - if (bitWidth) - sizeInBits = bitWidth->EvaluateAsInt(CGM.getContext()).getZExtValue(); + if (sizeInBitsOverride) + sizeInBits = sizeInBitsOverride; } unsigned flags = 0; @@ -667,8 +667,14 @@ CollectRecordFields(const RecordDecl *record, llvm::DIFile tunit, continue; } + uint64_t SizeInBitsOverride = 0; + if (field->isBitField()) { + SizeInBitsOverride = field->getBitWidthValue(CGM.getContext()); + assert(SizeInBitsOverride && "found named 0-width bitfield"); + } + llvm::DIType fieldType - = createFieldType(name, type, field->getBitWidth(), + = createFieldType(name, type, SizeInBitsOverride, field->getLocation(), field->getAccess(), layout.getFieldOffset(fieldNo), tunit, RecordTy); @@ -1215,12 +1221,10 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty, if (!FType->isIncompleteArrayType()) { // Bit size, align and offset of the type. - FieldSize = CGM.getContext().getTypeSize(FType); - Expr *BitWidth = Field->getBitWidth(); - if (BitWidth) - FieldSize = BitWidth->EvaluateAsInt(CGM.getContext()).getZExtValue(); - - FieldAlign = CGM.getContext().getTypeAlign(FType); + FieldSize = Field->isBitField() + ? Field->getBitWidthValue(CGM.getContext()) + : CGM.getContext().getTypeSize(FType); + FieldAlign = CGM.getContext().getTypeAlign(FType); } // We can't know the offset of our ivar in the structure if we're using diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h index 68b3985961..e6c701a9a8 100644 --- a/lib/CodeGen/CGDebugInfo.h +++ b/lib/CodeGen/CGDebugInfo.h @@ -139,7 +139,7 @@ class CGDebugInfo { llvm::DIFile F); llvm::DIType createFieldType(StringRef name, QualType type, - Expr *bitWidth, SourceLocation loc, + uint64_t sizeInBitsOverride, SourceLocation loc, AccessSpecifier AS, uint64_t offsetInBits, llvm::DIFile tunit, llvm::DIDescriptor scope); diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp index 1176eb1f9b..30c978e6a6 100644 --- a/lib/CodeGen/CGExprConstant.cpp +++ b/lib/CodeGen/CGExprConstant.cpp @@ -143,8 +143,7 @@ void ConstStructBuilder::AppendBitField(const FieldDecl *Field, AppendPadding(PadSize); } - uint64_t FieldSize = - Field->getBitWidth()->EvaluateAsInt(Context).getZExtValue(); + uint64_t FieldSize = Field->getBitWidthValue(Context); llvm::APInt FieldValue = CI->getValue(); diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index 1b317c45f2..308e0c7d37 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -3710,9 +3710,8 @@ void CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI, if (LastFieldBitfieldOrUnnamed) { if (LastFieldBitfieldOrUnnamed->isBitField()) { // Last field was a bitfield. Must update skip info. - Expr *BitWidth = LastFieldBitfieldOrUnnamed->getBitWidth(); - uint64_t BitFieldSize = - BitWidth->EvaluateAsInt(CGM.getContext()).getZExtValue(); + uint64_t BitFieldSize + = LastFieldBitfieldOrUnnamed->getBitWidthValue(CGM.getContext()); GC_IVAR skivar; skivar.ivar_bytepos = BytePos + LastBitfieldOrUnnamedOffset; skivar.ivar_size = (BitFieldSize / ByteSizeInBits) diff --git a/lib/CodeGen/CGObjCRuntime.cpp b/lib/CodeGen/CGObjCRuntime.cpp index f1e49ac81e..ef426ce6ed 100644 --- a/lib/CodeGen/CGObjCRuntime.cpp +++ b/lib/CodeGen/CGObjCRuntime.cpp @@ -119,8 +119,7 @@ LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF, uint64_t BitOffset = FieldBitOffset % CGF.CGM.getContext().getCharWidth(); uint64_t ContainingTypeAlign = CGF.CGM.getContext().getTargetInfo().getCharAlign(); uint64_t ContainingTypeSize = TypeSizeInBits - (FieldBitOffset - BitOffset); - uint64_t BitFieldSize = - Ivar->getBitWidth()->EvaluateAsInt(CGF.getContext()).getZExtValue(); + uint64_t BitFieldSize = Ivar->getBitWidthValue(CGF.getContext()); // Allocate a new CGBitFieldInfo object to describe this access. // diff --git a/lib/CodeGen/CGRecordLayoutBuilder.cpp b/lib/CodeGen/CGRecordLayoutBuilder.cpp index d55ea5171a..6475ccac03 100644 --- a/lib/CodeGen/CGRecordLayoutBuilder.cpp +++ b/lib/CodeGen/CGRecordLayoutBuilder.cpp @@ -363,8 +363,7 @@ CGBitFieldInfo CGBitFieldInfo::MakeInfo(CodeGenTypes &Types, void CGRecordLayoutBuilder::LayoutBitField(const FieldDecl *D, uint64_t fieldOffset) { - uint64_t fieldSize = - D->getBitWidth()->EvaluateAsInt(Types.getContext()).getZExtValue(); + uint64_t fieldSize = D->getBitWidthValue(Types.getContext()); if (fieldSize == 0) return; @@ -492,8 +491,7 @@ llvm::Type * CGRecordLayoutBuilder::LayoutUnionField(const FieldDecl *Field, const ASTRecordLayout &Layout) { if (Field->isBitField()) { - uint64_t FieldSize = - Field->getBitWidth()->EvaluateAsInt(Types.getContext()).getZExtValue(); + uint64_t FieldSize = Field->getBitWidthValue(Types.getContext()); // Ignore zero sized bit fields. if (FieldSize == 0) diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp index ec876a47f3..06a045f69b 100644 --- a/lib/CodeGen/CGStmt.cpp +++ b/lib/CodeGen/CGStmt.cpp @@ -834,8 +834,8 @@ void CodeGenFunction::EmitContinueStmt(const ContinueStmt &S) { void CodeGenFunction::EmitCaseStmtRange(const CaseStmt &S) { assert(S.getRHS() && "Expected RHS value in CaseStmt"); - llvm::APSInt LHS = S.getLHS()->EvaluateAsInt(getContext()); - llvm::APSInt RHS = S.getRHS()->EvaluateAsInt(getContext()); + llvm::APSInt LHS = S.getLHS()->EvaluateKnownConstInt(getContext()); + llvm::APSInt RHS = S.getRHS()->EvaluateKnownConstInt(getContext()); // Emit the code for this case. We do this first to make sure it is // properly chained from our predecessor before generating the @@ -894,7 +894,7 @@ void CodeGenFunction::EmitCaseStmt(const CaseStmt &S) { } llvm::ConstantInt *CaseVal = - Builder.getInt(S.getLHS()->EvaluateAsInt(getContext())); + Builder.getInt(S.getLHS()->EvaluateKnownConstInt(getContext())); // If the body of the case is just a 'break', and if there was no fallthrough, // try to not emit an empty block. @@ -935,7 +935,7 @@ void CodeGenFunction::EmitCaseStmt(const CaseStmt &S) { while (NextCase && NextCase->getRHS() == 0) { CurCase = NextCase; llvm::ConstantInt *CaseVal = - Builder.getInt(CurCase->getLHS()->EvaluateAsInt(getContext())); + Builder.getInt(CurCase->getLHS()->EvaluateKnownConstInt(getContext())); SwitchInsn->addCase(CaseVal, CaseDest); NextCase = dyn_cast(CurCase->getSubStmt()); } @@ -1125,7 +1125,7 @@ static bool FindCaseStatementsForValue(const SwitchStmt &S, if (CS->getRHS()) return false; // If we found our case, remember it as 'case'. - if (CS->getLHS()->EvaluateAsInt(C) == ConstantCondValue) + if (CS->getLHS()->EvaluateKnownConstInt(C) == ConstantCondValue) break; } diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp index ce729ce8da..97f9b718e0 100644 --- a/lib/CodeGen/TargetInfo.cpp +++ b/lib/CodeGen/TargetInfo.cpp @@ -1337,8 +1337,7 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, continue; uint64_t Offset = OffsetBase + Layout.getFieldOffset(idx); - uint64_t Size = - i->getBitWidth()->EvaluateAsInt(getContext()).getZExtValue(); + uint64_t Size = i->getBitWidthValue(getContext()); uint64_t EB_Lo = Offset / 64; uint64_t EB_Hi = (Offset + Size - 1) / 64; diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 181d40ba01..412ed0ebb5 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -2897,14 +2897,9 @@ IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) { IntRange::forValueOfType(C, E->getType()); } - FieldDecl *BitField = E->getBitField(); - if (BitField) { - llvm::APSInt BitWidthAP = BitField->getBitWidth()->EvaluateAsInt(C); - unsigned BitWidth = BitWidthAP.getZExtValue(); - - return IntRange(BitWidth, + if (FieldDecl *BitField = E->getBitField()) + return IntRange(BitField->getBitWidthValue(C), BitField->getType()->isUnsignedIntegerOrEnumerationType()); - } return IntRange::forValueOfType(C, E->getType()); } @@ -3106,16 +3101,14 @@ bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init, Expr *OriginalInit = Init->IgnoreParenImpCasts(); - llvm::APSInt Width(32); Expr::EvalResult InitValue; - if (!Bitfield->getBitWidth()->isIntegerConstantExpr(Width, S.Context) || - !OriginalInit->Evaluate(InitValue, S.Context) || + if (!OriginalInit->Evaluate(InitValue, S.Context) || !InitValue.Val.isInt()) return false; const llvm::APSInt &Value = InitValue.Val.getInt(); unsigned OriginalWidth = Value.getBitWidth(); - unsigned FieldWidth = Width.getZExtValue(); + unsigned FieldWidth = Bitfield->getBitWidthValue(S.Context); if (OriginalWidth <= FieldWidth) return false; diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 671ba615a8..2ce8a9acae 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -8757,11 +8757,7 @@ void Sema::ActOnLastBitfield(SourceLocation DeclLoc, Decl *ivarDecl = AllIvarDecls[AllIvarDecls.size()-1]; ObjCIvarDecl *Ivar = cast(ivarDecl); - if (!Ivar->isBitField()) - return; - uint64_t BitFieldSize = - Ivar->getBitWidth()->EvaluateAsInt(Context).getZExtValue(); - if (BitFieldSize == 0) + if (!Ivar->isBitField() || Ivar->getBitWidthValue(Context) == 0) return; ObjCInterfaceDecl *ID = dyn_cast(CurContext); if (!ID) { diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index ea0b06bacb..e9e9d5eb3d 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -2413,9 +2413,8 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, QualType ParamType = Param->getType().getNonReferenceType(); // Suppress copying zero-width bitfields. - if (const Expr *Width = Field->getBitWidth()) - if (Width->EvaluateAsInt(SemaRef.Context) == 0) - return false; + if (Field->isBitField() && Field->getBitWidthValue(SemaRef.Context) == 0) + return false; Expr *MemberExprBase = DeclRefExpr::Create(SemaRef.Context, NestedNameSpecifierLoc(), Param, @@ -7975,9 +7974,8 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, } // Suppress assigning zero-width bitfields. - if (const Expr *Width = Field->getBitWidth()) - if (Width->EvaluateAsInt(Context) == 0) - continue; + if (Field->isBitField() && Field->getBitWidthValue(Context) == 0) + continue; QualType FieldType = Field->getType().getNonReferenceType(); if (FieldType->isIncompleteArrayType()) { @@ -8396,9 +8394,8 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, } // Suppress assigning zero-width bitfields. - if (const Expr *Width = Field->getBitWidth()) - if (Width->EvaluateAsInt(Context) == 0) - continue; + if (Field->isBitField() && Field->getBitWidthValue(Context) == 0) + continue; QualType FieldType = Field->getType().getNonReferenceType(); if (FieldType->isIncompleteArrayType()) { diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 21b2622b4a..82b5b17fa4 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -1008,21 +1008,18 @@ void Sema::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl, assert (ClsIvar && "missing class ivar"); // First, make sure the types match. - if (Context.getCanonicalType(ImplIvar->getType()) != - Context.getCanonicalType(ClsIvar->getType())) { + if (!Context.hasSameType(ImplIvar->getType(), ClsIvar->getType())) { Diag(ImplIvar->getLocation(), diag::err_conflicting_ivar_type) << ImplIvar->getIdentifier() << ImplIvar->getType() << ClsIvar->getType(); Diag(ClsIvar->getLocation(), diag::note_previous_definition); - } else if (ImplIvar->isBitField() && ClsIvar->isBitField()) { - Expr *ImplBitWidth = ImplIvar->getBitWidth(); - Expr *ClsBitWidth = ClsIvar->getBitWidth(); - if (ImplBitWidth->EvaluateAsInt(Context).getZExtValue() != - ClsBitWidth->EvaluateAsInt(Context).getZExtValue()) { - Diag(ImplBitWidth->getLocStart(), diag::err_conflicting_ivar_bitwidth) - << ImplIvar->getIdentifier(); - Diag(ClsBitWidth->getLocStart(), diag::note_previous_definition); - } + } else if (ImplIvar->isBitField() && ClsIvar->isBitField() && + ImplIvar->getBitWidthValue(Context) != + ClsIvar->getBitWidthValue(Context)) { + Diag(ImplIvar->getBitWidth()->getLocStart(), + diag::err_conflicting_ivar_bitwidth) << ImplIvar->getIdentifier(); + Diag(ClsIvar->getBitWidth()->getLocStart(), + diag::note_previous_definition); } // Make sure the names are identical. if (ImplIvar->getIdentifier() != ClsIvar->getIdentifier()) { diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index ee985f4ba7..34be5db15b 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -1405,7 +1405,8 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, D, NameInfo, Ty, VK); // Just in case we're building an illegal pointer-to-member. - if (isa(D) && cast(D)->getBitWidth()) + FieldDecl *FD = dyn_cast(D); + if (FD && FD->isBitField()) E->setObjectKind(OK_BitField); return Owned(E); @@ -8389,7 +8390,7 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc, // (If the specified member is a bit-field, the behavior is undefined.) // // We diagnose this as an error. - if (MemberDecl->getBitWidth()) { + if (MemberDecl->isBitField()) { Diag(OC.LocEnd, diag::err_offsetof_bitfield) << MemberDecl->getDeclName() << SourceRange(BuiltinLoc, RParenLoc); diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index e9d4b82c8c..f195d10222 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -1850,15 +1850,15 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, llvm::APSInt DesignatedStartIndex, DesignatedEndIndex; if (D->isArrayDesignator()) { IndexExpr = DIE->getArrayIndex(*D); - DesignatedStartIndex = IndexExpr->EvaluateAsInt(SemaRef.Context); + DesignatedStartIndex = IndexExpr->EvaluateKnownConstInt(SemaRef.Context); DesignatedEndIndex = DesignatedStartIndex; } else { assert(D->isArrayRangeDesignator() && "Need array-range designator"); DesignatedStartIndex = - DIE->getArrayRangeStart(*D)->EvaluateAsInt(SemaRef.Context); + DIE->getArrayRangeStart(*D)->EvaluateKnownConstInt(SemaRef.Context); DesignatedEndIndex = - DIE->getArrayRangeEnd(*D)->EvaluateAsInt(SemaRef.Context); + DIE->getArrayRangeEnd(*D)->EvaluateKnownConstInt(SemaRef.Context); IndexExpr = DIE->getArrayRangeEnd(*D); // Codegen can't handle evaluating array range designators that have side diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index b30be82cee..7abfdd09de 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -626,7 +626,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, break; } - llvm::APSInt LoVal = Lo->EvaluateAsInt(Context); + llvm::APSInt LoVal = Lo->EvaluateKnownConstInt(Context); // Convert the value to the same width/sign as the condition. ConvertIntegerToTypeWarnOnOverflow(LoVal, CondWidth, CondIsSigned, @@ -705,7 +705,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, llvm::APSInt &LoVal = CaseRanges[i].first; CaseStmt *CR = CaseRanges[i].second; Expr *Hi = CR->getRHS(); - llvm::APSInt HiVal = Hi->EvaluateAsInt(Context); + llvm::APSInt HiVal = Hi->EvaluateKnownConstInt(Context); // Convert the value to the same width/sign as the condition. ConvertIntegerToTypeWarnOnOverflow(HiVal, CondWidth, CondIsSigned, @@ -845,7 +845,8 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, << ED->getDeclName(); } - llvm::APSInt Hi = RI->second->getRHS()->EvaluateAsInt(Context); + llvm::APSInt Hi = + RI->second->getRHS()->EvaluateKnownConstInt(Context); AdjustAPSInt(Hi, CondWidth, CondIsSigned); while (EI != EIend && EI->first < Hi) EI++; @@ -873,7 +874,8 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, // Drop unneeded case ranges for (; RI != CaseRanges.end(); RI++) { - llvm::APSInt Hi = RI->second->getRHS()->EvaluateAsInt(Context); + llvm::APSInt Hi = + RI->second->getRHS()->EvaluateKnownConstInt(Context); AdjustAPSInt(Hi, CondWidth, CondIsSigned); if (EI->first <= Hi) break; diff --git a/lib/StaticAnalyzer/Checkers/MallocOverflowSecurityChecker.cpp b/lib/StaticAnalyzer/Checkers/MallocOverflowSecurityChecker.cpp index 0f6b621bf7..cf5501a4ac 100644 --- a/lib/StaticAnalyzer/Checkers/MallocOverflowSecurityChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/MallocOverflowSecurityChecker.cpp @@ -118,9 +118,12 @@ private: ASTContext &Context; bool isIntZeroExpr(const Expr *E) const { - return (E->getType()->isIntegralOrEnumerationType() - && E->isEvaluatable(Context) - && E->EvaluateAsInt(Context) == 0); + if (!E->getType()->isIntegralOrEnumerationType()) + return false; + llvm::APSInt Result; + if (E->EvaluateAsInt(Result, Context)) + return Result == 0; + return false; } void CheckExpr(const Expr *E_p) { @@ -263,4 +266,3 @@ void MallocOverflowSecurityChecker::checkASTCodeBody(const Decl *D, void ento::registerMallocOverflowSecurityChecker(CheckerManager &mgr) { mgr.registerChecker(); } - diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp index 9e1c12ce1f..cdc9dcf752 100644 --- a/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -599,7 +599,7 @@ static void GenerateMinimalPathDiagnostic(PathDiagnostic& PD, } if (GetRawInt) - os << LHS->EvaluateAsInt(PDB.getASTContext()); + os << LHS->EvaluateKnownConstInt(PDB.getASTContext()); os << ":' at line " << End.asLocation().getExpansionLineNumber(); diff --git a/utils/TableGen/ClangAttrEmitter.cpp b/utils/TableGen/ClangAttrEmitter.cpp index 5f25b8fa56..5c236be559 100644 --- a/utils/TableGen/ClangAttrEmitter.cpp +++ b/utils/TableGen/ClangAttrEmitter.cpp @@ -239,7 +239,7 @@ namespace { OS << " assert(!is" << getUpperName() << "Dependent());\n"; OS << " if (is" << getLowerName() << "Expr)\n"; OS << " return (" << getLowerName() << "Expr ? " << getLowerName() - << "Expr->EvaluateAsInt(Ctx).getZExtValue() : 16)" + << "Expr->EvaluateKnownConstInt(Ctx).getZExtValue() : 16)" << "* Ctx.getCharWidth();\n"; OS << " else\n"; OS << " return 0; // FIXME\n";