]> granicus.if.org Git - clang/commitdiff
Add a C++11 and C2x spelling for the type safety attribute (argument_with_type_tag...
authorAaron Ballman <aaron@aaronballman.com>
Sun, 25 Feb 2018 14:01:04 +0000 (14:01 +0000)
committerAaron Ballman <aaron@aaronballman.com>
Sun, 25 Feb 2018 14:01:04 +0000 (14:01 +0000)
The TypeTagForDatatype attribute had custom parsing rules that previously prevented it from being supported with square bracket notation. The ArgumentWithTypeTag attribute previously had unnecessary custom parsing that could be handled declaratively.

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

include/clang/Basic/Attr.td
lib/Parse/ParseDecl.cpp
lib/Sema/SemaDeclAttr.cpp
test/Sema/attr-type-safety.c [new file with mode: 0644]
test/Sema/warn-type-safety.c

index 339fbb812020c0383434c478be747e6c2e7d5baa..aa3cc6944bb2b6250c610ac84cac13be0061fa3c 100644 (file)
@@ -2458,18 +2458,18 @@ def TestTypestate : InheritableAttr {
 // Type safety attributes for `void *' pointers and type tags.
 
 def ArgumentWithTypeTag : InheritableAttr {
-  let Spellings = [GNU<"argument_with_type_tag">,
-                   GNU<"pointer_with_type_tag">];
+  let Spellings = [Clang<"argument_with_type_tag", 1>,
+                   Clang<"pointer_with_type_tag", 1>];
+  let Subjects = SubjectList<[HasFunctionProto], ErrorDiag>;
   let Args = [IdentifierArgument<"ArgumentKind">,
               UnsignedArgument<"ArgumentIdx">,
               UnsignedArgument<"TypeTagIdx">,
-              BoolArgument<"IsPointer">];
-  let HasCustomParsing = 1;
+              BoolArgument<"IsPointer", /*opt*/0, /*fake*/1>];
   let Documentation = [ArgumentWithTypeTagDocs, PointerWithTypeTagDocs];
 }
 
 def TypeTagForDatatype : InheritableAttr {
-  let Spellings = [GNU<"type_tag_for_datatype">];
+  let Spellings = [Clang<"type_tag_for_datatype", 1>];
   let Args = [IdentifierArgument<"ArgumentKind">,
               TypeArgument<"MatchingCType">,
               BoolArgument<"LayoutCompatible">,
index d79ca8a0b2a55e09dbf6ddbbae715d1375e03d22..491ad31e176e9feda3a9ce035ea34c384b43ee00 100644 (file)
@@ -420,6 +420,10 @@ unsigned Parser::ParseClangAttributeArgs(
     ParseObjCBridgeRelatedAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,
                                     ScopeName, ScopeLoc, Syntax);
     break;
+  case AttributeList::AT_TypeTagForDatatype:
+    ParseTypeTagForDatatypeAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,
+                                     ScopeName, ScopeLoc, Syntax);
+    break;
   }
   return Attrs.getList() ? Attrs.getList()->getNumArgs() : 0;
 }
index 458c31881dc16e7b3da0dd6563814c790500f8ef..4247b32a672c176af72f64ff5883b6ad8a53676a 100644 (file)
@@ -4554,17 +4554,6 @@ static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D,
     return;
   }
   
-  if (!checkAttributeNumArgs(S, AL, 3))
-    return;
-
-  IdentifierInfo *ArgumentKind = AL.getArgAsIdent(0)->Ident;
-
-  if (!isFunctionOrMethod(D) || !hasFunctionProto(D)) {
-    S.Diag(AL.getLoc(), diag::err_attribute_wrong_decl_type)
-      << AL.getName() << ExpectedFunctionOrMethod;
-    return;
-  }
-
   uint64_t ArgumentIdx;
   if (!checkFunctionOrMethodParameterIndex(S, D, AL, 2, AL.getArgAsExpr(1),
                                            ArgumentIdx))
@@ -4575,7 +4564,7 @@ static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D,
                                            TypeTagIdx))
     return;
 
-  bool IsPointer = (AL.getName()->getName() == "pointer_with_type_tag");
+  bool IsPointer = AL.getName()->getName() == "pointer_with_type_tag";
   if (IsPointer) {
     // Ensure that buffer has a pointer type.
     QualType BufferTy = getFunctionOrMethodParamType(D, ArgumentIdx);
@@ -4585,10 +4574,9 @@ static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D,
     }
   }
 
-  D->addAttr(::new (S.Context)
-             ArgumentWithTypeTagAttr(AL.getRange(), S.Context, ArgumentKind,
-                                     ArgumentIdx, TypeTagIdx, IsPointer,
-                                     AL.getAttributeSpellingListIndex()));
+  D->addAttr(::new (S.Context) ArgumentWithTypeTagAttr(
+      AL.getRange(), S.Context, AL.getArgAsIdent(0)->Ident, ArgumentIdx,
+      TypeTagIdx, IsPointer, AL.getAttributeSpellingListIndex()));
 }
 
 static void handleTypeTagForDatatypeAttr(Sema &S, Decl *D,
diff --git a/test/Sema/attr-type-safety.c b/test/Sema/attr-type-safety.c
new file mode 100644 (file)
index 0000000..d7dab5d
--- /dev/null
@@ -0,0 +1,45 @@
+// RUN: %clang_cc1 -fsyntax-only -fdouble-square-bracket-attributes -verify %s
+
+struct A {};
+
+typedef struct A *MPI_Datatype;
+
+extern struct A datatype_wrong1 [[clang::type_tag_for_datatype]]; // expected-error {{'type_tag_for_datatype' attribute requires parameter 1 to be an identifier}}
+
+extern struct A datatype_wrong2 [[clang::type_tag_for_datatype(mpi,1,2)]]; // expected-error {{expected a type}}
+
+extern struct A datatype_wrong3 [[clang::type_tag_for_datatype(mpi,not_a_type)]]; // expected-error {{unknown type name 'not_a_type'}}
+
+extern struct A datatype_wrong4 [[clang::type_tag_for_datatype(mpi,int,int)]]; // expected-error {{expected identifier}}
+
+extern struct A datatype_wrong5 [[clang::type_tag_for_datatype(mpi,int,not_a_flag)]]; // expected-error {{invalid comparison flag 'not_a_flag'}}
+
+extern struct A datatype_wrong6 [[clang::type_tag_for_datatype(mpi,int,layout_compatible,not_a_flag)]]; // expected-error {{invalid comparison flag 'not_a_flag'}}
+
+extern struct A A_tag [[clang::type_tag_for_datatype(a,int)]];
+extern struct A B_tag [[clang::type_tag_for_datatype(b,int)]];
+
+static const int C_tag [[clang::type_tag_for_datatype(c,int)]] = 10;
+static const int D_tag [[clang::type_tag_for_datatype(d,int)]] = 20;
+
+[[clang::pointer_with_type_tag]] // expected-error {{'pointer_with_type_tag' attribute requires exactly 3 arguments}}
+int wrong1(void *buf, MPI_Datatype datatype);
+
+[[clang::pointer_with_type_tag(mpi,0,7)]]  // expected-error {{attribute parameter 2 is out of bounds}}
+int wrong2(void *buf, MPI_Datatype datatype);
+
+[[clang::pointer_with_type_tag(mpi,3,7)]] // expected-error {{attribute parameter 2 is out of bounds}}
+int wrong3(void *buf, MPI_Datatype datatype);
+
+[[clang::pointer_with_type_tag(mpi,1,0)]] // expected-error {{attribute parameter 3 is out of bounds}}
+int wrong4(void *buf, MPI_Datatype datatype);
+
+[[clang::pointer_with_type_tag(mpi,1,3)]] // expected-error {{attribute parameter 3 is out of bounds}}
+int wrong5(void *buf, MPI_Datatype datatype);
+
+[[clang::pointer_with_type_tag(mpi,0x8000000000000001ULL,1)]] // expected-error {{attribute parameter 2 is out of bounds}}
+int wrong6(void *buf, MPI_Datatype datatype);
+
+[[clang::pointer_with_type_tag(a,1,2)]] void A_func(void *ptr, void *tag);
+[[clang::pointer_with_type_tag(c,1,2)]] void C_func(void *ptr, int tag);
+
index 04313865a8b853689f0e633645145e55ebbb9ef8..36fb47e254a51a55736ca6900689161bd19ed024 100644 (file)
@@ -7,7 +7,7 @@ struct A {};
 typedef struct A *MPI_Datatype;
 
 int wrong1(void *buf, MPI_Datatype datatype)
-    __attribute__(( pointer_with_type_tag )); // expected-error {{'pointer_with_type_tag' attribute requires parameter 1 to be an identifier}}
+    __attribute__(( pointer_with_type_tag )); // expected-error {{'pointer_with_type_tag' attribute requires exactly 3 arguments}}
 
 int wrong2(void *buf, MPI_Datatype datatype)
     __attribute__(( pointer_with_type_tag(mpi,0,7) )); // expected-error {{attribute parameter 2 is out of bounds}}
@@ -32,7 +32,7 @@ int wrong7(void *buf, MPI_Datatype datatype)
 int wrong8(void *buf, MPI_Datatype datatype)
     __attribute__(( pointer_with_type_tag(mpi,1,x) )); // expected-error {{attribute requires parameter 3 to be an integer constant}}
 
-int wrong9 __attribute__(( pointer_with_type_tag(mpi,1,2) )); // expected-error {{attribute only applies to functions and methods}}
+int wrong9 __attribute__(( pointer_with_type_tag(mpi,1,2) )); // expected-error {{'pointer_with_type_tag' attribute only applies to non-K&R-style functions}}
 
 int wrong10(double buf, MPI_Datatype type)
     __attribute__(( pointer_with_type_tag(mpi,1,2) )); // expected-error {{'pointer_with_type_tag' attribute only applies to pointer arguments}}