diff options
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 23 | ||||
-rw-r--r-- | clang/test/Parser/cxx-altivec.cpp | 17 |
3 files changed, 43 insertions, 1 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index e796a4d564f..b0dcf320d54 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/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/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index a47d84fa35c..dce1bf84fcc 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/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<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)); } diff --git a/clang/test/Parser/cxx-altivec.cpp b/clang/test/Parser/cxx-altivec.cpp index 8f463308112..0ceb9f2e80e 100644 --- a/clang/test/Parser/cxx-altivec.cpp +++ b/clang/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}} |