forked from OSchip/llvm-project
Allow GNU-style attributes on lambda expressions.
llvm-svn: 203628
This commit is contained in:
parent
5876656c5e
commit
e8d69b7fc9
|
@ -995,7 +995,6 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
|
||||||
ParsedAttributes Attr(AttrFactory);
|
ParsedAttributes Attr(AttrFactory);
|
||||||
SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo;
|
SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo;
|
||||||
SourceLocation EllipsisLoc;
|
SourceLocation EllipsisLoc;
|
||||||
|
|
||||||
|
|
||||||
if (Tok.isNot(tok::r_paren)) {
|
if (Tok.isNot(tok::r_paren)) {
|
||||||
Actions.RecordParsingTemplateParameterDepth(TemplateParameterDepth);
|
Actions.RecordParsingTemplateParameterDepth(TemplateParameterDepth);
|
||||||
|
@ -1009,6 +1008,10 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
|
||||||
SourceLocation RParenLoc = T.getCloseLocation();
|
SourceLocation RParenLoc = T.getCloseLocation();
|
||||||
DeclEndLoc = RParenLoc;
|
DeclEndLoc = RParenLoc;
|
||||||
|
|
||||||
|
// GNU-style attributes must be parsed before the mutable specifier to be
|
||||||
|
// compatible with GCC.
|
||||||
|
MaybeParseGNUAttributes(Attr, &DeclEndLoc);
|
||||||
|
|
||||||
// Parse 'mutable'[opt].
|
// Parse 'mutable'[opt].
|
||||||
SourceLocation MutableLoc;
|
SourceLocation MutableLoc;
|
||||||
if (TryConsumeToken(tok::kw_mutable, MutableLoc))
|
if (TryConsumeToken(tok::kw_mutable, MutableLoc))
|
||||||
|
@ -1067,6 +1070,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
|
||||||
TrailingReturnType),
|
TrailingReturnType),
|
||||||
Attr, DeclEndLoc);
|
Attr, DeclEndLoc);
|
||||||
} else if (Tok.is(tok::kw_mutable) || Tok.is(tok::arrow) ||
|
} else if (Tok.is(tok::kw_mutable) || Tok.is(tok::arrow) ||
|
||||||
|
Tok.is(tok::kw___attribute) ||
|
||||||
(Tok.is(tok::l_square) && NextToken().is(tok::l_square))) {
|
(Tok.is(tok::l_square) && NextToken().is(tok::l_square))) {
|
||||||
// It's common to forget that one needs '()' before 'mutable', an attribute
|
// It's common to forget that one needs '()' before 'mutable', an attribute
|
||||||
// specifier, or the result type. Deal with this.
|
// specifier, or the result type. Deal with this.
|
||||||
|
@ -1074,6 +1078,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
|
||||||
switch (Tok.getKind()) {
|
switch (Tok.getKind()) {
|
||||||
case tok::kw_mutable: TokKind = 0; break;
|
case tok::kw_mutable: TokKind = 0; break;
|
||||||
case tok::arrow: TokKind = 1; break;
|
case tok::arrow: TokKind = 1; break;
|
||||||
|
case tok::kw___attribute:
|
||||||
case tok::l_square: TokKind = 2; break;
|
case tok::l_square: TokKind = 2; break;
|
||||||
default: llvm_unreachable("Unknown token kind");
|
default: llvm_unreachable("Unknown token kind");
|
||||||
}
|
}
|
||||||
|
@ -1083,7 +1088,12 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
|
||||||
<< FixItHint::CreateInsertion(Tok.getLocation(), "() ");
|
<< FixItHint::CreateInsertion(Tok.getLocation(), "() ");
|
||||||
SourceLocation DeclLoc = Tok.getLocation();
|
SourceLocation DeclLoc = Tok.getLocation();
|
||||||
SourceLocation DeclEndLoc = DeclLoc;
|
SourceLocation DeclEndLoc = DeclLoc;
|
||||||
|
|
||||||
|
// GNU-style attributes must be parsed before the mutable specifier to be
|
||||||
|
// compatible with GCC.
|
||||||
|
ParsedAttributes Attr(AttrFactory);
|
||||||
|
MaybeParseGNUAttributes(Attr, &DeclEndLoc);
|
||||||
|
|
||||||
// Parse 'mutable', if it's there.
|
// Parse 'mutable', if it's there.
|
||||||
SourceLocation MutableLoc;
|
SourceLocation MutableLoc;
|
||||||
if (Tok.is(tok::kw_mutable)) {
|
if (Tok.is(tok::kw_mutable)) {
|
||||||
|
@ -1092,7 +1102,6 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse attribute-specifier[opt].
|
// Parse attribute-specifier[opt].
|
||||||
ParsedAttributes Attr(AttrFactory);
|
|
||||||
MaybeParseCXX11Attributes(Attr, &DeclEndLoc);
|
MaybeParseCXX11Attributes(Attr, &DeclEndLoc);
|
||||||
|
|
||||||
// Parse the return type, if there is one.
|
// Parse the return type, if there is one.
|
||||||
|
|
|
@ -114,3 +114,18 @@ extern "C" int printf(const char *format, ...);
|
||||||
int __attribute__((cdecl)) TestOne(void), TestTwo(void);
|
int __attribute__((cdecl)) TestOne(void), TestTwo(void);
|
||||||
// CHECK: FunctionDecl{{.*}}TestOne{{.*}}__attribute__((cdecl))
|
// CHECK: FunctionDecl{{.*}}TestOne{{.*}}__attribute__((cdecl))
|
||||||
// CHECK: FunctionDecl{{.*}}TestTwo{{.*}}__attribute__((cdecl))
|
// CHECK: FunctionDecl{{.*}}TestTwo{{.*}}__attribute__((cdecl))
|
||||||
|
|
||||||
|
void func() {
|
||||||
|
auto Test = []() __attribute__((no_thread_safety_analysis)) {};
|
||||||
|
// CHECK: CXXMethodDecl{{.*}}operator() 'void (void) const'
|
||||||
|
// CHECK: NoThreadSafetyAnalysisAttr
|
||||||
|
|
||||||
|
// Because GNU's noreturn applies to the function type, and this lambda does
|
||||||
|
// not have a capture list, the call operator and the function pointer
|
||||||
|
// conversion should both be noreturn, but the method should not contain a
|
||||||
|
// NoReturnAttr because the attribute applied to the type.
|
||||||
|
auto Test2 = []() __attribute__((noreturn)) { while(1); };
|
||||||
|
// CHECK: CXXMethodDecl{{.*}}operator() 'void (void) __attribute__((noreturn)) const'
|
||||||
|
// CHECK-NOT: NoReturnAttr
|
||||||
|
// CHECK: CXXConversionDecl{{.*}}operator void (*)() __attribute__((noreturn))
|
||||||
|
}
|
||||||
|
|
|
@ -67,6 +67,7 @@ class C {
|
||||||
|
|
||||||
void attributes() {
|
void attributes() {
|
||||||
[] [[]] {}; // expected-error {{lambda requires '()' before attribute specifier}}
|
[] [[]] {}; // expected-error {{lambda requires '()' before attribute specifier}}
|
||||||
|
[] __attribute__((noreturn)) {}; // expected-error {{lambda requires '()' before attribute specifier}}
|
||||||
[]() [[]]
|
[]() [[]]
|
||||||
mutable {}; // expected-error {{expected body of lambda expression}}
|
mutable {}; // expected-error {{expected body of lambda expression}}
|
||||||
|
|
||||||
|
@ -75,5 +76,10 @@ class C {
|
||||||
[]() mutable [[]] -> void {};
|
[]() mutable [[]] -> void {};
|
||||||
[]() mutable noexcept [[]] -> void {};
|
[]() mutable noexcept [[]] -> void {};
|
||||||
|
|
||||||
}
|
// Testing GNU-style attributes on lambdas -- the attribute is specified
|
||||||
|
// before the mutable specifier instead of after (unlike C++11).
|
||||||
|
[]() __attribute__((noreturn)) mutable { while(1); };
|
||||||
|
[]() mutable
|
||||||
|
__attribute__((noreturn)) { while(1); }; // expected-error {{expected body of lambda expression}}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue