[PATCH] D114439: [Annotation] Allow parameter pack expansions in annotate attribute

2022-01-26 Thread Steffen Larsen via Phabricator via cfe-commits
steffenlarsen marked 2 inline comments as done.
steffenlarsen added inline comments.



Comment at: clang/lib/Parse/ParseDecl.cpp:497
+// Pack expansion is only allowed in the variadic argument at the end.
+const size_t attrNumArgs = attributeNumberOfArguments(*AttrName);
+if (ArgExprs.size() + I + 1 < attrNumArgs) {

aaron.ballman wrote:
> aaron.ballman wrote:
> > Coding style nits.
> We don't typically use top-level `const`, so that should go as well.
Completely missed that. My bad!



Comment at: clang/lib/Parse/ParseExpr.cpp:3374-3375
 
+if (EarlyTypoCorrection)
+  Expr = Actions.CorrectDelayedTyposInExpr(Expr);
+

aaron.ballman wrote:
> steffenlarsen wrote:
> > aaron.ballman wrote:
> > > steffenlarsen wrote:
> > > > aaron.ballman wrote:
> > > > > Not that I think this is a bad change, but it seems unrelated to the 
> > > > > patch. Can you explain why you made the change?
> > > > Admittedly I am not sure why it is needed, but in the previous version 
> > > > of the parsing for attribute parameters it does the typo-correction 
> > > > immediately after parsing the expression and if this isn't added a 
> > > > handful of tests fail.
> > > Ah, thanks for the info! So this is basically doing the same work as 
> > > what's done on line 3410 in the late failure case -- I wonder if this 
> > > should actually be tied to the `FailImmediatelyOnInvalidExpr` parameter 
> > > instead of having its own parameter?
> > They could be unified in the current version, but I don't think there is an 
> > actual relation between them.
> Do we fail tests if this isn't conditionalized at all (we always do the early 
> typo correction)? (I'd like to avoid adding the new parameter because I'm not 
> certain how a caller would determine whether they do or do not want that 
> behavior. If we need the parameter, then so be it, but it seems like this is 
> something generally useful.)
11 tests fail if we don't make it conditional. The most telling one is probably 
`SemaCXX/typo-correction-delayed.cpp` which will have more errors if we do typo 
correction early, so it seems that the delay is intentional. 



Comment at: clang/test/Parser/cxx0x-attributes.cpp:262
 
-template void variadic() {
+template  void variadic() {
   void bar [[noreturn...]] (); // expected-error {{attribute 'noreturn' cannot 
be used as an attribute pack}}

aaron.ballman wrote:
> You can back out the whitespace changes for an ever-so-slightly smaller 
> patch. :-D
Absolutely. Clang-format was very insistent, but since it isn't added by this 
patch I shouldn't worry.  



Comment at: clang/test/Parser/cxx0x-attributes.cpp:276-277
+  void foz [[clang::annotate("E", 1, 2, 3, Is...)]] ();
+  void fiz [[clang::annotate("F", Is..., 1, 2, 3)]] ();
+  void fir [[clang::annotate("G", 1, Is..., 2, 3)]] ();
+}

aaron.ballman wrote:
> Shouldn't these cases also give the `// expected-error {{pack expansion in 
> 'annotate' may only be applied to the last argument}}` diagnostic?
These should preferably pass. They are part of the "last" argument as 
`annotate` has one non-variadic argument and one variadic argument. I agree 
though that the error message is a little vague. Originally the error did 
specify that it had to be "argument %1 or later" to try and convey this intent, 
but maybe you have an idea for a clearer error message?


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D114439/new/

https://reviews.llvm.org/D114439

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D114439: [Annotation] Allow parameter pack expansions in annotate attribute

2022-01-26 Thread Steffen Larsen via Phabricator via cfe-commits
steffenlarsen updated this revision to Diff 403187.
steffenlarsen marked an inline comment as done.
steffenlarsen added a comment.

Removing top-level `const` and adjusting style.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D114439/new/

https://reviews.llvm.org/D114439

Files:
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/DiagnosticParseKinds.td
  clang/include/clang/Parse/Parser.h
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Parse/ParseExpr.cpp
  clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
  clang/test/Parser/cxx0x-attributes.cpp
  clang/test/SemaTemplate/attributes.cpp
  clang/utils/TableGen/ClangAttrEmitter.cpp

Index: clang/utils/TableGen/ClangAttrEmitter.cpp
===
--- clang/utils/TableGen/ClangAttrEmitter.cpp
+++ clang/utils/TableGen/ClangAttrEmitter.cpp
@@ -1164,10 +1164,12 @@
   };
 
   class VariadicExprArgument : public VariadicArgument {
+bool AllowPack = false;
+
   public:
 VariadicExprArgument(const Record , StringRef Attr)
-  : VariadicArgument(Arg, Attr, "Expr *")
-{}
+: VariadicArgument(Arg, Attr, "Expr *"),
+  AllowPack(Arg.getValueAsBit("AllowPack")) {}
 
 void writeASTVisitorTraversal(raw_ostream ) const override {
   OS << "  {\n";
@@ -2264,6 +2266,47 @@
   OS << "#endif // CLANG_ATTR_THIS_ISA_IDENTIFIER_ARG_LIST\n\n";
 }
 
+static void emitClangAttrNumArgs(RecordKeeper , raw_ostream ) {
+  OS << "#if defined(CLANG_ATTR_NUM_ARGS)\n";
+  std::vector Attrs = Records.getAllDerivedDefinitions("Attr");
+  for (const auto *A : Attrs) {
+std::vector Args = A->getValueAsListOfDefs("Args");
+forEachUniqueSpelling(*A, [&](const FlattenedSpelling ) {
+  OS << ".Case(\"" << S.name() << "\", " << Args.size() << ")\n";
+});
+  }
+  OS << "#endif // CLANG_ATTR_NUM_ARGS\n\n";
+}
+
+static bool argSupportsParmPack(const Record *Arg) {
+  return !Arg->getSuperClasses().empty() &&
+ llvm::StringSwitch(
+ Arg->getSuperClasses().back().first->getName())
+ .Case("VariadicExprArgument", true)
+ .Default(false) &&
+ Arg->getValueAsBit("AllowPack");
+}
+
+static void emitClangAttrLastArgParmPackSupport(RecordKeeper ,
+raw_ostream ) {
+  OS << "#if defined(CLANG_ATTR_LAST_ARG_PARM_PACK_SUPPORT)\n";
+  std::vector Attrs = Records.getAllDerivedDefinitions("Attr");
+  for (const auto *A : Attrs) {
+std::vector Args = A->getValueAsListOfDefs("Args");
+bool LastArgSupportsParmPack =
+!Args.empty() && argSupportsParmPack(Args.back());
+forEachUniqueSpelling(*A, [&](const FlattenedSpelling ) {
+  OS << ".Case(\"" << S.name() << "\", " << LastArgSupportsParmPack
+ << ")\n";
+});
+  }
+  OS << "#endif // CLANG_ATTR_LAST_ARG_PARM_PACK_SUPPORT\n\n";
+}
+
+static bool isArgVariadic(const Record , StringRef AttrName) {
+  return createArgument(R, AttrName)->isVariadic();
+}
+
 static void emitAttributes(RecordKeeper , raw_ostream ,
bool Header) {
   std::vector Attrs = Records.getAllDerivedDefinitions("Attr");
@@ -2320,6 +2363,18 @@
 std::vector> Args;
 Args.reserve(ArgRecords.size());
 
+if (!ArgRecords.empty()) {
+  const bool LastArgSupportsPack = argSupportsParmPack(ArgRecords.back());
+  for (size_t I = 0; I < ArgRecords.size() - 1; ++I) {
+assert((!LastArgSupportsPack ||
+!isArgVariadic(*ArgRecords[I], R.getName())) &&
+   "Attributes supporting packs can only have the last "
+   "argument as variadic");
+assert(!argSupportsParmPack(ArgRecords[I]) &&
+   "Only the last argument can allow packs");
+  }
+}
+
 bool HasOptArg = false;
 bool HasFakeArg = false;
 for (const auto *ArgRecord : ArgRecords) {
@@ -3382,10 +3437,6 @@
   }
 }
 
-static bool isArgVariadic(const Record , StringRef AttrName) {
-  return createArgument(R, AttrName)->isVariadic();
-}
-
 static void emitArgInfo(const Record , raw_ostream ) {
   // This function will count the number of arguments specified for the
   // attribute and emit the number of required arguments followed by the
@@ -4219,6 +4270,8 @@
   emitClangAttrIdentifierArgList(Records, OS);
   emitClangAttrVariadicIdentifierArgList(Records, OS);
   emitClangAttrThisIsaIdentifierArgList(Records, OS);
+  emitClangAttrNumArgs(Records, OS);
+  emitClangAttrLastArgParmPackSupport(Records, OS);
   emitClangAttrTypeArgList(Records, OS);
   emitClangAttrLateParsedList(Records, OS);
 }
Index: clang/test/SemaTemplate/attributes.cpp
===
--- clang/test/SemaTemplate/attributes.cpp
+++ clang/test/SemaTemplate/attributes.cpp
@@ -64,6 +64,23 @@
 template [[clang::annotate("ANNOTATE_FOO"), clang::annotate("ANNOTATE_BAR")]] void HasAnnotations();
 void UseAnnotations() { HasAnnotations(); }
 
+// CHECK:  FunctionTemplateDecl 

[PATCH] D114439: [Annotation] Allow parameter pack expansions in annotate attribute

2022-01-25 Thread Aaron Ballman via Phabricator via cfe-commits
aaron.ballman added inline comments.



Comment at: clang/lib/Parse/ParseDecl.cpp:497
+// Pack expansion is only allowed in the variadic argument at the end.
+const size_t attrNumArgs = attributeNumberOfArguments(*AttrName);
+if (ArgExprs.size() + I + 1 < attrNumArgs) {

aaron.ballman wrote:
> Coding style nits.
We don't typically use top-level `const`, so that should go as well.



Comment at: clang/lib/Parse/ParseExpr.cpp:3374-3375
 
+if (EarlyTypoCorrection)
+  Expr = Actions.CorrectDelayedTyposInExpr(Expr);
+

steffenlarsen wrote:
> aaron.ballman wrote:
> > steffenlarsen wrote:
> > > aaron.ballman wrote:
> > > > Not that I think this is a bad change, but it seems unrelated to the 
> > > > patch. Can you explain why you made the change?
> > > Admittedly I am not sure why it is needed, but in the previous version of 
> > > the parsing for attribute parameters it does the typo-correction 
> > > immediately after parsing the expression and if this isn't added a 
> > > handful of tests fail.
> > Ah, thanks for the info! So this is basically doing the same work as what's 
> > done on line 3410 in the late failure case -- I wonder if this should 
> > actually be tied to the `FailImmediatelyOnInvalidExpr` parameter instead of 
> > having its own parameter?
> They could be unified in the current version, but I don't think there is an 
> actual relation between them.
Do we fail tests if this isn't conditionalized at all (we always do the early 
typo correction)? (I'd like to avoid adding the new parameter because I'm not 
certain how a caller would determine whether they do or do not want that 
behavior. If we need the parameter, then so be it, but it seems like this is 
something generally useful.)



Comment at: clang/test/Parser/cxx0x-attributes.cpp:262
 
-template void variadic() {
+template  void variadic() {
   void bar [[noreturn...]] (); // expected-error {{attribute 'noreturn' cannot 
be used as an attribute pack}}

You can back out the whitespace changes for an ever-so-slightly smaller patch. 
:-D



Comment at: clang/test/Parser/cxx0x-attributes.cpp:276-277
+  void foz [[clang::annotate("E", 1, 2, 3, Is...)]] ();
+  void fiz [[clang::annotate("F", Is..., 1, 2, 3)]] ();
+  void fir [[clang::annotate("G", 1, Is..., 2, 3)]] ();
+}

Shouldn't these cases also give the `// expected-error {{pack expansion in 
'annotate' may only be applied to the last argument}}` diagnostic?


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D114439/new/

https://reviews.llvm.org/D114439

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D114439: [Annotation] Allow parameter pack expansions in annotate attribute

2022-01-21 Thread Steffen Larsen via Phabricator via cfe-commits
steffenlarsen marked an inline comment as done.
steffenlarsen added inline comments.



Comment at: clang/lib/Parse/ParseDecl.cpp:468
+
+  // General case. Parse all available expressions.
+  CommaLocsTy CommaLocs;

aaron.ballman wrote:
> I think it'd be good to move this comment up closer to the `else` on line 461 
> so that it's clear what the else clause covers (and more clear that this is 
> the common case).
I completely agree. It has been moved to right after the `else`.



Comment at: clang/lib/Parse/ParseExpr.cpp:3374-3375
 
+if (EarlyTypoCorrection)
+  Expr = Actions.CorrectDelayedTyposInExpr(Expr);
+

aaron.ballman wrote:
> steffenlarsen wrote:
> > aaron.ballman wrote:
> > > Not that I think this is a bad change, but it seems unrelated to the 
> > > patch. Can you explain why you made the change?
> > Admittedly I am not sure why it is needed, but in the previous version of 
> > the parsing for attribute parameters it does the typo-correction 
> > immediately after parsing the expression and if this isn't added a handful 
> > of tests fail.
> Ah, thanks for the info! So this is basically doing the same work as what's 
> done on line 3410 in the late failure case -- I wonder if this should 
> actually be tied to the `FailImmediatelyOnInvalidExpr` parameter instead of 
> having its own parameter?
They could be unified in the current version, but I don't think there is an 
actual relation between them.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D114439/new/

https://reviews.llvm.org/D114439

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D114439: [Annotation] Allow parameter pack expansions in annotate attribute

2022-01-21 Thread Steffen Larsen via Phabricator via cfe-commits
steffenlarsen updated this revision to Diff 401910.
steffenlarsen added a comment.

Moved comment.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D114439/new/

https://reviews.llvm.org/D114439

Files:
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/DiagnosticParseKinds.td
  clang/include/clang/Parse/Parser.h
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Parse/ParseExpr.cpp
  clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
  clang/test/Parser/cxx0x-attributes.cpp
  clang/test/SemaTemplate/attributes.cpp
  clang/utils/TableGen/ClangAttrEmitter.cpp

Index: clang/utils/TableGen/ClangAttrEmitter.cpp
===
--- clang/utils/TableGen/ClangAttrEmitter.cpp
+++ clang/utils/TableGen/ClangAttrEmitter.cpp
@@ -1164,10 +1164,12 @@
   };
 
   class VariadicExprArgument : public VariadicArgument {
+bool AllowPack = false;
+
   public:
 VariadicExprArgument(const Record , StringRef Attr)
-  : VariadicArgument(Arg, Attr, "Expr *")
-{}
+: VariadicArgument(Arg, Attr, "Expr *"),
+  AllowPack(Arg.getValueAsBit("AllowPack")) {}
 
 void writeASTVisitorTraversal(raw_ostream ) const override {
   OS << "  {\n";
@@ -2264,6 +2266,47 @@
   OS << "#endif // CLANG_ATTR_THIS_ISA_IDENTIFIER_ARG_LIST\n\n";
 }
 
+static void emitClangAttrNumArgs(RecordKeeper , raw_ostream ) {
+  OS << "#if defined(CLANG_ATTR_NUM_ARGS)\n";
+  std::vector Attrs = Records.getAllDerivedDefinitions("Attr");
+  for (const auto *A : Attrs) {
+std::vector Args = A->getValueAsListOfDefs("Args");
+forEachUniqueSpelling(*A, [&](const FlattenedSpelling ) {
+  OS << ".Case(\"" << S.name() << "\", " << Args.size() << ")\n";
+});
+  }
+  OS << "#endif // CLANG_ATTR_NUM_ARGS\n\n";
+}
+
+static bool argSupportsParmPack(const Record *Arg) {
+  return !Arg->getSuperClasses().empty() &&
+ llvm::StringSwitch(
+ Arg->getSuperClasses().back().first->getName())
+ .Case("VariadicExprArgument", true)
+ .Default(false) &&
+ Arg->getValueAsBit("AllowPack");
+}
+
+static void emitClangAttrLastArgParmPackSupport(RecordKeeper ,
+raw_ostream ) {
+  OS << "#if defined(CLANG_ATTR_LAST_ARG_PARM_PACK_SUPPORT)\n";
+  std::vector Attrs = Records.getAllDerivedDefinitions("Attr");
+  for (const auto *A : Attrs) {
+std::vector Args = A->getValueAsListOfDefs("Args");
+bool LastArgSupportsParmPack =
+!Args.empty() && argSupportsParmPack(Args.back());
+forEachUniqueSpelling(*A, [&](const FlattenedSpelling ) {
+  OS << ".Case(\"" << S.name() << "\", " << LastArgSupportsParmPack
+ << ")\n";
+});
+  }
+  OS << "#endif // CLANG_ATTR_LAST_ARG_PARM_PACK_SUPPORT\n\n";
+}
+
+static bool isArgVariadic(const Record , StringRef AttrName) {
+  return createArgument(R, AttrName)->isVariadic();
+}
+
 static void emitAttributes(RecordKeeper , raw_ostream ,
bool Header) {
   std::vector Attrs = Records.getAllDerivedDefinitions("Attr");
@@ -2320,6 +2363,18 @@
 std::vector> Args;
 Args.reserve(ArgRecords.size());
 
+if (!ArgRecords.empty()) {
+  const bool LastArgSupportsPack = argSupportsParmPack(ArgRecords.back());
+  for (size_t I = 0; I < ArgRecords.size() - 1; ++I) {
+assert((!LastArgSupportsPack ||
+!isArgVariadic(*ArgRecords[I], R.getName())) &&
+   "Attributes supporting packs can only have the last "
+   "argument as variadic");
+assert(!argSupportsParmPack(ArgRecords[I]) &&
+   "Only the last argument can allow packs");
+  }
+}
+
 bool HasOptArg = false;
 bool HasFakeArg = false;
 for (const auto *ArgRecord : ArgRecords) {
@@ -3382,10 +3437,6 @@
   }
 }
 
-static bool isArgVariadic(const Record , StringRef AttrName) {
-  return createArgument(R, AttrName)->isVariadic();
-}
-
 static void emitArgInfo(const Record , raw_ostream ) {
   // This function will count the number of arguments specified for the
   // attribute and emit the number of required arguments followed by the
@@ -4219,6 +4270,8 @@
   emitClangAttrIdentifierArgList(Records, OS);
   emitClangAttrVariadicIdentifierArgList(Records, OS);
   emitClangAttrThisIsaIdentifierArgList(Records, OS);
+  emitClangAttrNumArgs(Records, OS);
+  emitClangAttrLastArgParmPackSupport(Records, OS);
   emitClangAttrTypeArgList(Records, OS);
   emitClangAttrLateParsedList(Records, OS);
 }
Index: clang/test/SemaTemplate/attributes.cpp
===
--- clang/test/SemaTemplate/attributes.cpp
+++ clang/test/SemaTemplate/attributes.cpp
@@ -64,6 +64,23 @@
 template [[clang::annotate("ANNOTATE_FOO"), clang::annotate("ANNOTATE_BAR")]] void HasAnnotations();
 void UseAnnotations() { HasAnnotations(); }
 
+// CHECK:  FunctionTemplateDecl {{.*}} HasPackAnnotations
+// CHECK:AnnotateAttr {{.*}} "ANNOTATE_BAZ"
+// 

[PATCH] D114439: [Annotation] Allow parameter pack expansions in annotate attribute

2022-01-20 Thread Aaron Ballman via Phabricator via cfe-commits
aaron.ballman added inline comments.



Comment at: clang/lib/Parse/ParseDecl.cpp:468
+
+  // General case. Parse all available expressions.
+  CommaLocsTy CommaLocs;

I think it'd be good to move this comment up closer to the `else` on line 461 
so that it's clear what the else clause covers (and more clear that this is the 
common case).



Comment at: clang/lib/Parse/ParseDecl.cpp:436-438
+// Interpret "kw_this" as an identifier if the attributed requests it.
+if (ChangeKWThisToIdent && Tok.is(tok::kw_this))
+  Tok.setKind(tok::identifier);

steffenlarsen wrote:
> aaron.ballman wrote:
> > I'm a bit surprised this logic moved -- are there no times when we'd need 
> > it within the new `else` clause?
> This is done because `ParseExpressionList` wouldn't know what to do with 
> identifiers, so it keeps the old logic. This means that attributes that 
> consist of a variadic identifier argument cannot parse packs and initializer 
> lists. It shouldn't be a problem for now, but it does kill some generality.
> 
> An alternative is to split the individual expression parsing from 
> `ParseExpressionList` and use that in here in a similar way to how it parsed 
> before. Would that be preferred?
> This is done because ParseExpressionList wouldn't know what to do with 
> identifiers, so it keeps the old logic.

Ah, I think I confused myself into thinking `{a, b, c}` would be using a 
DeclRefExpr for each of the identifiers, but this code path is for identifiers 
that are *not* expressions. Got it.

> An alternative is to split the individual expression parsing from 
> ParseExpressionList and use that in here in a similar way to how it parsed 
> before. Would that be preferred?

I think this is okay for now.



Comment at: clang/lib/Parse/ParseExpr.cpp:3360
+ llvm::function_ref ExpressionStarts,
+ bool FailImmediatelyOnInvalidExpr,
+ bool EarlyTypoCorrection) {

steffenlarsen wrote:
> aaron.ballman wrote:
> > or something along those lines (note, the logic has reversed meaning). 
> > "Fail immediately" doesn't quite convey the behavior to me because we fail 
> > immediately either way, it's more about whether we attempt to skip tokens 
> > to get to the end of the expression list. I'm not strongly tied to the name 
> > I suggested either, btw.
> > "Fail immediately" doesn't quite convey the behavior to me because we fail 
> > immediately either way
> 
> Am I misunderstanding `FailUntil` or is the intention of 
> `SkipUntil(tok::comma, tok::r_paren, StopBeforeMatch)` to either stop at the 
> next "," or ")"? If I am not misunderstanding, I believe it will continue 
> parsing expressions after comma if `SkipUntil` stopped before it. As such I 
> don't think `FailImmediatelyOnInvalidExpr` is inherently wrong, but I agree 
> that skipping the skipping isn't very well conveyed by the name as is.
You're correct about the behavior (I had missed that we stopped on a comma as 
well as closing paren, I was thinking we were stopping on the closing curly 
brace). So the parameter name isn't inherently wrong, just seems a bit unclear 
to me. I don't insist on a change, but if someone has a better name for the 
parameter, I won't be sad either.



Comment at: clang/lib/Parse/ParseExpr.cpp:3374-3375
 
+if (EarlyTypoCorrection)
+  Expr = Actions.CorrectDelayedTyposInExpr(Expr);
+

steffenlarsen wrote:
> aaron.ballman wrote:
> > Not that I think this is a bad change, but it seems unrelated to the patch. 
> > Can you explain why you made the change?
> Admittedly I am not sure why it is needed, but in the previous version of the 
> parsing for attribute parameters it does the typo-correction immediately 
> after parsing the expression and if this isn't added a handful of tests fail.
Ah, thanks for the info! So this is basically doing the same work as what's 
done on line 3410 in the late failure case -- I wonder if this should actually 
be tied to the `FailImmediatelyOnInvalidExpr` parameter instead of having its 
own parameter?


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D114439/new/

https://reviews.llvm.org/D114439

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D114439: [Annotation] Allow parameter pack expansions in annotate attribute

2022-01-20 Thread Steffen Larsen via Phabricator via cfe-commits
steffenlarsen updated this revision to Diff 401580.
steffenlarsen added a comment.

Applied suggestions.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D114439/new/

https://reviews.llvm.org/D114439

Files:
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/DiagnosticParseKinds.td
  clang/include/clang/Parse/Parser.h
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Parse/ParseExpr.cpp
  clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
  clang/test/Parser/cxx0x-attributes.cpp
  clang/test/SemaTemplate/attributes.cpp
  clang/utils/TableGen/ClangAttrEmitter.cpp

Index: clang/utils/TableGen/ClangAttrEmitter.cpp
===
--- clang/utils/TableGen/ClangAttrEmitter.cpp
+++ clang/utils/TableGen/ClangAttrEmitter.cpp
@@ -1164,10 +1164,12 @@
   };
 
   class VariadicExprArgument : public VariadicArgument {
+bool AllowPack = false;
+
   public:
 VariadicExprArgument(const Record , StringRef Attr)
-  : VariadicArgument(Arg, Attr, "Expr *")
-{}
+: VariadicArgument(Arg, Attr, "Expr *"),
+  AllowPack(Arg.getValueAsBit("AllowPack")) {}
 
 void writeASTVisitorTraversal(raw_ostream ) const override {
   OS << "  {\n";
@@ -2264,6 +2266,47 @@
   OS << "#endif // CLANG_ATTR_THIS_ISA_IDENTIFIER_ARG_LIST\n\n";
 }
 
+static void emitClangAttrNumArgs(RecordKeeper , raw_ostream ) {
+  OS << "#if defined(CLANG_ATTR_NUM_ARGS)\n";
+  std::vector Attrs = Records.getAllDerivedDefinitions("Attr");
+  for (const auto *A : Attrs) {
+std::vector Args = A->getValueAsListOfDefs("Args");
+forEachUniqueSpelling(*A, [&](const FlattenedSpelling ) {
+  OS << ".Case(\"" << S.name() << "\", " << Args.size() << ")\n";
+});
+  }
+  OS << "#endif // CLANG_ATTR_NUM_ARGS\n\n";
+}
+
+static bool argSupportsParmPack(const Record *Arg) {
+  return !Arg->getSuperClasses().empty() &&
+ llvm::StringSwitch(
+ Arg->getSuperClasses().back().first->getName())
+ .Case("VariadicExprArgument", true)
+ .Default(false) &&
+ Arg->getValueAsBit("AllowPack");
+}
+
+static void emitClangAttrLastArgParmPackSupport(RecordKeeper ,
+raw_ostream ) {
+  OS << "#if defined(CLANG_ATTR_LAST_ARG_PARM_PACK_SUPPORT)\n";
+  std::vector Attrs = Records.getAllDerivedDefinitions("Attr");
+  for (const auto *A : Attrs) {
+std::vector Args = A->getValueAsListOfDefs("Args");
+bool LastArgSupportsParmPack =
+!Args.empty() && argSupportsParmPack(Args.back());
+forEachUniqueSpelling(*A, [&](const FlattenedSpelling ) {
+  OS << ".Case(\"" << S.name() << "\", " << LastArgSupportsParmPack
+ << ")\n";
+});
+  }
+  OS << "#endif // CLANG_ATTR_LAST_ARG_PARM_PACK_SUPPORT\n\n";
+}
+
+static bool isArgVariadic(const Record , StringRef AttrName) {
+  return createArgument(R, AttrName)->isVariadic();
+}
+
 static void emitAttributes(RecordKeeper , raw_ostream ,
bool Header) {
   std::vector Attrs = Records.getAllDerivedDefinitions("Attr");
@@ -2320,6 +2363,18 @@
 std::vector> Args;
 Args.reserve(ArgRecords.size());
 
+if (!ArgRecords.empty()) {
+  const bool LastArgSupportsPack = argSupportsParmPack(ArgRecords.back());
+  for (size_t I = 0; I < ArgRecords.size() - 1; ++I) {
+assert((!LastArgSupportsPack ||
+!isArgVariadic(*ArgRecords[I], R.getName())) &&
+   "Attributes supporting packs can only have the last "
+   "argument as variadic");
+assert(!argSupportsParmPack(ArgRecords[I]) &&
+   "Only the last argument can allow packs");
+  }
+}
+
 bool HasOptArg = false;
 bool HasFakeArg = false;
 for (const auto *ArgRecord : ArgRecords) {
@@ -3382,10 +3437,6 @@
   }
 }
 
-static bool isArgVariadic(const Record , StringRef AttrName) {
-  return createArgument(R, AttrName)->isVariadic();
-}
-
 static void emitArgInfo(const Record , raw_ostream ) {
   // This function will count the number of arguments specified for the
   // attribute and emit the number of required arguments followed by the
@@ -4219,6 +4270,8 @@
   emitClangAttrIdentifierArgList(Records, OS);
   emitClangAttrVariadicIdentifierArgList(Records, OS);
   emitClangAttrThisIsaIdentifierArgList(Records, OS);
+  emitClangAttrNumArgs(Records, OS);
+  emitClangAttrLastArgParmPackSupport(Records, OS);
   emitClangAttrTypeArgList(Records, OS);
   emitClangAttrLateParsedList(Records, OS);
 }
Index: clang/test/SemaTemplate/attributes.cpp
===
--- clang/test/SemaTemplate/attributes.cpp
+++ clang/test/SemaTemplate/attributes.cpp
@@ -64,6 +64,23 @@
 template [[clang::annotate("ANNOTATE_FOO"), clang::annotate("ANNOTATE_BAR")]] void HasAnnotations();
 void UseAnnotations() { HasAnnotations(); }
 
+// CHECK:  FunctionTemplateDecl {{.*}} HasPackAnnotations
+// CHECK:AnnotateAttr {{.*}} 

[PATCH] D114439: [Annotation] Allow parameter pack expansions in annotate attribute

2022-01-20 Thread Steffen Larsen via Phabricator via cfe-commits
steffenlarsen added a comment.

Thank you, @aaron.ballman ! I will update the revision in a moment with some of 
the suggested changes.




Comment at: clang/lib/Parse/ParseDecl.cpp:436-438
+// Interpret "kw_this" as an identifier if the attributed requests it.
+if (ChangeKWThisToIdent && Tok.is(tok::kw_this))
+  Tok.setKind(tok::identifier);

aaron.ballman wrote:
> I'm a bit surprised this logic moved -- are there no times when we'd need it 
> within the new `else` clause?
This is done because `ParseExpressionList` wouldn't know what to do with 
identifiers, so it keeps the old logic. This means that attributes that consist 
of a variadic identifier argument cannot parse packs and initializer lists. It 
shouldn't be a problem for now, but it does kill some generality.

An alternative is to split the individual expression parsing from 
`ParseExpressionList` and use that in here in a similar way to how it parsed 
before. Would that be preferred?



Comment at: clang/lib/Parse/ParseExpr.cpp:3360
+ llvm::function_ref ExpressionStarts,
+ bool FailImmediatelyOnInvalidExpr,
+ bool EarlyTypoCorrection) {

aaron.ballman wrote:
> or something along those lines (note, the logic has reversed meaning). "Fail 
> immediately" doesn't quite convey the behavior to me because we fail 
> immediately either way, it's more about whether we attempt to skip tokens to 
> get to the end of the expression list. I'm not strongly tied to the name I 
> suggested either, btw.
> "Fail immediately" doesn't quite convey the behavior to me because we fail 
> immediately either way

Am I misunderstanding `FailUntil` or is the intention of `SkipUntil(tok::comma, 
tok::r_paren, StopBeforeMatch)` to either stop at the next "," or ")"? If I am 
not misunderstanding, I believe it will continue parsing expressions after 
comma if `SkipUntil` stopped before it. As such I don't think 
`FailImmediatelyOnInvalidExpr` is inherently wrong, but I agree that skipping 
the skipping isn't very well conveyed by the name as is.



Comment at: clang/lib/Parse/ParseExpr.cpp:3374-3375
 
+if (EarlyTypoCorrection)
+  Expr = Actions.CorrectDelayedTyposInExpr(Expr);
+

aaron.ballman wrote:
> Not that I think this is a bad change, but it seems unrelated to the patch. 
> Can you explain why you made the change?
Admittedly I am not sure why it is needed, but in the previous version of the 
parsing for attribute parameters it does the typo-correction immediately after 
parsing the expression and if this isn't added a handful of tests fail.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D114439/new/

https://reviews.llvm.org/D114439

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D114439: [Annotation] Allow parameter pack expansions in annotate attribute

2022-01-19 Thread Aaron Ballman via Phabricator via cfe-commits
aaron.ballman added a comment.

Thanks for this, I think it's shaping up well!




Comment at: clang/include/clang/Basic/DiagnosticParseKinds.td:723
+def err_attribute_argument_parm_pack_not_supported : Error<
+  "attribute %0 does not support pack expansion in arguments">;
+def err_attribute_parm_pack_last_argument_only : Error<





Comment at: clang/include/clang/Basic/DiagnosticParseKinds.td:725
+def err_attribute_parm_pack_last_argument_only : Error<
+  "pack expansion in %0 is restricted to argument %1 or later">;
 def err_ms_declspec_type : Error<





Comment at: clang/lib/Parse/ParseDecl.cpp:436-438
+// Interpret "kw_this" as an identifier if the attributed requests it.
+if (ChangeKWThisToIdent && Tok.is(tok::kw_this))
+  Tok.setKind(tok::identifier);

I'm a bit surprised this logic moved -- are there no times when we'd need it 
within the new `else` clause?



Comment at: clang/lib/Parse/ParseDecl.cpp:497
+// Pack expansion is only allowed in the variadic argument at the end.
+const size_t attrNumArgs = attributeNumberOfArguments(*AttrName);
+if (ArgExprs.size() + I + 1 < attrNumArgs) {

Coding style nits.



Comment at: clang/lib/Parse/ParseExpr.cpp:3360
+ llvm::function_ref ExpressionStarts,
+ bool FailImmediatelyOnInvalidExpr,
+ bool EarlyTypoCorrection) {

or something along those lines (note, the logic has reversed meaning). "Fail 
immediately" doesn't quite convey the behavior to me because we fail 
immediately either way, it's more about whether we attempt to skip tokens to 
get to the end of the expression list. I'm not strongly tied to the name I 
suggested either, btw.



Comment at: clang/lib/Parse/ParseExpr.cpp:3374-3375
 
+if (EarlyTypoCorrection)
+  Expr = Actions.CorrectDelayedTyposInExpr(Expr);
+

Not that I think this is a bad change, but it seems unrelated to the patch. Can 
you explain why you made the change?



Comment at: clang/test/Parser/cxx0x-attributes.cpp:261
 
-template void variadic() {
+template  void variadic() {
   void bar [[noreturn...]] (); // expected-error {{attribute 'noreturn' cannot 
be used as an attribute pack}}

steffenlarsen wrote:
> erichkeane wrote:
> > What is the point of this change?
> It makes more sense for the new test cases to get expressions rather than 
> types and since `Ts` wasn't used for its contents it did not seem like an 
> intrusive change.
Non-type templates are different from type templates, so I don't really want to 
lose the test coverage for that (if nothing else, it ensures the parser doesn't 
explode when it encounters one). It's fine to add a `variadic_nttp()` function 
or something along those lines.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D114439/new/

https://reviews.llvm.org/D114439

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D114439: [Annotation] Allow parameter pack expansions in annotate attribute

2022-01-12 Thread Steffen Larsen via Phabricator via cfe-commits
steffenlarsen updated this revision to Diff 399334.
steffenlarsen added a comment.

I have made the changes suggested in my previous comment. This makes 
significantly more changes to the parsing of attribute arguments as the old 
path was needed for attributes that allow both expressions and types. It also 
required some new controlling arguments for `ParseExpressionList`.

Because these changes also allow intializer lists in attribute arguments I have 
added a test case showing that `clang::annotate` parses these but will not 
accept them.

@erichkeane & @aaron.ballman - Is this in line with what you were thinking?


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D114439/new/

https://reviews.llvm.org/D114439

Files:
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/DiagnosticParseKinds.td
  clang/include/clang/Parse/Parser.h
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Parse/ParseExpr.cpp
  clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
  clang/test/Parser/cxx0x-attributes.cpp
  clang/test/SemaTemplate/attributes.cpp
  clang/utils/TableGen/ClangAttrEmitter.cpp

Index: clang/utils/TableGen/ClangAttrEmitter.cpp
===
--- clang/utils/TableGen/ClangAttrEmitter.cpp
+++ clang/utils/TableGen/ClangAttrEmitter.cpp
@@ -1164,10 +1164,12 @@
   };
 
   class VariadicExprArgument : public VariadicArgument {
+bool AllowPack = false;
+
   public:
 VariadicExprArgument(const Record , StringRef Attr)
-  : VariadicArgument(Arg, Attr, "Expr *")
-{}
+: VariadicArgument(Arg, Attr, "Expr *"),
+  AllowPack(Arg.getValueAsBit("AllowPack")) {}
 
 void writeASTVisitorTraversal(raw_ostream ) const override {
   OS << "  {\n";
@@ -2264,6 +2266,47 @@
   OS << "#endif // CLANG_ATTR_THIS_ISA_IDENTIFIER_ARG_LIST\n\n";
 }
 
+static void emitClangAttrNumArgs(RecordKeeper , raw_ostream ) {
+  OS << "#if defined(CLANG_ATTR_NUM_ARGS)\n";
+  std::vector Attrs = Records.getAllDerivedDefinitions("Attr");
+  for (const auto *A : Attrs) {
+std::vector Args = A->getValueAsListOfDefs("Args");
+forEachUniqueSpelling(*A, [&](const FlattenedSpelling ) {
+  OS << ".Case(\"" << S.name() << "\", " << Args.size() << ")\n";
+});
+  }
+  OS << "#endif // CLANG_ATTR_NUM_ARGS\n\n";
+}
+
+static bool argSupportsParmPack(const Record *Arg) {
+  return !Arg->getSuperClasses().empty() &&
+ llvm::StringSwitch(
+ Arg->getSuperClasses().back().first->getName())
+ .Case("VariadicExprArgument", true)
+ .Default(false) &&
+ Arg->getValueAsBit("AllowPack");
+}
+
+static void emitClangAttrLastArgParmPackSupport(RecordKeeper ,
+raw_ostream ) {
+  OS << "#if defined(CLANG_ATTR_LAST_ARG_PARM_PACK_SUPPORT)\n";
+  std::vector Attrs = Records.getAllDerivedDefinitions("Attr");
+  for (const auto *A : Attrs) {
+std::vector Args = A->getValueAsListOfDefs("Args");
+bool LastArgSupportsParmPack =
+!Args.empty() && argSupportsParmPack(Args.back());
+forEachUniqueSpelling(*A, [&](const FlattenedSpelling ) {
+  OS << ".Case(\"" << S.name() << "\", " << LastArgSupportsParmPack
+ << ")\n";
+});
+  }
+  OS << "#endif // CLANG_ATTR_LAST_ARG_PARM_PACK_SUPPORT\n\n";
+}
+
+static bool isArgVariadic(const Record , StringRef AttrName) {
+  return createArgument(R, AttrName)->isVariadic();
+}
+
 static void emitAttributes(RecordKeeper , raw_ostream ,
bool Header) {
   std::vector Attrs = Records.getAllDerivedDefinitions("Attr");
@@ -2320,6 +2363,18 @@
 std::vector> Args;
 Args.reserve(ArgRecords.size());
 
+if (!ArgRecords.empty()) {
+  const bool LastArgSupportsPack = argSupportsParmPack(ArgRecords.back());
+  for (size_t I = 0; I < ArgRecords.size() - 1; ++I) {
+assert((!LastArgSupportsPack ||
+!isArgVariadic(*ArgRecords[I], R.getName())) &&
+   "Attributes supporting packs can only have the last "
+   "argument as variadic");
+assert(!argSupportsParmPack(ArgRecords[I]) &&
+   "Only the last argument can allow packs");
+  }
+}
+
 bool HasOptArg = false;
 bool HasFakeArg = false;
 for (const auto *ArgRecord : ArgRecords) {
@@ -3382,10 +3437,6 @@
   }
 }
 
-static bool isArgVariadic(const Record , StringRef AttrName) {
-  return createArgument(R, AttrName)->isVariadic();
-}
-
 static void emitArgInfo(const Record , raw_ostream ) {
   // This function will count the number of arguments specified for the
   // attribute and emit the number of required arguments followed by the
@@ -4219,6 +4270,8 @@
   emitClangAttrIdentifierArgList(Records, OS);
   emitClangAttrVariadicIdentifierArgList(Records, OS);
   emitClangAttrThisIsaIdentifierArgList(Records, OS);
+  emitClangAttrNumArgs(Records, OS);
+  emitClangAttrLastArgParmPackSupport(Records, OS);
   emitClangAttrTypeArgList(Records, OS);
   

[PATCH] D114439: [Annotation] Allow parameter pack expansions in annotate attribute

2021-12-21 Thread Steffen Larsen via Phabricator via cfe-commits
steffenlarsen added a comment.

I agree that reusing existing parser logic for this would be preferable, but as 
@aaron.ballman mentions `Parser::ParseSimpleExpressionList` does not give us 
the parameter pack expansion parsing we need. We could potentially unify it 
with the logic from 
https://github.com/llvm/llvm-project/blob/main/clang/lib/Parse/ParseExpr.cpp#L3059
 but on the other hand there could be potential benefits to using 
`Parser::ParseExpressionList` instead.

The primary difference between the behavior of `Parser::ParseExpressionList` 
and what we are looking for is that it will allow initializer lists as 
arguments. Since most (if not all) attributes check the validity of their 
expression arguments, they would likely fail accordingly if they get an 
initializer list, likely specifying they expected an argument of type X. It may 
be a blessing in disguise to parse these arguments as well as we are more 
permissive w.r.t. attribute arguments. Please let me know if there is anything 
fundamentally wrong with this line of logic. One concern I have is that we 
currently run `Actions.CorrectDelayedTyposInExpr` on the expression right after 
parsing it, then we run pack expansion, whereas `Parser::ParseExpressionList` 
only runs the former action in failure case. I am unsure whether or not that 
might pose a problem.

One problem is that if we only use `Parser::ParseExpressionList` to parse the 
arguments of the last argument (if it is variadic) then we get the odd behavior 
that the initializer lists will only be permitted in variadic arguments, which 
arguably is a little obscure. However, upon further investigation the only case 
that stops us from using this for all expression arguments are when the 
attribute has either `VariadicIdentifierArgument` or 
`VariadicParamOrParamIdxArgument` as the first argument. If we assume that 
these variadic expressions are limited to the last argument as well (as they 
are variadic) leaving them as the only argument of the attributes we are 
parsing here, then we can parse expressions as we did before if we are parsing 
one of these arguments or switch to using e.g. `Parser::ParseExpressionList` 
for all expressions of the attribute (even non-variadic) if not. Then we would 
just have to iterate over the produced expressions to make sure no parameter 
pack expansions occur before the last (variadic) argument of the parsed 
attribute.

//Summary of suggested changes://
Split attribute parsing into 3: First case parsing a type (currently exists). 
Second case keeping the current logic for parsing identifiers and single 
assignment-expressions if the attribute has a single argument of type 
`VariadicIdentifierArgument` or `VariadicParamOrParamIdxArgument`. Third case, 
applicable if none of the former ran, parses all expression parameters in one 
using `Parser::ParseExpressionList` and then checks that parameter packs only 
occur in the last variadic argument (if it allows it). Side effect is it allows 
initializer lists in the third case, but attributes are likely to complain 
about unexpected expression types if these are passed.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D114439/new/

https://reviews.llvm.org/D114439

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D114439: [Annotation] Allow parameter pack expansions in annotate attribute

2021-12-15 Thread Aaron Ballman via Phabricator via cfe-commits
aaron.ballman added inline comments.



Comment at: clang/lib/Parse/ParseDecl.cpp:447
 Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()));
+
+if (Tok.is(tok::ellipsis)) {

erichkeane wrote:
> steffenlarsen wrote:
> > erichkeane wrote:
> > > steffenlarsen wrote:
> > > > erichkeane wrote:
> > > > > steffenlarsen wrote:
> > > > > > erichkeane wrote:
> > > > > > > So I was thinking about this overnight... I wonder if this logic 
> > > > > > > is inverted here?  Aaron can better answer, but I wonder if we 
> > > > > > > should be instead detecting when we are on the 'last' parameter 
> > > > > > > and it is one of these `VariadicExprArgument` things (that accept 
> > > > > > > a pack), then dropping the parser into a loop of:
> > > > > > > 
> > > > > > > while (Tok.is(tok::comma)){
> > > > > > >   Tok.Consume();
> > > > > > >   ArgExpr = CorrectTypos(ParseAssignmentExpr(...));
> > > > > > > }
> > > > > > > // finally, consume the closing paren.
> > > > > > > 
> > > > > > > WDYT?
> > > > > > The parsing of attribute arguments is already this lenient. It does 
> > > > > > not actually care how many arguments the attribute says it takes 
> > > > > > (unless it takes a type and then it will only currently supply 
> > > > > > _one_ argument). It simply consumes as many expressions it can 
> > > > > > before reaching the end parenthesis, then leaves the attributes to 
> > > > > > consume them in `clang/lib/Sema/SemaDeclAttr.cpp`.
> > > > > > As a result we do not need any additional work here to handle 
> > > > > > variadic arguments, but it also means that we have to introduce the 
> > > > > > restrictions that we can only allow packs in the last argument and 
> > > > > > allow only that argument to be variadic, as otherwise we have no 
> > > > > > way of knowing when and where the packs pass between argument 
> > > > > > boundaries.
> > > > > My point is, I don't think THIS function should be handling the 
> > > > > ellipsis, the expression parsing functions we send the parsing of 
> > > > > each component off to should do that.
> > > > > 
> > > > > We unfortunately cannot move the entirety of this parsing section to 
> > > > > do that, since 'identifier'/'type', and 'Function' argument types end 
> > > > > up needing special handling, but it would be nice if our 'expr' types 
> > > > > would all be able to do this, and I suggested earlier that we could 
> > > > > start with the `VariadicExprArgument` to make this an easier patch 
> > > > > that didn't have to deal with the issues that come with that.
> > > > > 
> > > > > That said, it would be nice if we could get CLOSE to that.
> > > > Sorry. I am still not sure I am following. Do you mean the consumption 
> > > > of pack expressions should be moved into the expression parsing so 
> > > > other places (not just attributes) would accept it? If so, I am not 
> > > > opposed to the idea though I have no idea which expressions these would 
> > > > be nor the full implications of such a change. For these we at least 
> > > > have the isolation of having to explicitly support the packs in the 
> > > > given attributes.
> > > I'm saying the other expression parsers should ALREADY properly handle 
> > > packs, and we should just use those.
> > I think I see what you mean. There is the `Parser::ParseExpressionList` 
> > which may fit the bill, though it seems to also accept initializer lists. 
> > But since it is an expression the attributes can decide if it is a valid 
> > expression for them, so maybe that is not a problem?
> Hmm... I don't have a good idea of that, Aaron has better visibility into 
> that sort of thing.
> 
> Part of the advantage to doing it the way I suggest is that it ends up being 
> a single call (that is, the parser should parse the commas!), so we should 
> only have to consume the closing paren.
I think we want something more like `Parser::ParseSimpleExpressionList()` 
but... that doesn't handle packs, so those appear to be handled special: 
https://github.com/llvm/llvm-project/blob/main/clang/lib/Parse/ParseExpr.cpp#L3059.
 But one of these two functions seems to be along the correct lines of what we 
want (with modification).

FWIW, I like the sound of Erich's approach better than what's in the current 
patch. I'd rather not try to specially handle the ellipsis so much as 
recognizing when we expect an arbitrary list of variadic expression arguments 
as the last "parameter" for an attribute.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D114439/new/

https://reviews.llvm.org/D114439

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D114439: [Annotation] Allow parameter pack expansions in annotate attribute

2021-12-09 Thread Erich Keane via Phabricator via cfe-commits
erichkeane added inline comments.



Comment at: clang/lib/Parse/ParseDecl.cpp:447
 Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()));
+
+if (Tok.is(tok::ellipsis)) {

steffenlarsen wrote:
> erichkeane wrote:
> > steffenlarsen wrote:
> > > erichkeane wrote:
> > > > steffenlarsen wrote:
> > > > > erichkeane wrote:
> > > > > > So I was thinking about this overnight... I wonder if this logic is 
> > > > > > inverted here?  Aaron can better answer, but I wonder if we should 
> > > > > > be instead detecting when we are on the 'last' parameter and it is 
> > > > > > one of these `VariadicExprArgument` things (that accept a pack), 
> > > > > > then dropping the parser into a loop of:
> > > > > > 
> > > > > > while (Tok.is(tok::comma)){
> > > > > >   Tok.Consume();
> > > > > >   ArgExpr = CorrectTypos(ParseAssignmentExpr(...));
> > > > > > }
> > > > > > // finally, consume the closing paren.
> > > > > > 
> > > > > > WDYT?
> > > > > The parsing of attribute arguments is already this lenient. It does 
> > > > > not actually care how many arguments the attribute says it takes 
> > > > > (unless it takes a type and then it will only currently supply _one_ 
> > > > > argument). It simply consumes as many expressions it can before 
> > > > > reaching the end parenthesis, then leaves the attributes to consume 
> > > > > them in `clang/lib/Sema/SemaDeclAttr.cpp`.
> > > > > As a result we do not need any additional work here to handle 
> > > > > variadic arguments, but it also means that we have to introduce the 
> > > > > restrictions that we can only allow packs in the last argument and 
> > > > > allow only that argument to be variadic, as otherwise we have no way 
> > > > > of knowing when and where the packs pass between argument boundaries.
> > > > My point is, I don't think THIS function should be handling the 
> > > > ellipsis, the expression parsing functions we send the parsing of each 
> > > > component off to should do that.
> > > > 
> > > > We unfortunately cannot move the entirety of this parsing section to do 
> > > > that, since 'identifier'/'type', and 'Function' argument types end up 
> > > > needing special handling, but it would be nice if our 'expr' types 
> > > > would all be able to do this, and I suggested earlier that we could 
> > > > start with the `VariadicExprArgument` to make this an easier patch that 
> > > > didn't have to deal with the issues that come with that.
> > > > 
> > > > That said, it would be nice if we could get CLOSE to that.
> > > Sorry. I am still not sure I am following. Do you mean the consumption of 
> > > pack expressions should be moved into the expression parsing so other 
> > > places (not just attributes) would accept it? If so, I am not opposed to 
> > > the idea though I have no idea which expressions these would be nor the 
> > > full implications of such a change. For these we at least have the 
> > > isolation of having to explicitly support the packs in the given 
> > > attributes.
> > I'm saying the other expression parsers should ALREADY properly handle 
> > packs, and we should just use those.
> I think I see what you mean. There is the `Parser::ParseExpressionList` which 
> may fit the bill, though it seems to also accept initializer lists. But since 
> it is an expression the attributes can decide if it is a valid expression for 
> them, so maybe that is not a problem?
Hmm... I don't have a good idea of that, Aaron has better visibility into that 
sort of thing.

Part of the advantage to doing it the way I suggest is that it ends up being a 
single call (that is, the parser should parse the commas!), so we should only 
have to consume the closing paren.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D114439/new/

https://reviews.llvm.org/D114439

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D114439: [Annotation] Allow parameter pack expansions in annotate attribute

2021-12-09 Thread Steffen Larsen via Phabricator via cfe-commits
steffenlarsen added inline comments.



Comment at: clang/lib/Parse/ParseDecl.cpp:447
 Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()));
+
+if (Tok.is(tok::ellipsis)) {

erichkeane wrote:
> steffenlarsen wrote:
> > erichkeane wrote:
> > > steffenlarsen wrote:
> > > > erichkeane wrote:
> > > > > So I was thinking about this overnight... I wonder if this logic is 
> > > > > inverted here?  Aaron can better answer, but I wonder if we should be 
> > > > > instead detecting when we are on the 'last' parameter and it is one 
> > > > > of these `VariadicExprArgument` things (that accept a pack), then 
> > > > > dropping the parser into a loop of:
> > > > > 
> > > > > while (Tok.is(tok::comma)){
> > > > >   Tok.Consume();
> > > > >   ArgExpr = CorrectTypos(ParseAssignmentExpr(...));
> > > > > }
> > > > > // finally, consume the closing paren.
> > > > > 
> > > > > WDYT?
> > > > The parsing of attribute arguments is already this lenient. It does not 
> > > > actually care how many arguments the attribute says it takes (unless it 
> > > > takes a type and then it will only currently supply _one_ argument). It 
> > > > simply consumes as many expressions it can before reaching the end 
> > > > parenthesis, then leaves the attributes to consume them in 
> > > > `clang/lib/Sema/SemaDeclAttr.cpp`.
> > > > As a result we do not need any additional work here to handle variadic 
> > > > arguments, but it also means that we have to introduce the restrictions 
> > > > that we can only allow packs in the last argument and allow only that 
> > > > argument to be variadic, as otherwise we have no way of knowing when 
> > > > and where the packs pass between argument boundaries.
> > > My point is, I don't think THIS function should be handling the ellipsis, 
> > > the expression parsing functions we send the parsing of each component 
> > > off to should do that.
> > > 
> > > We unfortunately cannot move the entirety of this parsing section to do 
> > > that, since 'identifier'/'type', and 'Function' argument types end up 
> > > needing special handling, but it would be nice if our 'expr' types would 
> > > all be able to do this, and I suggested earlier that we could start with 
> > > the `VariadicExprArgument` to make this an easier patch that didn't have 
> > > to deal with the issues that come with that.
> > > 
> > > That said, it would be nice if we could get CLOSE to that.
> > Sorry. I am still not sure I am following. Do you mean the consumption of 
> > pack expressions should be moved into the expression parsing so other 
> > places (not just attributes) would accept it? If so, I am not opposed to 
> > the idea though I have no idea which expressions these would be nor the 
> > full implications of such a change. For these we at least have the 
> > isolation of having to explicitly support the packs in the given attributes.
> I'm saying the other expression parsers should ALREADY properly handle packs, 
> and we should just use those.
I think I see what you mean. There is the `Parser::ParseExpressionList` which 
may fit the bill, though it seems to also accept initializer lists. But since 
it is an expression the attributes can decide if it is a valid expression for 
them, so maybe that is not a problem?


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D114439/new/

https://reviews.llvm.org/D114439

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D114439: [Annotation] Allow parameter pack expansions in annotate attribute

2021-12-09 Thread Erich Keane via Phabricator via cfe-commits
erichkeane added inline comments.



Comment at: clang/lib/Parse/ParseDecl.cpp:447
 Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()));
+
+if (Tok.is(tok::ellipsis)) {

steffenlarsen wrote:
> erichkeane wrote:
> > steffenlarsen wrote:
> > > erichkeane wrote:
> > > > So I was thinking about this overnight... I wonder if this logic is 
> > > > inverted here?  Aaron can better answer, but I wonder if we should be 
> > > > instead detecting when we are on the 'last' parameter and it is one of 
> > > > these `VariadicExprArgument` things (that accept a pack), then dropping 
> > > > the parser into a loop of:
> > > > 
> > > > while (Tok.is(tok::comma)){
> > > >   Tok.Consume();
> > > >   ArgExpr = CorrectTypos(ParseAssignmentExpr(...));
> > > > }
> > > > // finally, consume the closing paren.
> > > > 
> > > > WDYT?
> > > The parsing of attribute arguments is already this lenient. It does not 
> > > actually care how many arguments the attribute says it takes (unless it 
> > > takes a type and then it will only currently supply _one_ argument). It 
> > > simply consumes as many expressions it can before reaching the end 
> > > parenthesis, then leaves the attributes to consume them in 
> > > `clang/lib/Sema/SemaDeclAttr.cpp`.
> > > As a result we do not need any additional work here to handle variadic 
> > > arguments, but it also means that we have to introduce the restrictions 
> > > that we can only allow packs in the last argument and allow only that 
> > > argument to be variadic, as otherwise we have no way of knowing when and 
> > > where the packs pass between argument boundaries.
> > My point is, I don't think THIS function should be handling the ellipsis, 
> > the expression parsing functions we send the parsing of each component off 
> > to should do that.
> > 
> > We unfortunately cannot move the entirety of this parsing section to do 
> > that, since 'identifier'/'type', and 'Function' argument types end up 
> > needing special handling, but it would be nice if our 'expr' types would 
> > all be able to do this, and I suggested earlier that we could start with 
> > the `VariadicExprArgument` to make this an easier patch that didn't have to 
> > deal with the issues that come with that.
> > 
> > That said, it would be nice if we could get CLOSE to that.
> Sorry. I am still not sure I am following. Do you mean the consumption of 
> pack expressions should be moved into the expression parsing so other places 
> (not just attributes) would accept it? If so, I am not opposed to the idea 
> though I have no idea which expressions these would be nor the full 
> implications of such a change. For these we at least have the isolation of 
> having to explicitly support the packs in the given attributes.
I'm saying the other expression parsers should ALREADY properly handle packs, 
and we should just use those.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D114439/new/

https://reviews.llvm.org/D114439

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D114439: [Annotation] Allow parameter pack expansions in annotate attribute

2021-12-09 Thread Steffen Larsen via Phabricator via cfe-commits
steffenlarsen added inline comments.



Comment at: clang/lib/Parse/ParseDecl.cpp:447
 Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()));
+
+if (Tok.is(tok::ellipsis)) {

erichkeane wrote:
> steffenlarsen wrote:
> > erichkeane wrote:
> > > So I was thinking about this overnight... I wonder if this logic is 
> > > inverted here?  Aaron can better answer, but I wonder if we should be 
> > > instead detecting when we are on the 'last' parameter and it is one of 
> > > these `VariadicExprArgument` things (that accept a pack), then dropping 
> > > the parser into a loop of:
> > > 
> > > while (Tok.is(tok::comma)){
> > >   Tok.Consume();
> > >   ArgExpr = CorrectTypos(ParseAssignmentExpr(...));
> > > }
> > > // finally, consume the closing paren.
> > > 
> > > WDYT?
> > The parsing of attribute arguments is already this lenient. It does not 
> > actually care how many arguments the attribute says it takes (unless it 
> > takes a type and then it will only currently supply _one_ argument). It 
> > simply consumes as many expressions it can before reaching the end 
> > parenthesis, then leaves the attributes to consume them in 
> > `clang/lib/Sema/SemaDeclAttr.cpp`.
> > As a result we do not need any additional work here to handle variadic 
> > arguments, but it also means that we have to introduce the restrictions 
> > that we can only allow packs in the last argument and allow only that 
> > argument to be variadic, as otherwise we have no way of knowing when and 
> > where the packs pass between argument boundaries.
> My point is, I don't think THIS function should be handling the ellipsis, the 
> expression parsing functions we send the parsing of each component off to 
> should do that.
> 
> We unfortunately cannot move the entirety of this parsing section to do that, 
> since 'identifier'/'type', and 'Function' argument types end up needing 
> special handling, but it would be nice if our 'expr' types would all be able 
> to do this, and I suggested earlier that we could start with the 
> `VariadicExprArgument` to make this an easier patch that didn't have to deal 
> with the issues that come with that.
> 
> That said, it would be nice if we could get CLOSE to that.
Sorry. I am still not sure I am following. Do you mean the consumption of pack 
expressions should be moved into the expression parsing so other places (not 
just attributes) would accept it? If so, I am not opposed to the idea though I 
have no idea which expressions these would be nor the full implications of such 
a change. For these we at least have the isolation of having to explicitly 
support the packs in the given attributes.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D114439/new/

https://reviews.llvm.org/D114439

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D114439: [Annotation] Allow parameter pack expansions in annotate attribute

2021-12-08 Thread Erich Keane via Phabricator via cfe-commits
erichkeane added inline comments.



Comment at: clang/lib/Parse/ParseDecl.cpp:447
 Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()));
+
+if (Tok.is(tok::ellipsis)) {

steffenlarsen wrote:
> erichkeane wrote:
> > So I was thinking about this overnight... I wonder if this logic is 
> > inverted here?  Aaron can better answer, but I wonder if we should be 
> > instead detecting when we are on the 'last' parameter and it is one of 
> > these `VariadicExprArgument` things (that accept a pack), then dropping the 
> > parser into a loop of:
> > 
> > while (Tok.is(tok::comma)){
> >   Tok.Consume();
> >   ArgExpr = CorrectTypos(ParseAssignmentExpr(...));
> > }
> > // finally, consume the closing paren.
> > 
> > WDYT?
> The parsing of attribute arguments is already this lenient. It does not 
> actually care how many arguments the attribute says it takes (unless it takes 
> a type and then it will only currently supply _one_ argument). It simply 
> consumes as many expressions it can before reaching the end parenthesis, then 
> leaves the attributes to consume them in `clang/lib/Sema/SemaDeclAttr.cpp`.
> As a result we do not need any additional work here to handle variadic 
> arguments, but it also means that we have to introduce the restrictions that 
> we can only allow packs in the last argument and allow only that argument to 
> be variadic, as otherwise we have no way of knowing when and where the packs 
> pass between argument boundaries.
My point is, I don't think THIS function should be handling the ellipsis, the 
expression parsing functions we send the parsing of each component off to 
should do that.

We unfortunately cannot move the entirety of this parsing section to do that, 
since 'identifier'/'type', and 'Function' argument types end up needing special 
handling, but it would be nice if our 'expr' types would all be able to do 
this, and I suggested earlier that we could start with the 
`VariadicExprArgument` to make this an easier patch that didn't have to deal 
with the issues that come with that.

That said, it would be nice if we could get CLOSE to that.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D114439/new/

https://reviews.llvm.org/D114439

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D114439: [Annotation] Allow parameter pack expansions in annotate attribute

2021-12-08 Thread Steffen Larsen via Phabricator via cfe-commits
steffenlarsen added inline comments.



Comment at: clang/lib/Parse/ParseDecl.cpp:447
 Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()));
+
+if (Tok.is(tok::ellipsis)) {

erichkeane wrote:
> So I was thinking about this overnight... I wonder if this logic is inverted 
> here?  Aaron can better answer, but I wonder if we should be instead 
> detecting when we are on the 'last' parameter and it is one of these 
> `VariadicExprArgument` things (that accept a pack), then dropping the parser 
> into a loop of:
> 
> while (Tok.is(tok::comma)){
>   Tok.Consume();
>   ArgExpr = CorrectTypos(ParseAssignmentExpr(...));
> }
> // finally, consume the closing paren.
> 
> WDYT?
The parsing of attribute arguments is already this lenient. It does not 
actually care how many arguments the attribute says it takes (unless it takes a 
type and then it will only currently supply _one_ argument). It simply consumes 
as many expressions it can before reaching the end parenthesis, then leaves the 
attributes to consume them in `clang/lib/Sema/SemaDeclAttr.cpp`.
As a result we do not need any additional work here to handle variadic 
arguments, but it also means that we have to introduce the restrictions that we 
can only allow packs in the last argument and allow only that argument to be 
variadic, as otherwise we have no way of knowing when and where the packs pass 
between argument boundaries.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D114439/new/

https://reviews.llvm.org/D114439

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D114439: [Annotation] Allow parameter pack expansions in annotate attribute

2021-12-07 Thread Erich Keane via Phabricator via cfe-commits
erichkeane added inline comments.



Comment at: clang/lib/Parse/ParseDecl.cpp:447
 Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()));
+
+if (Tok.is(tok::ellipsis)) {

So I was thinking about this overnight... I wonder if this logic is inverted 
here?  Aaron can better answer, but I wonder if we should be instead detecting 
when we are on the 'last' parameter and it is one of these 
`VariadicExprArgument` things (that accept a pack), then dropping the parser 
into a loop of:

while (Tok.is(tok::comma)){
  Tok.Consume();
  ArgExpr = CorrectTypos(ParseAssignmentExpr(...));
}
// finally, consume the closing paren.

WDYT?


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D114439/new/

https://reviews.llvm.org/D114439

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D114439: [Annotation] Allow parameter pack expansions in annotate attribute

2021-12-07 Thread Steffen Larsen via Phabricator via cfe-commits
steffenlarsen added inline comments.



Comment at: clang/test/Parser/cxx0x-attributes.cpp:268
+  void faz [[clang::annotate("B", (Is + ...))]] (); // expected-warning {{pack 
fold expression is a C++17 extension}}
+  void foz [[clang::annotate("C", Is...)]] ();
 }

erichkeane wrote:
> what about:
> void foz [[clang::annotate("D", Is)]] ();
> 
> I would expect that to error.
> 
> Another test I'd like to see:
> 
> void foz[[clang::annotate("E", 1, 2, 3, Is...)]]
> 
> Also, I don't see why if THAT works, that:
> void foz[[clang::annotate("E", 1, Is..., 2, 3)]]
> 
> shouldn't be allowed as well.
> what about:
> void foz [[clang::annotate("D", Is)]] ();
>
> I would expect that to error.

So would I, but it seems that the parser and annotate is more than happy to 
consume this example, even in the current state of Clang: 
https://godbolt.org/z/rx64EKeeE
I am not sure as to why, but seeing as it is a preexisting bug I don't know if 
it makes sense to include it in the scope of this patch.

>Another test I'd like to see:
>
> void foz[[clang::annotate("E", 1, 2, 3, Is...)]]
> 
> Also, I don't see why if THAT works, that:
> void foz[[clang::annotate("E", 1, Is..., 2, 3)]]
> 
> shouldn't be allowed as well.

They seem to work as expected. I have added these cases.



Comment at: clang/utils/TableGen/ClangAttrEmitter.cpp:1166
 
   class VariadicExprArgument : public VariadicArgument {
+bool AllowPack = false;

erichkeane wrote:
> The rule of 'only the last argument is allowed to support a pack' should be 
> in the attribute emitter.
> The rule of 'only the last argument is allowed to support a pack' should be 
> in the attribute emitter.

I have added some assertions around the area where attributes are generate, as 
that carries more surrounding information. Is that approximately what you had 
in mind?


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D114439/new/

https://reviews.llvm.org/D114439

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D114439: [Annotation] Allow parameter pack expansions in annotate attribute

2021-12-07 Thread Steffen Larsen via Phabricator via cfe-commits
steffenlarsen updated this revision to Diff 392340.
steffenlarsen added a comment.

The new revision does the following:

1. Revisits the diagnostics. Now parameter packs will cause the same error on 
attributes that do not support parameter packs in arguments, while attributes 
that support it will cause an error if parameter packs are used in the 
incorrect argument, specifying which argument should be the earliest for it.
2. Adds additional tests to ensure that variadic arguments supporting packs 
also allow pack expansion intermingled with other arguments.
3. Adds assertions to attribute generation to check that attributes only ever 
support packs in the last variadic argument and that there are no other 
variadic arguments if they do.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D114439/new/

https://reviews.llvm.org/D114439

Files:
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/DiagnosticParseKinds.td
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
  clang/test/Parser/cxx0x-attributes.cpp
  clang/test/SemaTemplate/attributes.cpp
  clang/utils/TableGen/ClangAttrEmitter.cpp

Index: clang/utils/TableGen/ClangAttrEmitter.cpp
===
--- clang/utils/TableGen/ClangAttrEmitter.cpp
+++ clang/utils/TableGen/ClangAttrEmitter.cpp
@@ -1164,10 +1164,12 @@
   };
 
   class VariadicExprArgument : public VariadicArgument {
+bool AllowPack = false;
+
   public:
 VariadicExprArgument(const Record , StringRef Attr)
-  : VariadicArgument(Arg, Attr, "Expr *")
-{}
+: VariadicArgument(Arg, Attr, "Expr *"),
+  AllowPack(Arg.getValueAsBit("AllowPack")) {}
 
 void writeASTVisitorTraversal(raw_ostream ) const override {
   OS << "  {\n";
@@ -2264,6 +2266,47 @@
   OS << "#endif // CLANG_ATTR_THIS_ISA_IDENTIFIER_ARG_LIST\n\n";
 }
 
+static void emitClangAttrNumArgs(RecordKeeper , raw_ostream ) {
+  OS << "#if defined(CLANG_ATTR_NUM_ARGS)\n";
+  std::vector Attrs = Records.getAllDerivedDefinitions("Attr");
+  for (const auto *A : Attrs) {
+std::vector Args = A->getValueAsListOfDefs("Args");
+forEachUniqueSpelling(*A, [&](const FlattenedSpelling ) {
+  OS << ".Case(\"" << S.name() << "\", " << Args.size() << ")\n";
+});
+  }
+  OS << "#endif // CLANG_ATTR_NUM_ARGS\n\n";
+}
+
+static bool argSupportsParmPack(const Record *Arg) {
+  return !Arg->getSuperClasses().empty() &&
+ llvm::StringSwitch(
+ Arg->getSuperClasses().back().first->getName())
+ .Case("VariadicExprArgument", true)
+ .Default(false) &&
+ Arg->getValueAsBit("AllowPack");
+}
+
+static void emitClangAttrLastArgParmPackSupport(RecordKeeper ,
+raw_ostream ) {
+  OS << "#if defined(CLANG_ATTR_LAST_ARG_PARM_PACK_SUPPORT)\n";
+  std::vector Attrs = Records.getAllDerivedDefinitions("Attr");
+  for (const auto *A : Attrs) {
+std::vector Args = A->getValueAsListOfDefs("Args");
+bool LastArgSupportsParmPack =
+!Args.empty() && argSupportsParmPack(Args.back());
+forEachUniqueSpelling(*A, [&](const FlattenedSpelling ) {
+  OS << ".Case(\"" << S.name() << "\", " << LastArgSupportsParmPack
+ << ")\n";
+});
+  }
+  OS << "#endif // CLANG_ATTR_LAST_ARG_PARM_PACK_SUPPORT\n\n";
+}
+
+static bool isArgVariadic(const Record , StringRef AttrName) {
+  return createArgument(R, AttrName)->isVariadic();
+}
+
 static void emitAttributes(RecordKeeper , raw_ostream ,
bool Header) {
   std::vector Attrs = Records.getAllDerivedDefinitions("Attr");
@@ -2320,6 +2363,18 @@
 std::vector> Args;
 Args.reserve(ArgRecords.size());
 
+if (!ArgRecords.empty()) {
+  const bool LastArgSupportsPack = argSupportsParmPack(ArgRecords.back());
+  for (size_t I = 0; I < ArgRecords.size() - 1; ++I) {
+assert((!LastArgSupportsPack ||
+!isArgVariadic(*ArgRecords[I], R.getName())) &&
+   "Attributes supporting packs can only have the last "
+   "argument as variadic");
+assert(!argSupportsParmPack(ArgRecords[I]) &&
+   "Only the last argument can allow packs");
+  }
+}
+
 bool HasOptArg = false;
 bool HasFakeArg = false;
 for (const auto *ArgRecord : ArgRecords) {
@@ -3382,10 +3437,6 @@
   }
 }
 
-static bool isArgVariadic(const Record , StringRef AttrName) {
-  return createArgument(R, AttrName)->isVariadic();
-}
-
 static void emitArgInfo(const Record , raw_ostream ) {
   // This function will count the number of arguments specified for the
   // attribute and emit the number of required arguments followed by the
@@ -4219,6 +4270,8 @@
   emitClangAttrIdentifierArgList(Records, OS);
   emitClangAttrVariadicIdentifierArgList(Records, OS);
   emitClangAttrThisIsaIdentifierArgList(Records, OS);
+  emitClangAttrNumArgs(Records, OS);
+  emitClangAttrLastArgParmPackSupport(Records, 

[PATCH] D114439: [Annotation] Allow parameter pack expansions in annotate attribute

2021-12-07 Thread Steffen Larsen via Phabricator via cfe-commits
steffenlarsen added inline comments.



Comment at: clang/include/clang/Basic/DiagnosticParseKinds.td:724
+  "attribute %0 does not support pack expansion in the last argument">;
+def err_attribute_parm_pack_last_argument_only : Error<
+  "pack expansion in attributes is restricted to only the last argument">;

erichkeane wrote:
> I don't really see why this is required?  I would think the 722 would be all 
> you would need.
Intention was to make a distinction between the two cases, since we had the 
granularity to do so. I.e. `clang::annotate` would never use 722 as it 
explicitly states that the attribute doesn't support pack expansion (in the 
last argument) which is untrue for `clang::annotate`, but if a user was to do 
pack expansion on the first argument of `clang::annotate` they would get this 
error telling them that the given argument cannot accept the pack expansion.



Comment at: clang/lib/Parse/ParseDecl.cpp:450
+  // Pack expansion is only allowed in the last attribute argument.
+  if (ArgExprs.size() + 1 < attributeNumberOfArguments(*AttrName)) {
+Diag(Tok.getLocation(),

erichkeane wrote:
> I don't think this should be diagnosed here, and I don't think it is 'right'. 
>  I think the ClangAttrEmitter should ensure that the VariadicExprArgument 
> needs to be the 'last' thing, but I think that REALLY means "supports a pack 
> anywhere inside of it".
> 
> See my test examples below, I don't think this parsing is sufficient for that.
That is also the intention here. All it checks is that we are in or beyond the 
last argument of the attribute. For example, `clang::annotate` will return 2 
from `attributeNumberOfArguments` as `VariadicExprArgument` only counts as a 
single argument. Thus, any pack expansion expressions parsed after the first 
will be accepted. I do agree though that the error message may be a little 
confusing for users.

I will add the suggested tests and rethink the diagnostics.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D114439/new/

https://reviews.llvm.org/D114439

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D114439: [Annotation] Allow parameter pack expansions in annotate attribute

2021-12-06 Thread Erich Keane via Phabricator via cfe-commits
erichkeane added inline comments.



Comment at: clang/include/clang/Basic/DiagnosticParseKinds.td:724
+  "attribute %0 does not support pack expansion in the last argument">;
+def err_attribute_parm_pack_last_argument_only : Error<
+  "pack expansion in attributes is restricted to only the last argument">;

I don't really see why this is required?  I would think the 722 would be all 
you would need.



Comment at: clang/lib/Parse/ParseDecl.cpp:450
+  // Pack expansion is only allowed in the last attribute argument.
+  if (ArgExprs.size() + 1 < attributeNumberOfArguments(*AttrName)) {
+Diag(Tok.getLocation(),

I don't think this should be diagnosed here, and I don't think it is 'right'.  
I think the ClangAttrEmitter should ensure that the VariadicExprArgument needs 
to be the 'last' thing, but I think that REALLY means "supports a pack anywhere 
inside of it".

See my test examples below, I don't think this parsing is sufficient for that.



Comment at: clang/test/Parser/cxx0x-attributes.cpp:268
+  void faz [[clang::annotate("B", (Is + ...))]] (); // expected-warning {{pack 
fold expression is a C++17 extension}}
+  void foz [[clang::annotate("C", Is...)]] ();
 }

what about:
void foz [[clang::annotate("D", Is)]] ();

I would expect that to error.

Another test I'd like to see:

void foz[[clang::annotate("E", 1, 2, 3, Is...)]]

Also, I don't see why if THAT works, that:
void foz[[clang::annotate("E", 1, Is..., 2, 3)]]

shouldn't be allowed as well.



Comment at: clang/utils/TableGen/ClangAttrEmitter.cpp:1166
 
   class VariadicExprArgument : public VariadicArgument {
+bool AllowPack = false;

The rule of 'only the last argument is allowed to support a pack' should be in 
the attribute emitter.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D114439/new/

https://reviews.llvm.org/D114439

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D114439: [Annotation] Allow parameter pack expansions in annotate attribute

2021-12-03 Thread Steffen Larsen via Phabricator via cfe-commits
steffenlarsen added a comment.

Thank you both for the reviews! Consensus seems to be having support for pack 
expansion at argument level for now and let more complicated logic be added 
when there is an actual need. I have applied these changes as I understood them 
and have added/adjusted the requested test cases. Please have a look and let me 
know what you think. 

> That's what I want to avoid. :-D I would prefer that the arguments have to 
> opt into that behavior because the alternative could get ambiguous. I'd 
> rather we do some extra work to explicitly support that situation once we 
> have a specific attribute in mind for it.

I'm okay with that! I have made the changes to only allow it in the last 
argument if it is marked as supporting pack expansion. Note that it assumes 
that there are no other variadic parameters except the last one, as suggested.

> Hmm, let's make sure we're on the same page. The situations I think we should 
> avoid are:
>
>   // Mixing variadics and packs.
>   let Args = [VariadicExprArgument<"VarArgs">, VariadicExprArgument<"Pack", 
> /*AllowPack*/1>];
>   
>   // Multiple packs.
>   let Args = [VariadicExprArgument<"FirstPack", /*AllowPack*/1>, 
> VariadicExprArgument<"SecondPack", /*AllowPack*/1>];

Oh, I see what you mean. Yeah I agree for sure. I think the only exceptions we 
currently have to this is `omp` attributes, but given that they are pragmas 
they should be nowhere close to this.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D114439/new/

https://reviews.llvm.org/D114439

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D114439: [Annotation] Allow parameter pack expansions in annotate attribute

2021-12-03 Thread Steffen Larsen via Phabricator via cfe-commits
steffenlarsen updated this revision to Diff 391588.
steffenlarsen edited the summary of this revision.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D114439/new/

https://reviews.llvm.org/D114439

Files:
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/DiagnosticParseKinds.td
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
  clang/test/Parser/cxx0x-attributes.cpp
  clang/test/SemaTemplate/attributes.cpp
  clang/utils/TableGen/ClangAttrEmitter.cpp

Index: clang/utils/TableGen/ClangAttrEmitter.cpp
===
--- clang/utils/TableGen/ClangAttrEmitter.cpp
+++ clang/utils/TableGen/ClangAttrEmitter.cpp
@@ -1164,10 +1164,12 @@
   };
 
   class VariadicExprArgument : public VariadicArgument {
+bool AllowPack = false;
+
   public:
 VariadicExprArgument(const Record , StringRef Attr)
-  : VariadicArgument(Arg, Attr, "Expr *")
-{}
+: VariadicArgument(Arg, Attr, "Expr *"),
+  AllowPack(Arg.getValueAsBit("AllowPack")) {}
 
 void writeASTVisitorTraversal(raw_ostream ) const override {
   OS << "  {\n";
@@ -2264,6 +2266,43 @@
   OS << "#endif // CLANG_ATTR_THIS_ISA_IDENTIFIER_ARG_LIST\n\n";
 }
 
+static void emitClangAttrNumArgs(RecordKeeper , raw_ostream ) {
+  OS << "#if defined(CLANG_ATTR_NUM_ARGS)\n";
+  std::vector Attrs = Records.getAllDerivedDefinitions("Attr");
+  for (const auto *A : Attrs) {
+std::vector Args = A->getValueAsListOfDefs("Args");
+forEachUniqueSpelling(*A, [&](const FlattenedSpelling ) {
+  OS << ".Case(\"" << S.name() << "\", " << Args.size() << ")\n";
+});
+  }
+  OS << "#endif // CLANG_ATTR_NUM_ARGS\n\n";
+}
+
+static bool argSupportsParmPack(const Record *Arg) {
+  return !Arg->getSuperClasses().empty() &&
+ llvm::StringSwitch(
+ Arg->getSuperClasses().back().first->getName())
+ .Case("VariadicExprArgument", true)
+ .Default(false) &&
+ Arg->getValueAsBit("AllowPack");
+}
+
+static void emitClangAttrLastArgParmPackSupport(RecordKeeper ,
+raw_ostream ) {
+  OS << "#if defined(CLANG_ATTR_LAST_ARG_PARM_PACK_SUPPORT)\n";
+  std::vector Attrs = Records.getAllDerivedDefinitions("Attr");
+  for (const auto *A : Attrs) {
+std::vector Args = A->getValueAsListOfDefs("Args");
+bool LastArgSupportsParmPack =
+!Args.empty() && argSupportsParmPack(Args.back());
+forEachUniqueSpelling(*A, [&](const FlattenedSpelling ) {
+  OS << ".Case(\"" << S.name() << "\", " << LastArgSupportsParmPack
+ << ")\n";
+});
+  }
+  OS << "#endif // CLANG_ATTR_LAST_ARG_PARM_PACK_SUPPORT\n\n";
+}
+
 static void emitAttributes(RecordKeeper , raw_ostream ,
bool Header) {
   std::vector Attrs = Records.getAllDerivedDefinitions("Attr");
@@ -4219,6 +4258,8 @@
   emitClangAttrIdentifierArgList(Records, OS);
   emitClangAttrVariadicIdentifierArgList(Records, OS);
   emitClangAttrThisIsaIdentifierArgList(Records, OS);
+  emitClangAttrNumArgs(Records, OS);
+  emitClangAttrLastArgParmPackSupport(Records, OS);
   emitClangAttrTypeArgList(Records, OS);
   emitClangAttrLateParsedList(Records, OS);
 }
Index: clang/test/SemaTemplate/attributes.cpp
===
--- clang/test/SemaTemplate/attributes.cpp
+++ clang/test/SemaTemplate/attributes.cpp
@@ -64,6 +64,23 @@
 template [[clang::annotate("ANNOTATE_FOO"), clang::annotate("ANNOTATE_BAR")]] void HasAnnotations();
 void UseAnnotations() { HasAnnotations(); }
 
+// CHECK:  FunctionTemplateDecl {{.*}} HasPackAnnotations
+// CHECK:AnnotateAttr {{.*}} "ANNOTATE_BAZ"
+// CHECK:  FunctionDecl {{.*}} HasPackAnnotations
+// CHECK:TemplateArgument{{.*}} pack
+// CHECK-NEXT: TemplateArgument{{.*}} integral 1
+// CHECK-NEXT: TemplateArgument{{.*}} integral 2
+// CHECK-NEXT: TemplateArgument{{.*}} integral 3
+// CHECK:AnnotateAttr {{.*}} "ANNOTATE_BAZ"
+// CHECK:  ConstantExpr {{.*}} 'int'
+// CHECK-NEXT:   value: Int 1
+// CHECK:  ConstantExpr {{.*}} 'int'
+// CHECK-NEXT:   value: Int 2
+// CHECK:  ConstantExpr {{.*}} 'int'
+// CHECK-NEXT:   value: Int 3
+template  [[clang::annotate("ANNOTATE_BAZ", Is...)]] void HasPackAnnotations();
+void UsePackAnnotations() { HasPackAnnotations<1, 2, 3>(); }
+
 namespace preferred_name {
   int x [[clang::preferred_name("frank")]]; // expected-error {{expected a type}}
   int y [[clang::preferred_name(int)]]; // expected-warning {{'preferred_name' attribute only applies to class templates}}
Index: clang/test/Parser/cxx0x-attributes.cpp
===
--- clang/test/Parser/cxx0x-attributes.cpp
+++ clang/test/Parser/cxx0x-attributes.cpp
@@ -258,8 +258,14 @@
   [[]] return;
 }
 
-template void variadic() {
-  void bar [[noreturn...]] (); // expected-error 

[PATCH] D114439: [Annotation] Allow parameter pack expansions in annotate attribute

2021-12-02 Thread Erich Keane via Phabricator via cfe-commits
erichkeane added inline comments.



Comment at: clang/include/clang/Basic/Attr.td:544-546
+  // Set to true for attributes that support parameter pack expansion in its
+  // arguments.
+  bit ParmExpansionArgsSupport = 0;

aaron.ballman wrote:
> steffenlarsen wrote:
> > aaron.ballman wrote:
> > > From a design perspective, I think this is a property of the parameters 
> > > of an attribute rather than of an attribute itself. So I'd rather not add 
> > > a bit to the `Attr` class, but instead modify the `Argument` class. There 
> > > are a few approaches to that which I can think of, and I'm not certain 
> > > which is the best approach.
> > > 
> > > 1) Introduce `ExpressionPackArgument` and attributes can opt into using 
> > > it if they want to support packs.
> > > 2) Add this bit to `VariadicExprArgument` and attributes can opt into 
> > > using it if they want to support packs.
> > > 3) Change `VariadicExprArgument` to also mean "allows packs" and all 
> > > attributes using this automatically support packs.
> > > 
> > > I think that my conservative preference is for #2, but my intuition is 
> > > that #3 is where we probably ultimately want to get to.
> > > 
> > > There are definitely some open questions with this approach that we'll 
> > > have to figure out:
> > > 
> > > * Can you mix packs with variadics in the same attribute?
> > > * Can you have two pack arguments in the same attribute?
> > > * Does the tablegen design also seem likely to work when we want to 
> > > introduce type packs instead of value packs?
> > > 
> > > I think the safest bet is to be conservative and not allow mixing packs 
> > > with variadics, and not allowing multiple packs. We should be able to 
> > > diagnose that situation from ClangAttrEmitter.cpp to help attribute 
> > > authors out. However, it'd be worth adding a FIXME comment to that 
> > > diagnostic logic asking whether we want to relax the behavior at some 
> > > point. But if you feel strongly that we should support these situations 
> > > initially, I wouldn't be opposed.
> > Having `ParmExpansionArgsSupport` in `Attr` would allow attributes to 
> > populate with parameter packs across argument boundaries. It seems more 
> > permissive, but frankly I have no attachment to it, so I am okay with tying 
> > it to `Argument` instead.
> > 
> > Of the mentioned options, I agree #2 and #3 are the preferred paths. For 
> > simplicity I prefer #2, though I will have to figure out how best to add a 
> > check on individual arguments, which @erichkeane's suggestion to limit the 
> > attributes to only allowing parameter packs in variadic arguments as the 
> > last argument would help with. On the other hand, the population logic for 
> > most of the relevant attributes are explicitly defined in 
> > `clang/lib/Sema/SemaDeclAttr.cpp` (which will have to be changed with #3) 
> > so being more permissive - like the current version of the patch is - gives 
> > more freedom to the attributes.
> > 
> > > Does the tablegen design also seem likely to work when we want to 
> > > introduce type packs instead of value packs?
> > 
> > I am not sure about how tablegen would take it, but the parser doesn't 
> > currently parse more than a single type argument, so I don't see a need for 
> > allowing type packs at the moment.
> > 
> > > I think the safest bet is to be conservative and not allow mixing packs 
> > > with variadics, and not allowing multiple packs. We should be able to 
> > > diagnose that situation from ClangAttrEmitter.cpp to help attribute 
> > > authors out. However, it'd be worth adding a FIXME comment to that 
> > > diagnostic logic asking whether we want to relax the behavior at some 
> > > point. But if you feel strongly that we should support these situations 
> > > initially, I wouldn't be opposed.
> > 
> > If we limit packs to `VariadicExprArgument` - like `annotate` does in the 
> > current state of this patch - having multiple packs in the same argument is 
> > simple to handle. Both are represented as `Expr` and the variadic argument 
> > will simply contain two expressions until the templates are instantiated 
> > and the packs are expanded. This is also a feature I would like to keep, 
> > though it should be possible to work around the limitation if we conclude 
> > it can't stay.
> > 
> > Having ParmExpansionArgsSupport in Attr would allow attributes to populate 
> > with parameter packs across argument boundaries. 
> 
> That's what I want to avoid. :-D I would prefer that the arguments have to 
> opt into that behavior because the alternative could get ambiguous. I'd 
> rather we do some extra work to explicitly support that situation once we 
> have a specific attribute in mind for it.
> 
> > ... which @erichkeane's suggestion to limit the attributes to only allowing 
> > parameter packs in variadic arguments as the last argument would help with. 
> 
> I agree with that suggestion, btw.
> 
> > I am not sure about how 

[PATCH] D114439: [Annotation] Allow parameter pack expansions in annotate attribute

2021-12-02 Thread Aaron Ballman via Phabricator via cfe-commits
aaron.ballman added inline comments.



Comment at: clang/include/clang/Basic/Attr.td:544-546
+  // Set to true for attributes that support parameter pack expansion in its
+  // arguments.
+  bit ParmExpansionArgsSupport = 0;

steffenlarsen wrote:
> aaron.ballman wrote:
> > From a design perspective, I think this is a property of the parameters of 
> > an attribute rather than of an attribute itself. So I'd rather not add a 
> > bit to the `Attr` class, but instead modify the `Argument` class. There are 
> > a few approaches to that which I can think of, and I'm not certain which is 
> > the best approach.
> > 
> > 1) Introduce `ExpressionPackArgument` and attributes can opt into using it 
> > if they want to support packs.
> > 2) Add this bit to `VariadicExprArgument` and attributes can opt into using 
> > it if they want to support packs.
> > 3) Change `VariadicExprArgument` to also mean "allows packs" and all 
> > attributes using this automatically support packs.
> > 
> > I think that my conservative preference is for #2, but my intuition is that 
> > #3 is where we probably ultimately want to get to.
> > 
> > There are definitely some open questions with this approach that we'll have 
> > to figure out:
> > 
> > * Can you mix packs with variadics in the same attribute?
> > * Can you have two pack arguments in the same attribute?
> > * Does the tablegen design also seem likely to work when we want to 
> > introduce type packs instead of value packs?
> > 
> > I think the safest bet is to be conservative and not allow mixing packs 
> > with variadics, and not allowing multiple packs. We should be able to 
> > diagnose that situation from ClangAttrEmitter.cpp to help attribute authors 
> > out. However, it'd be worth adding a FIXME comment to that diagnostic logic 
> > asking whether we want to relax the behavior at some point. But if you feel 
> > strongly that we should support these situations initially, I wouldn't be 
> > opposed.
> Having `ParmExpansionArgsSupport` in `Attr` would allow attributes to 
> populate with parameter packs across argument boundaries. It seems more 
> permissive, but frankly I have no attachment to it, so I am okay with tying 
> it to `Argument` instead.
> 
> Of the mentioned options, I agree #2 and #3 are the preferred paths. For 
> simplicity I prefer #2, though I will have to figure out how best to add a 
> check on individual arguments, which @erichkeane's suggestion to limit the 
> attributes to only allowing parameter packs in variadic arguments as the last 
> argument would help with. On the other hand, the population logic for most of 
> the relevant attributes are explicitly defined in 
> `clang/lib/Sema/SemaDeclAttr.cpp` (which will have to be changed with #3) so 
> being more permissive - like the current version of the patch is - gives more 
> freedom to the attributes.
> 
> > Does the tablegen design also seem likely to work when we want to introduce 
> > type packs instead of value packs?
> 
> I am not sure about how tablegen would take it, but the parser doesn't 
> currently parse more than a single type argument, so I don't see a need for 
> allowing type packs at the moment.
> 
> > I think the safest bet is to be conservative and not allow mixing packs 
> > with variadics, and not allowing multiple packs. We should be able to 
> > diagnose that situation from ClangAttrEmitter.cpp to help attribute authors 
> > out. However, it'd be worth adding a FIXME comment to that diagnostic logic 
> > asking whether we want to relax the behavior at some point. But if you feel 
> > strongly that we should support these situations initially, I wouldn't be 
> > opposed.
> 
> If we limit packs to `VariadicExprArgument` - like `annotate` does in the 
> current state of this patch - having multiple packs in the same argument is 
> simple to handle. Both are represented as `Expr` and the variadic argument 
> will simply contain two expressions until the templates are instantiated and 
> the packs are expanded. This is also a feature I would like to keep, though 
> it should be possible to work around the limitation if we conclude it can't 
> stay.
> 
> Having ParmExpansionArgsSupport in Attr would allow attributes to populate 
> with parameter packs across argument boundaries. 

That's what I want to avoid. :-D I would prefer that the arguments have to opt 
into that behavior because the alternative could get ambiguous. I'd rather we 
do some extra work to explicitly support that situation once we have a specific 
attribute in mind for it.

> ... which @erichkeane's suggestion to limit the attributes to only allowing 
> parameter packs in variadic arguments as the last argument would help with. 

I agree with that suggestion, btw.

> I am not sure about how tablegen would take it, but the parser doesn't 
> currently parse more than a single type argument, so I don't see a need for 
> allowing type packs at the moment.

Fair point, and yet 

[PATCH] D114439: [Annotation] Allow parameter pack expansions in annotate attribute

2021-12-02 Thread Steffen Larsen via Phabricator via cfe-commits
steffenlarsen added inline comments.



Comment at: clang/lib/Parse/ParseDecl.cpp:447
+  }
+  ArgExpr = Actions.ActOnPackExpansion(ArgExpr.get(), ConsumeToken());
+}

steffenlarsen wrote:
> erichkeane wrote:
> > Do you have a test for something that isn't a pack followed by an ellipsis? 
> >  What is the behavior there?   I'm also concerned that there doesn't seem 
> > to be anything here that handles complex-pack expansions (like folds), can 
> > you test that as well?
> > 
> > Also, why is this 'if' not up on line 429 (that is, outside of this 
> > 'else'?).  I believe ParseAssignmentExpression is going to muck-up the 
> > tokens, so I'm not particularly sure what is going to happen here?
> > Do you have a test for something that isn't a pack followed by an ellipsis? 
> > What is the behavior there? I'm also concerned that there doesn't seem to 
> > be anything here that handles complex-pack expansions (like folds), can you 
> > test that as well?
> 
> Good question! I would expect it to fail in kind during template 
> instantiation, or earlier if it is not an expression, but I will test it out 
> once we converge on a new solution.
> 
> > Also, why is this 'if' not up on line 429 (that is, outside of this 
> > 'else'?). I believe ParseAssignmentExpression is going to muck-up the 
> > tokens, so I'm not particularly sure what is going to happen here?
> 
> I originally tried having the `ActOnPackExpansion` earlier, but it did indeed 
> cause trouble. However, if my understanding of the previous two branches is 
> correct, they are:
> 
> 
>   # Type argument. This could be consuming the ellipsis as well, though I 
> suspect it needs another path given that it does not seem to produce any 
> expressions. Note however that it currently seems to stop argument parsing 
> after reading the first type (confirmed by the FIXME) so parameter pack logic 
> for this branch would probably be more suitable once it actually allows 
> attributes to take multiple types.
>   # Identifier argument. Correct me if I am wrong, but I don't think this can 
> be populated by a parameter pack.
> 
> I could add the diagnostic to these if ellipsis is found, but if my 
> assumptions are correct it doesn't make much sense to expand these branches 
> beyond that.
> I'm also concerned that there doesn't seem to be anything here that handles 
> complex-pack expansions (like folds), can you test that as well?

Sorry, I forgot to address this. I have not tested it, but I would expect 
complex-pack expansions like folds to be at expression-level. I will make sure 
to test this as well.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D114439/new/

https://reviews.llvm.org/D114439

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D114439: [Annotation] Allow parameter pack expansions in annotate attribute

2021-12-02 Thread Steffen Larsen via Phabricator via cfe-commits
steffenlarsen added inline comments.



Comment at: clang/include/clang/Basic/Attr.td:544-546
+  // Set to true for attributes that support parameter pack expansion in its
+  // arguments.
+  bit ParmExpansionArgsSupport = 0;

aaron.ballman wrote:
> From a design perspective, I think this is a property of the parameters of an 
> attribute rather than of an attribute itself. So I'd rather not add a bit to 
> the `Attr` class, but instead modify the `Argument` class. There are a few 
> approaches to that which I can think of, and I'm not certain which is the 
> best approach.
> 
> 1) Introduce `ExpressionPackArgument` and attributes can opt into using it if 
> they want to support packs.
> 2) Add this bit to `VariadicExprArgument` and attributes can opt into using 
> it if they want to support packs.
> 3) Change `VariadicExprArgument` to also mean "allows packs" and all 
> attributes using this automatically support packs.
> 
> I think that my conservative preference is for #2, but my intuition is that 
> #3 is where we probably ultimately want to get to.
> 
> There are definitely some open questions with this approach that we'll have 
> to figure out:
> 
> * Can you mix packs with variadics in the same attribute?
> * Can you have two pack arguments in the same attribute?
> * Does the tablegen design also seem likely to work when we want to introduce 
> type packs instead of value packs?
> 
> I think the safest bet is to be conservative and not allow mixing packs with 
> variadics, and not allowing multiple packs. We should be able to diagnose 
> that situation from ClangAttrEmitter.cpp to help attribute authors out. 
> However, it'd be worth adding a FIXME comment to that diagnostic logic asking 
> whether we want to relax the behavior at some point. But if you feel strongly 
> that we should support these situations initially, I wouldn't be opposed.
Having `ParmExpansionArgsSupport` in `Attr` would allow attributes to populate 
with parameter packs across argument boundaries. It seems more permissive, but 
frankly I have no attachment to it, so I am okay with tying it to `Argument` 
instead.

Of the mentioned options, I agree #2 and #3 are the preferred paths. For 
simplicity I prefer #2, though I will have to figure out how best to add a 
check on individual arguments, which @erichkeane's suggestion to limit the 
attributes to only allowing parameter packs in variadic arguments as the last 
argument would help with. On the other hand, the population logic for most of 
the relevant attributes are explicitly defined in 
`clang/lib/Sema/SemaDeclAttr.cpp` (which will have to be changed with #3) so 
being more permissive - like the current version of the patch is - gives more 
freedom to the attributes.

> Does the tablegen design also seem likely to work when we want to introduce 
> type packs instead of value packs?

I am not sure about how tablegen would take it, but the parser doesn't 
currently parse more than a single type argument, so I don't see a need for 
allowing type packs at the moment.

> I think the safest bet is to be conservative and not allow mixing packs with 
> variadics, and not allowing multiple packs. We should be able to diagnose 
> that situation from ClangAttrEmitter.cpp to help attribute authors out. 
> However, it'd be worth adding a FIXME comment to that diagnostic logic asking 
> whether we want to relax the behavior at some point. But if you feel strongly 
> that we should support these situations initially, I wouldn't be opposed.

If we limit packs to `VariadicExprArgument` - like `annotate` does in the 
current state of this patch - having multiple packs in the same argument is 
simple to handle. Both are represented as `Expr` and the variadic argument will 
simply contain two expressions until the templates are instantiated and the 
packs are expanded. This is also a feature I would like to keep, though it 
should be possible to work around the limitation if we conclude it can't stay.




Comment at: clang/lib/Parse/ParseDecl.cpp:447
+  }
+  ArgExpr = Actions.ActOnPackExpansion(ArgExpr.get(), ConsumeToken());
+}

erichkeane wrote:
> Do you have a test for something that isn't a pack followed by an ellipsis?  
> What is the behavior there?   I'm also concerned that there doesn't seem to 
> be anything here that handles complex-pack expansions (like folds), can you 
> test that as well?
> 
> Also, why is this 'if' not up on line 429 (that is, outside of this 'else'?). 
>  I believe ParseAssignmentExpression is going to muck-up the tokens, so I'm 
> not particularly sure what is going to happen here?
> Do you have a test for something that isn't a pack followed by an ellipsis? 
> What is the behavior there? I'm also concerned that there doesn't seem to be 
> anything here that handles complex-pack expansions (like folds), can you test 
> that as well?

Good question! I would expect it to fail 

[PATCH] D114439: [Annotation] Allow parameter pack expansions in annotate attribute

2021-12-01 Thread Erich Keane via Phabricator via cfe-commits
erichkeane added a comment.

>> I think the safest bet is to be conservative and not allow mixing packs with 
>> variadics, and not allowing multiple packs. We should be able to diagnose 
>> that situation from ClangAttrEmitter.cpp to help attribute authors out. 
>> However, it'd be worth adding a FIXME comment to that diagnostic logic 
>> asking whether we want to relax the behavior at some point. But if you feel 
>> strongly that we should support these situations initially, I wouldn't be 
>> opposed.

From a practical perspective, the only difference between a list of 
`ExprArgument` and `VariadicExprArgument` is the enforced arity I would 
also consider seeing if we can just generalize the pack logic to work for BOTH 
cases.  I'd be all for limiting the pack/ExprArgument list to be the 'last' 
argument to simplify it.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D114439/new/

https://reviews.llvm.org/D114439

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D114439: [Annotation] Allow parameter pack expansions in annotate attribute

2021-12-01 Thread Aaron Ballman via Phabricator via cfe-commits
aaron.ballman requested changes to this revision.
aaron.ballman added inline comments.
This revision now requires changes to proceed.



Comment at: clang/include/clang/Basic/Attr.td:544-546
+  // Set to true for attributes that support parameter pack expansion in its
+  // arguments.
+  bit ParmExpansionArgsSupport = 0;

From a design perspective, I think this is a property of the parameters of an 
attribute rather than of an attribute itself. So I'd rather not add a bit to 
the `Attr` class, but instead modify the `Argument` class. There are a few 
approaches to that which I can think of, and I'm not certain which is the best 
approach.

1) Introduce `ExpressionPackArgument` and attributes can opt into using it if 
they want to support packs.
2) Add this bit to `VariadicExprArgument` and attributes can opt into using it 
if they want to support packs.
3) Change `VariadicExprArgument` to also mean "allows packs" and all attributes 
using this automatically support packs.

I think that my conservative preference is for #2, but my intuition is that #3 
is where we probably ultimately want to get to.

There are definitely some open questions with this approach that we'll have to 
figure out:

* Can you mix packs with variadics in the same attribute?
* Can you have two pack arguments in the same attribute?
* Does the tablegen design also seem likely to work when we want to introduce 
type packs instead of value packs?

I think the safest bet is to be conservative and not allow mixing packs with 
variadics, and not allowing multiple packs. We should be able to diagnose that 
situation from ClangAttrEmitter.cpp to help attribute authors out. However, 
it'd be worth adding a FIXME comment to that diagnostic logic asking whether we 
want to relax the behavior at some point. But if you feel strongly that we 
should support these situations initially, I wouldn't be opposed.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D114439/new/

https://reviews.llvm.org/D114439

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D114439: [Annotation] Allow parameter pack expansions in annotate attribute

2021-12-01 Thread Erich Keane via Phabricator via cfe-commits
erichkeane added a comment.

Aaron is way more familiar with this code than I am, but I've got some 
suggestions for more tests in the parsing, we need to make sure that we handle 
pack expansion completely here.




Comment at: clang/lib/Parse/ParseDecl.cpp:447
+  }
+  ArgExpr = Actions.ActOnPackExpansion(ArgExpr.get(), ConsumeToken());
+}

Do you have a test for something that isn't a pack followed by an ellipsis?  
What is the behavior there?   I'm also concerned that there doesn't seem to be 
anything here that handles complex-pack expansions (like folds), can you test 
that as well?

Also, why is this 'if' not up on line 429 (that is, outside of this 'else'?).  
I believe ParseAssignmentExpression is going to muck-up the tokens, so I'm not 
particularly sure what is going to happen here?



Comment at: clang/test/Parser/cxx0x-attributes.cpp:261
 
-template void variadic() {
+template  void variadic() {
   void bar [[noreturn...]] (); // expected-error {{attribute 'noreturn' cannot 
be used as an attribute pack}}

What is the point of this change?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D114439/new/

https://reviews.llvm.org/D114439

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D114439: [Annotation] Allow parameter pack expansions in annotate attribute

2021-11-23 Thread Tyker via Phabricator via cfe-commits
Tyker added a comment.

This seems like a good change to me. but i don't think my approval is enough


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D114439/new/

https://reviews.llvm.org/D114439

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D114439: [Annotation] Allow parameter pack expansions in annotate attribute

2021-11-23 Thread Steffen Larsen via Phabricator via cfe-commits
steffenlarsen created this revision.
steffenlarsen added reviewers: erichkeane, aaron.ballman, Tyker, Naghasan.
Herald added a subscriber: jdoerfert.
steffenlarsen requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

These changes make the Clang parser recognize parameter pack expansion in 
attribute arguments and consume them if the attribute is marked as supporting 
parameter pack expansions.
Currently only the `clang::annotate` attribute will support parameter pack 
expansions in its arguments. The parser will issue an error diagnostic if other 
attributes are passed parameter pack expansion arguments.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D114439

Files:
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/DiagnosticParseKinds.td
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
  clang/test/Parser/cxx0x-attributes.cpp
  clang/test/SemaTemplate/attributes.cpp
  clang/utils/TableGen/ClangAttrEmitter.cpp

Index: clang/utils/TableGen/ClangAttrEmitter.cpp
===
--- clang/utils/TableGen/ClangAttrEmitter.cpp
+++ clang/utils/TableGen/ClangAttrEmitter.cpp
@@ -1697,6 +1697,22 @@
   OS << "#endif // CLANG_ATTR_LATE_PARSED_LIST\n\n";
 }
 
+// Emits the ParmExpansionArgsSupport property for attributes.
+static void emitClangAttrParmExpansionArgsSupportList(RecordKeeper ,
+  raw_ostream ) {
+  OS << "#if defined(CLANG_ATTR_PARM_EXPANSION_ARGS_SUPPORT_LIST)\n";
+  std::vector Attrs = Records.getAllDerivedDefinitions("Attr");
+
+  for (const auto *Attr : Attrs) {
+if (Attr->getValueAsBit("ParmExpansionArgsSupport")) {
+  std::vector Spellings = GetFlattenedSpellings(*Attr);
+  for (const auto  : Spellings)
+OS << ".Case(\"" << I.name() << "\", true)\n";
+}
+  }
+  OS << "#endif // CLANG_ATTR_PARM_EXPANSION_ARGS_SUPPORT_LIST\n\n";
+}
+
 static bool hasGNUorCXX11Spelling(const Record ) {
   std::vector Spellings = GetFlattenedSpellings(Attribute);
   for (const auto  : Spellings) {
@@ -4221,6 +4237,7 @@
   emitClangAttrThisIsaIdentifierArgList(Records, OS);
   emitClangAttrTypeArgList(Records, OS);
   emitClangAttrLateParsedList(Records, OS);
+  emitClangAttrParmExpansionArgsSupportList(Records, OS);
 }
 
 void EmitClangAttrSubjectMatchRulesParserStringSwitches(RecordKeeper ,
Index: clang/test/SemaTemplate/attributes.cpp
===
--- clang/test/SemaTemplate/attributes.cpp
+++ clang/test/SemaTemplate/attributes.cpp
@@ -64,6 +64,23 @@
 template [[clang::annotate("ANNOTATE_FOO"), clang::annotate("ANNOTATE_BAR")]] void HasAnnotations();
 void UseAnnotations() { HasAnnotations(); }
 
+// CHECK:  FunctionTemplateDecl {{.*}} HasPackAnnotations
+// CHECK:AnnotateAttr {{.*}} "ANNOTATE_BAZ"
+// CHECK:  FunctionDecl {{.*}} HasPackAnnotations
+// CHECK:TemplateArgument{{.*}} pack
+// CHECK-NEXT: TemplateArgument{{.*}} integral 1
+// CHECK-NEXT: TemplateArgument{{.*}} integral 2
+// CHECK-NEXT: TemplateArgument{{.*}} integral 3
+// CHECK:AnnotateAttr {{.*}} "ANNOTATE_BAZ"
+// CHECK:  ConstantExpr {{.*}} 'int'
+// CHECK-NEXT:   value: Int 1
+// CHECK:  ConstantExpr {{.*}} 'int'
+// CHECK-NEXT:   value: Int 2
+// CHECK:  ConstantExpr {{.*}} 'int'
+// CHECK-NEXT:   value: Int 3
+template  [[clang::annotate("ANNOTATE_BAZ", Is...)]] void HasPackAnnotations();
+void UsePackAnnotations() { HasPackAnnotations<1, 2, 3>(); }
+
 namespace preferred_name {
   int x [[clang::preferred_name("frank")]]; // expected-error {{expected a type}}
   int y [[clang::preferred_name(int)]]; // expected-warning {{'preferred_name' attribute only applies to class templates}}
Index: clang/test/Parser/cxx0x-attributes.cpp
===
--- clang/test/Parser/cxx0x-attributes.cpp
+++ clang/test/Parser/cxx0x-attributes.cpp
@@ -258,8 +258,10 @@
   [[]] return;
 }
 
-template void variadic() {
+template  void variadic() {
   void bar [[noreturn...]] (); // expected-error {{attribute 'noreturn' cannot be used as an attribute pack}}
+  void baz [[clang::no_sanitize(Is...)]] (); // expected-error {{attribute 'no_sanitize' does not support parameter pack expansion in arguments}}
+  void boo [[unknown::foo(Is...)]] ();   // expected-warning {{unknown attribute 'foo' ignored}}
 }
 
 // Expression tests
Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
===
--- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -189,13 +189,9 @@
   EnterExpressionEvaluationContext Unevaluated(
   S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
   SmallVector Args;
-  Args.reserve(Attr->args_size());
-  for