Skip to content

Commit f32c431

Browse files
authored
[SYCL] Refactor of [[intel::private_copies()] and [[intel::max_replicates()]] attributes (#3251)
This patch 1. refactors two declaration attributes using #3224: [[intel::private_copies()] and [[intel::max_replicates()]] to better fit for community standards. 2. refactors the way we handle duplicate attributes and mutually exclusive attributes logic when present on a given declaration. 3. handles redeclarations or template instantiations properly. 4. adds test Signed-off-by: Soumi Manna <[email protected]>
1 parent dcfb6b1 commit f32c431

File tree

7 files changed

+223
-49
lines changed

7 files changed

+223
-49
lines changed

clang/include/clang/Basic/Attr.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2038,7 +2038,7 @@ def IntelFPGAMerge : Attr {
20382038
let Documentation = [IntelFPGAMergeAttrDocs];
20392039
}
20402040

2041-
def IntelFPGAMaxReplicates : Attr {
2041+
def IntelFPGAMaxReplicates : InheritableAttr {
20422042
let Spellings = [CXX11<"intelfpga","max_replicates">,
20432043
CXX11<"intel","max_replicates">];
20442044
let Args = [ExprArgument<"Value">];

clang/include/clang/Sema/Sema.h

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10234,6 +10234,12 @@ class Sema final {
1023410234
Expr *E);
1023510235
SYCLIntelLoopFuseAttr *
1023610236
MergeSYCLIntelLoopFuseAttr(Decl *D, const SYCLIntelLoopFuseAttr &A);
10237+
void AddIntelFPGAPrivateCopiesAttr(Decl *D, const AttributeCommonInfo &CI,
10238+
Expr *E);
10239+
void AddIntelFPGAMaxReplicatesAttr(Decl *D, const AttributeCommonInfo &CI,
10240+
Expr *E);
10241+
IntelFPGAMaxReplicatesAttr *
10242+
MergeIntelFPGAMaxReplicatesAttr(Decl *D, const IntelFPGAMaxReplicatesAttr &A);
1023710243

1023810244
/// AddAlignedAttr - Adds an aligned attribute to a particular declaration.
1023910245
void AddAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E,
@@ -13093,13 +13099,6 @@ void Sema::addIntelSingleArgAttr(Decl *D, const AttributeCommonInfo &CI,
1309313099
return;
1309413100
E = ICE.get();
1309513101
int32_t ArgInt = ArgVal.getSExtValue();
13096-
if (CI.getParsedKind() == ParsedAttr::AT_IntelFPGAMaxReplicates) {
13097-
if (ArgInt <= 0) {
13098-
Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer)
13099-
<< CI << /*positive*/ 0;
13100-
return;
13101-
}
13102-
}
1310313102
if (CI.getParsedKind() == ParsedAttr::AT_SYCLIntelMaxGlobalWorkDim) {
1310413103
if (ArgInt < 0) {
1310513104
Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer)
@@ -13114,19 +13113,6 @@ void Sema::addIntelSingleArgAttr(Decl *D, const AttributeCommonInfo &CI,
1311413113
return;
1311513114
}
1311613115
}
13117-
if (CI.getParsedKind() == ParsedAttr::AT_IntelFPGAPrivateCopies) {
13118-
if (ArgInt < 0) {
13119-
Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer)
13120-
<< CI << /*non-negative*/ 1;
13121-
return;
13122-
}
13123-
}
13124-
}
13125-
13126-
if (CI.getParsedKind() == ParsedAttr::AT_IntelFPGAPrivateCopies) {
13127-
if (!D->hasAttr<IntelFPGAMemoryAttr>())
13128-
D->addAttr(IntelFPGAMemoryAttr::CreateImplicit(
13129-
Context, IntelFPGAMemoryAttr::Default));
1313013116
}
1313113117

1313213118
D->addAttr(::new (Context) AttrType(Context, CI, E));

clang/lib/Sema/SemaDecl.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2626,6 +2626,8 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D,
26262626
NewAttr = S.MergeSYCLIntelSchedulerTargetFmaxMhzAttr(D, *A);
26272627
else if (const auto *A = dyn_cast<SYCLIntelNoGlobalWorkOffsetAttr>(Attr))
26282628
NewAttr = S.MergeSYCLIntelNoGlobalWorkOffsetAttr(D, *A);
2629+
else if (const auto *A = dyn_cast<IntelFPGAMaxReplicatesAttr>(Attr))
2630+
NewAttr = S.MergeIntelFPGAMaxReplicatesAttr(D, *A);
26292631
else if (Attr->shouldInheritEvenIfAlreadyPresent() || !DeclHasAttr(D, Attr))
26302632
NewAttr = cast<InheritableAttr>(Attr->clone(S.Context));
26312633

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 110 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,8 @@ static bool checkPositiveIntArgument(Sema &S, const AttrInfo &AI, const Expr *Ex
300300
/// Diagnose mutually exclusive attributes when present on a given
301301
/// declaration. Returns true if diagnosed.
302302
template <typename AttrTy>
303-
static bool checkAttrMutualExclusion(Sema &S, Decl *D, const ParsedAttr &AL) {
303+
static bool checkAttrMutualExclusion(Sema &S, Decl *D,
304+
const AttributeCommonInfo &AL) {
304305
if (const auto *A = D->getAttr<AttrTy>()) {
305306
S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible) << AL << A;
306307
S.Diag(A->getLocation(), diag::note_conflicting_attribute);
@@ -5961,16 +5962,73 @@ static void handleIntelFPGASimpleDualPortAttr(Sema &S, Decl *D,
59615962
IntelFPGASimpleDualPortAttr(S.Context, AL));
59625963
}
59635964

5964-
static void handleIntelFPGAMaxReplicatesAttr(Sema &S, Decl *D,
5965-
const ParsedAttr &A) {
5966-
checkForDuplicateAttribute<IntelFPGAMaxReplicatesAttr>(S, D, A);
5965+
void Sema::AddIntelFPGAMaxReplicatesAttr(Decl *D, const AttributeCommonInfo &CI,
5966+
Expr *E) {
5967+
if (!E->isValueDependent()) {
5968+
// Validate that we have an integer constant expression and then store the
5969+
// converted constant expression into the semantic attribute so that we
5970+
// don't have to evaluate it again later.
5971+
llvm::APSInt ArgVal;
5972+
ExprResult Res = VerifyIntegerConstantExpression(E, &ArgVal);
5973+
if (Res.isInvalid())
5974+
return;
5975+
E = Res.get();
5976+
// This attribute requires a strictly positive value.
5977+
if (ArgVal <= 0) {
5978+
Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer)
5979+
<< CI << /*positive*/ 0;
5980+
return;
5981+
}
5982+
// Check to see if there's a duplicate attribute with different values
5983+
// already applied to the declaration.
5984+
if (const auto *DeclAttr = D->getAttr<IntelFPGAMaxReplicatesAttr>()) {
5985+
// If the other attribute argument is instantiation dependent, we won't
5986+
// have converted it to a constant expression yet and thus we test
5987+
// whether this is a null pointer.
5988+
const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getValue());
5989+
if (DeclExpr && ArgVal != DeclExpr->getResultAsAPSInt()) {
5990+
Diag(CI.getLoc(), diag::warn_duplicate_attribute) << CI;
5991+
Diag(DeclAttr->getLocation(), diag::note_previous_attribute);
5992+
return;
5993+
}
5994+
}
5995+
// [[intel::fpga_register]] and [[intel::max_replicates()]]
5996+
// attributes are incompatible.
5997+
if (checkAttrMutualExclusion<IntelFPGARegisterAttr>(*this, D, CI))
5998+
return;
5999+
}
59676000

5968-
if (checkAttrMutualExclusion<IntelFPGARegisterAttr>(S, D, A))
5969-
return;
6001+
D->addAttr(::new (Context) IntelFPGAMaxReplicatesAttr(Context, CI, E));
6002+
}
59706003

6004+
IntelFPGAMaxReplicatesAttr *
6005+
Sema::MergeIntelFPGAMaxReplicatesAttr(Decl *D,
6006+
const IntelFPGAMaxReplicatesAttr &A) {
6007+
// Check to see if there's a duplicate attribute with different values
6008+
// already applied to the declaration.
6009+
if (const auto *DeclAttr = D->getAttr<IntelFPGAMaxReplicatesAttr>()) {
6010+
const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getValue());
6011+
const auto *MergeExpr = dyn_cast<ConstantExpr>(A.getValue());
6012+
if (DeclExpr && MergeExpr &&
6013+
DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) {
6014+
Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A;
6015+
Diag(A.getLoc(), diag::note_previous_attribute);
6016+
return nullptr;
6017+
}
6018+
}
6019+
// [[intel::fpga_register]] and [[intel::max_replicates()]]
6020+
// attributes are incompatible.
6021+
if (checkAttrMutualExclusion<IntelFPGARegisterAttr>(*this, D, A))
6022+
return nullptr;
6023+
6024+
return ::new (Context) IntelFPGAMaxReplicatesAttr(Context, A, A.getValue());
6025+
}
6026+
6027+
static void handleIntelFPGAMaxReplicatesAttr(Sema &S, Decl *D,
6028+
const ParsedAttr &A) {
59716029
S.CheckDeprecatedSYCLAttributeSpelling(A);
59726030

5973-
S.addIntelSingleArgAttr<IntelFPGAMaxReplicatesAttr>(D, A, A.getArgAsExpr(0));
6031+
S.AddIntelFPGAMaxReplicatesAttr(D, A, A.getArgAsExpr(0));
59746032
}
59756033

59766034
/// Handle the merge attribute.
@@ -6096,15 +6154,55 @@ void Sema::AddIntelFPGABankBitsAttr(Decl *D, const AttributeCommonInfo &CI,
60966154
IntelFPGABankBitsAttr(Context, CI, Args.data(), Args.size()));
60976155
}
60986156

6157+
void Sema::AddIntelFPGAPrivateCopiesAttr(Decl *D, const AttributeCommonInfo &CI,
6158+
Expr *E) {
6159+
if (!E->isValueDependent()) {
6160+
// Validate that we have an integer constant expression and then store the
6161+
// converted constant expression into the semantic attribute so that we
6162+
// don't have to evaluate it again later.
6163+
llvm::APSInt ArgVal;
6164+
ExprResult Res = VerifyIntegerConstantExpression(E, &ArgVal);
6165+
if (Res.isInvalid())
6166+
return;
6167+
E = Res.get();
6168+
// This attribute requires a non-negative value.
6169+
if (ArgVal < 0) {
6170+
Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer)
6171+
<< CI << /*non-negative*/ 1;
6172+
return;
6173+
}
6174+
// Check to see if there's a duplicate attribute with different values
6175+
// already applied to the declaration.
6176+
if (const auto *DeclAttr = D->getAttr<IntelFPGAPrivateCopiesAttr>()) {
6177+
// If the other attribute argument is instantiation dependent, we won't
6178+
// have converted it to a constant expression yet and thus we test
6179+
// whether this is a null pointer.
6180+
const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getValue());
6181+
if (DeclExpr && ArgVal != DeclExpr->getResultAsAPSInt()) {
6182+
Diag(CI.getLoc(), diag::warn_duplicate_attribute) << CI;
6183+
Diag(DeclAttr->getLoc(), diag::note_previous_attribute);
6184+
return;
6185+
}
6186+
}
6187+
// [[intel::fpga_register]] and [[intel::private_copies()]]
6188+
// attributes are incompatible.
6189+
if (checkAttrMutualExclusion<IntelFPGARegisterAttr>(*this, D, CI))
6190+
return;
6191+
// If the declaration does not have [[intel::memory]]
6192+
// attribute, this creates default implicit memory.
6193+
if (!D->hasAttr<IntelFPGAMemoryAttr>())
6194+
D->addAttr(IntelFPGAMemoryAttr::CreateImplicit(
6195+
Context, IntelFPGAMemoryAttr::Default));
6196+
}
6197+
6198+
D->addAttr(::new (Context) IntelFPGAPrivateCopiesAttr(Context, CI, E));
6199+
}
6200+
60996201
static void handleIntelFPGAPrivateCopiesAttr(Sema &S, Decl *D,
61006202
const ParsedAttr &A) {
6101-
checkForDuplicateAttribute<IntelFPGAPrivateCopiesAttr>(S, D, A);
6102-
if (checkAttrMutualExclusion<IntelFPGARegisterAttr>(S, D, A))
6103-
return;
6104-
61056203
S.CheckDeprecatedSYCLAttributeSpelling(A);
61066204

6107-
S.addIntelSingleArgAttr<IntelFPGAPrivateCopiesAttr>(D, A, A.getArgAsExpr(0));
6205+
S.AddIntelFPGAPrivateCopiesAttr(D, A, A.getArgAsExpr(0));
61086206
}
61096207

61106208
static void handleIntelFPGAForcePow2DepthAttr(Sema &S, Decl *D,

clang/lib/Sema/SemaTemplateInstantiateDecl.cpp

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -694,6 +694,26 @@ static void instantiateIntelSYCLFunctionAttr(
694694
S.addIntelSingleArgAttr<AttrName>(New, *Attr, Result.getAs<Expr>());
695695
}
696696

697+
static void instantiateIntelFPGAPrivateCopiesAttr(
698+
Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs,
699+
const IntelFPGAPrivateCopiesAttr *A, Decl *New) {
700+
EnterExpressionEvaluationContext Unevaluated(
701+
S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
702+
ExprResult Result = S.SubstExpr(A->getValue(), TemplateArgs);
703+
if (!Result.isInvalid())
704+
S.AddIntelFPGAPrivateCopiesAttr(New, *A, Result.getAs<Expr>());
705+
}
706+
707+
static void instantiateIntelFPGAMaxReplicatesAttr(
708+
Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs,
709+
const IntelFPGAMaxReplicatesAttr *A, Decl *New) {
710+
EnterExpressionEvaluationContext Unevaluated(
711+
S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
712+
ExprResult Result = S.SubstExpr(A->getValue(), TemplateArgs);
713+
if (!Result.isInvalid())
714+
S.AddIntelFPGAMaxReplicatesAttr(New, *A, Result.getAs<Expr>());
715+
}
716+
697717
/// Determine whether the attribute A might be relevent to the declaration D.
698718
/// If not, we can skip instantiating it. The attribute may or may not have
699719
/// been instantiated yet.
@@ -850,13 +870,13 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
850870
}
851871
if (const auto *IntelFPGAPrivateCopies =
852872
dyn_cast<IntelFPGAPrivateCopiesAttr>(TmplAttr)) {
853-
instantiateIntelSYCLFunctionAttr<IntelFPGAPrivateCopiesAttr>(
854-
*this, TemplateArgs, IntelFPGAPrivateCopies, New);
873+
instantiateIntelFPGAPrivateCopiesAttr(*this, TemplateArgs,
874+
IntelFPGAPrivateCopies, New);
855875
}
856876
if (const auto *IntelFPGAMaxReplicates =
857877
dyn_cast<IntelFPGAMaxReplicatesAttr>(TmplAttr)) {
858-
instantiateIntelSYCLFunctionAttr<IntelFPGAMaxReplicatesAttr>(
859-
*this, TemplateArgs, IntelFPGAMaxReplicates, New);
878+
instantiateIntelFPGAMaxReplicatesAttr(*this, TemplateArgs,
879+
IntelFPGAMaxReplicates, New);
860880
}
861881
if (const auto *IntelFPGABankBits =
862882
dyn_cast<IntelFPGABankBitsAttr>(TmplAttr)) {
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// RUN: %clang_cc1 -fsycl -fsycl-is-device -fsyntax-only -ast-dump -verify -pedantic %s | FileCheck %s
2+
3+
// Test that checks global constant variable (which allows the redeclaration) since
4+
// IntelFPGAConstVar is one of the subjects listed for [[intel::max_replicates()]] attribute.
5+
6+
// Checking of duplicate argument values.
7+
//CHECK: VarDecl{{.*}}var_max_replicates
8+
//CHECK: IntelFPGAMaxReplicatesAttr
9+
//CHECK-NEXT: ConstantExpr
10+
//CHECK-NEXT: value:{{.*}}12
11+
//CHECK-NEXT: IntegerLiteral{{.*}}12{{$}}
12+
//CHECK: IntelFPGAMaxReplicatesAttr
13+
//CHECK-NEXT: ConstantExpr
14+
//CHECK-NEXT: value:{{.*}}12
15+
//CHECK-NEXT: IntegerLiteral{{.*}}12{{$}}
16+
[[intel::max_replicates(12)]] extern const int var_max_replicates;
17+
[[intel::max_replicates(12)]] const int var_max_replicates = 0; // OK
18+
19+
// Merging of different arg values.
20+
//expected-warning@+2{{attribute 'max_replicates' is already applied with different arguments}}
21+
[[intel::max_replicates(12)]] extern const int var_max_replicates_1;
22+
[[intel::max_replicates(14)]] const int var_max_replicates_1 = 0;
23+
//expected-note@-2{{previous attribute is here}}
24+
25+
// Merging of incompatible attributes.
26+
// FIXME: Diagnostic order isn't correct, this isn't what we'd want here but
27+
// this is an upstream issue. Merge function is calling here
28+
// checkAttrMutualExclusion() function that has backwards diagnostic behavior.
29+
// This should be fixed into upstream.
30+
//expected-error@+2{{'max_replicates' and 'fpga_register' attributes are not compatible}}
31+
//expected-note@+2{{conflicting attribute is here}}
32+
[[intel::max_replicates(12)]] extern const int var_max_replicates_2;
33+
[[intel::fpga_register]] const int var_max_replicates_2 =0;

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

Lines changed: 47 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,33 @@ void check_ast()
145145
[[intel::simple_dual_port]] int var_dual_port;
146146
[[intel::force_pow2_depth(1)]] int var_force_p2d;
147147
[[intel::force_pow2_depth(1)]] const int const_force_p2d[64] = {0, 1};
148+
149+
// Checking of duplicate argument values.
150+
//CHECK: VarDecl{{.*}}var_max_replicates
151+
//CHECK: IntelFPGAMaxReplicatesAttr
152+
//CHECK-NEXT: ConstantExpr
153+
//CHECK-NEXT: value:{{.*}}12
154+
//CHECK-NEXT: IntegerLiteral{{.*}}12{{$}}
155+
//CHECK: IntelFPGAMaxReplicatesAttr
156+
//CHECK-NEXT: ConstantExpr
157+
//CHECK-NEXT: value:{{.*}}12
158+
//CHECK-NEXT: IntegerLiteral{{.*}}12{{$}}
159+
[[intel::max_replicates(12)]]
160+
[[intel::max_replicates(12)]] int var_max_replicates; // OK
161+
162+
// Checking of duplicate argument values.
163+
//CHECK: VarDecl{{.*}}var_private_copies
164+
//CHECK: IntelFPGAMemoryAttr{{.*}}Implicit
165+
//CHECK: IntelFPGAPrivateCopiesAttr
166+
//CHECK-NEXT: ConstantExpr
167+
//CHECK-NEXT: value:{{.*}}12
168+
//CHECK-NEXT: IntegerLiteral{{.*}}12{{$}}
169+
//CHECK: IntelFPGAPrivateCopiesAttr
170+
//CHECK-NEXT: ConstantExpr
171+
//CHECK-NEXT: value:{{.*}}12
172+
//CHECK-NEXT: IntegerLiteral{{.*}}12{{$}}
173+
[[intel::private_copies(12)]]
174+
[[intel::private_copies(12)]] int var_private_copies; // OK
148175
}
149176

150177
//CHECK: FunctionDecl{{.*}}diagnostics
@@ -318,11 +345,17 @@ void diagnostics()
318345
//expected-note@+1 {{did you mean to use 'intel::max_replicates' instead?}}
319346
[[intelfpga::max_replicates(2)]] unsigned int max_replicates[64];
320347

348+
// Checking of different argument values.
349+
//expected-warning@+2{{attribute 'max_replicates' is already applied with different arguments}}
350+
[[intel::max_replicates(8)]] //expected-note{{previous attribute is here}}
351+
[[intel::max_replicates(16)]] unsigned int max_repl[64];
352+
321353
//expected-error@+1{{'max_replicates' attribute requires a positive integral compile time constant expression}}
322354
[[intel::max_replicates(0)]] unsigned int maxrepl_zero[64];
323355
//expected-error@+1{{'max_replicates' attribute requires a positive integral compile time constant expression}}
324356
[[intel::max_replicates(-1)]] unsigned int maxrepl_negative[64];
325357

358+
// Checking of incompatible attributes.
326359
//expected-error@+3{{'max_replicates' and 'fpga_register' attributes are not compatible}}
327360
[[intel::fpga_register]]
328361
//expected-note@-1 {{conflicting attribute is here}}
@@ -386,23 +419,16 @@ void diagnostics()
386419
//expected-note@+1 {{did you mean to use 'intel::private_copies' instead?}}
387420
[[intelfpga::private_copies(8)]] unsigned int private_copies[64];
388421

422+
// Checking of incompatible attributes.
389423
//expected-error@+2{{attributes are not compatible}}
390424
[[intel::private_copies(16)]]
391425
[[intel::fpga_register]]
392426
//expected-note@-2 {{conflicting attribute is here}}
393427
unsigned int pc_reg[64];
394428

395-
//CHECK: VarDecl{{.*}}pc_pc
396-
//CHECK: IntelFPGAPrivateCopiesAttr
397-
//CHECK-NEXT: ConstantExpr
398-
//CHECK-NEXT: value:{{.*}}8
399-
//CHECK-NEXT: IntegerLiteral{{.*}}8{{$}}
400-
//CHECK: IntelFPGAPrivateCopiesAttr
401-
//CHECK-NEXT: ConstantExpr
402-
//CHECK-NEXT: value:{{.*}}16
403-
//CHECK-NEXT: IntegerLiteral{{.*}}16{{$}}
404-
//expected-warning@+2{{is already applied}}
405-
[[intel::private_copies(8)]]
429+
// Checking of different argument values.
430+
//expected-warning@+2{{attribute 'private_copies' is already applied with different arguments}}
431+
[[intel::private_copies(8)]] //expected-note{{previous attribute is here}}
406432
[[intel::private_copies(16)]] unsigned int pc_pc[64];
407433

408434
//expected-error@+1{{'private_copies' attribute requires a non-negative integral compile time constant expression}}
@@ -803,9 +829,18 @@ void check_template_parameters() {
803829
//expected-error@+1{{'max_replicates' attribute requires a positive integral compile time constant expression}}
804830
[[intel::max_replicates(D)]]
805831
[[intel::max_replicates(C)]]
806-
//expected-warning@-1{{attribute 'max_replicates' is already applied}}
807832
unsigned int max_replicates_duplicate;
808833

834+
// Test that checks template instantiations for different arg values.
835+
[[intel::max_replicates(4)]] // expected-note {{previous attribute is here}}
836+
// expected-warning@+1 {{attribute 'max_replicates' is already applied with different arguments}}
837+
[[intel::max_replicates(C)]] unsigned int max_repl_duplicate[64];
838+
839+
// Test that checks template instantiations for different arg values.
840+
[[intel::private_copies(4)]] // expected-note {{previous attribute is here}}
841+
// expected-warning@+1 {{attribute 'private_copies' is already applied with different arguments}}
842+
[[intel::private_copies(C)]] unsigned int var_private_copies;
843+
809844
//expected-error@+3{{'max_replicates' and 'fpga_register' attributes are not compatible}}
810845
[[intel::fpga_register]]
811846
//expected-note@-1 {{conflicting attribute is here}}

0 commit comments

Comments
 (0)