Skip to content

Commit

Permalink
Add the alloc_size attribute to clang.
Browse files Browse the repository at this point in the history
This patch does three things:

- Gives us the alloc_size attribute in clang, which lets us infer the
  number of bytes handed back to us by malloc/realloc/calloc/any user
  functions that act in a similar manner.
- Teaches our constexpr evaluator that evaluating some `const` variables
  is OK sometimes. This is why we have a change in
  test/SemaCXX/constant-expression-cxx11.cpp and other seemingly
  unrelated tests. Richard Smith okay'ed this idea some time ago in
  person.
- Uniques some Blocks in CodeGen, which was reviewed separately at
  D26410. Lack of uniquing only really shows up as a problem when
  combined with our new eagerness in the face of const.

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

llvm-svn: 290149
  • Loading branch information
gburgessiv committed Dec 20, 2016
1 parent 891cbcc commit a747027
Show file tree
Hide file tree
Showing 16 changed files with 1,079 additions and 205 deletions.
9 changes: 9 additions & 0 deletions clang/include/clang/Basic/Attr.td
Expand Up @@ -780,6 +780,15 @@ def EmptyBases : InheritableAttr, TargetSpecificAttr<TargetMicrosoftCXXABI> {
let Documentation = [EmptyBasesDocs];
}

def AllocSize : InheritableAttr {
let Spellings = [GCC<"alloc_size">];
let Subjects = SubjectList<[HasFunctionProto], WarnDiag,
"ExpectedFunctionWithProtoType">;
let Args = [IntArgument<"ElemSizeParam">, IntArgument<"NumElemsParam", 1>];
let TemplateDependent = 1;
let Documentation = [AllocSizeDocs];
}

def EnableIf : InheritableAttr {
let Spellings = [GNU<"enable_if">];
let Subjects = SubjectList<[Function]>;
Expand Down
38 changes: 38 additions & 0 deletions clang/include/clang/Basic/AttrDocs.td
Expand Up @@ -206,6 +206,44 @@ to enforce the provided alignment assumption.
}];
}

def AllocSizeDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
The ``alloc_size`` attribute can be placed on functions that return pointers in
order to hint to the compiler how many bytes of memory will be available at the
returned poiner. ``alloc_size`` takes one or two arguments.

- ``alloc_size(N)`` implies that argument number N equals the number of
available bytes at the returned pointer.
- ``alloc_size(N, M)`` implies that the product of argument number N and
argument number M equals the number of available bytes at the returned
pointer.

Argument numbers are 1-based.

An example of how to use ``alloc_size``

.. code-block:: c

void *my_malloc(int a) __attribute__((alloc_size(1)));
void *my_calloc(int a, int b) __attribute__((alloc_size(1, 2)));

int main() {
void *const p = my_malloc(100);
assert(__builtin_object_size(p, 0) == 100);
void *const a = my_calloc(20, 5);
assert(__builtin_object_size(a, 0) == 100);
}

.. Note:: This attribute works differently in clang than it does in GCC.
Specifically, clang will only trace ``const`` pointers (as above); we give up
on pointers that are not marked as ``const``. In the vast majority of cases,
this is unimportant, because LLVM has support for the ``alloc_size``
attribute. However, this may cause mildly unintuitive behavior when used with
other attributes, such as ``enable_if``.
}];
}

def EnableIfDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Expand Up @@ -2297,6 +2297,9 @@ def warn_attribute_pointers_only : Warning<
"%0 attribute only applies to%select{| constant}1 pointer arguments">,
InGroup<IgnoredAttributes>;
def err_attribute_pointers_only : Error<warn_attribute_pointers_only.Text>;
def err_attribute_integers_only : Error<
"%0 attribute argument may only refer to a function parameter of integer "
"type">;
def warn_attribute_return_pointers_only : Warning<
"%0 attribute only applies to return values that are pointers">,
InGroup<IgnoredAttributes>;
Expand Down

0 comments on commit a747027

Please sign in to comment.