Skip to content

Commit 74eff80

Browse files
committed
Merge from 'sycl' to 'sycl-web' (#5)
Merged to sycl-web with no conflict or build issue
2 parents 2c97528 + c9d71d4 commit 74eff80

File tree

17 files changed

+794
-140
lines changed

17 files changed

+794
-140
lines changed

clang/include/clang/Basic/Attr.td

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1383,8 +1383,10 @@ def OpenCLUnrollHint : InheritableAttr {
13831383
let Documentation = [OpenCLUnrollHintDocs];
13841384
}
13851385

1386-
def LoopUnrollHint : InheritableAttr {
1386+
def LoopUnrollHint : StmtAttr {
13871387
let Spellings = [CXX11<"clang","loop_unroll">];
1388+
let Subjects = SubjectList<[ForStmt, CXXForRangeStmt, WhileStmt, DoStmt],
1389+
ErrorDiag, "'for', 'while', and 'do' statements">;
13881390
let Args = [ExprArgument<"UnrollHintExpr">];
13891391
let LangOpts = [SYCLIsDevice, SYCLIsHost];
13901392
let HasCustomTypeTransform = 1;
@@ -1802,9 +1804,11 @@ def Mode : Attr {
18021804
let PragmaAttributeSupport = 0;
18031805
}
18041806

1805-
def SYCLIntelFPGAIVDep : Attr {
1807+
def SYCLIntelFPGAIVDep : StmtAttr {
18061808
let Spellings = [CXX11<"intelfpga","ivdep">,
18071809
CXX11<"intel","ivdep">];
1810+
let Subjects = SubjectList<[ForStmt, CXXForRangeStmt, WhileStmt, DoStmt],
1811+
ErrorDiag, "'for', 'while', and 'do' statements">;
18081812
let Args = [
18091813
ExprArgument<"SafelenExpr">, ExprArgument<"ArrayExpr">,
18101814
UnsignedArgument<"SafelenValue">
@@ -1850,58 +1854,72 @@ def SYCLIntelFPGAInitiationInterval : StmtAttr {
18501854
let Spellings = [CXX11<"intelfpga","ii">,
18511855
CXX11<"intel","ii">,
18521856
CXX11<"intel", "initiation_interval">];
1857+
let Subjects = SubjectList<[ForStmt, CXXForRangeStmt, WhileStmt, DoStmt],
1858+
ErrorDiag, "'for', 'while', and 'do' statements">;
18531859
let Args = [ExprArgument<"IntervalExpr">];
18541860
let LangOpts = [SYCLIsDevice, SYCLIsHost];
18551861
let HasCustomTypeTransform = 1;
18561862
let Documentation = [SYCLIntelFPGAInitiationIntervalAttrDocs];
18571863
}
18581864

1859-
def SYCLIntelFPGAMaxConcurrency : Attr {
1865+
def SYCLIntelFPGAMaxConcurrency : StmtAttr {
18601866
let Spellings = [CXX11<"intelfpga","max_concurrency">,
18611867
CXX11<"intel","max_concurrency">];
1868+
let Subjects = SubjectList<[ForStmt, CXXForRangeStmt, WhileStmt, DoStmt],
1869+
ErrorDiag, "'for', 'while', and 'do' statements">;
18621870
let Args = [ExprArgument<"NThreadsExpr">];
18631871
let LangOpts = [SYCLIsDevice, SYCLIsHost];
18641872
let HasCustomTypeTransform = 1;
18651873
let Documentation = [SYCLIntelFPGAMaxConcurrencyAttrDocs];
18661874
}
18671875

1868-
def SYCLIntelFPGALoopCoalesce : Attr {
1876+
def SYCLIntelFPGALoopCoalesce : StmtAttr {
18691877
let Spellings = [CXX11<"intelfpga","loop_coalesce">,
18701878
CXX11<"intel","loop_coalesce">];
1879+
let Subjects = SubjectList<[ForStmt, CXXForRangeStmt, WhileStmt, DoStmt],
1880+
ErrorDiag, "'for', 'while', and 'do' statements">;
18711881
let Args = [ExprArgument<"NExpr">];
18721882
let LangOpts = [SYCLIsDevice, SYCLIsHost];
18731883
let HasCustomTypeTransform = 1;
18741884
let Documentation = [SYCLIntelFPGALoopCoalesceAttrDocs];
18751885
}
18761886

1877-
def SYCLIntelFPGADisableLoopPipelining : Attr {
1887+
def SYCLIntelFPGADisableLoopPipelining : StmtAttr {
18781888
let Spellings = [CXX11<"intelfpga","disable_loop_pipelining">,
18791889
CXX11<"intel","disable_loop_pipelining">];
1890+
let Subjects = SubjectList<[ForStmt, CXXForRangeStmt, WhileStmt, DoStmt],
1891+
ErrorDiag, "'for', 'while', and 'do' statements">;
18801892
let LangOpts = [SYCLIsDevice, SYCLIsHost];
18811893
let HasCustomTypeTransform = 1;
18821894
let Documentation = [SYCLIntelFPGADisableLoopPipeliningAttrDocs];
18831895
}
18841896

1885-
def SYCLIntelFPGAMaxInterleaving : Attr {
1897+
def SYCLIntelFPGAMaxInterleaving : StmtAttr {
18861898
let Spellings = [CXX11<"intelfpga","max_interleaving">,
18871899
CXX11<"intel","max_interleaving">];
1900+
let Subjects = SubjectList<[ForStmt, CXXForRangeStmt, WhileStmt, DoStmt],
1901+
ErrorDiag, "'for', 'while', and 'do' statements">;
18881902
let Args = [ExprArgument<"NExpr">];
18891903
let LangOpts = [SYCLIsDevice, SYCLIsHost];
18901904
let HasCustomTypeTransform = 1;
18911905
let Documentation = [SYCLIntelFPGAMaxInterleavingAttrDocs];
18921906
}
18931907

1894-
def SYCLIntelFPGASpeculatedIterations : Attr {
1908+
def SYCLIntelFPGASpeculatedIterations : StmtAttr {
18951909
let Spellings = [CXX11<"intelfpga","speculated_iterations">,
18961910
CXX11<"intel","speculated_iterations">];
1911+
let Subjects = SubjectList<[ForStmt, CXXForRangeStmt, WhileStmt, DoStmt],
1912+
ErrorDiag, "'for', 'while', and 'do' statements">;
18971913
let Args = [ExprArgument<"NExpr">];
18981914
let LangOpts = [SYCLIsDevice, SYCLIsHost];
18991915
let HasCustomTypeTransform = 1;
19001916
let Documentation = [SYCLIntelFPGASpeculatedIterationsAttrDocs];
19011917
}
19021918

1903-
def SYCLIntelFPGANofusion : Attr {
1919+
def SYCLIntelFPGANofusion : StmtAttr {
19041920
let Spellings = [CXX11<"intel","nofusion">];
1921+
let Subjects = SubjectList<[ForStmt, CXXForRangeStmt, WhileStmt, DoStmt],
1922+
ErrorDiag, "'for', 'while', and 'do' statements">;
19051923
let LangOpts = [SYCLIsDevice, SYCLIsHost];
19061924
let HasCustomTypeTransform = 1;
19071925
let Documentation = [SYCLIntelFPGANofusionAttrDocs];

clang/include/clang/Basic/DiagnosticParseKinds.td

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1433,12 +1433,6 @@ def err_pragma_cannot_end_force_cuda_host_device : Error<
14331433
"force_cuda_host_device begin">;
14341434
} // end of Parse Issue category.
14351435

1436-
// SYCL loop pragmas and attributes support
1437-
// * Intel FPGA attribute ivdep, ii, max_concurrency support
1438-
// * clang::loop_unroll attribute support
1439-
def err_loop_attr_on_non_loop : Error<
1440-
"%select{clang|intelfpga}0 loop attributes must be applied to for, while, or do statements">;
1441-
14421436
let CategoryName = "Modules Issue" in {
14431437
def err_unexpected_module_decl : Error<
14441438
"module declaration can only appear at the top level">;

clang/include/clang/Parse/Parser.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2834,14 +2834,6 @@ class Parser : public CodeCompletionHandler {
28342834
/// \return false if error happens.
28352835
bool ParseOpenCLUnrollHintAttribute(ParsedAttributes &Attrs);
28362836

2837-
/// Parses intelfpga:: and clang:: loop attributes if the language is SYCL
2838-
bool MaybeParseSYCLLoopAttributes(ParsedAttributes &Attrs) {
2839-
if (getLangOpts().SYCLIsDevice || getLangOpts().SYCLIsHost)
2840-
return ParseSYCLLoopAttributes(Attrs);
2841-
return true;
2842-
}
2843-
bool ParseSYCLLoopAttributes(ParsedAttributes &Attrs);
2844-
28452837
void ParseNullabilityTypeSpecifiers(ParsedAttributes &attrs);
28462838
VersionTuple ParseVersionTuple(SourceRange &Range);
28472839
void ParseAvailabilityAttribute(IdentifierInfo &Availability,

clang/lib/Parse/ParseStmt.cpp

Lines changed: 1 addition & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,7 @@ Parser::ParseStatementOrDeclaration(StmtVector &Stmts,
100100

101101
ParsedAttributesWithRange Attrs(AttrFactory);
102102
MaybeParseCXX11Attributes(Attrs, nullptr, /*MightBeObjCMessageSend*/ true);
103-
if (!MaybeParseOpenCLUnrollHintAttribute(Attrs) ||
104-
!MaybeParseSYCLLoopAttributes(Attrs))
103+
if (!MaybeParseOpenCLUnrollHintAttribute(Attrs))
105104
return StmtError();
106105

107106
StmtResult Res = ParseStatementOrDeclarationAfterAttributes(
@@ -2565,32 +2564,3 @@ bool Parser::ParseOpenCLUnrollHintAttribute(ParsedAttributes &Attrs) {
25652564
}
25662565
return true;
25672566
}
2568-
2569-
bool Parser::ParseSYCLLoopAttributes(ParsedAttributes &Attrs) {
2570-
MaybeParseCXX11Attributes(Attrs);
2571-
2572-
if (Attrs.empty())
2573-
return true;
2574-
2575-
if (Attrs.begin()->getKind() != ParsedAttr::AT_SYCLIntelFPGAIVDep &&
2576-
Attrs.begin()->getKind() !=
2577-
ParsedAttr::AT_SYCLIntelFPGAInitiationInterval &&
2578-
Attrs.begin()->getKind() != ParsedAttr::AT_SYCLIntelFPGAMaxConcurrency &&
2579-
Attrs.begin()->getKind() != ParsedAttr::AT_SYCLIntelFPGALoopCoalesce &&
2580-
Attrs.begin()->getKind() !=
2581-
ParsedAttr::AT_SYCLIntelFPGADisableLoopPipelining &&
2582-
Attrs.begin()->getKind() != ParsedAttr::AT_SYCLIntelFPGAMaxInterleaving &&
2583-
Attrs.begin()->getKind() !=
2584-
ParsedAttr::AT_SYCLIntelFPGASpeculatedIterations &&
2585-
Attrs.begin()->getKind() != ParsedAttr::AT_LoopUnrollHint &&
2586-
Attrs.begin()->getKind() != ParsedAttr::AT_SYCLIntelFPGANofusion)
2587-
return true;
2588-
2589-
bool IsIntelFPGAAttribute = (Attrs.begin()->getKind() != ParsedAttr::AT_LoopUnrollHint);
2590-
2591-
if (!(Tok.is(tok::kw_for) || Tok.is(tok::kw_while) || Tok.is(tok::kw_do))) {
2592-
Diag(Tok, diag::err_loop_attr_on_non_loop) << IsIntelFPGAAttribute;
2593-
return false;
2594-
}
2595-
return true;
2596-
}

clang/lib/Sema/SemaStmtAttr.cpp

Lines changed: 50 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,16 @@ static Attr *handleSuppressAttr(Sema &S, Stmt *St, const ParsedAttr &A,
7676
}
7777

7878
template <typename FPGALoopAttrT>
79-
static Attr *handleIntelFPGALoopAttr(Sema &S, const ParsedAttr &A) {
79+
static Attr *handleIntelFPGALoopAttr(Sema &S, Stmt *St, const ParsedAttr &A) {
8080
if(S.LangOpts.SYCLIsHost)
8181
return nullptr;
8282

83+
if (!isa<ForStmt, CXXForRangeStmt, DoStmt, WhileStmt>(St)) {
84+
S.Diag(A.getLoc(), diag::err_attribute_wrong_decl_type_str)
85+
<< A << "'for', 'while', and 'do' statements";
86+
return nullptr;
87+
}
88+
8389
unsigned NumArgs = A.getNumArgs();
8490
if (NumArgs > 1) {
8591
S.Diag(A.getLoc(), diag::warn_attribute_too_many_arguments) << A << 1;
@@ -104,10 +110,16 @@ static Attr *handleIntelFPGALoopAttr(Sema &S, const ParsedAttr &A) {
104110

105111
template <>
106112
Attr *handleIntelFPGALoopAttr<SYCLIntelFPGADisableLoopPipeliningAttr>(
107-
Sema &S, const ParsedAttr &A) {
113+
Sema &S, Stmt *St, const ParsedAttr &A) {
108114
if (S.LangOpts.SYCLIsHost)
109115
return nullptr;
110116

117+
if (!isa<ForStmt, CXXForRangeStmt, DoStmt, WhileStmt>(St)) {
118+
S.Diag(A.getLoc(), diag::err_attribute_wrong_decl_type_str)
119+
<< A << "'for', 'while', and 'do' statements";
120+
return nullptr;
121+
}
122+
111123
unsigned NumArgs = A.getNumArgs();
112124
if (NumArgs > 0) {
113125
S.Diag(A.getLoc(), diag::warn_attribute_too_many_arguments) << A << 0;
@@ -270,7 +282,13 @@ CheckRedundantSYCLIntelFPGAIVDepAttrs(Sema &S, ArrayRef<const Attr *> Attrs) {
270282
}
271283
}
272284

273-
static Attr *handleIntelFPGAIVDepAttr(Sema &S, const ParsedAttr &A) {
285+
static Attr *handleIntelFPGAIVDepAttr(Sema &S, Stmt *St, const ParsedAttr &A) {
286+
if (!isa<ForStmt, CXXForRangeStmt, DoStmt, WhileStmt>(St)) {
287+
S.Diag(A.getLoc(), diag::err_attribute_wrong_decl_type_str)
288+
<< A << "'for', 'while', and 'do' statements";
289+
return nullptr;
290+
}
291+
274292
unsigned NumArgs = A.getNumArgs();
275293
if (NumArgs > 2) {
276294
S.Diag(A.getLoc(), diag::err_attribute_too_many_arguments) << A << 2;
@@ -284,10 +302,17 @@ static Attr *handleIntelFPGAIVDepAttr(Sema &S, const ParsedAttr &A) {
284302
NumArgs == 2 ? A.getArgAsExpr(1) : nullptr);
285303
}
286304

287-
static Attr *handleIntelFPGANofusionAttr(Sema &S, const ParsedAttr &A) {
305+
static Attr *handleIntelFPGANofusionAttr(Sema &S, Stmt *St,
306+
const ParsedAttr &A) {
288307
if (S.LangOpts.SYCLIsHost)
289308
return nullptr;
290309

310+
if (!isa<ForStmt, CXXForRangeStmt, DoStmt, WhileStmt>(St)) {
311+
S.Diag(A.getLoc(), diag::err_attribute_wrong_decl_type_str)
312+
<< A << "'for', 'while', and 'do' statements";
313+
return nullptr;
314+
}
315+
291316
unsigned NumArgs = A.getNumArgs();
292317
if (NumArgs > 0) {
293318
S.Diag(A.getLoc(), diag::warn_attribute_too_many_arguments) << A << 0;
@@ -751,8 +776,17 @@ static Attr *handleLoopUnrollHint(Sema &S, Stmt *St, const ParsedAttr &A,
751776
Expr *E = NumArgs ? A.getArgAsExpr(0) : nullptr;
752777
if (A.getParsedKind() == ParsedAttr::AT_OpenCLUnrollHint)
753778
return S.BuildOpenCLLoopUnrollHintAttr(A, E);
754-
else if (A.getParsedKind() == ParsedAttr::AT_LoopUnrollHint)
779+
else if (A.getParsedKind() == ParsedAttr::AT_LoopUnrollHint) {
780+
// FIXME: this should be hoisted up to the top level, but can't be placed
781+
// there until the opencl attribute has its parsing error converted into a
782+
// semantic error. See: Parser::ParseOpenCLUnrollHintAttribute().
783+
if (!isa<ForStmt, CXXForRangeStmt, DoStmt, WhileStmt>(St)) {
784+
S.Diag(A.getLoc(), diag::err_attribute_wrong_decl_type_str)
785+
<< A << "'for', 'while', and 'do' statements";
786+
return nullptr;
787+
}
755788
return S.BuildLoopUnrollHintAttr(A, E);
789+
}
756790

757791
return nullptr;
758792
}
@@ -771,20 +805,22 @@ static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const ParsedAttr &A,
771805
case ParsedAttr::AT_LoopHint:
772806
return handleLoopHintAttr(S, St, A, Range);
773807
case ParsedAttr::AT_SYCLIntelFPGAIVDep:
774-
return handleIntelFPGAIVDepAttr(S, A);
808+
return handleIntelFPGAIVDepAttr(S, St, A);
775809
case ParsedAttr::AT_SYCLIntelFPGAInitiationInterval:
776-
return handleIntelFPGALoopAttr<SYCLIntelFPGAInitiationIntervalAttr>(S, A);
810+
return handleIntelFPGALoopAttr<SYCLIntelFPGAInitiationIntervalAttr>(S, St,
811+
A);
777812
case ParsedAttr::AT_SYCLIntelFPGAMaxConcurrency:
778-
return handleIntelFPGALoopAttr<SYCLIntelFPGAMaxConcurrencyAttr>(S, A);
813+
return handleIntelFPGALoopAttr<SYCLIntelFPGAMaxConcurrencyAttr>(S, St, A);
779814
case ParsedAttr::AT_SYCLIntelFPGALoopCoalesce:
780-
return handleIntelFPGALoopAttr<SYCLIntelFPGALoopCoalesceAttr>(S, A);
815+
return handleIntelFPGALoopAttr<SYCLIntelFPGALoopCoalesceAttr>(S, St, A);
781816
case ParsedAttr::AT_SYCLIntelFPGADisableLoopPipelining:
782-
return handleIntelFPGALoopAttr<SYCLIntelFPGADisableLoopPipeliningAttr>(S,
783-
A);
817+
return handleIntelFPGALoopAttr<SYCLIntelFPGADisableLoopPipeliningAttr>(
818+
S, St, A);
784819
case ParsedAttr::AT_SYCLIntelFPGAMaxInterleaving:
785-
return handleIntelFPGALoopAttr<SYCLIntelFPGAMaxInterleavingAttr>(S, A);
820+
return handleIntelFPGALoopAttr<SYCLIntelFPGAMaxInterleavingAttr>(S, St, A);
786821
case ParsedAttr::AT_SYCLIntelFPGASpeculatedIterations:
787-
return handleIntelFPGALoopAttr<SYCLIntelFPGASpeculatedIterationsAttr>(S, A);
822+
return handleIntelFPGALoopAttr<SYCLIntelFPGASpeculatedIterationsAttr>(S, St,
823+
A);
788824
case ParsedAttr::AT_OpenCLUnrollHint:
789825
case ParsedAttr::AT_LoopUnrollHint:
790826
return handleLoopUnrollHint(S, St, A, Range);
@@ -797,7 +833,7 @@ static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const ParsedAttr &A,
797833
case ParsedAttr::AT_Unlikely:
798834
return handleUnlikely(S, St, A, Range);
799835
case ParsedAttr::AT_SYCLIntelFPGANofusion:
800-
return handleIntelFPGANofusionAttr(S, A);
836+
return handleIntelFPGANofusionAttr(S, St, A);
801837
default:
802838
// if we're here, then we parsed a known attribute, but didn't recognize
803839
// it as a statement attribute => it is declaration attribute

clang/test/SemaSYCL/intel-fpga-loops.cpp

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,21 @@
22

33
// Test for Intel FPGA loop attributes applied not to a loop
44
void foo() {
5-
// expected-error@+1 {{intelfpga loop attributes must be applied to for, while, or do statements}}
5+
// expected-error@+1 {{'ivdep' attribute only applies to 'for', 'while', and 'do' statements}}
66
[[intel::ivdep]] int a[10];
7-
// expected-error@+1 {{intelfpga loop attributes must be applied to for, while, or do statements}}
8-
[[intel::ivdep(2)]] int b[10];
9-
// expected-error@+1 {{intelfpga loop attributes must be applied to for, while, or do statements}}
7+
// expected-error@+1 {{'initiation_interval' attribute only applies to 'for', 'while', and 'do' statements}}
108
[[intel::initiation_interval(2)]] int c[10];
11-
// expected-error@+1 {{intelfpga loop attributes must be applied to for, while, or do statements}}
9+
// expected-error@+1 {{'max_concurrency' attribute only applies to 'for', 'while', and 'do' statements}}
1210
[[intel::max_concurrency(2)]] int d[10];
13-
14-
int arr[10];
15-
// expected-error@+1 {{intelfpga loop attributes must be applied to for, while, or do statements}}
16-
[[intel::ivdep(arr)]] int e[10];
17-
// expected-error@+1 {{intelfpga loop attributes must be applied to for, while, or do statements}}
18-
[[intel::ivdep(arr, 2)]] int f[10];
19-
20-
// expected-error@+1 {{intelfpga loop attributes must be applied to for, while, or do statements}}
11+
// expected-error@+1 {{'disable_loop_pipelining' attribute only applies to 'for', 'while', and 'do' statements}}
2112
[[intel::disable_loop_pipelining]] int g[10];
22-
// expected-error@+1 {{intelfpga loop attributes must be applied to for, while, or do statements}}
13+
// expected-error@+1 {{'loop_coalesce' attribute only applies to 'for', 'while', and 'do' statements}}
2314
[[intel::loop_coalesce(2)]] int h[10];
24-
// expected-error@+1 {{intelfpga loop attributes must be applied to for, while, or do statements}}
15+
// expected-error@+1 {{'max_interleaving' attribute only applies to 'for', 'while', and 'do' statements}}
2516
[[intel::max_interleaving(4)]] int i[10];
26-
// expected-error@+1 {{intelfpga loop attributes must be applied to for, while, or do statements}}
17+
// expected-error@+1 {{'speculated_iterations' attribute only applies to 'for', 'while', and 'do' statements}}
2718
[[intel::speculated_iterations(6)]] int j[10];
28-
// expected-error@+1 {{intelfpga loop attributes must be applied to for, while, or do statements}}
19+
// expected-error@+1 {{'nofusion' attribute only applies to 'for', 'while', and 'do' statements}}
2920
[[intel::nofusion]] int k[10];
3021
}
3122

@@ -426,3 +417,14 @@ int main() {
426417
});
427418
return 0;
428419
}
420+
421+
void parse_order_error() {
422+
// We had a bug where we would only look at the first attribute in the group
423+
// when trying to determine whether to diagnose the loop attributes on an
424+
// incorrect subject. Test that we properly catch this situation.
425+
[[clang::nomerge, intel::max_concurrency(1)]] // expected-error {{'max_concurrency' attribute only applies to 'for', 'while', and 'do' statements}}
426+
if (1) { parse_order_error(); } // Recursive call silences unrelated diagnostic about nomerge.
427+
428+
[[clang::nomerge, intel::max_concurrency(1)]] // OK
429+
while (1) { parse_order_error(); } // Recursive call silences unrelated diagnostic about nomerge.
430+
}

clang/test/SemaSYCL/loop_unroll.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ void bar() {
88
}
99

1010
void foo() {
11-
// expected-error@+1 {{clang loop attributes must be applied to for, while, or do statements}}
11+
// expected-error@+1 {{'loop_unroll' attribute only applies to 'for', 'while', and 'do' statements}}
1212
[[clang::loop_unroll(8)]] int a[10];
1313

1414
// expected-error@+1 {{'loop_unroll' attribute takes no more than 1 argument}}

clang/utils/TableGen/ClangAttrEmitter.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3507,6 +3507,9 @@ static void GenerateCustomAppertainsTo(const Record &Subject, raw_ostream &OS) {
35073507
}
35083508

35093509
static void GenerateAppertainsTo(const Record &Attr, raw_ostream &OS) {
3510+
// FIXME: this function only diagnoses declaration attributes and lacks
3511+
// reasonable support for statement attributes.
3512+
35103513
// If the attribute does not contain a Subjects definition, then use the
35113514
// default appertainsTo logic.
35123515
if (Attr.isValueUnset("Subjects"))
@@ -3538,7 +3541,16 @@ static void GenerateAppertainsTo(const Record &Attr, raw_ostream &OS) {
35383541
// because it requires the subject to be of a specific type, and were that
35393542
// information inlined here, it would not support an attribute with multiple
35403543
// custom subjects.
3541-
if ((*I)->isSubClassOf("SubsetSubject")) {
3544+
//
3545+
// If the subject is a statement rather than a declaration node, use 'true'
3546+
// as the test so that statement nodes can be mixed with declaration nodes
3547+
// for attributes which appertain to both statements and declarations. If
3548+
// all of the nodes are statement nodes (so the diagnostic predicate is
3549+
// trivially true), this will diagnose the use of the attribute on any
3550+
// declaration, which is reasonable.
3551+
if ((*I)->isSubClassOf("StmtNode")) {
3552+
OS << "true";
3553+
} else if ((*I)->isSubClassOf("SubsetSubject")) {
35423554
OS << "!" << functionNameForCustomAppertainsTo(**I) << "(D)";
35433555
} else {
35443556
OS << "!isa<" << GetSubjectWithSuffix(*I) << ">(D)";

0 commit comments

Comments
 (0)