From: Eli Friedman Date: Thu, 21 Feb 2008 17:57:49 +0000 (+0000) Subject: Clean up constant implicit cast emission; fixes a few edge cases X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3b707e7476cd46945e4e187b57b7f0ad811d8752;p=clang Clean up constant implicit cast emission; fixes a few edge cases invlolving implicit casts that cause both a decay to pointer type and a type conversion. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@47440 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/CodeGen/CGExprConstant.cpp b/CodeGen/CGExprConstant.cpp index 2cdd5bbb3e..1a60cae5a0 100644 --- a/CodeGen/CGExprConstant.cpp +++ b/CodeGen/CGExprConstant.cpp @@ -200,34 +200,36 @@ public: // Make sure we have an array at this point assert(0 && "Unable to handle InitListExpr"); } - + llvm::Constant *VisitImplicitCastExpr(ImplicitCastExpr *ICExpr) { - // If this is due to array->pointer conversion, emit the array expression as - // an l-value. - if (ICExpr->getSubExpr()->getType()->isArrayType()) { - // Note that VLAs can't exist for global variables. - llvm::Constant *C = EmitLValue(ICExpr->getSubExpr()); - assert(isa(C->getType()) && - isa(cast(C->getType()) - ->getElementType())); + Expr* SExpr = ICExpr->getSubExpr(); + QualType SType = SExpr->getType(); + llvm::Constant *C; // the intermediate expression + QualType T; // the type of the intermediate expression + if (SType->isArrayType()) { + // Arrays decay to a pointer to the first element + // VLAs would require special handling, but they can't occur here + C = EmitLValue(SExpr); llvm::Constant *Idx0 = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0); - llvm::Constant *Ops[] = {Idx0, Idx0}; C = llvm::ConstantExpr::getGetElementPtr(C, Ops, 2); - - // The resultant pointer type can be implicitly cast to other pointer - // types as well, for example void*. - const llvm::Type *DestPTy = ConvertType(ICExpr->getType()); - assert(isa(DestPTy) && - "Only expect implicit cast to pointer"); - return llvm::ConstantExpr::getBitCast(C, DestPTy); + + QualType ElemType = SType->getAsArrayType()->getElementType(); + T = CGM.getContext().getPointerType(ElemType); + } else if (SType->isFunctionType()) { + // Function types decay to a pointer to the function + C = EmitLValue(SExpr); + T = CGM.getContext().getPointerType(SType); + } else { + C = Visit(SExpr); + T = SType; } - - llvm::Constant *C = Visit(ICExpr->getSubExpr()); - - return EmitConversion(C, ICExpr->getSubExpr()->getType(),ICExpr->getType()); + + // Perform the conversion; note that an implicit cast can both promote + // and convert an array/function + return EmitConversion(C, T, ICExpr->getType()); } - + llvm::Constant *VisitStringLiteral(StringLiteral *E) { const char *StrData = E->getStrData(); unsigned Len = E->getByteLength(); @@ -254,8 +256,6 @@ public: llvm::Constant *VisitDeclRefExpr(DeclRefExpr *E) { const ValueDecl *Decl = E->getDecl(); - if (const FunctionDecl *FD = dyn_cast(Decl)) - return CGM.GetAddrOfFunctionDecl(FD, false); if (const EnumConstantDecl *EC = dyn_cast(Decl)) return llvm::ConstantInt::get(EC->getInitVal()); assert(0 && "Unsupported decl ref type!");