From 631a90b6bc1d8526d463660934dedf21c1904e5f Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Wed, 4 Feb 2015 07:23:21 +0000 Subject: [PATCH] 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 --- clang/include/clang/Basic/Attr.td | 6 ++--- .../clang/Basic/DiagnosticSemaKinds.td | 3 --- clang/include/clang/Sema/Sema.h | 2 +- clang/lib/CodeGen/CGCall.cpp | 2 +- clang/lib/Sema/SemaDeclAttr.cpp | 22 +++++++++---------- clang/lib/Sema/SemaExprCXX.cpp | 12 +++++----- clang/test/Parser/MicrosoftExtensions.c | 2 +- clang/test/Sema/attr-malloc.c | 10 ++++----- clang/test/SemaObjC/attr-malloc.m | 10 ++++----- 9 files changed, 33 insertions(+), 36 deletions(-) diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 5171b0c63e65..48e04beeaa49 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -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]; } diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 039c8937bd4a..5c66952979a9 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -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; -def warn_attribute_malloc_pointer_only : Warning< - "'malloc' attribute only applies to functions returning a pointer type">, - InGroup; def warn_attribute_sentinel_named_arguments : Warning< "'sentinel' attribute requires named arguments">, InGroup; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 744ce2191d62..91aee24a6b89 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -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, diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 6515d14f8bbb..b0b30a6133a4 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -1402,7 +1402,7 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI, FuncAttrs.addAttribute(llvm::Attribute::ReadOnly); FuncAttrs.addAttribute(llvm::Attribute::NoUnwind); } - if (TargetDecl->hasAttr()) + if (TargetDecl->hasAttr()) RetAttrs.addAttribute(llvm::Attribute::NoAlias); if (TargetDecl->hasAttr()) RetAttrs.addAttribute(llvm::Attribute::NonNull); diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index a05856ed7d3c..2f92d3dbb2d3 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -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(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(S, D, Attr); diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index c142efb11d52..26493078fda4 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -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()) - Func->addAttr(MallocAttr::CreateImplicit(Context)); + if (AddRestrictAttr && !Func->hasAttr()) + 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) { diff --git a/clang/test/Parser/MicrosoftExtensions.c b/clang/test/Parser/MicrosoftExtensions.c index ea25ccd1af33..83e0921f8b55 100644 --- a/clang/test/Parser/MicrosoftExtensions.c +++ b/clang/test/Parser/MicrosoftExtensions.c @@ -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) { diff --git a/clang/test/Sema/attr-malloc.c b/clang/test/Sema/attr-malloc.c index c78d15c802ce..5351d757a23f 100644 --- a/clang/test/Sema/attr-malloc.c +++ b/clang/test/Sema/attr-malloc.c @@ -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 diff --git a/clang/test/SemaObjC/attr-malloc.m b/clang/test/SemaObjC/attr-malloc.m index a504b333b51f..0874a476806c 100644 --- a/clang/test/SemaObjC/attr-malloc.m +++ b/clang/test/SemaObjC/attr-malloc.m @@ -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}}