1*de59f564SAaron Ballman // RUN: %clang_cc1 -std=c++17 -fopenmp -fopenmp-version=51 -fsyntax-only -verify %s
2*de59f564SAaron Ballman 
3*de59f564SAaron Ballman // This file tests the custom parsing logic for the OpenMP 5.1 attribute
4*de59f564SAaron Ballman // syntax. It does not test actual OpenMP directive syntax, just the attribute
5*de59f564SAaron Ballman // parsing bits.
6*de59f564SAaron Ballman 
7*de59f564SAaron Ballman // FIXME: the diagnostic here is a bit unsatisfying. We handle the custom omp
8*de59f564SAaron Ballman // attribute parsing logic when parsing the attribute argument list, and we
9*de59f564SAaron Ballman // only process an attribute argument list when we see an open paren after the
10*de59f564SAaron Ballman // attribute name. So this means we never hit the omp-specific parsing and
11*de59f564SAaron Ballman // instead handle this through the usual Sema attribute handling in
12*de59f564SAaron Ballman // SemaDeclAttr.cpp, which diagnoses this as an unknown attribute.
13*de59f564SAaron Ballman [[omp::directive]]; // expected-warning {{unknown attribute 'directive' ignored}}
14*de59f564SAaron Ballman [[omp::sequence]]; // expected-warning {{unknown attribute 'sequence' ignored}}
15*de59f564SAaron Ballman [[omp::unknown]]; // expected-warning {{unknown attribute 'unknown' ignored}}
16*de59f564SAaron Ballman 
17*de59f564SAaron Ballman [[omp::directive()]]; // expected-error {{expected an OpenMP directive}}
18*de59f564SAaron Ballman [[omp::sequence()]]; // expected-error {{expected an OpenMP 'directive' or 'sequence' attribute argument}}
19*de59f564SAaron Ballman 
20*de59f564SAaron Ballman // Both sequence and directive require an argument list, test that we diagnose
21*de59f564SAaron Ballman // when the inner directive or sequence is missing its argument list.
22*de59f564SAaron Ballman [[omp::sequence(directive)]]; // expected-error {{expected '('}}
23*de59f564SAaron Ballman [[omp::sequence(sequence)]]; // expected-error {{expected '('}}
24*de59f564SAaron Ballman [[omp::sequence(omp::directive)]]; // expected-error {{expected '('}}
25*de59f564SAaron Ballman [[omp::sequence(omp::sequence)]]; // expected-error {{expected '('}}
26*de59f564SAaron Ballman 
27*de59f564SAaron Ballman // All of the diagnostics here come from the inner sequence and directive not
28*de59f564SAaron Ballman // being given an argument, but this tests that we can parse either with or
29*de59f564SAaron Ballman // without the 'omp::'.
30*de59f564SAaron Ballman [[omp::sequence(directive(), sequence())]]; // expected-error {{expected an OpenMP directive}} expected-error {{expected an OpenMP 'directive' or 'sequence' attribute argument}}
31*de59f564SAaron Ballman [[omp::sequence(omp::directive(), sequence())]]; // expected-error {{expected an OpenMP directive}} expected-error {{expected an OpenMP 'directive' or 'sequence' attribute argument}}
32*de59f564SAaron Ballman [[omp::sequence(directive(), omp::sequence())]]; // expected-error {{expected an OpenMP directive}} expected-error {{expected an OpenMP 'directive' or 'sequence' attribute argument}}
33*de59f564SAaron Ballman [[omp::sequence(omp::directive(), omp::sequence())]]; // expected-error {{expected an OpenMP directive}} expected-error {{expected an OpenMP 'directive' or 'sequence' attribute argument}}
34*de59f564SAaron Ballman 
35*de59f564SAaron Ballman // Test that we properly diagnose missing parens within the inner arguments of
36*de59f564SAaron Ballman // a sequence attribute.
37*de59f564SAaron Ballman [[omp::sequence( // expected-note {{to match this '('}}
38*de59f564SAaron Ballman   directive(
39*de59f564SAaron Ballman )]]; // expected-error {{expected ')'}} expected-error {{expected an OpenMP directive}}
40*de59f564SAaron Ballman [[omp::sequence( // expected-note {{to match this '('}}
41*de59f564SAaron Ballman   sequence(
42*de59f564SAaron Ballman )]]; // expected-error {{expected ')'}} expected-error {{expected an OpenMP 'directive' or 'sequence' attribute argument}}
43*de59f564SAaron Ballman 
44*de59f564SAaron Ballman // Test that we properly handle the using attribute syntax.
45*de59f564SAaron Ballman [[using omp: directive()]]; // expected-error {{expected an OpenMP directive}}
46*de59f564SAaron Ballman [[using omp: sequence()]]; // expected-error {{expected an OpenMP 'directive' or 'sequence' attribute argument}}
47*de59f564SAaron Ballman [[using omp: sequence(omp::directive())]]; // expected-error {{expected an OpenMP directive}}
48*de59f564SAaron Ballman [[using omp: sequence(directive())]]; // expected-error {{expected an OpenMP directive}}
49*de59f564SAaron Ballman 
50*de59f564SAaron Ballman // Test that we give a sensible error on an unknown attribute in the omp
51*de59f564SAaron Ballman // namespace that has an argument list.
52*de59f564SAaron Ballman [[omp::unknown()]]; // expected-warning {{unknown attribute 'unknown' ignored}}
53*de59f564SAaron Ballman [[using omp: unknown()]]; // expected-warning {{unknown attribute 'unknown' ignored}}
54*de59f564SAaron Ballman 
55*de59f564SAaron Ballman // Test that unknown arguments to the omp::sequence are rejected, regardless of
56*de59f564SAaron Ballman // what level they're at.
57*de59f564SAaron Ballman [[omp::sequence(unknown)]]; // expected-error {{expected an OpenMP 'directive' or 'sequence' attribute argument}}
58*de59f564SAaron Ballman [[omp::sequence(sequence(unknown))]]; // expected-error {{expected an OpenMP 'directive' or 'sequence' attribute argument}}
59*de59f564SAaron Ballman [[omp::sequence(omp::unknown)]]; // expected-error {{expected an OpenMP 'directive' or 'sequence' attribute argument}}
60*de59f564SAaron Ballman [[omp::sequence(sequence(omp::unknown))]]; // expected-error {{expected an OpenMP 'directive' or 'sequence' attribute argument}}
61*de59f564SAaron Ballman 
62*de59f564SAaron Ballman // FIXME: combining non-openmp attributes with openmp attributes has surprising
63*de59f564SAaron Ballman // results due to the replay of tokens. We properly parse the non-openmp
64*de59f564SAaron Ballman // attributes, but we also replay the OpenMP tokens. The attributes then get
65*de59f564SAaron Ballman // passed to the OpenMP parsing functions and it does not attach the attribute
66*de59f564SAaron Ballman // to the declaration statement AST node as you might expect. This means that
67*de59f564SAaron Ballman // the expected diagnostics are not issued. Thankfully, due to the positioning
68*de59f564SAaron Ballman // of OpenMP attributes and what they appertain to, this should not be a
69*de59f564SAaron Ballman // frequent issue (hopefully).
70*de59f564SAaron Ballman int x;
71*de59f564SAaron Ballman [[deprecated, omp::directive(threadprivate(x))]] int y; // FIXME-expected-note {{'y' has been explicitly marked deprecated here}}
72*de59f564SAaron Ballman [[omp::directive(threadprivate(x)), deprecated]] int z; // FIXME-expected-note {{'z' has been explicitly marked deprecated here}}
test()73*de59f564SAaron Ballman void test() {
74*de59f564SAaron Ballman   x = 1;
75*de59f564SAaron Ballman   y = 1; // FIXME-expected-warning {{warning: 'y' is deprecated}}
76*de59f564SAaron Ballman   z = 1; // FIXME-expected-warning {{warning: 'z' is deprecated}}
77*de59f564SAaron Ballman }
78