forked from OSchip/llvm-project
Sema: Add support for __declspec(restrict)
__declspec(restrict) and __attribute(malloc) are both handled identically by clang: they are allowed to the noalias LLVM attribute. Seeing as how noalias models the C99 notion of 'restrict', rename the internal clang attribute to Restrict from Malloc. llvm-svn: 228120
This commit is contained in:
parent
a3d9534248
commit
631a90b6bc
|
@ -790,9 +790,9 @@ def IBOutletCollection : InheritableAttr {
|
|||
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];
|
||||
}
|
||||
|
||||
|
|
|
@ -2649,9 +2649,6 @@ def warn_attribute_nonnull_no_pointers : Warning<
|
|||
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>;
|
||||
|
|
|
@ -4498,7 +4498,7 @@ public:
|
|||
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,
|
||||
|
|
|
@ -1402,7 +1402,7 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
|
|||
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);
|
||||
|
|
|
@ -1548,18 +1548,16 @@ static void handleTLSModelAttr(Sema &S, Decl *D,
|
|||
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) {
|
||||
|
@ -4453,8 +4451,8 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
|
|||
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);
|
||||
|
|
|
@ -2054,7 +2054,7 @@ void Sema::DeclareGlobalNewDelete() {
|
|||
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;
|
||||
|
||||
|
@ -2077,8 +2077,9 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
|
|||
// 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.
|
||||
|
@ -2121,8 +2122,9 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
|
|||
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) {
|
||||
|
|
|
@ -5,7 +5,7 @@ typedef int (__cdecl *tptr)(void);
|
|||
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) {
|
||||
|
|
|
@ -6,16 +6,16 @@
|
|||
// 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
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
// 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
|
||||
|
@ -10,7 +10,7 @@ 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}}
|
||||
|
||||
|
|
Loading…
Reference in New Issue