diff options
| -rw-r--r-- | clang/lib/CodeGen/CGCXX.cpp | 74 | ||||
| -rw-r--r-- | clang/test/CodeGenCXX/new.cpp | 5 | 
2 files changed, 77 insertions, 2 deletions
diff --git a/clang/lib/CodeGen/CGCXX.cpp b/clang/lib/CodeGen/CGCXX.cpp index 805805c6632..cf09bf62a02 100644 --- a/clang/lib/CodeGen/CGCXX.cpp +++ b/clang/lib/CodeGen/CGCXX.cpp @@ -227,8 +227,78 @@ CodeGenFunction::EmitCXXExprWithTemporaries(const CXXExprWithTemporaries *E,  }  llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) { -  ErrorUnsupported(E, "new expression"); -  return llvm::UndefValue::get(ConvertType(E->getType())); +  if (E->isArray()) { +    ErrorUnsupported(E, "new[] expression"); +    return llvm::UndefValue::get(ConvertType(E->getType())); +  } +   +  QualType AllocType = E->getAllocatedType(); +  FunctionDecl *NewFD = E->getOperatorNew(); +  const FunctionProtoType *NewFTy = NewFD->getType()->getAsFunctionProtoType(); +   +  CallArgList NewArgs; + +  // The allocation size is the first argument. +  QualType SizeTy = getContext().getSizeType(); +  llvm::Value *AllocSize =  +    llvm::ConstantInt::get(ConvertType(SizeTy),  +                           getContext().getTypeSize(AllocType) / 8); + +  NewArgs.push_back(std::make_pair(RValue::get(AllocSize), SizeTy)); +   +  // Emit the rest of the arguments. +  // FIXME: Ideally, this should just use EmitCallArgs. +  CXXNewExpr::const_arg_iterator NewArg = E->placement_arg_begin(); + +  // First, use the types from the function type. +  // We start at 1 here because the first argument (the allocation size) +  // has already been emitted. +  for (unsigned i = 1, e = NewFTy->getNumArgs(); i != e; ++i, ++NewArg) { +    QualType ArgType = NewFTy->getArgType(i); +     +    assert(getContext().getCanonicalType(ArgType.getNonReferenceType()). +           getTypePtr() ==  +           getContext().getCanonicalType(NewArg->getType()).getTypePtr() &&  +           "type mismatch in call argument!"); +     +    NewArgs.push_back(std::make_pair(EmitCallArg(*NewArg, ArgType),  +                                     ArgType)); +     +  } +   +  // Either we've emitted all the call args, or we have a call to a  +  // variadic function. +  assert((NewArg == E->placement_arg_end() || NewFTy->isVariadic()) &&  +         "Extra arguments in non-variadic function!"); +   +  // If we still have any arguments, emit them using the type of the argument. +  for (CXXNewExpr::const_arg_iterator NewArgEnd = E->placement_arg_end();  +       NewArg != NewArgEnd; ++NewArg) { +    QualType ArgType = NewArg->getType(); +    NewArgs.push_back(std::make_pair(EmitCallArg(*NewArg, ArgType), +                                     ArgType)); +  } + +  // Emit the call to new. +  RValue RV =  +    EmitCall(CGM.getTypes().getFunctionInfo(NewFTy->getResultType(), NewArgs), +             CGM.GetAddrOfFunction(GlobalDecl(NewFD)), +             NewArgs, NewFD); + +  llvm::Value *V = Builder.CreateBitCast(RV.getScalarVal(),  +                                         ConvertType(E->getType())); + +  if (E->hasInitializer()) { +    ErrorUnsupported(E, "new expression with initializer"); +    return llvm::UndefValue::get(ConvertType(E->getType())); +  } +   +  if (!AllocType->isPODType()) { +    ErrorUnsupported(E, "new expression with non-POD type"); +    return llvm::UndefValue::get(ConvertType(E->getType())); +  }     +     +  return V;  }  static bool canGenerateCXXstructor(const CXXRecordDecl *RD,  diff --git a/clang/test/CodeGenCXX/new.cpp b/clang/test/CodeGenCXX/new.cpp new file mode 100644 index 00000000000..fddda2b5b5f --- /dev/null +++ b/clang/test/CodeGenCXX/new.cpp @@ -0,0 +1,5 @@ +// RUN: clang-cc %s -emit-llvm -o %t + +void t1() { +  int* a = new int; +}  | 

