[PATCH] D30806: [nonnull] Teach Clang to attach the nonnull LLVM attribute to declarations and calls instead of just definitions, and then teach it to *not* attach such attributes even if the source c

2018-09-27 Thread Sanjay Patel via Phabricator via cfe-commits
spatel added a comment.

In https://reviews.llvm.org/D30806#1248575, @efriedma wrote:

> This was merged in https://reviews.llvm.org/rC298491 .


But it got reverted soon after due to miscompiles:
https://reviews.llvm.org/rL298695

And the functionality hasn't been reimplemented AFAICT.


https://reviews.llvm.org/D30806



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D30806: [nonnull] Teach Clang to attach the nonnull LLVM attribute to declarations and calls instead of just definitions, and then teach it to *not* attach such attributes even if the source c

2018-09-27 Thread Eli Friedman via Phabricator via cfe-commits
efriedma closed this revision.
efriedma added a comment.

This was merged in https://reviews.llvm.org/rC298491 .


https://reviews.llvm.org/D30806



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D30806: [nonnull] Teach Clang to attach the nonnull LLVM attribute to declarations and calls instead of just definitions, and then teach it to *not* attach such attributes even if the source c

2018-09-27 Thread Dávid Bolvanský via Phabricator via cfe-commits
xbolva00 added a comment.
Herald added a subscriber: sanjoy.

Coming from https://reviews.llvm.org/D50039. This patch was accepted but never 
merged?


https://reviews.llvm.org/D30806



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D30806: [nonnull] Teach Clang to attach the nonnull LLVM attribute to declarations and calls instead of just definitions, and then teach it to *not* attach such attributes even if the source c

2017-03-18 Thread Hal Finkel via Phabricator via cfe-commits
hfinkel accepted this revision.
hfinkel added a comment.
This revision is now accepted and ready to land.

LGTM


https://reviews.llvm.org/D30806



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D30806: [nonnull] Teach Clang to attach the nonnull LLVM attribute to declarations and calls instead of just definitions, and then teach it to *not* attach such attributes even if the source c

2017-03-17 Thread Chandler Carruth via Phabricator via cfe-commits
chandlerc updated this revision to Diff 92245.
chandlerc added a comment.

Update with fixes suggested in review.


https://reviews.llvm.org/D30806

Files:
  include/clang/AST/ASTContext.h
  include/clang/Basic/Builtins.def
  lib/AST/ASTContext.cpp
  lib/CodeGen/CGCall.cpp
  test/CodeGen/nonnull.c

Index: test/CodeGen/nonnull.c
===
--- test/CodeGen/nonnull.c
+++ test/CodeGen/nonnull.c
@@ -49,3 +49,87 @@
 // CHECK: define void @bar8(i32* nonnull %a, i32* nonnull %b)
 void bar8(int *a, int *b) __attribute__((nonnull))
 __attribute__((nonnull(1))) {}
+
+// CHECK: declare void @foo_decl(i32* nonnull)
+void foo_decl(int *__attribute__((nonnull)));
+
+// CHECK: declare void @bar_decl(i32* nonnull)
+void bar_decl(int *) __attribute__((nonnull(1)));
+
+// CHECK: declare void @bar2_decl(i32*, i32* nonnull)
+void bar2_decl(int *, int *) __attribute__((nonnull(2)));
+
+// CHECK: declare nonnull i32* @bar3_decl()
+int *bar3_decl(void) __attribute__((returns_nonnull));
+
+// CHECK: declare i32 @bar4_decl(i32, i32* nonnull)
+int bar4_decl(int, int *) __attribute__((nonnull));
+
+// CHECK: declare i32 @bar5_decl(i32, i32* nonnull)
+int bar5_decl(int, int *) __attribute__((nonnull(1, 2)));
+
+// CHECK: declare i32 @bar6_decl(i64)
+int bar6_decl(TransparentUnion) __attribute__((nonnull(1)));
+
+// CHECK: declare void @bar7_decl(i32* nonnull, i32* nonnull)
+void bar7_decl(int *, int *)
+__attribute__((nonnull(1))) __attribute__((nonnull(2)));
+
+// CHECK: declare void @bar8_decl(i32* nonnull, i32* nonnull)
+void bar8_decl(int *, int *)
+__attribute__((nonnull)) __attribute__((nonnull(1)));
+
+// Clang specially disables nonnull attributes on some library builtin
+// functions to work around the fact that the standard and some vendors mark
+// them as nonnull even though they are frequently called in practice with null
+// arguments if a corresponding size argument is zero.
+
+// CHECK: declare i8* @memcpy(i8*, i8*, i64)
+void *memcpy(void *, const void *, unsigned long)
+__attribute__((nonnull(1, 2))) __attribute__((returns_nonnull));
+
+// CHECK: declare i32 @memcmp(i8*, i8*, i64)
+int memcmp(const void *, const void *, unsigned long) __attribute__((nonnull(1, 2)));
+
+// CHECK: declare i8* @memmove(i8*, i8*, i64)
+void *memmove(void *, const void *, unsigned long)
+__attribute__((nonnull(1, 2))) __attribute__((returns_nonnull));
+
+// CHECK: declare i8* @strncpy(i8*, i8*, i64)
+char *strncpy(char *, const char *, unsigned long)
+__attribute__((nonnull(1, 2))) __attribute__((returns_nonnull));
+
+// CHECK: declare i32 @strncmp(i8*, i8*, i64)
+int strncmp(const char *, const char *, unsigned long) __attribute__((nonnull(1, 2)));
+
+// CHECK: declare nonnull i8* @strncat(i8* nonnull, i8*, i64)
+char *strncat(char *, const char *, unsigned long)
+__attribute__((nonnull(1, 2))) __attribute__((returns_nonnull));
+
+// CHECK: declare i8* @memchr(i8*, i32, i64)
+void *memchr(const void *__attribute__((nonnull)), int, unsigned long)
+__attribute__((returns_nonnull));
+
+// CHECK: declare i8* @memset(i8*, i32, i64)
+void *memset(void *__attribute__((nonnull)), int, unsigned long)
+__attribute__((returns_nonnull));
+
+void use_declarations(int *p, void *volatile *sink) {
+  foo_decl(p);
+  bar_decl(p);
+  bar2_decl(p, p);
+  (void)bar3_decl();
+  bar4_decl(42, p);
+  bar5_decl(42, p);
+  bar6_decl(p);
+  bar7_decl(p, p);
+  bar8_decl(p, p);
+  *sink = (void *)
+  *sink = (void *)
+  *sink = (void *)
+  *sink = (void *)
+  *sink = (void *)
+  *sink = (void *)
+  *sink = (void *)
+  *sink = (void *)
+}
Index: lib/CodeGen/CGCall.cpp
===
--- lib/CodeGen/CGCall.cpp
+++ lib/CodeGen/CGCall.cpp
@@ -1759,6 +1759,34 @@
   F.addAttributes(llvm::AttributeSet::FunctionIndex, AS);
 }
 
+/// Returns the attribute (either parameter attribute, or function
+/// attribute), which declares argument ArgNo to be non-null.
+static const NonNullAttr *getNonNullAttr(const Decl *FD, const ParmVarDecl *PVD,
+ QualType ArgType, unsigned ArgNo) {
+  // FIXME: __attribute__((nonnull)) can also be applied to:
+  //   - references to pointers, where the pointee is known to be
+  // nonnull (apparently a Clang extension)
+  //   - transparent unions containing pointers
+  // In the former case, LLVM IR cannot represent the constraint. In
+  // the latter case, we have no guarantee that the transparent union
+  // is in fact passed as a pointer.
+  if (!ArgType->isAnyPointerType() && !ArgType->isBlockPointerType())
+return nullptr;
+  // First, check attribute on parameter itself.
+  if (PVD) {
+if (auto ParmNNAttr = PVD->getAttr())
+  return ParmNNAttr;
+  }
+  // Check function attributes.
+  if (!FD)
+return nullptr;
+  for (const auto *NNAttr : FD->specific_attrs()) {
+if (NNAttr->isNonNull(ArgNo))
+  return NNAttr;
+  }
+  return 

[PATCH] D30806: [nonnull] Teach Clang to attach the nonnull LLVM attribute to declarations and calls instead of just definitions, and then teach it to *not* attach such attributes even if the source c

2017-03-17 Thread Chandler Carruth via Phabricator via cfe-commits
chandlerc marked an inline comment as done.
chandlerc added a comment.

Function argument order fixed.


https://reviews.llvm.org/D30806



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D30806: [nonnull] Teach Clang to attach the nonnull LLVM attribute to declarations and calls instead of just definitions, and then teach it to *not* attach such attributes even if the source c

2017-03-16 Thread Hal Finkel via Phabricator via cfe-commits
hfinkel added inline comments.



Comment at: include/clang/AST/ASTContext.h:1868
+  bool *OverrideNonnullReturn = nullptr,
+  unsigned *OverrideNonnullArgs = nullptr,
   unsigned *IntegerConstantArgs = nullptr) const;

chandlerc wrote:
> hfinkel wrote:
> > It seems like you had to touch more code than necessary because you decided 
> > to add these parameters before IntegerConstantArgs. Why don't you add them 
> > afterward instead?
> It seemed more natural But I'm happy to change the order. I'm not worreid 
> about how much code I have to touch, I'd rather just get the options in the 
> right place. What order would you suggest?
I suggest the other order because it is more common to want the 
IntegerConstantArgs than the nonnull args (which essentially only one caller 
wants).


https://reviews.llvm.org/D30806



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D30806: [nonnull] Teach Clang to attach the nonnull LLVM attribute to declarations and calls instead of just definitions, and then teach it to *not* attach such attributes even if the source c

2017-03-16 Thread Chandler Carruth via Phabricator via cfe-commits
chandlerc added inline comments.



Comment at: include/clang/AST/ASTContext.h:1868
+  bool *OverrideNonnullReturn = nullptr,
+  unsigned *OverrideNonnullArgs = nullptr,
   unsigned *IntegerConstantArgs = nullptr) const;

hfinkel wrote:
> It seems like you had to touch more code than necessary because you decided 
> to add these parameters before IntegerConstantArgs. Why don't you add them 
> afterward instead?
It seemed more natural But I'm happy to change the order. I'm not worreid 
about how much code I have to touch, I'd rather just get the options in the 
right place. What order would you suggest?


https://reviews.llvm.org/D30806



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D30806: [nonnull] Teach Clang to attach the nonnull LLVM attribute to declarations and calls instead of just definitions, and then teach it to *not* attach such attributes even if the source c

2017-03-16 Thread Hal Finkel via Phabricator via cfe-commits
hfinkel added inline comments.



Comment at: include/clang/AST/ASTContext.h:1865
   /// arguments to the builtin that are required to be integer constant
   /// expressions.
   QualType GetBuiltinType(unsigned ID, GetBuiltinTypeError ,

Please add some description of the new parameters.



Comment at: include/clang/AST/ASTContext.h:1868
+  bool *OverrideNonnullReturn = nullptr,
+  unsigned *OverrideNonnullArgs = nullptr,
   unsigned *IntegerConstantArgs = nullptr) const;

It seems like you had to touch more code than necessary because you decided to 
add these parameters before IntegerConstantArgs. Why don't you add them 
afterward instead?


https://reviews.llvm.org/D30806



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D30806: [nonnull] Teach Clang to attach the nonnull LLVM attribute to declarations and calls instead of just definitions, and then teach it to *not* attach such attributes even if the source c

2017-03-16 Thread Chandler Carruth via Phabricator via cfe-commits
chandlerc added a comment.

Ping?


https://reviews.llvm.org/D30806



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D30806: [nonnull] Teach Clang to attach the nonnull LLVM attribute to declarations and calls instead of just definitions, and then teach it to *not* attach such attributes even if the source c

2017-03-10 Thread Chandler Carruth via Phabricator via cfe-commits
chandlerc updated this revision to Diff 91286.
chandlerc added a comment.

Update to fix subtle bugs in handling arguments. Thanks to David for the review
comments that caused me to see the issue here.


https://reviews.llvm.org/D30806

Files:
  include/clang/AST/ASTContext.h
  include/clang/Basic/Builtins.def
  lib/AST/ASTContext.cpp
  lib/CodeGen/CGBuiltin.cpp
  lib/CodeGen/CGCall.cpp
  lib/Sema/SemaChecking.cpp
  test/CodeGen/nonnull.c

Index: test/CodeGen/nonnull.c
===
--- test/CodeGen/nonnull.c
+++ test/CodeGen/nonnull.c
@@ -49,3 +49,87 @@
 // CHECK: define void @bar8(i32* nonnull %a, i32* nonnull %b)
 void bar8(int *a, int *b) __attribute__((nonnull))
 __attribute__((nonnull(1))) {}
+
+// CHECK: declare void @foo_decl(i32* nonnull)
+void foo_decl(int *__attribute__((nonnull)));
+
+// CHECK: declare void @bar_decl(i32* nonnull)
+void bar_decl(int *) __attribute__((nonnull(1)));
+
+// CHECK: declare void @bar2_decl(i32*, i32* nonnull)
+void bar2_decl(int *, int *) __attribute__((nonnull(2)));
+
+// CHECK: declare nonnull i32* @bar3_decl()
+int *bar3_decl(void) __attribute__((returns_nonnull));
+
+// CHECK: declare i32 @bar4_decl(i32, i32* nonnull)
+int bar4_decl(int, int *) __attribute__((nonnull));
+
+// CHECK: declare i32 @bar5_decl(i32, i32* nonnull)
+int bar5_decl(int, int *) __attribute__((nonnull(1, 2)));
+
+// CHECK: declare i32 @bar6_decl(i64)
+int bar6_decl(TransparentUnion) __attribute__((nonnull(1)));
+
+// CHECK: declare void @bar7_decl(i32* nonnull, i32* nonnull)
+void bar7_decl(int *, int *)
+__attribute__((nonnull(1))) __attribute__((nonnull(2)));
+
+// CHECK: declare void @bar8_decl(i32* nonnull, i32* nonnull)
+void bar8_decl(int *, int *)
+__attribute__((nonnull)) __attribute__((nonnull(1)));
+
+// Clang specially disables nonnull attributes on some library builtin
+// functions to work around the fact that the standard and some vendors mark
+// them as nonnull even though they are frequently called in practice with null
+// arguments if a corresponding size argument is zero.
+
+// CHECK: declare i8* @memcpy(i8*, i8*, i64)
+void *memcpy(void *, const void *, unsigned long)
+__attribute__((nonnull(1, 2))) __attribute__((returns_nonnull));
+
+// CHECK: declare i32 @memcmp(i8*, i8*, i64)
+int memcmp(const void *, const void *, unsigned long) __attribute__((nonnull(1, 2)));
+
+// CHECK: declare i8* @memmove(i8*, i8*, i64)
+void *memmove(void *, const void *, unsigned long)
+__attribute__((nonnull(1, 2))) __attribute__((returns_nonnull));
+
+// CHECK: declare i8* @strncpy(i8*, i8*, i64)
+char *strncpy(char *, const char *, unsigned long)
+__attribute__((nonnull(1, 2))) __attribute__((returns_nonnull));
+
+// CHECK: declare i32 @strncmp(i8*, i8*, i64)
+int strncmp(const char *, const char *, unsigned long) __attribute__((nonnull(1, 2)));
+
+// CHECK: declare nonnull i8* @strncat(i8* nonnull, i8*, i64)
+char *strncat(char *, const char *, unsigned long)
+__attribute__((nonnull(1, 2))) __attribute__((returns_nonnull));
+
+// CHECK: declare i8* @memchr(i8*, i32, i64)
+void *memchr(const void *__attribute__((nonnull)), int, unsigned long)
+__attribute__((returns_nonnull));
+
+// CHECK: declare i8* @memset(i8*, i32, i64)
+void *memset(void *__attribute__((nonnull)), int, unsigned long)
+__attribute__((returns_nonnull));
+
+void use_declarations(int *p, void *volatile *sink) {
+  foo_decl(p);
+  bar_decl(p);
+  bar2_decl(p, p);
+  (void)bar3_decl();
+  bar4_decl(42, p);
+  bar5_decl(42, p);
+  bar6_decl(p);
+  bar7_decl(p, p);
+  bar8_decl(p, p);
+  *sink = (void *)
+  *sink = (void *)
+  *sink = (void *)
+  *sink = (void *)
+  *sink = (void *)
+  *sink = (void *)
+  *sink = (void *)
+  *sink = (void *)
+}
Index: lib/Sema/SemaChecking.cpp
===
--- lib/Sema/SemaChecking.cpp
+++ lib/Sema/SemaChecking.cpp
@@ -735,7 +735,8 @@
   // Find out if any arguments are required to be integer constant expressions.
   unsigned ICEArguments = 0;
   ASTContext::GetBuiltinTypeError Error;
-  Context.GetBuiltinType(BuiltinID, Error, );
+  Context.GetBuiltinType(BuiltinID, Error, /*OverrideNonnullReturn=*/nullptr,
+ /*OverrideNonnullArgs=*/nullptr, );
   if (Error != ASTContext::GE_None)
 ICEArguments = 0;  // Don't diagnose previously diagnosed errors.
   
Index: lib/CodeGen/CGCall.cpp
===
--- lib/CodeGen/CGCall.cpp
+++ lib/CodeGen/CGCall.cpp
@@ -1759,6 +1759,34 @@
   F.addAttributes(llvm::AttributeSet::FunctionIndex, AS);
 }
 
+/// Returns the attribute (either parameter attribute, or function
+/// attribute), which declares argument ArgNo to be non-null.
+static const NonNullAttr *getNonNullAttr(const Decl *FD, const ParmVarDecl *PVD,
+ QualType ArgType, unsigned ArgNo) {
+  // FIXME: __attribute__((nonnull)) can also be 

[PATCH] D30806: [nonnull] Teach Clang to attach the nonnull LLVM attribute to declarations and calls instead of just definitions, and then teach it to *not* attach such attributes even if the source c

2017-03-10 Thread Chandler Carruth via Phabricator via cfe-commits
chandlerc added inline comments.



Comment at: lib/AST/ASTContext.cpp:8786
+if (OverrideNonnull && OverrideNonnullArgs)
+  *OverrideNonnullArgs |= 1 << ArgTypes.size();
+

majnemer wrote:
> `1U` to avoid overflow UB?
I'd mildly prefer an assert (or rely on UBSan) that it *doesn't* overflow.

Also note that this is the same pattern we use just a few lines down for the 
ICE argument bitmask -- we have a pretty baked in assumption that all the 
builtins here don't have more than 31 arguments.

Anyways, happy to make whatever change you would prefer here. I just copied the 
code below, I don't have any strong opinion here.



Comment at: lib/CodeGen/CGCall.cpp:2082
+  if (getNonNullAttr(FD, PVD, ParamType, PVD->getFunctionScopeIndex()) &&
+  (OverrideNonnullArgs & (1 << ArgNo)) == 0)
+Attrs.addAttribute(llvm::Attribute::NonNull);

majnemer wrote:
> Ditto.
See above, I'll keep these in sync.

However, this exposes a related bug: we shouldn't be even doing this bit test 
if the function isn't a builtin. I'll add a check for that. That seems cleaner 
than relying on the bittest itself failing.


https://reviews.llvm.org/D30806



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D30806: [nonnull] Teach Clang to attach the nonnull LLVM attribute to declarations and calls instead of just definitions, and then teach it to *not* attach such attributes even if the source c

2017-03-10 Thread David Majnemer via Phabricator via cfe-commits
majnemer added inline comments.



Comment at: lib/AST/ASTContext.cpp:8786
+if (OverrideNonnull && OverrideNonnullArgs)
+  *OverrideNonnullArgs |= 1 << ArgTypes.size();
+

`1U` to avoid overflow UB?



Comment at: lib/CodeGen/CGCall.cpp:2082
+  if (getNonNullAttr(FD, PVD, ParamType, PVD->getFunctionScopeIndex()) &&
+  (OverrideNonnullArgs & (1 << ArgNo)) == 0)
+Attrs.addAttribute(llvm::Attribute::NonNull);

Ditto.


https://reviews.llvm.org/D30806



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D30806: [nonnull] Teach Clang to attach the nonnull LLVM attribute to declarations and calls instead of just definitions, and then teach it to *not* attach such attributes even if the source c

2017-03-10 Thread Chandler Carruth via Phabricator via cfe-commits
chandlerc added a comment.

In https://reviews.llvm.org/D30806#697372, @ahatanak wrote:

> Are users allowed to call these routines with a null pointer and a non-zero 
> size? Or can we assume that if the size is known to be non-zero at compile 
> time, the pointers are not null?


If the sizes are non-zero, all of these will access memory through the pointer.

But we don't currently have any way of easily expressing this in the IR. We 
could try something fancy like call-side attributes when the size is known, but 
it is pretty redundant -- we could just teach the same things that look at the 
attributes to know that these are reads or writes of a constant size...

> I'm thinking we might miss optimization opportunities if it's not possible to 
> mark the pointer parameters as nonnull.

Note that currently, *nothing marks these parameters as nonnull*. So in all the 
years that folks have used Clang and LLVM with libc headers that have an 
__attribute__((nonnull)), no one has found a performance problem with this as 
the root cause and fixed it.

To me, this indicates that this isn't that important of an optimization *for 
these libc routines*.

If someone ever comes up with a testcase where this is important thing for 
performance, I think we can cross the bridge of finding a fancier way to 
analyze things then.


https://reviews.llvm.org/D30806



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D30806: [nonnull] Teach Clang to attach the nonnull LLVM attribute to declarations and calls instead of just definitions, and then teach it to *not* attach such attributes even if the source c

2017-03-10 Thread Akira Hatanaka via Phabricator via cfe-commits
ahatanak added a comment.

Are users allowed to call these routines with a null pointer and a non-zero 
size? Or can we assume that if the size is known to be non-zero at compile 
time, the pointers are not null?

I'm thinking we might miss optimization opportunities if it's not possible to 
mark the pointer parameters as nonnull.


https://reviews.llvm.org/D30806



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D30806: [nonnull] Teach Clang to attach the nonnull LLVM attribute to declarations and calls instead of just definitions, and then teach it to *not* attach such attributes even if the source c

2017-03-09 Thread Chandler Carruth via Phabricator via cfe-commits
chandlerc created this revision.
Herald added a subscriber: mcrosier.

This follows the design direction discussed on cfe-dev here:
http://lists.llvm.org/pipermail/cfe-dev/2017-January/052066.html

The idea is that for C standard library builtins, even if the library
vendor chooses to annotate their routines with __attribute__((nonnull)),
we will ignore those attributes which pertain to pointer arguments that
have an associated size. This allows the widespread (and seemingly
reasonable) pattern of calling these routines with a null pointer and
a zero size. I have only done this for the library builtins currently
recognized by Clang, but we can now trivially add to this set. This will
be controllable with -fno-builtin if anyone should care to do so.

Note that this does *not* change the AST. As a consequence, warnings,
static analysis, and source code rewriting are not impacted.

This isn't even a regression on any platform as neither Clang nor LLVM
have ever put 'nonnull' onto these arguments for declarations. All this
patch does is enable it on other declarations while preventing us from
ever accidentally enabling it on these libc functions due to a library
vendor.


https://reviews.llvm.org/D30806

Files:
  include/clang/AST/ASTContext.h
  include/clang/Basic/Builtins.def
  lib/AST/ASTContext.cpp
  lib/CodeGen/CGBuiltin.cpp
  lib/CodeGen/CGCall.cpp
  lib/Sema/SemaChecking.cpp
  test/CodeGen/nonnull.c

Index: test/CodeGen/nonnull.c
===
--- test/CodeGen/nonnull.c
+++ test/CodeGen/nonnull.c
@@ -49,3 +49,87 @@
 // CHECK: define void @bar8(i32* nonnull %a, i32* nonnull %b)
 void bar8(int *a, int *b) __attribute__((nonnull))
 __attribute__((nonnull(1))) {}
+
+// CHECK: declare void @foo_decl(i32* nonnull)
+void foo_decl(int *__attribute__((nonnull)));
+
+// CHECK: declare void @bar_decl(i32* nonnull)
+void bar_decl(int *) __attribute__((nonnull(1)));
+
+// CHECK: declare void @bar2_decl(i32*, i32* nonnull)
+void bar2_decl(int *, int *) __attribute__((nonnull(2)));
+
+// CHECK: declare nonnull i32* @bar3_decl()
+int *bar3_decl(void) __attribute__((returns_nonnull));
+
+// CHECK: declare i32 @bar4_decl(i32, i32* nonnull)
+int bar4_decl(int, int *) __attribute__((nonnull));
+
+// CHECK: declare i32 @bar5_decl(i32, i32* nonnull)
+int bar5_decl(int, int *) __attribute__((nonnull(1, 2)));
+
+// CHECK: declare i32 @bar6_decl(i64)
+int bar6_decl(TransparentUnion) __attribute__((nonnull(1)));
+
+// CHECK: declare void @bar7_decl(i32* nonnull, i32* nonnull)
+void bar7_decl(int *, int *)
+__attribute__((nonnull(1))) __attribute__((nonnull(2)));
+
+// CHECK: declare void @bar8_decl(i32* nonnull, i32* nonnull)
+void bar8_decl(int *, int *)
+__attribute__((nonnull)) __attribute__((nonnull(1)));
+
+// Clang specially disables nonnull attributes on some library builtin
+// functions to work around the fact that the standard and some vendors mark
+// them as nonnull even though they are frequently called in practice with null
+// arguments if a corresponding size argument is zero.
+
+// CHECK: declare i8* @memcpy(i8*, i8*, i64)
+void *memcpy(void *, const void *, unsigned long)
+__attribute__((nonnull(1, 2))) __attribute__((returns_nonnull));
+
+// CHECK: declare i32 @memcmp(i8*, i8*, i64)
+int memcmp(const void *, const void *, unsigned long) __attribute__((nonnull(1, 2)));
+
+// CHECK: declare i8* @memmove(i8*, i8*, i64)
+void *memmove(void *, const void *, unsigned long)
+__attribute__((nonnull(1, 2))) __attribute__((returns_nonnull));
+
+// CHECK: declare i8* @strncpy(i8*, i8*, i64)
+char *strncpy(char *, const char *, unsigned long)
+__attribute__((nonnull(1, 2))) __attribute__((returns_nonnull));
+
+// CHECK: declare i32 @strncmp(i8*, i8*, i64)
+int strncmp(const char *, const char *, unsigned long) __attribute__((nonnull(1, 2)));
+
+// CHECK: declare nonnull i8* @strncat(i8* nonnull, i8*, i64)
+char *strncat(char *, const char *, unsigned long)
+__attribute__((nonnull(1, 2))) __attribute__((returns_nonnull));
+
+// CHECK: declare i8* @memchr(i8*, i32, i64)
+void *memchr(const void *__attribute__((nonnull)), int, unsigned long)
+__attribute__((returns_nonnull));
+
+// CHECK: declare i8* @memset(i8*, i32, i64)
+void *memset(void *__attribute__((nonnull)), int, unsigned long)
+__attribute__((returns_nonnull));
+
+void use_declarations(int *p, void *volatile *sink) {
+  foo_decl(p);
+  bar_decl(p);
+  bar2_decl(p, p);
+  (void)bar3_decl();
+  bar4_decl(42, p);
+  bar5_decl(42, p);
+  bar6_decl(p);
+  bar7_decl(p, p);
+  bar8_decl(p, p);
+  *sink = (void *)
+  *sink = (void *)
+  *sink = (void *)
+  *sink = (void *)
+  *sink = (void *)
+  *sink = (void *)
+  *sink = (void *)
+  *sink = (void *)
+}
Index: lib/Sema/SemaChecking.cpp
===
--- lib/Sema/SemaChecking.cpp
+++ lib/Sema/SemaChecking.cpp
@@ -735,7 +735,8 @@
   // Find out if any arguments are required to be