This is an archive of the discontinued LLVM Phabricator instance.

[Parse] Fix `TryParsePtrOperatorSeq`.
ClosedPublic

Authored by michele.scandale on Feb 14 2020, 1:30 PM.

Details

Summary

The syntax rules for ptr-operator allow attributes after *, &,
&&, therefore we should be able to parse the following:

void fn() {
    void (*[[attr]] x)() = &fn;
    void (&[[attr]] y)() = fn;
    void (&&[[attr]] z)() = fn;
}

However the current logic in TryParsePtrOperatorSeq does not consider
the presence of attributes leading to unexpected parsing errors.

Moreover we should also consider _Atomic a possible qualifier that can
appear after the sequence of attribute specifiers.

Event Timeline

Herald added a project: Restricted Project. · View Herald TranscriptFeb 14 2020, 1:30 PM
Herald added a subscriber: cfe-commits. · View Herald Transcript

Missed GNU style attributes

Harbormaster completed remote builds in B46549: Diff 244756.
rjmccall added inline comments.Feb 17 2020, 11:09 AM
clang/lib/Parse/ParseTentative.cpp
811

Do you want to check for double-brackets here?

Check for double brackets for C++11 style attributes, and outline the loop to skip attributes in TrySkipAttributes to fix also the other use in TryConsumeDeclarationSpecifier

michele.scandale marked an inline comment as done.Feb 17 2020, 6:52 PM
michele.scandale added inline comments.
clang/lib/Parse/ParseTentative.cpp
811

The copy of the code I was replicating here wasn't doing that. But it makes sense to check at least that.

rjmccall accepted this revision.Feb 17 2020, 7:04 PM
rjmccall added inline comments.
clang/lib/Parse/ParseTentative.cpp
780

Okay, great. The check for adjacent squares at the end makes sure this doesn't catch an ObjC message send, in case this is ever used in a context where there's attribute/expression ambiguity; that might be worth a comment. Otherwise LGTM.

This revision is now accepted and ready to land.Feb 17 2020, 7:04 PM

Add comment about ObjC message send being rejected + rebase

michele.scandale marked an inline comment as done.Feb 17 2020, 7:24 PM

Assuming this is fine, I would need someone landing this change on my behalf since I do not have commit rights. Thanks!

clang/lib/Parse/ParseTentative.cpp
780

Comment added. Let me know if the wording is fine.

rjmccall accepted this revision.Feb 17 2020, 8:48 PM

LGTM.

@rsmith: is this fine for you as well?

If this is ready for landing, I would appreciate if somebody can land this on my behalf since I do not have commit rights. Thanks!

rsmith accepted this revision.Feb 22 2020, 6:56 PM
rsmith added inline comments.
clang/include/clang/Parse/Parser.h
2445

Stray "of' here. (And an 's' after "attribute-specifier" would improve readability.)

Fixed comment wording + rebase.

aaron.ballman requested changes to this revision.Feb 23 2020, 6:06 AM
aaron.ballman added a reviewer: aaron.ballman.
aaron.ballman added a subscriber: aaron.ballman.
aaron.ballman added inline comments.
clang/lib/Parse/ParseTentative.cpp
773

Do we need to also skip other keyword attributes as well as alignas? For instance, tok::kw__Noreturn or tok::kw__Alignas

779

I think this gets the parsing logic wrong when there is a balanced [] that is not part of the attribute introducer syntax, such as finding an array in the middle of the attribute argument clause. A test case would be handy, like:

constexpr int foo[] = { 2, 4 };
[[gnu::assume_aligned(foo[0])]] int *func() { return nullptr; }

You should probably use a BalancedDelimiterTracker to handle the brackets.

789

If we're skipping __attribute__(()), this looks to miss the second closing right paren. Also, this logic won't work if we need to skip _Noreturn, which has no parens.

This branch is missing test coverage.

rsmith added inline comments.Feb 23 2020, 11:12 AM
clang/lib/Parse/ParseTentative.cpp
773

_Alignas and _Noreturn are their own kinds of decl-specifiers, not attributes. In particular, they're not syntactically valid in any of the places that call this (after a * or a tag keyword). It looks like we're missing support for them, but we should recognize them in isCXXDeclarationSpecifier, not here -- but I think that's unrelated to this patch.

779

SkipUntil properly handles nested brackets; I think this is fine (though more testcases can't hurt!). I don't think BalancedDelimiterTracker would help -- this function can intentionally terminate with unbalanced delimiters, if it bails out part-way through skipping an attribute.

As for a testcase, the example you give above doesn't get here. Perhaps something like:

int *p;
void f(float *q) {
  float(* [[attr([])]] p);
  p = q; // check we disambiguated as a declaration not an expression
}
789

Because SkipUntil handles nested parens, this does the right thing for __attribute__((...)). Agreed on test coverage :)

811–813

We're missing _Atomic from this list. Eg:

void f() {
  int (*_Atomic p);
}

... is incorrectly disambiguated as an expression.

aaron.ballman added inline comments.Feb 23 2020, 11:24 AM
clang/lib/Parse/ParseTentative.cpp
773

Okay, that's a good point. Thanks!

789

I'll update the docs for SkipUntil(), because they don't suggest that this magic takes place. :-)

Tests for __attribute__(()) syntax + attribute arguments + fix for _Atomic qualifier.

michele.scandale retitled this revision from [Parse] Consider attributes in `TryParsePtrOperatorSeq`. to [Parse] Fix `TryParsePtrOperatorSeq`..Feb 23 2020, 11:28 PM
michele.scandale edited the summary of this revision. (Show Details)
michele.scandale edited the summary of this revision. (Show Details)Feb 23 2020, 11:30 PM
aaron.ballman accepted this revision.Feb 24 2020, 4:52 AM

Thank you for the new tests and drive-by fix for _Atomic! LGTM

aaron.ballman closed this revision.Feb 24 2020, 5:10 AM

Thank you for the patch -- I've commit on your behalf in bd5b22070b6984d89c13b6cf38c3e54fc98ce291