let Documentation = [Undocumented];
}
-def Malloc : InheritableAttr {
- let Spellings = [GCC<"malloc">];
-// let Subjects = [Function];
+def Restrict : InheritableAttr {
+ let Spellings = [Declspec<"restrict">, GCC<"malloc">];
+ let Subjects = SubjectList<[Function]>;
let Documentation = [Undocumented];
}
def warn_attribute_nonnull_parm_no_args : Warning<
"'nonnull' attribute when used on parameters takes no arguments">,
InGroup<IgnoredAttributes>;
-def warn_attribute_malloc_pointer_only : Warning<
- "'malloc' attribute only applies to functions returning a pointer type">,
- InGroup<IgnoredAttributes>;
def warn_attribute_sentinel_named_arguments : Warning<
"'sentinel' attribute requires named arguments">,
InGroup<IgnoredAttributes>;
void DeclareGlobalAllocationFunction(DeclarationName Name, QualType Return,
QualType Param1,
QualType Param2 = QualType(),
- bool addMallocAttr = false);
+ bool addRestrictAttr = false);
bool FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
DeclarationName Name, FunctionDecl* &Operator,
FuncAttrs.addAttribute(llvm::Attribute::ReadOnly);
FuncAttrs.addAttribute(llvm::Attribute::NoUnwind);
}
- if (TargetDecl->hasAttr<MallocAttr>())
+ if (TargetDecl->hasAttr<RestrictAttr>())
RetAttrs.addAttribute(llvm::Attribute::NoAlias);
if (TargetDecl->hasAttr<ReturnsNonNullAttr>())
RetAttrs.addAttribute(llvm::Attribute::NonNull);
Attr.getAttributeSpellingListIndex()));
}
-static void handleMallocAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
- QualType RetTy = FD->getReturnType();
- if (RetTy->isAnyPointerType() || RetTy->isBlockPointerType()) {
- D->addAttr(::new (S.Context)
- MallocAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
- return;
- }
+static void handleRestrictAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+ QualType ResultType = getFunctionOrMethodResultType(D);
+ if (ResultType->isAnyPointerType() || ResultType->isBlockPointerType()) {
+ D->addAttr(::new (S.Context) RestrictAttr(
+ Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+ return;
}
- S.Diag(Attr.getLoc(), diag::warn_attribute_malloc_pointer_only);
+ S.Diag(Attr.getLoc(), diag::warn_attribute_return_pointers_only)
+ << Attr.getName() << getFunctionOrMethodResultSourceRange(D);
}
static void handleCommonAttr(Sema &S, Decl *D, const AttributeList &Attr) {
case AttributeList::AT_CUDALaunchBounds:
handleLaunchBoundsAttr(S, D, Attr);
break;
- case AttributeList::AT_Malloc:
- handleMallocAttr(S, D, Attr);
+ case AttributeList::AT_Restrict:
+ handleRestrictAttr(S, D, Attr);
break;
case AttributeList::AT_MayAlias:
handleSimpleAttribute<MayAliasAttr>(S, D, Attr);
void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
QualType Return,
QualType Param1, QualType Param2,
- bool AddMallocAttr) {
+ bool AddRestrictAttr) {
DeclContext *GlobalCtx = Context.getTranslationUnitDecl();
unsigned NumParams = Param2.isNull() ? 1 : 2;
// FIXME: Do we need to check for default arguments here?
if (InitialParam1Type == Param1 &&
(NumParams == 1 || InitialParam2Type == Param2)) {
- if (AddMallocAttr && !Func->hasAttr<MallocAttr>())
- Func->addAttr(MallocAttr::CreateImplicit(Context));
+ if (AddRestrictAttr && !Func->hasAttr<RestrictAttr>())
+ Func->addAttr(RestrictAttr::CreateImplicit(
+ Context, RestrictAttr::GNU_malloc));
// Make the function visible to name lookup, even if we found it in
// an unimported module. It either is an implicitly-declared global
// allocation function, or is suppressing that function.
Alloc->addAttr(VisibilityAttr::CreateImplicit(Context,
VisibilityAttr::Default));
- if (AddMallocAttr)
- Alloc->addAttr(MallocAttr::CreateImplicit(Context));
+ if (AddRestrictAttr)
+ Alloc->addAttr(
+ RestrictAttr::CreateImplicit(Context, RestrictAttr::GNU_malloc));
ParmVarDecl *ParamDecls[2];
for (unsigned I = 0; I != NumParams; ++I) {
void (*__fastcall fastpfunc)(void);
extern __declspec(dllimport) void __stdcall VarR4FromDec(void);
__declspec(deprecated) __declspec(deprecated) char * __cdecl ltoa( long _Val, char * _DstBuf, int _Radix);
-__declspec(safebuffers) __declspec(noalias) __declspec(restrict) void * __cdecl xxx(void *_Memory); /* expected-warning{{__declspec attribute 'safebuffers' is not supported}} expected-warning{{__declspec attribute 'noalias' is not supported}} expected-warning{{__declspec attribute 'restrict' is not supported}} */
+__declspec(safebuffers) __declspec(noalias) __declspec(restrict) void * __cdecl xxx(void *_Memory); /* expected-warning{{__declspec attribute 'safebuffers' is not supported}} expected-warning{{__declspec attribute 'noalias' is not supported}} */
typedef __w64 unsigned long ULONG_PTR, *PULONG_PTR;
void * __ptr64 PtrToPtr64(const void *p) {
// Declare malloc here explicitly so we don't depend on system headers.
void * malloc(size_t) __attribute((malloc));
-int no_vars __attribute((malloc)); // expected-warning {{functions returning a pointer type}}
+int no_vars __attribute((malloc)); // expected-warning {{attribute only applies to functions}}
-void returns_void (void) __attribute((malloc)); // expected-warning {{functions returning a pointer type}}
-int returns_int (void) __attribute((malloc)); // expected-warning {{functions returning a pointer type}}
+void returns_void (void) __attribute((malloc)); // expected-warning {{attribute only applies to return values that are pointers}}
+int returns_int (void) __attribute((malloc)); // expected-warning {{attribute only applies to return values that are pointers}}
int * returns_intptr(void) __attribute((malloc)); // no-warning
typedef int * iptr;
iptr returns_iptr (void) __attribute((malloc)); // no-warning
-__attribute((malloc)) void *(*f)(); // expected-warning{{'malloc' attribute only applies to functions returning a pointer type}}
-__attribute((malloc)) int (*g)(); // expected-warning{{'malloc' attribute only applies to functions returning a pointer type}}
+__attribute((malloc)) void *(*f)(); // expected-warning{{attribute only applies to functions}}
+__attribute((malloc)) int (*g)(); // expected-warning{{attribute only applies to functions}}
__attribute((malloc))
void * xalloc(unsigned n) { return malloc(n); } // no-warning
// RUN: %clang_cc1 -verify -fsyntax-only -fblocks %s
@interface TestAttrMallocOnMethods {}
-- (id) test1 __attribute((malloc)); // expected-warning {{functions returning a pointer type}}
-- (int) test2 __attribute((malloc)); // expected-warning {{functions returning a pointer type}}
+- (id) test1 __attribute((malloc)); // expected-warning {{attribute only applies to functions}}
+- (int) test2 __attribute((malloc)); // expected-warning {{attribute only applies to functions}}
@end
id bar(void) __attribute((malloc)); // no-warning
typedef void (^bptr)(void);
bptr baz(void) __attribute((malloc)); // no-warning
-__attribute((malloc)) id (*f)(); // expected-warning {{functions returning a pointer type}}
-__attribute((malloc)) bptr (*g)(); // expected-warning {{functions returning a pointer type}}
-__attribute((malloc)) void *(^h)(); // expected-warning {{functions returning a pointer type}}
+__attribute((malloc)) id (*f)(); // expected-warning {{attribute only applies to functions}}
+__attribute((malloc)) bptr (*g)(); // expected-warning {{attribute only applies to functions}}
+__attribute((malloc)) void *(^h)(); // expected-warning {{attribute only applies to functions}}