[clang] bd5b220 - Fix TryParsePtrOperatorSeq.
Aaron Ballman via cfe-commits
cfe-commits at lists.llvm.org
Mon Feb 24 05:08:56 PST 2020
Author: Michele Scandale
Date: 2020-02-24T08:08:47-05:00
New Revision: bd5b22070b6984d89c13b6cf38c3e54fc98ce291
URL: https://github.com/llvm/llvm-project/commit/bd5b22070b6984d89c13b6cf38c3e54fc98ce291
DIFF: https://github.com/llvm/llvm-project/commit/bd5b22070b6984d89c13b6cf38c3e54fc98ce291.diff
LOG: Fix TryParsePtrOperatorSeq.
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.
Added:
Modified:
clang/include/clang/Parse/Parser.h
clang/lib/Parse/ParseTentative.cpp
clang/test/CXX/dcl.decl/p4-0x.cpp
clang/test/Parser/cxx-ambig-decl-expr.cpp
clang/test/Parser/cxx-attributes.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index 879c7fdf682d..8802bf9bb90a 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -2442,6 +2442,10 @@ class Parser : public CodeCompletionHandler {
TPResult TryParseBracketDeclarator();
TPResult TryConsumeDeclarationSpecifier();
+ /// Try to skip a possibly empty sequence of 'attribute-specifier's without
+ /// full validation of the syntactic structure of attributes.
+ bool TrySkipAttributes();
+
public:
TypeResult ParseTypeName(SourceRange *Range = nullptr,
DeclaratorContext Context
diff --git a/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp
index ad0a15b0c8a6..75cc7c2912b5 100644
--- a/clang/lib/Parse/ParseTentative.cpp
+++ b/clang/lib/Parse/ParseTentative.cpp
@@ -186,21 +186,8 @@ Parser::TPResult Parser::TryConsumeDeclarationSpecifier() {
ConsumeToken();
// Skip attributes.
- while (Tok.isOneOf(tok::l_square, tok::kw___attribute, tok::kw___declspec,
- tok::kw_alignas)) {
- if (Tok.is(tok::l_square)) {
- ConsumeBracket();
- if (!SkipUntil(tok::r_square))
- return TPResult::Error;
- } else {
- ConsumeToken();
- if (Tok.isNot(tok::l_paren))
- return TPResult::Error;
- ConsumeParen();
- if (!SkipUntil(tok::r_paren))
- return TPResult::Error;
- }
- }
+ if (!TrySkipAttributes())
+ return TPResult::Error;
if (TryAnnotateOptionalCXXScopeToken())
return TPResult::Error;
@@ -781,6 +768,32 @@ Parser::isCXX11AttributeSpecifier(bool Disambiguate,
return CAK_NotAttributeSpecifier;
}
+bool Parser::TrySkipAttributes() {
+ while (Tok.isOneOf(tok::l_square, tok::kw___attribute, tok::kw___declspec,
+ tok::kw_alignas)) {
+ if (Tok.is(tok::l_square)) {
+ ConsumeBracket();
+ if (Tok.isNot(tok::l_square))
+ return false;
+ ConsumeBracket();
+ if (!SkipUntil(tok::r_square) || Tok.isNot(tok::r_square))
+ return false;
+ // Note that explicitly checking for `[[` and `]]` allows to fail as
+ // expected in the case of the Objective-C message send syntax.
+ ConsumeBracket();
+ } else {
+ ConsumeToken();
+ if (Tok.isNot(tok::l_paren))
+ return false;
+ ConsumeParen();
+ if (!SkipUntil(tok::r_paren))
+ return false;
+ }
+ }
+
+ return true;
+}
+
Parser::TPResult Parser::TryParsePtrOperatorSeq() {
while (true) {
if (TryAnnotateOptionalCXXScopeToken(true))
@@ -790,9 +803,14 @@ Parser::TPResult Parser::TryParsePtrOperatorSeq() {
(Tok.is(tok::annot_cxxscope) && NextToken().is(tok::star))) {
// ptr-operator
ConsumeAnyToken();
+
+ // Skip attributes.
+ if (!TrySkipAttributes())
+ return TPResult::Error;
+
while (Tok.isOneOf(tok::kw_const, tok::kw_volatile, tok::kw_restrict,
tok::kw__Nonnull, tok::kw__Nullable,
- tok::kw__Null_unspecified))
+ tok::kw__Null_unspecified, tok::kw__Atomic))
ConsumeToken();
} else {
return TPResult::True;
diff --git a/clang/test/CXX/dcl.decl/p4-0x.cpp b/clang/test/CXX/dcl.decl/p4-0x.cpp
index 35177a038697..3a7b21568044 100644
--- a/clang/test/CXX/dcl.decl/p4-0x.cpp
+++ b/clang/test/CXX/dcl.decl/p4-0x.cpp
@@ -1,5 +1,4 @@
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
-// expected-no-diagnostics
struct X {
void f() &;
@@ -7,3 +6,15 @@ struct X {
};
void (X::*pmf)() & = &X::f;
+
+void fn() {
+ void (*[[attr]] fn_ptr)() = &fn; // expected-warning{{unknown attribute 'attr' ignored}}
+ void (*[[attrA]] *[[attrB]] fn_ptr_ptr)() = &fn_ptr; // expected-warning{{unknown attribute 'attrA' ignored}} expected-warning{{unknown attribute 'attrB' ignored}}
+
+ void (&[[attr]] fn_lref)() = fn; // expected-warning{{unknown attribute 'attr' ignored}}
+ void (&&[[attr]] fn_rref)() = fn; // expected-warning{{unknown attribute 'attr' ignored}}
+
+ int i[5];
+ int (*[[attr(i[1])]] pi); // expected-warning{{unknown attribute 'attr' ignored}}
+ pi = &i[0];
+}
diff --git a/clang/test/Parser/cxx-ambig-decl-expr.cpp b/clang/test/Parser/cxx-ambig-decl-expr.cpp
index 02857e21f7c3..6203db2fbd22 100644
--- a/clang/test/Parser/cxx-ambig-decl-expr.cpp
+++ b/clang/test/Parser/cxx-ambig-decl-expr.cpp
@@ -38,4 +38,7 @@ void arr() {
// These are array declarations.
int(x[(1,1)]); // expected-error {{redefinition}}
int(x[true ? 1,1 : 1]); // expected-error {{redefinition}}
+
+ int (*_Atomic atomic_ptr_to_int);
+ *atomic_ptr_to_int = 42;
}
diff --git a/clang/test/Parser/cxx-attributes.cpp b/clang/test/Parser/cxx-attributes.cpp
index 6591532a91a2..53b098b6260a 100644
--- a/clang/test/Parser/cxx-attributes.cpp
+++ b/clang/test/Parser/cxx-attributes.cpp
@@ -22,3 +22,15 @@ namespace PR17666 {
}
__attribute((typename)) int x; // expected-warning {{unknown attribute 'typename' ignored}}
+
+void fn() {
+ void (*__attribute__((attr)) fn_ptr)() = &fn; // expected-warning{{unknown attribute 'attr' ignored}}
+ void (*__attribute__((attrA)) *__attribute__((attrB)) fn_ptr_ptr)() = &fn_ptr; // expected-warning{{unknown attribute 'attrA' ignored}} expected-warning{{unknown attribute 'attrB' ignored}}
+
+ void (&__attribute__((attr)) fn_lref)() = fn; // expected-warning{{unknown attribute 'attr' ignored}}
+ void (&&__attribute__((attr)) fn_rref)() = fn; // expected-warning{{unknown attribute 'attr' ignored}}
+
+ int i[5];
+ int (*__attribute__((attr(i[1]))) pi); // expected-warning{{unknown attribute 'attr' ignored}}
+ pi = &i[0];
+}
More information about the cfe-commits
mailing list