diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index bd61666d3fcb..c9376bce377a 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -12640,17 +12640,22 @@ Value *CodeGenFunction::EmitCheerpBuiltinExpr(unsigned BuiltinID, return Builder.CreateCall(Callee, {Vec}); } else if (BuiltinID == Builtin::BImalloc) { - const FunctionDecl* FD=dyn_cast(CurFuncDecl); - assert(FD); - ParentMap PM(FD->getBody()); + const FunctionDecl* FD=dyn_cast_if_present(CurFuncDecl); + const VarDecl* VD=dyn_cast_if_present(CurCodeDecl); + // Malloc might be used as a global initializer, thus CurFuncDecl being null + assert(FD || VD); + // This const_cast below probably is completely safe. When taking a brief + // look at ParentMap, it doesn't seem to ever modify what's passed to it + ParentMap PM(FD ? FD->getBody() : const_cast(VD->getInit())); const Stmt* parent=PM.getParent(E); // We need an explicit cast after the call, void* can't be used llvm::Type *Tys[] = { VoidPtrTy, VoidPtrTy }; const CastExpr* retCE=dyn_cast_or_null(parent); if (!retCE || retCE->getType()->isVoidPointerType()) { - if (asmjs) return 0; - CGM.getDiags().Report(E->getBeginLoc(), diag::err_cheerp_alloc_requires_cast); + if (!asmjs) + CGM.getDiags().Report(E->getBeginLoc(), diag::err_cheerp_alloc_requires_cast); + return 0; } else { @@ -12667,17 +12672,20 @@ Value *CodeGenFunction::EmitCheerpBuiltinExpr(unsigned BuiltinID, return CB; } else if (BuiltinID == Builtin::BIcalloc) { - const FunctionDecl* FD=dyn_cast(CurFuncDecl); - assert(FD); - ParentMap PM(FD->getBody()); + const FunctionDecl* FD=dyn_cast_if_present(CurFuncDecl); + const VarDecl* VD=dyn_cast_if_present(CurCodeDecl); + assert(FD || VD); + // See malloc for note on const_cast + ParentMap PM(FD ? FD->getBody() : const_cast(VD->getInit())); const Stmt* parent=PM.getParent(E); // We need an explicit cast after the call, void* can't be used llvm::Type *Tys[] = { VoidPtrTy , VoidPtrTy}; const CastExpr* retCE=dyn_cast_or_null(parent); if (!retCE || retCE->getType()->isVoidPointerType()) { - if (asmjs) return 0; - CGM.getDiags().Report(E->getBeginLoc(), diag::err_cheerp_alloc_requires_cast); + if (!asmjs) + CGM.getDiags().Report(E->getBeginLoc(), diag::err_cheerp_alloc_requires_cast); + return 0; } else { @@ -12714,16 +12722,19 @@ Value *CodeGenFunction::EmitCheerpBuiltinExpr(unsigned BuiltinID, llvm::Type *Tys[] = { VoidPtrTy, ConvertType(reallocType) }; Ops[0]=EmitScalarExpr(existingMem); // Some additional checks that can't be done in Sema - const FunctionDecl* FD=dyn_cast(CurFuncDecl); - assert(FD); - ParentMap PM(FD->getBody()); + const FunctionDecl* FD=dyn_cast_if_present(CurFuncDecl); + const VarDecl* VD=dyn_cast_if_present(CurCodeDecl); + assert(FD || VD); + // See malloc for note on const_cast + ParentMap PM(FD ? FD->getBody() : const_cast(VD->getInit())); const Stmt* parent=PM.getParent(E); // We need an explicit cast after the call, void* can't be used const CastExpr* retCE=dyn_cast_or_null(parent); if (!retCE || retCE->getType()->isVoidPointerType()) { - if (asmjs) return 0; - CGM.getDiags().Report(E->getBeginLoc(), diag::err_cheerp_alloc_requires_cast); + if (!asmjs) + CGM.getDiags().Report(E->getBeginLoc(), diag::err_cheerp_alloc_requires_cast); + return 0; } else if(retCE->getType().getCanonicalType()!=reallocType.getCanonicalType()) {