diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 49cc3201db97..4c242059b528 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -916,17 +916,22 @@ bool IntExprEvaluator::VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr *E) { // sizeof(vla) is not a constantexpr: C99 6.5.3.4p2. if (!SrcTy->isConstantSizeType()) return false; - - // sizeof (objc class) ? - if (SrcTy->isObjCInterfaceType()) - return false; // GCC extension: sizeof(function) = 1. if (SrcTy->isFunctionType()) { Result = 1; return true; } - + + if (SrcTy->isObjCInterfaceType()) { + // Slightly unusual case: the size of an ObjC interface type is the + // size of the class. This code intentionally falls through to the normal + // case. + ObjCInterfaceDecl *OI = SrcTy->getAsObjCInterfaceType()->getDecl(); + RecordDecl *RD = const_cast(Info.Ctx.addRecordToClass(OI)); + SrcTy = Info.Ctx.getTagDeclType(static_cast(RD)); + } + // Get information about the size. unsigned CharSize = Info.Ctx.Target.getCharWidth(); Result = Info.Ctx.getTypeSize(SrcTy) / CharSize; diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index b1150cb2d10b..766721e96b44 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -673,45 +673,23 @@ Value *ScalarExprEmitter::VisitUnaryLNot(const UnaryOperator *E) { /// argument of the sizeof expression as an integer. Value * ScalarExprEmitter::VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr *E) { - // Handle alignof with the constant folding logic. alignof always produces a - // constant. - if (!E->isSizeOf()) { - Expr::EvalResult Result; - E->Evaluate(Result, CGF.getContext()); - return llvm::ConstantInt::get(Result.Val.getInt()); - } - - QualType RetType = E->getType(); - assert(RetType->isIntegerType() && "Result type must be an integer!"); - uint32_t ResultWidth = - static_cast(CGF.getContext().getTypeSize(RetType)); - - // sizeof(void) and sizeof(function) = 1 as a strange gcc extension. QualType TypeToSize = E->getTypeOfArgument(); - if (TypeToSize->isVoidType() || TypeToSize->isFunctionType()) - return llvm::ConstantInt::get(llvm::APInt(ResultWidth, 1)); - - if (const VariableArrayType *VAT = - CGF.getContext().getAsVariableArrayType(TypeToSize)) { - if (E->isArgumentType()) { - // sizeof(type) - make sure to emit the VLA size. - CGF.EmitVLASize(TypeToSize); + if (E->isSizeOf()) { + if (const VariableArrayType *VAT = + CGF.getContext().getAsVariableArrayType(TypeToSize)) { + if (E->isArgumentType()) { + // sizeof(type) - make sure to emit the VLA size. + CGF.EmitVLASize(TypeToSize); + } + return CGF.GetVLASize(VAT); } - return CGF.GetVLASize(VAT); } - - if (TypeToSize->isObjCInterfaceType()) { - ObjCInterfaceDecl *OI = TypeToSize->getAsObjCInterfaceType()->getDecl(); - RecordDecl *RD = const_cast( - CGF.getContext().addRecordToClass(OI)); - TypeToSize = CGF.getContext().getTagDeclType(static_cast(RD)); - } - - uint64_t Val = CGF.getContext().getTypeSize(TypeToSize); - // Return size in bytes, not bits. - Val /= CGF.getContext().Target.getCharWidth(); - - return llvm::ConstantInt::get(llvm::APInt(ResultWidth, Val)); + + // If this isn't sizeof(vla), the result must be constant; use the + // constant folding logic so we don't have to duplicate it here. + Expr::EvalResult Result; + E->Evaluate(Result, CGF.getContext()); + return llvm::ConstantInt::get(Result.Val.getInt()); } Value *ScalarExprEmitter::VisitUnaryReal(const UnaryOperator *E) {