]> granicus.if.org Git - clang/commitdiff
Add more error checking to attribute vecreturn
authorJohn Thompson <John.Thompson.JTSoftware@gmail.com>
Sat, 18 Sep 2010 01:12:07 +0000 (01:12 +0000)
committerJohn Thompson <John.Thompson.JTSoftware@gmail.com>
Sat, 18 Sep 2010 01:12:07 +0000 (01:12 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@114251 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaDeclAttr.cpp
test/Parser/cxx-altivec.cpp

index e796a4d564f9f99881c47c13a59247e866c4b724..b0dcf320d545ce9b0a21fe0fd17b47aa7c1dc0fc 100644 (file)
@@ -947,6 +947,10 @@ def warn_function_attribute_wrong_type : Warning<
 def warn_gnu_inline_attribute_requires_inline : Warning<
   "'gnu_inline' attribute requires function to be marked 'inline',"
   " attribute ignored">;
+def err_attribute_vecreturn_only_vector_member : Error<
+  "the vecreturn attribute can only be used on a class or structure with one member, which must be a vector">;
+def err_attribute_vecreturn_only_pod_record : Error<
+  "the vecreturn attribute can only be used on a POD (plain old data) class or structure (i.e. no virtual functions)">;
 def err_cconv_change : Error<
   "function declared '%0' here was previously declared "
   "%select{'%2'|without calling convention}1">;
index a47d84fa35c45d003276e9f0677a01d61cd0eadd..dce1bf84fcc46290af7bd895206c2b87ef4ffea0 100644 (file)
@@ -724,7 +724,7 @@ static void HandleVecReturnAttr(Decl *d, const AttributeList &Attr,
     return result; // This will be returned in a register
   }
 */
-  if (!isa<CXXRecordDecl>(d)) {
+  if (!isa<RecordDecl>(d)) {
     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
       << Attr.getName() << 9 /*class*/;
     return;
@@ -735,6 +735,27 @@ static void HandleVecReturnAttr(Decl *d, const AttributeList &Attr,
     return;
   }
 
+  RecordDecl *record = cast<RecordDecl>(d);
+  int count = 0;
+
+  if (!isa<CXXRecordDecl>(record)) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_vecreturn_only_vector_member);
+    return;
+  }
+
+  if (!cast<CXXRecordDecl>(record)->isPOD()) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_vecreturn_only_pod_record);
+    return;
+  }
+
+  for (RecordDecl::field_iterator iter = record->field_begin(); iter != record->field_end(); iter++) {
+    if ((count == 1) || !iter->getType()->isVectorType()) {
+      S.Diag(Attr.getLoc(), diag::err_attribute_vecreturn_only_vector_member);
+      return;
+    }
+    count++;
+  }
+
   d->addAttr(::new (S.Context) VecReturnAttr(Attr.getLoc(), S.Context));
 }
 
index 8f463308112bdf0edc629ba3d723c29a69018fe7..0ceb9f2e80e828b2fd7d0627912da7992f322d1c 100644 (file)
@@ -161,3 +161,20 @@ Vector Add(Vector lhs, Vector rhs)
        result.xyzw = vec_add(lhs.xyzw, rhs.xyzw);
        return result; // This will (eventually) be returned in a register
 }
+
+// vecreturn attribute test - should error because of virtual function.
+class VectorClassNonPod
+{
+       __vector float xyzw;
+public:
+  VectorClassNonPod() {}
+  virtual ~VectorClassNonPod() {}
+} __attribute__((vecreturn));     // expected-error {{the vecreturn attribute can only be used on a POD (plain old data) class or structure (i.e. no virtual functions)}}
+
+// vecreturn attribute test - should error because of virtual function.
+class VectorClassMultipleMembers
+{
+public:
+       __vector float xyzw;
+       __vector float abcd;
+} __attribute__((vecreturn));     // expected-error {{the vecreturn attribute can only be used on a class or structure with one member, which must be a vector}}