On Thu, Jul 24, 2014 at 6:48 PM, Tyler Nowicki <[email protected]> wrote:
> Hi Aaron,
>
> Thanks for the review!
>
> There were a number of conflicts with the work on pragma unroll and nounroll.
> To accommodate these directives I changed the Enabled argument of the loop
> hint attribute to a state argument. The state argument can be default,
> enable, or disable. Attributes like ‘#pragma unroll’ that don’t have any
> arguments use the default state.
I would prefer this to be a separate change if at all possible (as a
predecessor to this patch) as it seems to be fairly substantive --
there's about a 17kb difference between this patch and the last one.
;-)
>
> I also applied most of your suggestions except for those below. Please review
> the updated patch.
>
>
>>> + ConsumeToken(); // The annotation token.
>>
>> I would hoist this out of the if statement and place it closer to the
>> assert at the top of the method.
> (see next)
>
>>> + // Enter constant expression including eof terminator into token
>>> stream.
>>> + PP.EnterTokenStream(Args, ArgSize, /*DisableMacroExpansion=*/false,
>>> + /*OwnsTokens=*/false);
>>> +
>>> + ConsumeToken(); // The annotation token.
>>
>> This winds up being hoisted and so can be removed.
>
> Moving a PP.Lex before the PP.EnterTokenStream means that when
> ParseConstantExpression() is called Tok is set to the token that follows the
> annotation token, but thats not what we want. What want Tok to be the first
> token in the constant expression. In other words
>
> ConsumeToken
> PP.EnterTokenStream
>
> isn’t the same as
>
> PP.EnterTokenStream
> ConsumeToken
>
> So we can’t hoist ConsumeToken to the top of the function.
Ahh, okay, that makes sense. Thank you for the explanation!
>
>
>>> +
>>> + ExprResult R = ParseConstantExpression();
>>> +
>>> + ConsumeToken(); // The constant expression eof terminator.
>>
>> You should not be assuming this is an eof terminator -- since this is
>> parser functionality, I think using ExpectAndConsume would make the
>> most sense (so you can diagnose if the token isn't present, and fail
>> out properly).
>>
>> A parsing tese where this fails would be good as well.
>
> The terminator is added after the pragma is parsed. I’m not sure how to write
> a test that makes ParseConstantExpression() fail to stop at the terminator.
> The terminator (eof) is specifically added to make sure
> ParseConstantExpression() doesn’t parse past the end of the directive.
Then I would add an assert ensuring that you really have consumed the
EOF and not something else.
> What can go wrong here is ParseConstantExpression() can stop before it has
> consumed all of the tokens in the constant expression. Because the expression
> was ill-formed something like '(1 2)’. It will parse ‘1’ and leave ‘2’ on the
> token stream. The pragma unroll test ‘#pragma unroll 1 2’ tests exactly this.
> I modified the code here to emit a warning and consume all remaining tokens
> in the constant expression.
Ah, great!
>
>
>>> void EmitClangAttrList(RecordKeeper &Records, raw_ostream &OS) {
>>> emitSourceFileHeader("List of all attributes that Clang recognizes", OS);
>>> @@ -1633,14 +1641,25 @@
>>> " INHERITABLE_PARAM_ATTR(NAME)\n";
>>> OS << "#endif\n\n";
>>>
>>> + OS << "#ifndef PRAGMA_SPELLING_ATTR\n";
>>> + OS << "#define PRAGMA_SPELLING_ATTR(NAME)\n";
>>> + OS << "#endif\n\n";
>>> +
>>> + OS << "#ifndef LAST_PRAGMA_SPELLING_ATTR\n";
>>> + OS << "#define LAST_PRAGMA_SPELLING_ATTR(NAME)
>>> PRAGMA_SPELLING_ATTR(NAME)\n";
>>> + OS << "#endif\n\n";
>>> +
>>> Record *InhClass = Records.getClass("InheritableAttr");
>>> Record *InhParamClass = Records.getClass("InheritableParamAttr");
>>> - std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"),
>>> - NonInhAttrs, InhAttrs, InhParamAttrs;
>>> + std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr"),
>>> + NonInhAttrs, InhAttrs, InhParamAttrs, PragmaAttrs;
>>> for (auto *Attr : Attrs) {
>>> if (!Attr->getValueAsBit("ASTNode"))
>>> continue;
>>> -
>>> +
>>> + if (AttrHasPragmaSpelling(Attr))
>>> + PragmaAttrs.push_back(Attr);
>>> +
>>
>> I think this is fine for now, but I am starting to get worried about
>> the maintainability of this list. It used to be about type
>> categorization, now it's a bit larger. But then again, the type
>> categorization wasn't always perfect either (for instance, something
>> can be a type attribute and an inheritable attribute at the same
>> time); we just sort of skirted around it.
>>
>> So at some point, this code may need to be revisited, but it seems
>> correct right now.
>
> Ok, thats great. The new list is used by sema during template instantiation.
> Rather than hard-coding the attributes that require a special template
> instantiation this list is used to automatically generate transform function
> stubs and their uses. Doing this for every attribute, not just attributes
> with pragma spellings, would be bad because most attributes can only be
> applied to declarations which are handled in a completely different way. So
> it would create many useless stub functions.
Good to know.
~Aaron
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits