From 7103f4ee638755a7b72aca009de9ceac64d09596 Mon Sep 17 00:00:00 2001 From: Matthias Gehre Date: Mon, 10 Jun 2019 23:18:54 +0200 Subject: [PATCH] WIP lifetime categories The test currently fails with ``` error: 'error' diagnostics seen but not expected: File /home/gehre/llvm-project/clang/test/SemaCXX/attr-gsl-owner-pointer.cpp Line 20: 'Owner' attribute takes one argument File /home/gehre/llvm-project/clang/test/SemaCXX/attr-gsl-owner-pointer.cpp Line 21: 'Pointer' attribute takes one argument File /home/gehre/llvm-project/clang/test/SemaCXX/attr-gsl-owner-pointer.cpp Line 24: expected '(' for function-style cast or type construction File /home/gehre/llvm-project/clang/test/SemaCXX/attr-gsl-owner-pointer.cpp Line 24: expected '(' for function-style cast or type construction File /home/gehre/llvm-project/clang/test/SemaCXX/attr-gsl-owner-pointer.cpp Line 26: expected '(' for function-style cast or type construction File /home/gehre/llvm-project/clang/test/SemaCXX/attr-gsl-owner-pointer.cpp Line 26: expected '(' for function-style cast or type construction File /home/gehre/llvm-project/clang/test/SemaCXX/attr-gsl-owner-pointer.cpp Line 27: expected '(' for function-style cast or type construction File /home/gehre/llvm-project/clang/test/SemaCXX/attr-gsl-owner-pointer.cpp Line 27: expected '(' for function-style cast or type construction File /home/gehre/llvm-project/clang/test/SemaCXX/attr-gsl-owner-pointer.cpp Line 29: expected '(' for function-style cast or type construction File /home/gehre/llvm-project/clang/test/SemaCXX/attr-gsl-owner-pointer.cpp Line 29: expected '(' for function-style cast or type construction File /home/gehre/llvm-project/clang/test/SemaCXX/attr-gsl-owner-pointer.cpp Line 30: expected '(' for function-style cast or type construction File /home/gehre/llvm-project/clang/test/SemaCXX/attr-gsl-owner-pointer.cpp Line 30: expected '(' for function-style cast or type construction File /home/gehre/llvm-project/clang/test/SemaCXX/attr-gsl-owner-pointer.cpp Line 32: expected '(' for function-style cast or type construction File /home/gehre/llvm-project/clang/test/SemaCXX/attr-gsl-owner-pointer.cpp Line 33: expected '(' for function-style cast or type construction File /home/gehre/llvm-project/clang/test/SemaCXX/attr-gsl-owner-pointer.cpp Line 35: expected '(' for function-style cast or type construction File /home/gehre/llvm-project/clang/test/SemaCXX/attr-gsl-owner-pointer.cpp Line 36: 'S' does not refer to a value error: 'note' diagnostics seen but not expected: File /home/gehre/llvm-project/clang/test/SemaCXX/attr-gsl-owner-pointer.cpp Line 8: declared here ``` --- clang/include/clang/Basic/Attr.td | 14 +++++++ clang/lib/Sema/SemaDeclAttr.cpp | 39 +++++++++++++++++++ clang/test/AST/ast-dump-attr.cpp | 9 +++++ clang/test/SemaCXX/attr-gsl-owner-pointer.cpp | 36 +++++++++++++++++ 4 files changed, 98 insertions(+) create mode 100644 clang/test/SemaCXX/attr-gsl-owner-pointer.cpp diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 9e2d5c63fbb2a..998db4f875ab8 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -2766,6 +2766,20 @@ def TypeTagForDatatype : InheritableAttr { let Documentation = [TypeTagForDatatypeDocs]; } +def Owner : InheritableAttr { + let Spellings = [CXX11<"gsl", "Owner">]; + let Subjects = SubjectList<[CXXRecord]>; + let Args = [TypeArgument<"DerefType">]; + let Documentation = [Undocumented]; // FIXME +} + +def Pointer : InheritableAttr { + let Subjects = SubjectList<[CXXRecord]>; + let Spellings = [CXX11<"gsl", "Pointer">]; + let Args = [TypeArgument<"DerefType">]; + let Documentation = [Undocumented]; // FIXME +} + // Microsoft-related attributes def MSNoVTable : InheritableAttr, TargetSpecificAttr { diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 932cb18a93cef..9c8d6f168e3e6 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -4533,6 +4533,39 @@ static void handleSuppressAttr(Sema &S, Decl *D, const ParsedAttr &AL) { DiagnosticIdentifiers.size(), AL.getAttributeSpellingListIndex())); } +static void handleLifetimeCategoryAttr(Sema &S, Decl *D, const ParsedAttr &AL) { + // if (!checkAttributeAtLeastNumArgs(S, AL, 1)) + // return; + + if (checkAttrMutualExclusion(S, D, AL)) + return; + if (checkAttrMutualExclusion(S, D, AL)) + return; + + if (!AL.hasParsedType()) { + S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1; + return; + } + + TypeSourceInfo *DerefTypeLoc = nullptr; + QualType ParmType = S.GetTypeFromParser(AL.getTypeArg(), &DerefTypeLoc); + assert(DerefTypeLoc && "no type source info for attribute argument"); + + if (ParmType->isVoidType()) { + S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << "'void'"; + return; + } + + if(AL.getKind() == ParsedAttr::AT_Owner) { + D->addAttr(::new (S.Context) OwnerAttr( + AL.getRange(), S.Context, DerefTypeLoc, AL.getAttributeSpellingListIndex())); + } + else { + D->addAttr(::new (S.Context) PointerAttr( + AL.getRange(), S.Context, DerefTypeLoc, AL.getAttributeSpellingListIndex())); + } +} + bool Sema::CheckCallingConvAttr(const ParsedAttr &Attrs, CallingConv &CC, const FunctionDecl *FD) { if (Attrs.isInvalid()) @@ -7110,6 +7143,12 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_Suppress: handleSuppressAttr(S, D, AL); break; + case ParsedAttr::AT_Owner: + handleLifetimeCategoryAttr(S, D, AL); + break; + case ParsedAttr::AT_Pointer: + handleLifetimeCategoryAttr(S, D, AL); + break; case ParsedAttr::AT_OpenCLKernel: handleSimpleAttribute(S, D, AL); break; diff --git a/clang/test/AST/ast-dump-attr.cpp b/clang/test/AST/ast-dump-attr.cpp index 8f67b9934e197..55a3205102792 100644 --- a/clang/test/AST/ast-dump-attr.cpp +++ b/clang/test/AST/ast-dump-attr.cpp @@ -211,6 +211,15 @@ namespace TestSuppress { } } +namespace TestLifetimeCategories { + class [[gsl::Owner(int)]] AOwner {}; + // CHECK: CXXRecordDecl{{.*}} struct AOwner + // CHECK-NEXT: ObjCBridgeRelatedAttr{{.*}} NSParagraphStyle + class [[gsl::Pointer(int)]] APointer {}; + // CHECK: CXXRecordDecl{{.*}} struct APointer + // CHECK-NEXT: ObjCBridgeRelatedAttr{{.*}} NSParagraphStyle +} + // Verify the order of attributes in the Ast. It must reflect the order // in the parsed source. int mergeAttrTest() __attribute__((deprecated)) __attribute__((warn_unused_result)); diff --git a/clang/test/SemaCXX/attr-gsl-owner-pointer.cpp b/clang/test/SemaCXX/attr-gsl-owner-pointer.cpp new file mode 100644 index 0000000000000..83efb672d50a3 --- /dev/null +++ b/clang/test/SemaCXX/attr-gsl-owner-pointer.cpp @@ -0,0 +1,36 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +int [[gsl::Owner]] i; +//expected-error@-1 {{'Owner' attribute cannot be applied to types}} +void [[gsl::Owner]] f(); +//expected-error@-1 {{'Owner' attribute cannot be applied to types}} + +struct S { +}; + +S [[gsl::Owner]] Instance; +//expected-error@-1 {{'Owner' attribute cannot be applied to types}} + +class [[gsl::Owner]] OwnerMissingParameter {}; +//expected-error@-1 {{'Owner' attribute takes one argument}} +class [[gsl::Pointer]] PointerMissingParameter {}; +//expected-error@-1 {{'Pointer' attribute takes one argument}} + + +class [[gsl::Owner(7)]] OwnerDerefNoType {}; +class [[gsl::Pointer("int")]] PointerDerefNoType {}; + + +class [[gsl::Owner(int)]] [[gsl::Pointer(int)]] BothOwnerPointer {}; + +class [[gsl::Owner(int)]] [[gsl::Owner(int)]] DuplicateOwner {}; +class [[gsl::Pointer(int)]] [[gsl::Pointer(int)]] DuplicatePointer {}; + +class [[gsl::Owner(int)]] [[gsl::Owner(char)]] OwnerDifferentTypes {}; +class [[gsl::Pointer(int)]] [[gsl::Pointer(char)]] PointerDifferentTypes {}; + +class [[gsl::Owner(void)]] OwnerVoidDerefType {}; +class [[gsl::Pointer(void)]] PointerVoidDerefType {}; + +class [[gsl::Owner(int)]] AnOwner {}; +class [[gsl::Pointer(S)]] APointer {};