/// allocation function. [...]
///
/// If this function is an aligned allocation/deallocation function, return
- /// true through IsAligned.
- bool isReplaceableGlobalAllocationFunction(bool *IsAligned = nullptr) const;
+ /// the parameter number of the requested alignment through AlignmentParam.
+ ///
+ /// If this function is an allocation/deallocation function that takes
+ /// the `std::nothrow_t` tag, return true through IsNothrow,
+ bool isReplaceableGlobalAllocationFunction(
+ Optional<unsigned> *AlignmentParam = nullptr,
+ bool *IsNothrow = nullptr) const;
/// Determine if this function provides an inline implementation of a builtin.
bool isInlineBuiltinDeclaration() const;
SourceLocation Loc);
NamedDecl *ImplicitlyDefineFunction(SourceLocation Loc, IdentifierInfo &II,
Scope *S);
+ void AddKnownFunctionAttributesForReplaceableGlobalAllocationFunction(
+ FunctionDecl *FD);
void AddKnownFunctionAttributes(FunctionDecl *FD);
// More parsing and symbol table subroutines.
return (proto->getParamType(1).getCanonicalType() == Context.VoidPtrTy);
}
-bool FunctionDecl::isReplaceableGlobalAllocationFunction(bool *IsAligned) const {
+bool FunctionDecl::isReplaceableGlobalAllocationFunction(
+ Optional<unsigned> *AlignmentParam, bool *IsNothrow) const {
if (getDeclName().getNameKind() != DeclarationName::CXXOperatorName)
return false;
if (getDeclName().getCXXOverloadedOperator() != OO_New &&
// In C++17, the next parameter can be a 'std::align_val_t' for aligned
// new/delete.
if (Ctx.getLangOpts().AlignedAllocation && !Ty.isNull() && Ty->isAlignValT()) {
- if (IsAligned)
- *IsAligned = true;
Consume();
+ if (AlignmentParam)
+ *AlignmentParam = Params;
}
// Finally, if this is not a sized delete, the final parameter can
Ty = Ty->getPointeeType();
if (Ty.getCVRQualifiers() != Qualifiers::Const)
return false;
- if (Ty->isNothrowT())
+ if (Ty->isNothrowT()) {
+ if (IsNothrow)
+ *IsNothrow = true;
Consume();
+ }
}
return Params == FPT->getNumParams();
if (const FunctionDecl *Fn = dyn_cast<FunctionDecl>(TargetDecl)) {
AddAttributesFromFunctionProtoType(
getContext(), FuncAttrs, Fn->getType()->getAs<FunctionProtoType>());
+ if (AttrOnCallSite && Fn->isReplaceableGlobalAllocationFunction()) {
+ // A sane operator new returns a non-aliasing pointer.
+ auto Kind = Fn->getDeclName().getCXXOverloadedOperator();
+ if (getCodeGenOpts().AssumeSaneOperatorNew &&
+ (Kind == OO_New || Kind == OO_Array_New))
+ RetAttrs.addAttribute(llvm::Attribute::NoAlias);
+ }
const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Fn);
const bool IsVirtualCall = MD && MD->isVirtual();
// Don't use [[noreturn]], _Noreturn or [[no_builtin]] for a call to a
// default, only if it is invoked by a new-expression or delete-expression.
F->addAttribute(llvm::AttributeList::FunctionIndex,
llvm::Attribute::NoBuiltin);
-
- // A sane operator new returns a non-aliasing pointer.
- // FIXME: Also add NonNull attribute to the return value
- // for the non-nothrow forms?
- auto Kind = FD->getDeclName().getCXXOverloadedOperator();
- if (getCodeGenOpts().AssumeSaneOperatorNew &&
- (Kind == OO_New || Kind == OO_Array_New))
- F->addAttribute(llvm::AttributeList::ReturnIndex,
- llvm::Attribute::NoAlias);
}
if (isa<CXXConstructorDecl>(FD) || isa<CXXDestructorDecl>(FD))
return FD;
}
+/// If this function is a C++ replaceable global allocation function
+/// (C++2a [basic.stc.dynamic.allocation], C++2a [new.delete]),
+/// adds any function attributes that we know a priori based on the standard.
+///
+/// We need to check for duplicate attributes both here and where user-written
+/// attributes are applied to declarations.
+void Sema::AddKnownFunctionAttributesForReplaceableGlobalAllocationFunction(
+ FunctionDecl *FD) {
+ if (FD->isInvalidDecl())
+ return;
+
+ if (FD->getDeclName().getCXXOverloadedOperator() != OO_New &&
+ FD->getDeclName().getCXXOverloadedOperator() != OO_Array_New)
+ return;
+
+ Optional<unsigned> AlignmentParam;
+ bool IsNothrow = false;
+ if (!FD->isReplaceableGlobalAllocationFunction(&AlignmentParam, &IsNothrow))
+ return;
+
+ // C++2a [basic.stc.dynamic.allocation]p4:
+ // An allocation function that has a non-throwing exception specification
+ // indicates failure by returning a null pointer value. Any other allocation
+ // function never returns a null pointer value and indicates failure only by
+ // throwing an exception [...]
+ if (!IsNothrow && !FD->hasAttr<ReturnsNonNullAttr>())
+ FD->addAttr(ReturnsNonNullAttr::CreateImplicit(Context, FD->getLocation()));
+
+ // C++2a [basic.stc.dynamic.allocation]p2:
+ // An allocation function attempts to allocate the requested amount of
+ // storage. [...] If the request succeeds, the value returned by a
+ // replaceable allocation function is a [...] pointer value p0 different
+ // from any previously returned value p1 [...]
+ //
+ // However, this particular information is being added in codegen,
+ // because there is an opt-out switch for it (-fno-assume-sane-operator-new)
+
+ // C++2a [basic.stc.dynamic.allocation]p2:
+ // An allocation function attempts to allocate the requested amount of
+ // storage. If it is successful, it returns the address of the start of a
+ // block of storage whose length in bytes is at least as large as the
+ // requested size.
+ if (!FD->hasAttr<AllocSizeAttr>()) {
+ FD->addAttr(AllocSizeAttr::CreateImplicit(
+ Context, /*ElemSizeParam=*/ParamIdx(1, FD),
+ /*NumElemsParam=*/ParamIdx(), FD->getLocation()));
+ }
+
+ // C++2a [basic.stc.dynamic.allocation]p3:
+ // For an allocation function [...], the pointer returned on a successful
+ // call shall represent the address of storage that is aligned as follows:
+ // (3.1) If the allocation function takes an argument of type
+ // std​::​align_Âval_Ât, the storage will have the alignment
+ // specified by the value of this argument.
+ if (AlignmentParam.hasValue() && !FD->hasAttr<AllocAlignAttr>()) {
+ FD->addAttr(AllocAlignAttr::CreateImplicit(
+ Context, ParamIdx(AlignmentParam.getValue(), FD), FD->getLocation()));
+ }
+
+ // FIXME:
+ // C++2a [basic.stc.dynamic.allocation]p3:
+ // For an allocation function [...], the pointer returned on a successful
+ // call shall represent the address of storage that is aligned as follows:
+ // (3.2) Otherwise, if the allocation function is named operator new[],
+ // the storage is aligned for any object that does not have
+ // new-extended alignment ([basic.align]) and is no larger than the
+ // requested size.
+ // (3.3) Otherwise, the storage is aligned for any object that does not
+ // have new-extended alignment and is of the requested size.
+}
+
/// Adds any function attributes that we know a priori based on
/// the declaration of this function.
///
}
}
+ AddKnownFunctionAttributesForReplaceableGlobalAllocationFunction(FD);
+
// If C++ exceptions are enabled but we are told extern "C" functions cannot
// throw, add an implicit nothrow attribute to any extern "C" function we come
// across.
return false;
if (FD.isDefined())
return false;
- bool IsAligned = false;
- if (FD.isReplaceableGlobalAllocationFunction(&IsAligned) && IsAligned)
+ Optional<unsigned> AlignmentParam;
+ if (FD.isReplaceableGlobalAllocationFunction(&AlignmentParam) &&
+ AlignmentParam.hasValue())
return true;
return false;
}
Alloc->setParams(ParamDecls);
if (ExtraAttr)
Alloc->addAttr(ExtraAttr);
+ AddKnownFunctionAttributesForReplaceableGlobalAllocationFunction(Alloc);
Context.getTranslationUnitDecl()->addDecl(Alloc);
IdResolver.tryAddTopLevelDecl(Alloc, Name);
};
// CHECK-NEXT: "end": {}
// CHECK-NEXT: },
// CHECK-NEXT: "implicit": true
+// CHECK-NEXT: },
+// CHECK-NEXT: {
+// CHECK-NEXT: "id": "0x{{.*}}",
+// CHECK-NEXT: "kind": "ReturnsNonNullAttr",
+// CHECK-NEXT: "range": {
+// CHECK-NEXT: "begin": {},
+// CHECK-NEXT: "end": {}
+// CHECK-NEXT: },
+// CHECK-NEXT: "implicit": true
+// CHECK-NEXT: },
+// CHECK-NEXT: {
+// CHECK-NEXT: "id": "0x{{.*}}",
+// CHECK-NEXT: "kind": "AllocSizeAttr",
+// CHECK-NEXT: "range": {
+// CHECK-NEXT: "begin": {},
+// CHECK-NEXT: "end": {}
+// CHECK-NEXT: },
+// CHECK-NEXT: "implicit": true
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: }
// CHECK-NEXT: "end": {}
// CHECK-NEXT: },
// CHECK-NEXT: "implicit": true
+// CHECK-NEXT: },
+// CHECK-NEXT: {
+// CHECK-NEXT: "id": "0x{{.*}}",
+// CHECK-NEXT: "kind": "ReturnsNonNullAttr",
+// CHECK-NEXT: "range": {
+// CHECK-NEXT: "begin": {},
+// CHECK-NEXT: "end": {}
+// CHECK-NEXT: },
+// CHECK-NEXT: "implicit": true
+// CHECK-NEXT: },
+// CHECK-NEXT: {
+// CHECK-NEXT: "id": "0x{{.*}}",
+// CHECK-NEXT: "kind": "AllocSizeAttr",
+// CHECK-NEXT: "range": {
+// CHECK-NEXT: "begin": {},
+// CHECK-NEXT: "end": {}
+// CHECK-NEXT: },
+// CHECK-NEXT: "implicit": true
+// CHECK-NEXT: },
+// CHECK-NEXT: {
+// CHECK-NEXT: "id": "0x{{.*}}",
+// CHECK-NEXT: "kind": "AllocAlignAttr",
+// CHECK-NEXT: "range": {
+// CHECK-NEXT: "begin": {},
+// CHECK-NEXT: "end": {}
+// CHECK-NEXT: },
+// CHECK-NEXT: "implicit": true
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: }
// CHECK-NEXT: "end": {}
// CHECK-NEXT: },
// CHECK-NEXT: "implicit": true
+// CHECK-NEXT: },
+// CHECK-NEXT: {
+// CHECK-NEXT: "id": "0x{{.*}}",
+// CHECK-NEXT: "kind": "ReturnsNonNullAttr",
+// CHECK-NEXT: "range": {
+// CHECK-NEXT: "begin": {},
+// CHECK-NEXT: "end": {}
+// CHECK-NEXT: },
+// CHECK-NEXT: "implicit": true
+// CHECK-NEXT: },
+// CHECK-NEXT: {
+// CHECK-NEXT: "id": "0x{{.*}}",
+// CHECK-NEXT: "kind": "AllocSizeAttr",
+// CHECK-NEXT: "range": {
+// CHECK-NEXT: "begin": {},
+// CHECK-NEXT: "end": {}
+// CHECK-NEXT: },
+// CHECK-NEXT: "implicit": true
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: }
// CHECK-NEXT: "end": {}
// CHECK-NEXT: },
// CHECK-NEXT: "implicit": true
+// CHECK-NEXT: },
+// CHECK-NEXT: {
+// CHECK-NEXT: "id": "0x{{.*}}",
+// CHECK-NEXT: "kind": "ReturnsNonNullAttr",
+// CHECK-NEXT: "range": {
+// CHECK-NEXT: "begin": {},
+// CHECK-NEXT: "end": {}
+// CHECK-NEXT: },
+// CHECK-NEXT: "implicit": true
+// CHECK-NEXT: },
+// CHECK-NEXT: {
+// CHECK-NEXT: "id": "0x{{.*}}",
+// CHECK-NEXT: "kind": "AllocSizeAttr",
+// CHECK-NEXT: "range": {
+// CHECK-NEXT: "begin": {},
+// CHECK-NEXT: "end": {}
+// CHECK-NEXT: },
+// CHECK-NEXT: "implicit": true
+// CHECK-NEXT: },
+// CHECK-NEXT: {
+// CHECK-NEXT: "id": "0x{{.*}}",
+// CHECK-NEXT: "kind": "AllocAlignAttr",
+// CHECK-NEXT: "range": {
+// CHECK-NEXT: "begin": {},
+// CHECK-NEXT: "end": {}
+// CHECK-NEXT: },
+// CHECK-NEXT: "implicit": true
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: }
if (!x) // expected-note {{Assuming 'x' is non-null}}
// expected-note@-1 {{Taking false branch}}
return nullptr;
+ // expected-warning@-1 {{null returned from function that requires a non-null return value}}
return x;
}
void *operator new(size_t size) {
return nullptr;
// expected-warning@-1 {{'operator new' should not return a null pointer unless it is declared 'throw()' or 'noexcept'}}
+ // expected-warning@-2 {{null returned from function that requires a non-null return value}}
}
void *operator new[](size_t size) {
return nullptr;
// expected-warning@-1 {{'operator new[]' should not return a null pointer unless it is declared 'throw()' or 'noexcept'}}
+ // expected-warning@-2 {{null returned from function that requires a non-null return value}}
}
struct S {
void *operator new(size_t size) throw() {
return nullptr;
+ // expected-warning@-1 {{null returned from function that requires a non-null return value}}
}
void *operator new[](size_t size) throw() {
return nullptr;
+ // expected-warning@-1 {{null returned from function that requires a non-null return value}}
}
struct S {
}
// CHECK: [[R:%.*]] = alloca <8 x float>, align 32
-// CHECK-NEXT: [[CALL:%.*]] = call i8* @_Znwm(i64 32)
+// CHECK-NEXT: [[CALL:%.*]] = call noalias nonnull i8* @_Znwm(i64 32)
// CHECK-NEXT: [[ZERO:%.*]] = bitcast i8* [[CALL]] to <8 x float>*
// CHECK-NEXT: store <8 x float>* [[ZERO]], <8 x float>** [[P:%.*]], align 8
// CHECK-NEXT: [[ONE:%.*]] = load <8 x float>*, <8 x float>** [[P]], align 8
}
// CHECK: [[R:%.*]] = alloca <8 x float>, align 32
-// CHECK-NEXT: [[CALL:%.*]] = call i8* @_Znwm(i64 32)
+// CHECK-NEXT: [[CALL:%.*]] = call noalias nonnull i8* @_Znwm(i64 32)
// CHECK-NEXT: [[ZERO:%.*]] = bitcast i8* [[CALL]] to <8 x float>*
// CHECK-NEXT: store <8 x float>* [[ZERO]], <8 x float>** [[P:%.*]], align 8
// CHECK-NEXT: [[ONE:%.*]] = load <8 x float>*, <8 x float>** [[P]], align 8
void a() {
// CHECK-LABEL: define void @_ZN5test31aEv()
- // CHECK: call i8* @_Znam(i32 48)
+ // CHECK: call noalias nonnull i8* @_Znam(i32 48)
// CHECK: store i32 4
// CHECK: store i32 10
A *x = new A[10];
// CHECK: @llvm.uadd.with.overflow.i32(i32 {{.*}}, i32 8)
// CHECK: [[OR:%.*]] = or i1
// CHECK: [[SZ:%.*]] = select i1 [[OR]]
- // CHECK: call i8* @_Znam(i32 [[SZ]])
+ // CHECK: call noalias nonnull i8* @_Znam(i32 [[SZ]])
// CHECK: store i32 4
// CHECK: store i32 [[N]]
A *x = new A[n];
void c() {
// CHECK-LABEL: define void @_ZN5test31cEv()
- // CHECK: call i8* @_Znam(i32 808)
+ // CHECK: call noalias nonnull i8* @_Znam(i32 808)
// CHECK: store i32 4
// CHECK: store i32 200
A (*x)[20] = new A[10][20];
// CHECK: [[NE:%.*]] = mul i32 [[N]], 20
// CHECK: @llvm.uadd.with.overflow.i32(i32 {{.*}}, i32 8)
// CHECK: [[SZ:%.*]] = select
- // CHECK: call i8* @_Znam(i32 [[SZ]])
+ // CHECK: call noalias nonnull i8* @_Znam(i32 [[SZ]])
// CHECK: store i32 4
// CHECK: store i32 [[NE]]
A (*x)[20] = new A[n][20];
void a() {
// CHECK-LABEL: define void @_ZN5test41aEv()
- // CHECK: call i8* @_Znam(i32 48)
+ // CHECK: call noalias nonnull i8* @_Znam(i32 48)
// CHECK: store i32 4
// CHECK: store i32 10
A *x = new A[10];
// CHECK: @llvm.umul.with.overflow.i32(i32 [[N]], i32 4)
// CHECK: @llvm.uadd.with.overflow.i32(i32 {{.*}}, i32 8)
// CHECK: [[SZ:%.*]] = select
- // CHECK: call i8* @_Znam(i32 [[SZ]])
+ // CHECK: call noalias nonnull i8* @_Znam(i32 [[SZ]])
// CHECK: store i32 4
// CHECK: store i32 [[N]]
A *x = new A[n];
void c() {
// CHECK-LABEL: define void @_ZN5test41cEv()
- // CHECK: call i8* @_Znam(i32 808)
+ // CHECK: call noalias nonnull i8* @_Znam(i32 808)
// CHECK: store i32 4
// CHECK: store i32 200
A (*x)[20] = new A[10][20];
// CHECK: [[NE:%.*]] = mul i32 [[N]], 20
// CHECK: @llvm.uadd.with.overflow.i32(i32 {{.*}}, i32 8)
// CHECK: [[SZ:%.*]] = select
- // CHECK: call i8* @_Znam(i32 [[SZ]])
+ // CHECK: call noalias nonnull i8* @_Znam(i32 [[SZ]])
// CHECK: store i32 4
// CHECK: store i32 [[NE]]
A (*x)[20] = new A[n][20];
// CHECK-NEXT: [[OVERFLOW:%.*]] = or i1 [[O0]], [[O1]]
// CHECK-NEXT: [[T3:%.*]] = extractvalue { i32, i1 } [[T2]], 0
// CHECK-NEXT: [[T4:%.*]] = select i1 [[OVERFLOW]], i32 -1, i32 [[T3]]
-// CHECK-NEXT: [[ALLOC:%.*]] = call i8* @_Znam(i32 [[T4]])
+// CHECK-NEXT: [[ALLOC:%.*]] = call noalias nonnull i8* @_Znam(i32 [[T4]])
// CHECK-NEXT: [[T0:%.*]] = bitcast i8* [[ALLOC]] to i32*
// CHECK-NEXT: store i32 16, i32* [[T0]]
// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i32, i32* [[T0]], i32 1
}
// LINUX: define void @_Z4userv()
-// LINUX: call i8* @_Znwm
+// LINUX: call noalias nonnull i8* @_Znwm
// LINUX: call float @atan2f
// LINUX: call void @_Z3foov
-// LINUX: declare noalias i8* @_Znwm(i64)
+// LINUX: declare nonnull i8* @_Znwm(i64)
// LINUX: declare float @atan2f(float, float)
// LINUX: declare void @_Z3foov()
// SPIR: define spir_func void @_Z4userv()
-// SPIR: call spir_func i8* @_Znwj
+// SPIR: call spir_func noalias nonnull i8* @_Znwj
// SPIR: call spir_func float @atan2f
// SPIR: call spir_func void @_Z3foov
-// SPIR: declare spir_func noalias i8* @_Znwj(i32)
+// SPIR: declare spir_func nonnull i8* @_Znwj(i32)
// SPIR: declare spir_func float @atan2f(float, float)
// SPIR: declare spir_func void @_Z3foov()
// Note: Windows /G options should not change the platform default calling
// convention of builtins.
// WIN32: define dso_local x86_stdcallcc void @"?user@@YGXXZ"()
-// WIN32: call i8* @"??2@YAPAXI@Z"
+// WIN32: call noalias nonnull i8* @"??2@YAPAXI@Z"
// WIN32: call float @atan2f
// WIN32: call x86_stdcallcc void @"?foo@@YGXXZ"
-// WIN32: declare dso_local noalias i8* @"??2@YAPAXI@Z"(
+// WIN32: declare dso_local nonnull i8* @"??2@YAPAXI@Z"(
// WIN32: declare dso_local float @atan2f(float, float)
// WIN32: declare dso_local x86_stdcallcc void @"?foo@@YGXXZ"()
// CHECK-ARR-LABEL: define void @_Z17test_new_arr_exprv
void test_new_arr_expr() {
- // CHECK-ARR: call i8* @_Znam(i64 17)
+ // CHECK-ARR: call noalias nonnull i8* @_Znam(i64 17)
new char[std::is_constant_evaluated() || __builtin_is_constant_evaluated() ? 1 : 17];
}
static int i_non_constant = 101;
// CHECK-FOLD: store i32* @_ZZ22test_ref_to_static_varvE10i_constant, i32** %r,
int &r = __builtin_is_constant_evaluated() ? i_constant : i_non_constant;
-}
\ No newline at end of file
+}
// CHECK-LABEL: define void @test_basic(
extern "C" void test_basic() {
- // CHECK: call i8* @_Znwm(i64 4) [[ATTR_BUILTIN_NEW:#[^ ]*]]
+ // CHECK: call noalias nonnull i8* @_Znwm(i64 4) [[ATTR_BUILTIN_NEW:#[^ ]*]]
// CHECK: call void @_ZdlPv({{.*}}) [[ATTR_BUILTIN_DELETE:#[^ ]*]]
// CHECK: ret void
__builtin_operator_delete(__builtin_operator_new(4));
}
-// CHECK: declare noalias i8* @_Znwm(i64) [[ATTR_NOBUILTIN:#[^ ]*]]
+// CHECK: declare nonnull i8* @_Znwm(i64) [[ATTR_NOBUILTIN:#[^ ]*]]
// CHECK: declare void @_ZdlPv(i8*) [[ATTR_NOBUILTIN_NOUNWIND:#[^ ]*]]
// CHECK-LABEL: define void @test_aligned_alloc(
extern "C" void test_aligned_alloc() {
- // CHECK: call i8* @_ZnwmSt11align_val_t(i64 4, i64 4) [[ATTR_BUILTIN_NEW:#[^ ]*]]
+ // CHECK: call noalias nonnull align 4 i8* @_ZnwmSt11align_val_t(i64 4, i64 4) [[ATTR_BUILTIN_NEW:#[^ ]*]]
// CHECK: call void @_ZdlPvSt11align_val_t({{.*}}, i64 4) [[ATTR_BUILTIN_DELETE:#[^ ]*]]
__builtin_operator_delete(__builtin_operator_new(4, std::align_val_t(4)), std::align_val_t(4));
}
-// CHECK: declare noalias i8* @_ZnwmSt11align_val_t(i64, i64) [[ATTR_NOBUILTIN:#[^ ]*]]
+// CHECK: declare nonnull i8* @_ZnwmSt11align_val_t(i64, i64) [[ATTR_NOBUILTIN:#[^ ]*]]
// CHECK: declare void @_ZdlPvSt11align_val_t(i8*, i64) [[ATTR_NOBUILTIN_NOUNWIND:#[^ ]*]]
-
// CHECK-LABEL: define void @test_sized_delete(
extern "C" void test_sized_delete() {
- // CHECK: call i8* @_Znwm(i64 4) [[ATTR_BUILTIN_NEW:#[^ ]*]]
+ // CHECK: call noalias nonnull i8* @_Znwm(i64 4) [[ATTR_BUILTIN_NEW:#[^ ]*]]
// CHECK: call void @_ZdlPvm({{.*}}, i64 4) [[ATTR_BUILTIN_DELETE:#[^ ]*]]
__builtin_operator_delete(__builtin_operator_new(4), 4);
}
void fn10(int i) {
// CHECK-LABEL: define void @_Z4fn10i
// CHECK: alloca [3 x i32]
- // CHECK: call i8* @_Znw{{[jm]}}
+ // CHECK-X86: call noalias nonnull align 16 i8* @_Znw{{[jm]}}
+ // CHECK-AMDGPU: call noalias nonnull align 8 i8* @_Znw{{[jm]}}
// CHECK: store i32 %
// CHECK: store i32 2
// CHECK: store i32 3
void *p = new S[2][3]{ { 1, 2, 3 }, { 4, 5, 6 } };
// CHECK-LABEL: define
-// CHECK: %[[ALLOC:.*]] = call i8* @_Znam(i64 32)
+// CHECK: %[[ALLOC:.*]] = call noalias nonnull i8* @_Znam(i64 32)
// CHECK: %[[COOKIE:.*]] = bitcast i8* %[[ALLOC]] to i64*
// CHECK: store i64 6, i64* %[[COOKIE]]
// CHECK: %[[START_AS_i8:.*]] = getelementptr inbounds i8, i8* %[[ALLOC]], i64 8
// CHECK: call {{.*}} @llvm.umul.with.overflow.i64(i64 %[[N:.*]], i64 12)
// CHECK: %[[ELTS:.*]] = mul i64 %[[N]], 3
// CHECK: call {{.*}} @llvm.uadd.with.overflow.i64(i64 %{{.*}}, i64 8)
-// CHECK: %[[ALLOC:.*]] = call i8* @_Znam(i64 %{{.*}})
+// CHECK: %[[ALLOC:.*]] = call noalias nonnull i8* @_Znam(i64 %{{.*}})
//
// CHECK: %[[COOKIE:.*]] = bitcast i8* %[[ALLOC]] to i64*
// CHECK: store i64 %[[ELTS]], i64* %[[COOKIE]]
// No cookie.
// CHECK-NOT: @llvm.uadd.with.overflow
//
-// CHECK: %[[ALLOC:.*]] = call i8* @_Znam(i64 %{{.*}})
+// CHECK: %[[ALLOC:.*]] = call noalias nonnull i8* @_Znam(i64 %{{.*}})
//
// CHECK: %[[START_AS_T:.*]] = bitcast i8* %[[ALLOC]] to %[[T:.*]]*
//
// CHECK: call void @llvm.memset.p0i8.i64(i8* align 4 %[[REST]], i8 0, i64 %[[SIZE]], i1 false)
//
// CHECK: }
-
struct OVERALIGNED A { A(); int n[128]; };
// CHECK-LABEL: define {{.*}} @_Z2a0v()
-// CHECK: %[[ALLOC:.*]] = call i8* @_ZnwmSt11align_val_t(i64 512, i64 32)
+// CHECK: %[[ALLOC:.*]] = call noalias nonnull align 32 i8* @_ZnwmSt11align_val_t(i64 512, i64 32)
// CHECK: call void @_ZdlPvSt11align_val_t(i8* %[[ALLOC]], i64 32)
// CHECK-MS-LABEL: define {{.*}} @"?a0@@YAPEAXXZ"()
-// CHECK-MS: %[[ALLOC:.*]] = call i8* @"??2@YAPEAX_KW4align_val_t@std@@@Z"(i64 512, i64 32)
+// CHECK-MS: %[[ALLOC:.*]] = call noalias nonnull align 32 i8* @"??2@YAPEAX_KW4align_val_t@std@@@Z"(i64 512, i64 32)
// CHECK-MS: cleanuppad
// CHECK-MS: call void @"??3@YAXPEAXW4align_val_t@std@@@Z"(i8* %[[ALLOC]], i64 32)
void *a0() { return new A; }
// The size is known.
//
// CHECK-LABEL: define {{.*}} @_Z2a1l(
-// CHECK: %[[ALLOC:.*]] = call i8* @_ZnamSt11align_val_t(i64 %{{.*}}, i64 32)
+// CHECK: %[[ALLOC:.*]] = call noalias nonnull align 32 i8* @_ZnamSt11align_val_t(i64 %{{.*}}, i64 32)
// No array cookie.
// CHECK-NOT: store
// CHECK: invoke void @_ZN1AC1Ev(
// CHECK: call void @_ZdaPvSt11align_val_t(i8* %[[ALLOC]], i64 32)
// CHECK-MS-LABEL: define {{.*}} @"?a1@@YAPEAXJ@Z"(
-// CHECK-MS: %[[ALLOC:.*]] = call i8* @"??_U@YAPEAX_KW4align_val_t@std@@@Z"(i64 %{{.*}}, i64 32)
+// CHECK-MS: %[[ALLOC:.*]] = call noalias nonnull align 32 i8* @"??_U@YAPEAX_KW4align_val_t@std@@@Z"(i64 %{{.*}}, i64 32)
// No array cookie.
// CHECK-MS-NOT: store
// CHECK-MS: invoke %struct.A* @"??0A@@QEAA@XZ"(
void *b0() { return new B; }
// CHECK-LABEL: define {{.*}} @_Z2b1l(
-// CHECK: %[[ALLOC:.*]] = call i8* @_ZnamSt11align_val_t(i64 %{{.*}}, i64 32)
+// CHECK: %[[ALLOC:.*]] = call noalias nonnull align 32 i8* @_ZnamSt11align_val_t(i64 %{{.*}}, i64 32)
// No array cookie.
// CHECK-NOT: store
// CHECK: invoke void @_ZN1BC1Ev(
#ifndef UNALIGNED
// CHECK-LABEL: define {{.*}} @_Z2e0v(
-// CHECK: %[[ALLOC:.*]] = call i8* @_ZnwmSt11align_val_t(i64 512, i64 5)
-// CHECK: call void @_ZdlPvSt11align_val_t(i8* %[[ALLOC]], i64 5)
-void *e0() { return new (std::align_val_t(5)) A; }
+// CHECK: %[[ALLOC:.*]] = call noalias nonnull align 4 i8* @_ZnwmSt11align_val_t(i64 512, i64 4)
+// CHECK: call void @_ZdlPvSt11align_val_t(i8* %[[ALLOC]], i64 4)
+void *e0() { return new (std::align_val_t(4)) A; }
// CHECK-LABEL: define {{.*}} @_Z2e1v(
-// CHECK: %[[ALLOC:.*]] = call i8* @_ZN1BnwEmSt11align_val_t(i64 512, i64 5)
-// CHECK: call void @_ZN1BdlEPvSt11align_val_t(i8* %[[ALLOC]], i64 5)
-void *e1() { return new (std::align_val_t(5)) B; }
+// CHECK: %[[ALLOC:.*]] = call i8* @_ZN1BnwEmSt11align_val_t(i64 512, i64 4)
+// CHECK: call void @_ZN1BdlEPvSt11align_val_t(i8* %[[ALLOC]], i64 4)
+void *e1() { return new (std::align_val_t(4)) B; }
#endif
// Variadic placement/non-placement allocation functions.
// CHECK: define [[A:%.*]]* @_ZN5test24testEv()
A *test() {
- // CHECK: [[NEW:%.*]] = call i8* @_Znaj(i32 44)
+ // CHECK: [[NEW:%.*]] = call noalias nonnull i8* @_Znaj(i32 44)
// CHECK-NEXT: [[T0:%.*]] = bitcast i8* [[NEW]] to i32*
// CHECK-NEXT: store i32 10, i32* [[T0]]
// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, i8* [[NEW]], i32 4
struct A {
int x;
void operator delete[](void *, size_t);
- };
+ };
struct B : A {};
// CHECK-LABEL: define void @_ZN5test34testEv()
void test() {
- // CHECK: call i8* @_Znaj(i32 24)
- // CHECK-NEXT: bitcast
+ // CHECK: [[CALL:%.*]] = call noalias nonnull i8* @_Znaj(i32 24)
+ // CHECK-NEXT: bitcast i8* [[CALL]] to i32*
// CHECK-NEXT: store i32 5
(void) new B[5];
}
void Befriended::func() {}
// Implicit declarations can be redeclared with dllexport.
-// MSC-DAG: define dso_local dllexport noalias i8* @"??2@{{YAPAXI|YAPEAX_K}}@Z"(
-// GNU-DAG: define dso_local dllexport noalias i8* @_Znw{{[yj]}}(
+// MSC-DAG: define dso_local dllexport nonnull i8* @"??2@{{YAPAXI|YAPEAX_K}}@Z"(
+// GNU-DAG: define dso_local dllexport nonnull i8* @_Znw{{[yj]}}(
void* alloc(__SIZE_TYPE__ n);
__declspec(dllexport) void* operator new(__SIZE_TYPE__ n) { return alloc(n); }
USE(friend5)
// Implicit declarations can be redeclared with dllimport.
-// MSC-DAG: declare dllimport noalias i8* @"??2@{{YAPAXI|YAPEAX_K}}@Z"(
-// GNU-DAG: declare dllimport noalias i8* @_Znw{{[yj]}}(
+// MSC-DAG: declare dllimport nonnull i8* @"??2@{{YAPAXI|YAPEAX_K}}@Z"(
+// GNU-DAG: declare dllimport nonnull i8* @_Znw{{[yj]}}(
__declspec(dllimport) void* operator new(__SIZE_TYPE__ n);
void UNIQ(use)() { ::operator new(42); }
A *a() {
// CHECK: define [[A:%.*]]* @_ZN5test11aEv()
- // CHECK: [[NEW:%.*]] = call i8* @_Znwm(i64 8)
+ // CHECK: [[NEW:%.*]] = call noalias nonnull i8* @_Znwm(i64 8)
// CHECK-NEXT: [[CAST:%.*]] = bitcast i8* [[NEW]] to [[A]]*
// CHECK-NEXT: invoke void @_ZN5test11AC1Ei([[A]]* [[CAST]], i32 5)
// CHECK: ret [[A]]* [[CAST]]
A *b() {
// CHECK: define [[A:%.*]]* @_ZN5test11bEv()
- // CHECK: [[NEW:%.*]] = call i8* @_Znwm(i64 8)
+ // CHECK: [[NEW:%.*]] = call noalias nonnull i8* @_Znwm(i64 8)
// CHECK-NEXT: [[CAST:%.*]] = bitcast i8* [[NEW]] to [[A]]*
// CHECK-NEXT: [[FOO:%.*]] = invoke i32 @_ZN5test13fooEv()
// CHECK: invoke void @_ZN5test11AC1Ei([[A]]* [[CAST]], i32 [[FOO]])
A *c() {
// CHECK: define [[A:%.*]]* @_ZN5test11cEv()
// CHECK: [[ACTIVE:%.*]] = alloca i1
- // CHECK-NEXT: [[NEW:%.*]] = call i8* @_Znwm(i64 8)
- // CHECK-NEXT: store i1 true, i1* [[ACTIVE]]
+ // CHECK-NEXT: [[NEW:%.*]] = call noalias nonnull i8* @_Znwm(i64 8)
+ // CHECK-NEXT: store i1 true, i1* [[ACTIVE]]
// CHECK-NEXT: [[CAST:%.*]] = bitcast i8* [[NEW]] to [[A]]*
// CHECK-NEXT: invoke void @_ZN5test11BC1Ev([[B:%.*]]* [[T0:%.*]])
// CHECK: [[T1:%.*]] = getelementptr inbounds [[B]], [[B]]* [[T0]], i32 0, i32 0
A *d() {
// CHECK: define [[A:%.*]]* @_ZN5test11dEv()
// CHECK: [[ACTIVE:%.*]] = alloca i1
- // CHECK-NEXT: [[NEW:%.*]] = call i8* @_Znwm(i64 8)
- // CHECK-NEXT: store i1 true, i1* [[ACTIVE]]
+ // CHECK-NEXT: [[NEW:%.*]] = call noalias nonnull i8* @_Znwm(i64 8)
+ // CHECK-NEXT: store i1 true, i1* [[ACTIVE]]
// CHECK-NEXT: [[CAST:%.*]] = bitcast i8* [[NEW]] to [[A]]*
// CHECK-NEXT: invoke void @_ZN5test11BC1Ev([[B:%.*]]* [[T0:%.*]])
// CHECK: [[T1:%.*]] = invoke i32 @_ZN5test11BcviEv([[B]]* [[T0]])
A *e() {
// CHECK: define [[A:%.*]]* @_ZN5test11eEv()
// CHECK: [[ACTIVE:%.*]] = alloca i1
- // CHECK-NEXT: [[NEW:%.*]] = call i8* @_Znwm(i64 8)
- // CHECK-NEXT: store i1 true, i1* [[ACTIVE]]
+ // CHECK-NEXT: [[NEW:%.*]] = call noalias nonnull i8* @_Znwm(i64 8)
+ // CHECK-NEXT: store i1 true, i1* [[ACTIVE]]
// CHECK-NEXT: [[CAST:%.*]] = bitcast i8* [[NEW]] to [[A]]*
// CHECK-NEXT: invoke void @_ZN5test11BC1Ev([[B:%.*]]* [[T0:%.*]])
// CHECK: [[T1:%.*]] = invoke i32 @_ZN5test11BcviEv([[B]]* [[T0]])
// CHECK: define [[A:%.*]]* @_ZN5test11iEv()
// CHECK: [[X:%.*]] = alloca [[A]]*, align 8
// CHECK: [[ACTIVE:%.*]] = alloca i1
- // CHECK: [[NEW:%.*]] = call i8* @_Znwm(i64 8)
- // CHECK-NEXT: store i1 true, i1* [[ACTIVE]]
+ // CHECK: [[NEW:%.*]] = call noalias nonnull i8* @_Znwm(i64 8)
+ // CHECK-NEXT: store i1 true, i1* [[ACTIVE]]
// CHECK-NEXT: [[CAST:%.*]] = bitcast i8* [[NEW]] to [[A]]*
// CHECK-NEXT: invoke void @_ZN5test15makeBEv([[B:%.*]]* sret [[T0:%.*]])
// CHECK: [[T1:%.*]] = invoke i32 @_ZN5test11BcviEv([[B]]* [[T0]])
return new A[10];
}
// CHECK: define {{%.*}}* @_ZN5test94testEv
- // CHECK: [[TEST9_NEW:%.*]] = call i8* @_Znam
+ // CHECK: [[TEST9_NEW:%.*]] = call noalias nonnull i8* @_Znam
// CHECK: call void @_ZdaPv(i8* [[TEST9_NEW]])
}
// CHECK-NEXT: [[CLEANUPACTIVE:%.*]] = alloca i1
// CHECK: call void @_ZN5test01AC1Ev([[A]]* [[Y]])
// CHECK-NEXT: invoke void @_ZN5test01AC1Ev([[A]]* [[Z]])
- // CHECK: [[NEW:%.*]] = invoke i8* @_Znwm(i64 1)
+ // CHECK: [[NEW:%.*]] = invoke noalias nonnull i8* @_Znwm(i64 1)
// CHECK: store i1 true, i1* [[CLEANUPACTIVE]]
// CHECK: [[NEWCAST:%.*]] = bitcast i8* [[NEW]] to [[V]]*
// CHECK-NEXT: invoke void @_ZN5test01AC1Ev([[A]]* [[TMP]])
void check_array_no_cookies() {
// CHECK: define dso_local void @"?check_array_no_cookies@@YAXXZ"() [[NUW:#[0-9]+]]
-// CHECK: call i8* @"??_U@YAPAXI@Z"(i32 42)
+// CHECK: call noalias nonnull i8* @"??_U@YAPAXI@Z"(i32 42)
ClassWithoutDtor *array = new ClassWithoutDtor[42];
// CHECK: call void @"??_V@YAXPAX@Z"(
// CHECK: define {{.*}} @"?check_array_cookies_simple@@YAXXZ"()
ClassWithDtor *array = new ClassWithDtor[42];
-// CHECK: [[ALLOCATED:%.*]] = call i8* @"??_U@YAPAXI@Z"(i32 46)
+// CHECK: [[ALLOCATED:%.*]] = call noalias nonnull i8* @"??_U@YAPAXI@Z"(i32 46)
// 46 = 42 + size of cookie (4)
// CHECK: [[COOKIE:%.*]] = bitcast i8* [[ALLOCATED]] to i32*
// CHECK: store i32 42, i32* [[COOKIE]]
void check_array_cookies_aligned() {
// CHECK: define {{.*}} @"?check_array_cookies_aligned@@YAXXZ"()
ClassWithAlignment *array = new ClassWithAlignment[42];
-// CHECK: [[ALLOCATED:%.*]] = call i8* @"??_U@YAPAXI@Z"(i32 344)
+// CHECK: [[ALLOCATED:%.*]] = call noalias nonnull i8* @"??_U@YAPAXI@Z"(i32 344)
// 344 = 42*8 + size of cookie (8, due to alignment)
// CHECK: [[COOKIE:%.*]] = bitcast i8* [[ALLOCATED]] to i32*
// CHECK: store i32 42, i32* [[COOKIE]]
return rv;
}
// O32-LABEL: define i32* @_Z10alloc_longv()
-// O32: call i8* @_Znwj(i32 signext 4)
+// O32: call noalias nonnull i8* @_Znwj(i32 signext 4)
// N32-LABEL: define i32* @_Z10alloc_longv()
-// N32: call i8* @_Znwj(i32 signext 4)
+// N32: call noalias nonnull i8* @_Znwj(i32 signext 4)
// N64-LABEL: define i64* @_Z10alloc_longv()
-// N64: call i8* @_Znwm(i64 zeroext 8)
+// N64: call noalias nonnull i8* @_Znwm(i64 zeroext 8)
long *alloc_long_array() {
long *rv = new long[2];
}
// O32-LABEL: define i32* @_Z16alloc_long_arrayv()
-// O32: call i8* @_Znaj(i32 signext 8)
+// O32: call noalias nonnull i8* @_Znaj(i32 signext 8)
// N32-LABEL: define i32* @_Z16alloc_long_arrayv()
-// N32: call i8* @_Znaj(i32 signext 8)
+// N32: call noalias nonnull i8* @_Znaj(i32 signext 8)
// N64-LABEL: define i64* @_Z16alloc_long_arrayv()
-// N64: call i8* @_Znam(i64 zeroext 16)
+// N64: call noalias nonnull i8* @_Znam(i64 zeroext 16)
#include <stddef.h>
return 0;
}
-// CHECK: call i8* @_Znam
-// CHECK: call i8* @_Znam
-// CHECK: call i8* @_Znam
-
+// CHECK: call noalias nonnull i8* @_Znam
+// CHECK: call noalias nonnull i8* @_Znam
+// CHECK: call noalias nonnull i8* @_Znam
void *operator new(size_t) __attribute__((alias("something")));
// PR16715: don't assert here.
-// CHECK: call i8* @_Znwm(i64 4){{$}}
+// CHECK: call noalias nonnull i8* @_Znwm(i64 4) #3{{$}}
int *pr16715 = new int;
struct S;
new (int S::*[3][4][5]) ();
- // CHECK: call i8* @_Zna{{.}}(i{{32 240|64 480}})
+ // CHECK: call noalias nonnull i8* @_Zna{{.}}(i{{32 240|64 480}})
// CHECK: getelementptr inbounds i{{32|64}}, i{{32|64}}* {{.*}}, i{{32|64}} 60
// CHECK: phi
// CHECK: icmp slt i{{32|64}} %{{[^ ]+}}, 4
// FIXME: Conditionally throw an exception rather than passing -1 to alloc function
// CHECK: select
- // CHECK: %[[PTR:.*]] = call i8* @_Zna{{.}}(i{{32|64}}
+ // CHECK: %[[PTR:.*]] = call noalias nonnull i8* @_Zna{{.}}(i{{32|64}}
// CHECK: call void @llvm.memcpy{{.*}}(i8* align {{[0-9]+}} %[[PTR]], i8* align {{[0-9]+}} getelementptr inbounds ([4 x i8], [4 x i8]* @[[ABC4]], i32 0, i32 0), i32 4,
// CHECK: %[[REST:.*]] = getelementptr inbounds i8, i8* %[[PTR]], i32 4
// CHECK: %[[RESTSIZE:.*]] = sub {{.*}}, 4
// CHECK-LABEL: define void @_Z12string_exactv
void string_exact() {
// CHECK-NOT: icmp
- // CHECK: %[[PTR:.*]] = call i8* @_Zna{{.}}(i{{32|64}} 4)
+ // CHECK: %[[PTR:.*]] = call noalias nonnull i8* @_Zna{{.}}(i{{32|64}} 4)
// CHECK: call void @llvm.memcpy{{.*}}(i8* align {{[0-9]+}} %[[PTR]], i8* align {{[0-9]+}} getelementptr inbounds ([4 x i8], [4 x i8]* @[[ABC4]], i32 0, i32 0), i32 4,
// CHECK-NOT: memset
new char[4] { "abc" };
// CHECK-LABEL: define void @_Z17string_sufficientv
void string_sufficient() {
// CHECK-NOT: icmp
- // CHECK: %[[PTR:.*]] = call i8* @_Zna{{.}}(i{{32|64}} 15)
+ // CHECK: %[[PTR:.*]] = call noalias nonnull i8* @_Zna{{.}}(i{{32|64}} 15)
// FIXME: For very large arrays, it would be preferable to emit a small copy and a memset.
// CHECK: call void @llvm.memcpy{{.*}}(i8* align {{[0-9]+}} %[[PTR]], i8* align {{[0-9]+}} getelementptr inbounds ([15 x i8], [15 x i8]* @[[ABC15]], i32 0, i32 0), i32 15,
// CHECK-NOT: memset
// CHECK-LABEL: define void @_Z10aggr_exactv
void aggr_exact() {
// CHECK-NOT: icmp
- // CHECK: %[[MEM:.*]] = call i8* @_Zna{{.}}(i{{32|64}} 16)
+ // CHECK: %[[MEM:.*]] = call noalias nonnull i8* @_Zna{{.}}(i{{32|64}} 16)
// CHECK: %[[PTR0:.*]] = bitcast i8* %[[MEM]] to %[[AGGR:.*]]*
// CHECK: %[[FIELD:.*]] = getelementptr inbounds %[[AGGR]], %[[AGGR]]* %[[PTR0]], i32 0, i32 0{{$}}
// CHECK: store i32 1, i32* %[[FIELD]]
// CHECK-LABEL: define void @_Z15aggr_sufficienti
void aggr_sufficient(int n) {
// CHECK: icmp ult i32 %{{.*}}, 2
- // CHECK: %[[MEM:.*]] = call i8* @_Zna{{.}}(
+ // CHECK: %[[MEM:.*]] = call noalias nonnull i8* @_Zna{{.}}(
// CHECK: %[[PTR0:.*]] = bitcast i8* %[[MEM]] to %[[AGGR:.*]]*
// CHECK: %[[FIELD:.*]] = getelementptr inbounds %[[AGGR]], %[[AGGR]]* %[[PTR0]], i32 0, i32 0{{$}}
// CHECK: store i32 1, i32* %[[FIELD]]
// SIO-LABEL: define void @_Z14constexpr_testv
void constexpr_test() {
- // SIO: call i8* @_Zna{{.}}(i32 4)
+ // SIO: call noalias nonnull i8* @_Zna{{.}}(i32 4)
new int[0+1]{0};
}
// CHECK-NEXT: [[T1:%.*]] = extractvalue { i32, i1 } [[T0]], 1
// CHECK-NEXT: [[T2:%.*]] = extractvalue { i32, i1 } [[T0]], 0
// CHECK-NEXT: [[T3:%.*]] = select i1 [[T1]], i32 -1, i32 [[T2]]
- // CHECK-NEXT: call i8* @_Znaj(i32 [[T3]])
+ // CHECK-NEXT: call noalias nonnull i8* @_Znaj(i32 [[T3]])
// CHECK: getelementptr inbounds {{.*}}, i32 [[N]]
elt *test(short s) {
return new elt[s];
// CHECK-NEXT: [[T2:%.*]] = extractvalue { i32, i1 } [[T0]], 0
// CHECK-NEXT: [[T3:%.*]] = mul i32 [[N]], 100
// CHECK-NEXT: [[T4:%.*]] = select i1 [[T1]], i32 -1, i32 [[T2]]
- // CHECK-NEXT: call i8* @_Znaj(i32 [[T4]])
+ // CHECK-NEXT: call noalias nonnull i8* @_Znaj(i32 [[T4]])
// CHECK: getelementptr inbounds {{.*}}, i32 [[T3]]
elt *test(short s) {
return new elt[s];
// CHECK-NEXT: [[T6:%.*]] = or i1 [[T1]], [[T5]]
// CHECK-NEXT: [[T7:%.*]] = extractvalue { i32, i1 } [[T4]], 0
// CHECK-NEXT: [[T8:%.*]] = select i1 [[T6]], i32 -1, i32 [[T7]]
- // CHECK-NEXT: call i8* @_Znaj(i32 [[T8]])
+ // CHECK-NEXT: call noalias nonnull i8* @_Znaj(i32 [[T8]])
// CHECK: getelementptr inbounds {{.*}}, i32 [[T3]]
elt *test(short s) {
return new elt[s];
// CHECK: define [[A:%.*]]* @_ZN5test44testEs(i16 signext
// CHECK: [[N:%.*]] = sext i16 {{%.*}} to i32
- // CHECK-NEXT: call i8* @_Znaj(i32 [[N]])
+ // CHECK-NEXT: call noalias nonnull i8* @_Znaj(i32 [[N]])
// CHECK: getelementptr inbounds {{.*}}, i32 [[N]]
elt *test(short s) {
return new elt[s];
// CHECK: define [[A:%.*]]* @_ZN5test54testEi(i32
// CHECK: [[N:%.*]] = load i32, i32*
- // CHECK-NEXT: call i8* @_Znaj(i32 [[N]])
+ // CHECK-NEXT: call noalias nonnull i8* @_Znaj(i32 [[N]])
// CHECK: getelementptr inbounds {{.*}}, i32 [[N]]
elt *test(int s) {
return new elt[s];
// CHECK-NEXT: [[T1:%.*]] = extractvalue { i32, i1 } [[T0]], 1
// CHECK-NEXT: [[T2:%.*]] = extractvalue { i32, i1 } [[T0]], 0
// CHECK-NEXT: [[T3:%.*]] = select i1 [[T1]], i32 -1, i32 [[T2]]
- // CHECK-NEXT: call i8* @_Znaj(i32 [[T3]])
+ // CHECK-NEXT: call noalias nonnull i8* @_Znaj(i32 [[T3]])
// CHECK: getelementptr inbounds {{.*}}, i32 [[N]]
elt *test(unsigned short s) {
return new elt[s];
// CHECK-NEXT: [[T2:%.*]] = extractvalue { i32, i1 } [[T0]], 0
// CHECK-NEXT: [[T3:%.*]] = mul i32 [[N]], 100
// CHECK-NEXT: [[T4:%.*]] = select i1 [[T1]], i32 -1, i32 [[T2]]
- // CHECK-NEXT: call i8* @_Znaj(i32 [[T4]])
+ // CHECK-NEXT: call noalias nonnull i8* @_Znaj(i32 [[T4]])
// CHECK: getelementptr inbounds {{.*}}, i32 [[T3]]
elt *test(unsigned short s) {
return new elt[s];
// CHECK-NEXT: [[T3:%.*]] = extractvalue { i32, i1 } [[T2]], 1
// CHECK-NEXT: [[T5:%.*]] = extractvalue { i32, i1 } [[T2]], 0
// CHECK-NEXT: [[T6:%.*]] = select i1 [[T3]], i32 -1, i32 [[T5]]
- // CHECK-NEXT: call i8* @_Znaj(i32 [[T6]])
+ // CHECK-NEXT: call noalias nonnull i8* @_Znaj(i32 [[T6]])
// CHECK: getelementptr inbounds {{.*}}, i32 [[T1]]
elt *test(long long s) {
return new elt[s];
// CHECK-NEXT: [[T3:%.*]] = extractvalue { i32, i1 } [[T2]], 1
// CHECK-NEXT: [[T5:%.*]] = extractvalue { i32, i1 } [[T2]], 0
// CHECK-NEXT: [[T6:%.*]] = select i1 [[T3]], i32 -1, i32 [[T5]]
- // CHECK-NEXT: call i8* @_Znaj(i32 [[T6]])
+ // CHECK-NEXT: call noalias nonnull i8* @_Znaj(i32 [[T6]])
// CHECK: getelementptr inbounds {{.*}}, i32 [[T1]]
elt *test(unsigned long long s) {
return new elt[s];
delete [] new int [3];
}
-// CHECK: declare noalias i8* @_Znwm(i64) [[ATTR_NOBUILTIN:#[^ ]*]]
+// CHECK: declare nonnull i8* @_Znwm(i64) [[ATTR_NOBUILTIN:#[^ ]*]]
// CHECK: declare void @_ZdlPv(i8*) [[ATTR_NOBUILTIN_NOUNWIND:#[^ ]*]]
-// CHECK: declare noalias i8* @_Znam(i64) [[ATTR_NOBUILTIN]]
+// CHECK: declare nonnull i8* @_Znam(i64) [[ATTR_NOBUILTIN]]
// CHECK: declare void @_ZdaPv(i8*) [[ATTR_NOBUILTIN_NOUNWIND]]
namespace std {
void t3() {
int *a = new int(10);
_Complex int* b = new _Complex int(10i);
-
+
S s;
s.a = 10;
S *sp = new S(s);
T2(int, int);
};
-void t5() {
+void t5() {
// CHECK: call void @_ZN2T2C1Eii
T2 *t2 = new T2(10, 10);
}
struct U {
~U();
};
-
+
void t8(int n) {
new int[10];
new int[n];
-
+
// Non-POD
new T[10];
new T[n];
-
+
// Cookie required
new U[10];
new U[n];
void t9() {
bool b;
- new bool(true);
+ new bool(true);
new (&b) bool(true);
}
struct Bmemptr { int Bmemptr::* memptr; int a; };
void t11(int n) {
- // CHECK: call i8* @_Znwm
+ // CHECK: call noalias nonnull i8* @_Znwm
// CHECK: call void @llvm.memset.p0i8.i64(
B* b = new B();
- // CHECK: call i8* @_Znam
+ // CHECK: call noalias nonnull i8* @_Znam
// CHECK: {{call void.*llvm.memset.p0i8.i64.*i8 0, i64 %}}
B *b2 = new B[n]();
- // CHECK: call i8* @_Znam
+ // CHECK: call noalias nonnull i8* @_Znam
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64
// CHECK: br
Bmemptr *b_memptr = new Bmemptr[n]();
-
+
// CHECK: ret void
}
// We don't need to initialize an empty class.
// CHECK-LABEL: define void @_Z3t12v
void t12() {
- // CHECK: call i8* @_Znam
+ // CHECK: call noalias nonnull i8* @_Znam
// CHECK-NOT: br
(void)new Empty[10];
- // CHECK: call i8* @_Znam
+ // CHECK: call noalias nonnull i8* @_Znam
// CHECK-NOT: br
(void)new Empty[10]();
// Zero-initialization
// CHECK-LABEL: define void @_Z3t13i
void t13(int n) {
- // CHECK: call i8* @_Znwm
+ // CHECK: call noalias nonnull i8* @_Znwm
// CHECK: store i32 0, i32*
(void)new int();
- // CHECK: call i8* @_Znam
+ // CHECK: call noalias nonnull i8* @_Znam
// CHECK: {{call void.*llvm.memset.p0i8.i64.*i8 0, i64 %}}
(void)new int[n]();
// CHECK: call void @_ZN5AllocD1Ev(
// CHECK: call void @_ZN5AllocdaEPv(i8*
delete[] new Alloc[10][20];
- // CHECK: call i8* @_Znwm
+ // CHECK: call noalias nonnull i8* @_Znwm
// CHECK: call void @_ZdlPv(i8*
delete new bool;
// CHECK: ret void
// CHECK-LABEL: define weak_odr void @_ZN7PR101971fIiEEvv()
template<typename T>
void f() {
- // CHECK: [[CALL:%.*]] = call i8* @_Znwm
- // CHECK-NEXT: [[CASTED:%.*]] = bitcast i8* [[CALL]] to
+ // CHECK: [[CALL:%.*]] = call noalias nonnull i8* @_Znwm
+ // CHECK-NEXT: [[CASTED:%.*]] = bitcast i8* [[CALL]] to
new T;
// CHECK-NEXT: ret void
}
struct X { X(); X(const X&); };
X* a(X* x) { return new X(X()); }
// CHECK: define {{.*}} @_ZN7PR117571aEPNS_1XE
- // CHECK: [[CALL:%.*]] = call i8* @_Znwm
+ // CHECK: [[CALL:%.*]] = call noalias nonnull i8* @_Znwm
// CHECK-NEXT: [[CASTED:%.*]] = bitcast i8* [[CALL]] to
// CHECK-NEXT: call void @_ZN7PR117571XC1Ev({{.*}}* [[CASTED]])
// CHECK-NEXT: ret {{.*}} [[CASTED]]
struct A { A() {} };
struct B : public A { int x; };
// CHECK-LABEL: define i8* @_ZN7PR133801fEv
- // CHECK: call i8* @_Znam(
+ // CHECK: call noalias nonnull i8* @_Znam(
// CHECK: call void @llvm.memset.p0i8
// CHECK-NEXT: call void @_ZN7PR133801BC1Ev
void* f() { return new B[2](); }
// CHECK-LABEL: define void @_ZN5N36641fEv
void f() {
- // CHECK: call i8* @_Znwm(i64 4) [[ATTR_BUILTIN_NEW:#[^ ]*]]
+ // CHECK: call noalias nonnull i8* @_Znwm(i64 4) [[ATTR_BUILTIN_NEW:#[^ ]*]]
int *p = new int; // expected-note {{allocated with 'new' here}}
// CHECK: call void @_ZdlPv({{.*}}) [[ATTR_BUILTIN_DELETE:#[^ ]*]]
delete p;
- // CHECK: call i8* @_Znam(i64 12) [[ATTR_BUILTIN_NEW]]
+ // CHECK: call noalias nonnull i8* @_Znam(i64 12) [[ATTR_BUILTIN_NEW]]
int *q = new int[3];
// CHECK: call void @_ZdaPv({{.*}}) [[ATTR_BUILTIN_DELETE]]
delete[] p; // expected-warning {{'delete[]' applied to a pointer that was allocated with 'new'; did you mean 'delete'?}}
- // CHECK: call i8* @_ZnamRKSt9nothrow_t(i64 3, {{.*}}) [[ATTR_BUILTIN_NOTHROW_NEW:#[^ ]*]]
+ // CHECK: call noalias i8* @_ZnamRKSt9nothrow_t(i64 3, {{.*}}) [[ATTR_BUILTIN_NOTHROW_NEW:#[^ ]*]]
(void) new (nothrow) S[3];
// CHECK: call i8* @_Znwm15MyPlacementType(i64 4){{$}}
(void) new (mpt) int;
}
- // CHECK: declare noalias i8* @_ZnamRKSt9nothrow_t(i64, {{.*}}) [[ATTR_NOBUILTIN_NOUNWIND]]
+ // CHECK: declare i8* @_ZnamRKSt9nothrow_t(i64, {{.*}}) [[ATTR_NOBUILTIN_NOUNWIND_ALLOCSIZE:#[^ ]*]]
// CHECK-LABEL: define void @_ZN5N36641gEv
void g() {
// It's OK for there to be attributes here, so long as we don't have a
// 'builtin' attribute.
- // CHECK: call i8* @_Znwm(i64 4){{$}}
+ // CHECK: call noalias nonnull i8* @_Znwm(i64 4) {{#[^ ]*}}{{$}}
int *p = (int*)operator new(4);
// CHECK: call void @_ZdlPv({{.*}}) [[ATTR_NOUNWIND:#[^ ]*]]
operator delete(p);
- // CHECK: call i8* @_Znam(i64 12){{$}}
+ // CHECK: call noalias nonnull i8* @_Znam(i64 12) {{#[^ ]*}}{{$}}
int *q = (int*)operator new[](12);
// CHECK: call void @_ZdaPv({{.*}}) [[ATTR_NOUNWIND]]
operator delete [](p);
- // CHECK: call i8* @_ZnamRKSt9nothrow_t(i64 3, {{.*}}) [[ATTR_NOUNWIND]]
+ // CHECK: call noalias i8* @_ZnamRKSt9nothrow_t(i64 3, {{.*}}) [[ATTR_NOUNWIND_ALLOCSIZE:#[^ ]*]]
(void) operator new[](3, nothrow);
}
}
namespace builtins {
// CHECK-LABEL: define void @_ZN8builtins1fEv
void f() {
- // CHECK: call i8* @_Znwm(i64 4) [[ATTR_BUILTIN_NEW]]
+ // CHECK: call noalias nonnull i8* @_Znwm(i64 4) [[ATTR_BUILTIN_NEW]]
// CHECK: call void @_ZdlPv({{.*}}) [[ATTR_BUILTIN_DELETE]]
__builtin_operator_delete(__builtin_operator_new(4));
}
}
-// CHECK-DAG: attributes [[ATTR_NOBUILTIN]] = {{[{].*}} nobuiltin {{.*[}]}}
+// CHECK-DAG: attributes [[ATTR_NOBUILTIN]] = {{[{].*}} nobuiltin allocsize(0) {{.*[}]}}
// CHECK-DAG: attributes [[ATTR_NOBUILTIN_NOUNWIND]] = {{[{].*}} nobuiltin nounwind {{.*[}]}}
+// CHECK-DAG: attributes [[ATTR_NOBUILTIN_NOUNWIND_ALLOCSIZE]] = {{[{].*}} nobuiltin nounwind allocsize(0) {{.*[}]}}
// CHECK-DAG: attributes [[ATTR_BUILTIN_NEW]] = {{[{].*}} builtin {{.*[}]}}
// CHECK-DAG: attributes [[ATTR_BUILTIN_DELETE]] = {{[{].*}} builtin {{.*[}]}}
// The ([^b}|...) monstrosity is matching a character that's not the start of 'builtin'.
// Add more letters if this matches some other attribute.
// CHECK-DAG: attributes [[ATTR_NOUNWIND]] = {{([^b]|b[^u]|bu[^i]|bui[^l])*}} nounwind {{([^b]|b[^u]|bu[^i]|bui[^l])*$}}
+// CHECK-DAG: attributes [[ATTR_NOUNWIND_ALLOCSIZE]] = {{([^b]|b[^u]|bu[^i]|bui[^l])*}} nounwind allocsize(0) {{([^b]|b[^u]|bu[^i]|bui[^l])*$}}
// RUN: %clang_cc1 -triple i686-pc-linux-gnu -emit-llvm -o %t-1.ll %s
-// RUN: FileCheck -check-prefix SANE --input-file=%t-1.ll %s
+// RUN: FileCheck --check-prefix=ALL -check-prefix SANE --input-file=%t-1.ll %s
// RUN: %clang_cc1 -triple i686-pc-linux-gnu -emit-llvm -fno-assume-sane-operator-new -o %t-2.ll %s
-// RUN: FileCheck -check-prefix SANENOT --input-file=%t-2.ll %s
-
+// RUN: FileCheck --check-prefix=ALL -check-prefix SANENOT --input-file=%t-2.ll %s
class teste {
int A;
};
void f1() {
- // SANE: declare noalias i8* @_Znwj(
- // SANENOT: declare i8* @_Znwj(
+ // ALL: declare nonnull i8* @_Znwj(
new teste();
}
// rdar://5739832 - operator new should check for overflow in multiply.
void *f2(long N) {
return new int[N];
-
-// SANE: [[UWO:%.*]] = call {{.*}} @llvm.umul.with.overflow
-// SANE-NEXT: [[OVER:%.*]] = extractvalue {{.*}} [[UWO]], 1
-// SANE-NEXT: [[SUM:%.*]] = extractvalue {{.*}} [[UWO]], 0
-// SANE-NEXT: [[RESULT:%.*]] = select i1 [[OVER]], i32 -1, i32 [[SUM]]
-// SANE-NEXT: call i8* @_Znaj(i32 [[RESULT]])
+
+ // ALL: [[UWO:%.*]] = call {{.*}} @llvm.umul.with.overflow
+ // ALL-NEXT: [[OVER:%.*]] = extractvalue {{.*}} [[UWO]], 1
+ // ALL-NEXT: [[SUM:%.*]] = extractvalue {{.*}} [[UWO]], 0
+ // ALL-NEXT: [[RESULT:%.*]] = select i1 [[OVER]], i32 -1, i32 [[SUM]]
+ // SANE-NEXT: call noalias nonnull i8* @_Znaj(i32 [[RESULT]])
+ // SANENOT-NEXT: call nonnull i8* @_Znaj(i32 [[RESULT]])
}
-// SANE: declare noalias i8* @_Znaj(
-// SANENOT: declare i8* @_Znaj(
+// ALL: declare nonnull i8* @_Znaj(
// CHECK-MS-DAG: declare dso_local i32 @atexit(void ()*)
// CHECK-MS-DYNAMIC-DAG: declare {{.*}} void @_CxxThrowException
// CHECK-MS-STATIC-DAG: declare {{.*}} void @_CxxThrowException
-// CHECK-MS-DAG: declare dso_local noalias i8* @"??2@YAPAXI@Z"
+// CHECK-MS-DAG: declare dso_local nonnull i8* @"??2@YAPAXI@Z"
// CHECK-MS-DAG: declare dso_local void @_Init_thread_header(i32*)
// CHECK-MS-DAG: declare dso_local void @_Init_thread_footer(i32*)
// CHECK-DYNAMIC-NODECL-IA-DAG: declare dllimport i32 @__cxa_guard_acquire(i64*)
// CHECK-DYNAMIC-IMPORT-IA-DAG: declare dllimport i32 @__cxa_guard_acquire(i64*)
// CHECK-DYNAMIC-EXPORT-IA-DAG: declare dllexport i32 @__cxa_guard_acquire(i64*)
-// CHECK-IA-DAG: declare dso_local noalias i8* @_Znwj(i32)
+// CHECK-IA-DAG: declare dso_local nonnull i8* @_Znwj(i32)
// CHECK-DYNAMIC-DECL-IA-DAG: declare dllimport void @__cxa_guard_release(i64*)
// CHECK-DYNAMIC-NODECL-IA-DAG: declare dllimport void @__cxa_guard_release(i64*)
// CHECK-DYNAMIC-IMPORT-IA-DAG: declare dllimport void @__cxa_guard_release(i64*)
// CHECK-STATIC-NODECL-IA-DAG: declare dso_local i32 @__cxa_guard_acquire(i64*)
// CHECK-STATIC-IMPORT-IA-DAG: declare dso_local i32 @__cxa_guard_acquire(i64*)
// CHECK-STATIC-EXPORT-IA-DAG: declare dso_local i32 @__cxa_guard_acquire(i64*)
-// CHECK-IA-DAG: declare dso_local noalias i8* @_Znwj(i32)
+// CHECK-IA-DAG: declare dso_local nonnull i8* @_Znwj(i32)
// CHECK-STATIC-DECL-IA-DAG: declare dso_local void @__cxa_guard_release(i64*)
// CHECK-STATIC-NODECL-IA-DAG: declare dso_local void @__cxa_guard_release(i64*)
// CHECK-STATIC-IMPORT-IA-DAG: declare dso_local void @__cxa_guard_release(i64*)
// CHECK-STATIC-NODECL-IA-DAG: declare dso_local void @_ZSt9terminatev()
// CHECK-STATIC-IMPORT-IA-DAG: declare dso_local void @_ZSt9terminatev()
// CHECK-STATIC-EXPORT-IA-DAG: declare dso_local dllexport void @_ZSt9terminatev()
-
}
void g() {
- // CHECK: call i8* @_Znwm(i64 1)
+ // CHECK: call noalias nonnull i8* @_Znwm(i64 1)
// CHECK: call void @_ZN1AC1Ev(
static A& a = *new A;
}
// CHECK: [[AllocBB]]:
// CHECK: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64()
- // CHECK: %[[MEM:.+]] = call i8* @_Znwm(i64 %[[SIZE]])
+ // CHECK: %[[MEM:.+]] = call noalias nonnull i8* @_Znwm(i64 %[[SIZE]])
// CHECK: br label %[[InitBB]]
// CHECK: [[InitBB]]:
// within the scope of the promise type's class.
// CHECK-LABEL: f1b(
extern "C" void f1b(promise_matching_global_placement_new_tag, dummy *) {
- // CHECK: call i8* @_Znwm(i64
+ // CHECK: call noalias nonnull i8* @_Znwm(i64
co_return;
}
extern "C" void f2(promise_delete_tag) {
// CHECK: %[[ID:.+]] = call token @llvm.coro.id(i32 16
// CHECK: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64()
- // CHECK: call i8* @_Znwm(i64 %[[SIZE]])
+ // CHECK: call noalias nonnull i8* @_Znwm(i64 %[[SIZE]])
// CHECK: %[[FRAME:.+]] = call i8* @llvm.coro.begin(
// CHECK: %[[MEM:.+]] = call i8* @llvm.coro.free(token %[[ID]], i8* %[[FRAME]])
extern "C" void f3(promise_sized_delete_tag) {
// CHECK: %[[ID:.+]] = call token @llvm.coro.id(i32 16
// CHECK: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64()
- // CHECK: call i8* @_Znwm(i64 %[[SIZE]])
+ // CHECK: call noalias nonnull i8* @_Znwm(i64 %[[SIZE]])
// CHECK: %[[FRAME:.+]] = call i8* @llvm.coro.begin(
// CHECK: %[[MEM:.+]] = call i8* @llvm.coro.free(token %[[ID]], i8* %[[FRAME]])
// CHECK: %[[Gro:.+]] = alloca i32
// CHECK: %[[ID:.+]] = call token @llvm.coro.id(i32 16
// CHECK: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64()
- // CHECK: %[[MEM:.+]] = call i8* @_ZnwmRKSt9nothrow_t(i64 %[[SIZE]], %"struct.std::nothrow_t"* dereferenceable(1) @_ZStL7nothrow)
+ // CHECK: %[[MEM:.+]] = call noalias i8* @_ZnwmRKSt9nothrow_t(i64 %[[SIZE]], %"struct.std::nothrow_t"* dereferenceable(1) @_ZStL7nothrow)
// CHECK: %[[OK:.+]] = icmp ne i8* %[[MEM]], null
// CHECK: br i1 %[[OK]], label %[[OKBB:.+]], label %[[ERRBB:.+]]
// CHECK-LABEL: define void @_Z1fv(
void f() {
- // CHECK: call i8* @_Znwm(i64
+ // CHECK: call noalias nonnull i8* @_Znwm(i64
// If promise constructor throws, check that we free the memory.
// Verify that the NRVO is applied to the Gro object.
// CHECK-LABEL: define void @_Z1fi(%struct.coro* noalias sret %agg.result, i32 %0)
coro f(int) {
-// CHECK: %call = call i8* @_Znwm(
+// CHECK: %call = call noalias nonnull i8* @_Znwm(
// CHECK-NEXT: br label %[[CoroInit:.*]]
// CHECK: {{.*}}[[CoroInit]]:
// CHECK-LABEL: define void @_Z1hi(%struct.coro_two* noalias sret %agg.result, i32 %0)
coro_two h(int) {
-// CHECK: %call = call i8* @_ZnwmRKSt9nothrow_t
+// CHECK: %call = call noalias i8* @_ZnwmRKSt9nothrow_t
// CHECK-NEXT: %[[CheckNull:.*]] = icmp ne i8* %call, null
// CHECK-NEXT: br i1 %[[CheckNull]], label %[[InitOnSuccess:.*]], label %[[InitOnFailure:.*]]
// CHECK: %[[GroActive:.+]] = alloca i1
// CHECK: %[[Size:.+]] = call i64 @llvm.coro.size.i64()
- // CHECK: call i8* @_Znwm(i64 %[[Size]])
+ // CHECK: call noalias nonnull i8* @_Znwm(i64 %[[Size]])
// CHECK: store i1 false, i1* %[[GroActive]]
// CHECK: call void @_ZNSt12experimental16coroutine_traitsIJiEE12promise_typeC1Ev(
// CHECK: call void @_ZNSt12experimental16coroutine_traitsIJiEE12promise_type17get_return_objectEv(
// CHECK-LABEL: f0(
extern "C" void f0() {
// CHECK: %__promise = alloca %"struct.std::experimental::coroutine_traits<void>::promise_type"
- // CHECK: %call = call i8* @_Znwm(
+ // CHECK: %call = call noalias nonnull i8* @_Znwm(
// CHECK: call void @_ZNSt12experimental16coroutine_traitsIJvEE12promise_type11return_voidEv(%"struct.std::experimental::coroutine_traits<void>::promise_type"* %__promise)
// CHECK: call void @_ZdlPv
co_return;
// CHECK-LABEL: f1(
extern "C" int f1() {
// CHECK: %__promise = alloca %"struct.std::experimental::coroutine_traits<int>::promise_type"
- // CHECK: %call = call i8* @_Znwm(
+ // CHECK: %call = call noalias nonnull i8* @_Znwm(
// CHECK: call void @_ZNSt12experimental16coroutine_traitsIJiEE12promise_type12return_valueEi(%"struct.std::experimental::coroutine_traits<int>::promise_type"* %__promise, i32 42)
// CHECK: call void @_ZdlPv
co_return 42;
// OPT-NEXT: [[T0:%.*]] = call i8* @llvm.objc.retain(i8* [[INVALUE:%.*]])
// OPT-NEXT: store i8* [[T0]], i8** [[INVALUEADDR]]
- // CHECK: call i8* @_Znwm
+ // CHECK: [[CALL:%.*]] = call noalias nonnull i8* @_Znwm
// CHECK-NEXT: {{bitcast i8\*.*to i8\*\*}}
// CHECK-NEXT: store i8* null, i8**
new strong_id;
- // CHECK: call i8* @_Znwm
+ // CHECK: [[CALL:%.*]] = call noalias nonnull i8* @_Znwm
// CHECK-NEXT: {{bitcast i8\*.*to i8\*\*}}
// UNOPT-NEXT: store i8* null, i8**
// OPT-NEXT: call i8* @llvm.objc.initWeak(i8** {{.*}}, i8* null)
new weak_id;
- // CHECK: call i8* @_Znwm
+ // CHECK: [[CALL:%.*]] = call noalias nonnull i8* @_Znwm
// CHECK-NEXT: {{bitcast i8\*.*to i8\*\*}}
// CHECK-NEXT: store i8* null, i8**
new __strong id;
- // CHECK: call i8* @_Znwm
+ // CHECK: [[CALL:%.*]] = call noalias nonnull i8* @_Znwm
// CHECK-NEXT: {{bitcast i8\*.*to i8\*\*}}
// UNOPT-NEXT: store i8* null, i8**
// OPT-NEXT: call i8* @llvm.objc.initWeak(i8** {{.*}}, i8* null)
new __weak id;
- // CHECK: call i8* @_Znwm
+ // CHECK: [[CALL:%.*]] = call noalias nonnull i8* @_Znwm
// CHECK: call i8* @llvm.objc.retain
// CHECK: store i8*
new __strong id(invalue);
- // CHECK: call i8* @_Znwm
+ // CHECK: [[CALL:%.*]] = call noalias nonnull i8* @_Znwm
// CHECK: call i8* @llvm.objc.initWeak
new __weak id(invalue);
// CHECK-LABEL: define void @_Z14test_array_new
void test_array_new() {
- // CHECK: call i8* @_Znam
+ // CHECK: call noalias nonnull i8* @_Znam
// CHECK: store i64 17, i64*
// CHECK: call void @llvm.memset.p0i8.i64
new strong_id[17];
- // CHECK: call i8* @_Znam
+ // CHECK: call noalias nonnull i8* @_Znam
// CHECK: store i64 17, i64*
// CHECK: call void @llvm.memset.p0i8.i64
new weak_id[17];
// CHECK: alloca
// CHECK-NEXT: getelementptr
// CHECK-NEXT: store
- // CHECK-NEXT: call i8* @_Znwm(
+ // CHECK-NEXT: [[CALL:%.*]] = call noalias nonnull i8* @_Znwm(
// CHECK-NEXT: bitcast
// CHECK-NEXT: bitcast
// CHECK-NEXT: bitcast
void test_arg_types() {
__builtin_operator_new(NP); // expected-error {{no matching function for call to 'operator new'}}
- __builtin_operator_new(NP, std::align_val_t(0)); // expected-error {{no matching function for call to 'operator new'}}}
+ __builtin_operator_new(NP, std::align_val_t(0)); // expected-error {{no matching function for call to 'operator new'}}
}
void test_return_type() {
int w = __builtin_operator_new(42); // expected-error {{cannot initialize a variable of type 'int' with an rvalue of type 'void *'}}
__attribute__((used))
inline void *operator new(size_t) { // no warning, due to __attribute__((used))
- return 0;
+ return 0; // expected-warning {{null returned from function that requires a non-null return value}}
}
// PR5823
pi = ::new int;
U *pu = new (ps) U;
V *pv = new (ps) V;
-
+
pi = new (S(1.0f, 2)) int;
-
+
(void)new int[true];
// PR7147
void f() {
(void)new int[10](1, 2); // expected-error {{array 'new' cannot have initialization arguments}}
-
+
typedef int T[10];
(void)new T(1, 2); // expected-error {{array 'new' cannot have initialization arguments}}
}
void operator delete(void* p); // expected-note {{declared private here}}
};
-void test(S1* s1, S2* s2) {
+void test(S1* s1, S2* s2) {
delete s1;
delete s2; // expected-error {{is a private member}}
(void)new S1();
// <rdar://problem/8248780>
namespace Instantiate {
- template<typename T> struct X {
+ template<typename T> struct X {
operator T*();
};