From: John Thompson Date: Sat, 18 Sep 2010 01:12:07 +0000 (+0000) Subject: Add more error checking to attribute vecreturn X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=01add59bc8fd178960ad61169bc01566b0d6614c;p=clang Add more error checking to attribute vecreturn git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@114251 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index e796a4d564..b0dcf320d5 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -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">; diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index a47d84fa35..dce1bf84fc 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -724,7 +724,7 @@ static void HandleVecReturnAttr(Decl *d, const AttributeList &Attr, return result; // This will be returned in a register } */ - if (!isa(d)) { + if (!isa(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(d); + int count = 0; + + if (!isa(record)) { + S.Diag(Attr.getLoc(), diag::err_attribute_vecreturn_only_vector_member); + return; + } + + if (!cast(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)); } diff --git a/test/Parser/cxx-altivec.cpp b/test/Parser/cxx-altivec.cpp index 8f46330811..0ceb9f2e80 100644 --- a/test/Parser/cxx-altivec.cpp +++ b/test/Parser/cxx-altivec.cpp @@ -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}}