]> granicus.if.org Git - clang/commitdiff
Sema: Add support for __declspec(restrict)
authorDavid Majnemer <david.majnemer@gmail.com>
Wed, 4 Feb 2015 07:23:21 +0000 (07:23 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Wed, 4 Feb 2015 07:23:21 +0000 (07:23 +0000)
__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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@228120 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/Attr.td
include/clang/Basic/DiagnosticSemaKinds.td
include/clang/Sema/Sema.h
lib/CodeGen/CGCall.cpp
lib/Sema/SemaDeclAttr.cpp
lib/Sema/SemaExprCXX.cpp
test/Parser/MicrosoftExtensions.c
test/Sema/attr-malloc.c
test/SemaObjC/attr-malloc.m

index 5171b0c63e658ce178e1d58b90e075971fcd1ccc..48e04beeaa49e5d9802ce3aa2cab3c5a1ee37722 100644 (file)
@@ -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];
 }
 
index 039c8937bd4ae82cce3edda7b99aee7aac3cc515..5c66952979a91ccedf1638e4f7a2b1ba1225f18c 100644 (file)
@@ -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>;
index 744ce2191d62fef9a580505d0b6fc13a73a07f38..91aee24a6b89fe2989f1e9ff386c830d565b9fbf 100644 (file)
@@ -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,
index 6515d14f8bbb1f0eb8dcd909ec182bddcd637b34..b0b30a6133a459fad72750af63cf3cdacb022ff9 100644 (file)
@@ -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);
index a05856ed7d3c1c5dc1b6c569f7df084e1ff5f8fa..2f92d3dbb2d35a6c8f7913ac2f9f68295706b3ac 100644 (file)
@@ -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);
index c142efb11d52b5b56f62d3bdf4a948dc8fe31cef..26493078fda48d57798395cb4bf4f25db6056645 100644 (file)
@@ -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) {
index ea25ccd1af332bb10e921a1b24cf82cce44c1aa6..83e0921f8b55196418c43e131473db2be71f7087 100644 (file)
@@ -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) {
index c78d15c802cef3d691ab760fb385715fb4b8ce57..5351d757a23f4d553bcbe71d2571d01b00f11313 100644 (file)
@@ -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
index a504b333b51fa8b10d3840869e8d3ff0ca296b0f..0874a476806ca6ce90c7c1bd29a5323835907161 100644 (file)
@@ -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}}