[clang] Annotating C++'s `operator new` with more attributes
authorRoman Lebedev <lebedev.ri@gmail.com>
Tue, 25 Feb 2020 22:37:17 +0000 (01:37 +0300)
committerRoman Lebedev <lebedev.ri@gmail.com>
Tue, 25 Feb 2020 22:37:17 +0000 (01:37 +0300)
Summary:
Right now we annotate C++'s `operator new` with `noalias` attribute,
which very much is healthy for optimizations.

However as per [[ http://eel.is/c++draft/basic.stc.dynamic.allocation | `[basic.stc.dynamic.allocation]` ]],
there are more promises on global `operator new`, namely:
* non-`std::nothrow_t` `operator new` *never* returns `nullptr`
* If `std::align_val_t align` parameter is taken, the pointer will also be `align`-aligned
* ~~global `operator new`-returned pointer is `__STDCPP_DEFAULT_NEW_ALIGNMENT__`-aligned ~~ It's more caveated than that.

Supplying this information may not cause immediate landslide effects
on any specific benchmarks, but it for sure will be healthy for optimizer
in the sense that the IR will better reflect the guarantees provided in the source code.

The caveat is `-fno-assume-sane-operator-new`, which currently prevents emitting `noalias`
attribute, and is automatically passed by Sanitizers ([[ https://bugs.llvm.org/show_bug.cgi?id=16386 | PR16386 ]]) - should it also cover these attributes?
The problem is that the flag is back-end-specific, as seen in `test/Modules/explicit-build-flags.cpp`.
But while it is okay to add `noalias` metadata in backend, we really should be adding at least
the alignment metadata to the AST, since that allows us to perform sema checks on it.

Reviewers: erichkeane, rjmccall, jdoerfert, eugenis, rsmith

Reviewed By: rsmith

Subscribers: xbolva00, jrtc27, atanasyan, nlopes, cfe-commits

Tags: #llvm, #clang

Differential Revision: https://reviews.llvm.org/D73380

43 files changed:
clang/include/clang/AST/Decl.h
clang/include/clang/Sema/Sema.h
clang/lib/AST/Decl.cpp
clang/lib/CodeGen/CGCall.cpp
clang/lib/CodeGen/CodeGenModule.cpp
clang/lib/Sema/SemaDecl.cpp
clang/lib/Sema/SemaExprCXX.cpp
clang/test/AST/ast-dump-stmt-json.cpp
clang/test/Analysis/new-ctor-malloc.cpp
clang/test/Analysis/new-ctor-null-throw.cpp
clang/test/Analysis/new-ctor-null.cpp
clang/test/CodeGenCXX/align-avx-complete-objects.cpp
clang/test/CodeGenCXX/arm.cpp
clang/test/CodeGenCXX/builtin-calling-conv.cpp
clang/test/CodeGenCXX/builtin-is-constant-evaluated.cpp
clang/test/CodeGenCXX/builtin-operator-new-delete.cpp
clang/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp
clang/test/CodeGenCXX/cxx11-initializer-array-new.cpp
clang/test/CodeGenCXX/cxx1z-aligned-allocation.cpp
clang/test/CodeGenCXX/delete-two-arg.cpp
clang/test/CodeGenCXX/dllexport.cpp
clang/test/CodeGenCXX/dllimport.cpp
clang/test/CodeGenCXX/exceptions.cpp
clang/test/CodeGenCXX/goto.cpp
clang/test/CodeGenCXX/microsoft-abi-array-cookies.cpp
clang/test/CodeGenCXX/mips-size_t-ptrdiff_t.cpp
clang/test/CodeGenCXX/multi-dim-operator-new.cpp
clang/test/CodeGenCXX/new-alias.cpp
clang/test/CodeGenCXX/new-array-init.cpp
clang/test/CodeGenCXX/new-overflow.cpp
clang/test/CodeGenCXX/new.cpp
clang/test/CodeGenCXX/operator-new.cpp
clang/test/CodeGenCXX/runtime-dllstorage.cpp
clang/test/CodeGenCXX/static-init.cpp
clang/test/CodeGenCoroutines/coro-alloc.cpp
clang/test/CodeGenCoroutines/coro-cleanup.cpp
clang/test/CodeGenCoroutines/coro-gro-nrvo.cpp
clang/test/CodeGenCoroutines/coro-gro.cpp
clang/test/CodeGenCoroutines/coro-return.cpp
clang/test/CodeGenObjCXX/arc-new-delete.mm
clang/test/CodeGenObjCXX/copy.mm
clang/test/SemaCXX/builtin-operator-new-delete.cpp
clang/test/SemaCXX/new-delete.cpp

index 43c6c7b..b31cbab 100644 (file)
@@ -2306,8 +2306,13 @@ public:
   ///    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;
index f100b57..2d7676e 100644 (file)
@@ -3796,6 +3796,8 @@ public:
                                  SourceLocation Loc);
   NamedDecl *ImplicitlyDefineFunction(SourceLocation Loc, IdentifierInfo &II,
                                       Scope *S);
+  void AddKnownFunctionAttributesForReplaceableGlobalAllocationFunction(
+      FunctionDecl *FD);
   void AddKnownFunctionAttributes(FunctionDecl *FD);
 
   // More parsing and symbol table subroutines.
index 216137b..7625acd 100644 (file)
@@ -2952,7 +2952,8 @@ bool FunctionDecl::isReservedGlobalPlacementOperator() const {
   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 &&
@@ -2999,9 +3000,9 @@ bool FunctionDecl::isReplaceableGlobalAllocationFunction(bool *IsAligned) const
   // 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
@@ -3010,8 +3011,11 @@ bool FunctionDecl::isReplaceableGlobalAllocationFunction(bool *IsAligned) const
     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();
index 98365db..42d5467 100644 (file)
@@ -1906,6 +1906,13 @@ void CodeGenModule::ConstructAttributeList(
     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
index d4ed486..652efd8 100644 (file)
@@ -1875,15 +1875,6 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F,
     // 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))
index 4c088aa..7fe3213 100644 (file)
@@ -14475,6 +14475,77 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
   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.
 ///
@@ -14575,6 +14646,8 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
     }
   }
 
+  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.
index 9e5c735..44fd699 100644 (file)
@@ -1788,8 +1788,9 @@ Sema::isUnavailableAlignedAllocationFunction(const FunctionDecl &FD) const {
     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;
 }
@@ -2943,6 +2944,7 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
     Alloc->setParams(ParamDecls);
     if (ExtraAttr)
       Alloc->addAttr(ExtraAttr);
+    AddKnownFunctionAttributesForReplaceableGlobalAllocationFunction(Alloc);
     Context.getTranslationUnitDecl()->addDecl(Alloc);
     IdResolver.tryAddTopLevelDecl(Alloc, Name);
   };
index 85a3a66..f7f3a2c 100644 (file)
@@ -1461,6 +1461,24 @@ void TestDependentGenericSelectionExpr(Ty T) {
 // 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: }
@@ -1513,6 +1531,33 @@ void TestDependentGenericSelectionExpr(Ty T) {
 // 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: }
@@ -1553,6 +1598,24 @@ void TestDependentGenericSelectionExpr(Ty T) {
 // 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: }
@@ -1605,6 +1668,33 @@ void TestDependentGenericSelectionExpr(Ty T) {
 // 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: }
index 74b1e21..e38433e 100644 (file)
@@ -11,6 +11,7 @@ void *operator new(size_t size) throw() {
   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;
 }
 
index 28922c0..6c17ceb 100644 (file)
@@ -15,10 +15,12 @@ typedef __typeof__(sizeof(int)) size_t;
 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 {
index f3c07e2..7b4d67a 100644 (file)
@@ -9,9 +9,11 @@ typedef __typeof__(sizeof(int)) size_t;
 
 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 {
index ad4a914..6477da5 100644 (file)
@@ -13,7 +13,7 @@ volatile float TestAlign(void)
 }
 
 // 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
@@ -42,7 +42,7 @@ volatile float TestAlign2(void)
 }
 
 // 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
index 7eba017..663c6a0 100644 (file)
@@ -110,7 +110,7 @@ namespace test3 {
 
   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];
@@ -123,7 +123,7 @@ namespace test3 {
     // 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];
@@ -131,7 +131,7 @@ namespace test3 {
 
   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];
@@ -144,7 +144,7 @@ namespace test3 {
     // 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];
@@ -185,7 +185,7 @@ namespace test4 {
 
   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];
@@ -197,7 +197,7 @@ namespace test4 {
     // 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];
@@ -205,7 +205,7 @@ namespace test4 {
 
   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];
@@ -218,7 +218,7 @@ namespace test4 {
     // 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];
@@ -386,7 +386,7 @@ namespace test9 {
 // 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
index f7759e3..11e8114 100644 (file)
@@ -27,27 +27,27 @@ void user() {
 }
 
 // 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"()
index 74f414d..cc4e375 100644 (file)
@@ -84,7 +84,7 @@ void test_arr_expr() {
 
 // 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];
 }
 
@@ -130,4 +130,4 @@ void test_ref_to_static_var() {
   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
+}
index 712805a..fe220fe 100644 (file)
@@ -37,27 +37,26 @@ void *operator new[](size_t, void*, bool) throw();
 
 // 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);
 }
index e3c7e26..13b6c63 100644 (file)
@@ -239,7 +239,8 @@ void fn9() {
 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
index 6e24212..f8e3441 100644 (file)
@@ -7,7 +7,7 @@ struct S { S(); S(int); ~S(); int n; };
 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
@@ -50,7 +50,7 @@ void *q = new S[n][3]{ { 1, 2, 3 }, { 4, 5, 6 } };
 // 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]]
@@ -113,7 +113,7 @@ void *r = new T[n][3]{ { 1, 2, 3 }, { 4, 5, 6 } };
 // 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:.*]]*
 //
@@ -157,4 +157,3 @@ void *r = new T[n][3]{ { 1, 2, 3 }, { 4, 5, 6 } };
 // CHECK: call void @llvm.memset.p0i8.i64(i8* align 4 %[[REST]], i8 0, i64 %[[SIZE]], i1 false)
 //
 // CHECK: }
-
index 2e2bfc5..d2b5b64 100644 (file)
@@ -27,10 +27,10 @@ namespace std { enum class align_val_t : size_t {}; }
 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; }
@@ -39,13 +39,13 @@ 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"(
@@ -84,7 +84,7 @@ struct OVERALIGNED B {
 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(
@@ -169,14 +169,14 @@ void *d0() { return new (q) D; }
 
 #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.
index 68a6fa6..3000ece 100644 (file)
@@ -27,7 +27,7 @@ namespace test2 {
 
   // 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
@@ -58,13 +58,13 @@ namespace test3 {
   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];
   }
index 045cb45..fcbd937 100644 (file)
@@ -305,8 +305,8 @@ struct __declspec(dllexport) Befriended {
 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); }
 
index 2f4a1b9..530ddd3 100644 (file)
@@ -308,8 +308,8 @@ USE(friend4)
 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); }
 
index 302488a..90db402 100644 (file)
@@ -31,7 +31,7 @@ namespace test1 {
 
   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]]
@@ -41,7 +41,7 @@ namespace test1 {
 
   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]])
@@ -57,8 +57,8 @@ namespace test1 {
   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
@@ -86,8 +86,8 @@ namespace test1 {
   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]])
@@ -107,8 +107,8 @@ namespace test1 {
   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]])
@@ -143,8 +143,8 @@ namespace test1 {
     // 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]])
@@ -455,7 +455,7 @@ namespace test9 {
     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]])
 }
 
index 2f5b719..d0107ff 100644 (file)
@@ -19,7 +19,7 @@ namespace test0 {
     // 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]])
index 2814045..52207b3 100644 (file)
@@ -7,7 +7,7 @@ struct ClassWithoutDtor {
 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"(
@@ -24,7 +24,7 @@ void check_array_cookies_simple() {
 // 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]]
@@ -46,7 +46,7 @@ struct __attribute__((aligned(8))) ClassWithAlignment {
 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]]
index 5b245a4..ff55735 100644 (file)
@@ -10,13 +10,13 @@ long *alloc_long() {
   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];
@@ -24,13 +24,13 @@ long *alloc_long_array() {
 }
 
 // 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>
 
index 0dfcffb..5cd7383 100644 (file)
@@ -43,7 +43,6 @@ int main() {
  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
index b21638a..d7669ce 100644 (file)
@@ -9,5 +9,5 @@ extern "C" char *something(long long x) {
 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;
index b504d5e..97977ba 100644 (file)
@@ -34,7 +34,7 @@ void check_array_value_init() {
   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
@@ -49,7 +49,7 @@ void string_nonconst(int n) {
   // 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
@@ -60,7 +60,7 @@ void string_nonconst(int n) {
 // 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" };
@@ -69,7 +69,7 @@ void string_exact() {
 // 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
@@ -79,7 +79,7 @@ void string_sufficient() {
 // 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]]
@@ -99,7 +99,7 @@ void aggr_exact() {
 // 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]]
@@ -120,7 +120,7 @@ void aggr_sufficient(int n) {
 
 // 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};
 }
 
index a2269bf..e596afb 100644 (file)
@@ -17,7 +17,7 @@ namespace test0 {
   // 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];
@@ -40,7 +40,7 @@ namespace test1 {
   // 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];
@@ -68,7 +68,7 @@ namespace test2 {
   // 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];
@@ -85,7 +85,7 @@ namespace test4 {
 
   // 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];
@@ -102,7 +102,7 @@ namespace test5 {
 
   // 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];
@@ -124,7 +124,7 @@ namespace test6 {
   // 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];
@@ -147,7 +147,7 @@ namespace test7 {
   // 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];
@@ -170,7 +170,7 @@ namespace test8 {
   // 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];
@@ -193,7 +193,7 @@ namespace test9 {
   // 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];
index 1f5288d..d8ad4c5 100644 (file)
@@ -14,9 +14,9 @@ void t1() {
   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 {
@@ -52,7 +52,7 @@ struct S {
 void t3() {
   int *a = new int(10);
   _Complex int* b = new _Complex int(10i);
-  
+
   S s;
   s.a = 10;
   S *sp = new S(s);
@@ -74,7 +74,7 @@ struct T2 {
   T2(int, int);
 };
 
-void t5() { 
+void t5() {
   // CHECK: call void @_ZN2T2C1Eii
   T2 *t2 = new T2(10, 10);
 }
@@ -91,15 +91,15 @@ void t7() {
 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];
@@ -108,7 +108,7 @@ void t8(int n) {
 void t9() {
   bool b;
 
-  new bool(true);  
+  new bool(true);
   new (&b) bool(true);
 }
 
@@ -127,19 +127,19 @@ struct B { int a; };
 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
 }
 
@@ -148,11 +148,11 @@ struct Empty { };
 // 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]();
 
@@ -162,11 +162,11 @@ void t12() {
 // 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]();
 
@@ -186,7 +186,7 @@ void f() {
   // 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
@@ -272,8 +272,8 @@ namespace PR10197 {
   // 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
   }
@@ -294,7 +294,7 @@ namespace PR11757 {
   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]]
@@ -304,7 +304,7 @@ namespace PR13380 {
   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](); }
@@ -318,40 +318,40 @@ namespace N3664 {
 
   // 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);
   }
 }
@@ -359,14 +359,15 @@ namespace N3664 {
 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 {{.*[}]}}
@@ -374,3 +375,4 @@ namespace builtins {
 // 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])*$}}
index dc1c36d..d3679be 100644 (file)
@@ -1,8 +1,7 @@
 // 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;
@@ -11,21 +10,20 @@ public:
 };
 
 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(
index 694a9b4..4f63c93 100644 (file)
@@ -110,7 +110,7 @@ void l() {
 // 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*)
 
@@ -129,7 +129,7 @@ void l() {
 // 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*)
@@ -147,7 +147,7 @@ void l() {
 // 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*)
@@ -156,4 +156,3 @@ void l() {
 // 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()
-
index 925ddec..a420e13 100644 (file)
@@ -28,7 +28,7 @@ void f() {
 }
 
 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;
 }
index 20b00d4..2e7a65a 100644 (file)
@@ -61,7 +61,7 @@ extern "C" void f0(global_new_delete_tag) {
 
   // 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]]:
@@ -156,7 +156,7 @@ struct std::experimental::coroutine_traits<void, promise_matching_global_placeme
 // 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;
 }
 
@@ -177,7 +177,7 @@ struct std::experimental::coroutine_traits<void, promise_delete_tag> {
 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]])
@@ -202,7 +202,7 @@ struct std::experimental::coroutine_traits<void, promise_sized_delete_tag> {
 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]])
@@ -230,7 +230,7 @@ extern "C" int f4(promise_on_alloc_failure_tag) {
   // 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:.+]]
 
index ba12469..16af75b 100644 (file)
@@ -39,7 +39,7 @@ void may_throw();
 
 // 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.
 
index f4a7186..8a0b234 100644 (file)
@@ -36,7 +36,7 @@ struct coro {
 // 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]]:
@@ -68,7 +68,7 @@ struct coro_two {
 // 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:.*]]
 
index 95bf206..b2b9c11 100644 (file)
@@ -49,7 +49,7 @@ int f() {
   // 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(
index 7577725..17356f9 100644 (file)
@@ -33,7 +33,7 @@ template <> struct std::experimental::coroutine_traits<void> {
 // 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;
@@ -52,7 +52,7 @@ struct std::experimental::coroutine_traits<int> {
 // 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;
index 0f66056..ae3a863 100644 (file)
@@ -12,32 +12,32 @@ void test_new(id invalue) {
   // 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);
 
@@ -48,12 +48,12 @@ void test_new(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];
index 7783137..19a32eb 100644 (file)
@@ -11,7 +11,7 @@ namespace test0 {
   // 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
index 40d4732..6fcff92 100644 (file)
@@ -75,7 +75,7 @@ void test_typo_in_args() {
 
 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 *'}}
index 4db1206..64d32f2 100644 (file)
@@ -27,7 +27,7 @@ inline void operator delete(void *); // expected-warning {{replacement function
 
 __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
@@ -53,9 +53,9 @@ void good_news()
   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
@@ -329,7 +329,7 @@ namespace Test1 {
 
 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}}
 }
@@ -363,7 +363,7 @@ class S2 {
   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();
@@ -397,7 +397,7 @@ namespace rdar8018245 {
 
 // <rdar://problem/8248780>
 namespace Instantiate {
-  template<typename T> struct X { 
+  template<typename T> struct X {
     operator T*();
   };