FormatArg,
GNUInline,
IBOutletKind, // Clang-specific. Use "Kind" suffix to not conflict with
+ Malloc,
NoReturn,
NoThrow,
Nodebug,
static bool classof(const IBOutletAttr *A) { return true; }
};
+DEF_SIMPLE_ATTR(Malloc);
DEF_SIMPLE_ATTR(NoReturn);
DEF_SIMPLE_ATTR(AnalyzerNoReturn);
DEF_SIMPLE_ATTR(Deprecated);
AT_format,
AT_format_arg,
AT_gnu_inline,
+ AT_malloc,
AT_mode,
AT_nodebug,
AT_noinline,
FuncAttrs |= llvm::Attribute::ReadNone;
else if (TargetDecl->hasAttr<PureAttr>())
FuncAttrs |= llvm::Attribute::ReadOnly;
+ if (TargetDecl->hasAttr<MallocAttr>())
+ RetAttrs |= llvm::Attribute::NoAlias;
}
if (CompileOpts.DisableRedZone)
New = ::new (*Context) IBOutletAttr();
break;
+ SIMPLE_ATTR(Malloc);
SIMPLE_ATTR(NoReturn);
SIMPLE_ATTR(NoThrow);
SIMPLE_ATTR(Nodebug);
case Attr::GNUInline:
case Attr::IBOutletKind:
+ case Attr::Malloc:
case Attr::NoReturn:
case Attr::NoThrow:
case Attr::Nodebug:
break;
case 6:
if (!memcmp(Str, "packed", 6)) return AT_packed;
- if (!memcmp(Str, "malloc", 6)) return IgnoredAttribute; // FIXME: noalias.
+ if (!memcmp(Str, "malloc", 6)) return AT_malloc;
if (!memcmp(Str, "format", 6)) return AT_format;
if (!memcmp(Str, "unused", 6)) return AT_unused;
if (!memcmp(Str, "blocks", 6)) return AT_blocks;
d->addAttr(::new (S.Context) AlwaysInlineAttr());
}
+static void HandleMallocAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+ // check the attribute arguments.
+ if (Attr.getNumArgs() != 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ return;
+ }
+
+ if (!isFunctionOrMethod(d)) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << 0 /*function*/;
+ return;
+ }
+
+ d->addAttr(::new (S.Context) MallocAttr());
+}
+
static bool HandleCommonNoReturnAttr(Decl *d, const AttributeList &Attr,
Sema &S) {
// check the attribute arguments.
case AttributeList::AT_format_arg: HandleFormatArgAttr (D, Attr, S); break;
case AttributeList::AT_gnu_inline: HandleGNUInlineAttr(D, Attr, S); break;
case AttributeList::AT_mode: HandleModeAttr (D, Attr, S); break;
+ case AttributeList::AT_malloc: HandleMallocAttr (D, Attr, S); break;
case AttributeList::AT_nonnull: HandleNonNullAttr (D, Attr, S); break;
case AttributeList::AT_noreturn: HandleNoReturnAttr (D, Attr, S); break;
case AttributeList::AT_nothrow: HandleNothrowAttr (D, Attr, S); break;
--- /dev/null
+// RUN: clang-cc -verify -fsyntax-only %s &&
+// RUN: clang-cc -emit-llvm -o %t %s &&
+
+#include <stdlib.h>
+
+int no_vars __attribute((malloc)); // expected-warning {{only applies to function types}}
+
+__attribute((malloc))
+void * xalloc(unsigned n) { return malloc(n); }
+// RUN: grep 'define noalias .* @xalloc(' %t &&
+
+#define __malloc_like __attribute((__malloc__))
+void * xalloc2(unsigned) __malloc_like;
+void * xalloc2(unsigned n) { return malloc(n); }
+// RUN: grep 'define noalias .* @xalloc2(' %t
+