Skip to content

Commit 5a6e060

Browse files
committed
Add an attr tablegen feature for checking langopts
For SYCL, we want some attributes to be ignored in host mode, but without diagnosing the attribute as being ignored. This adds a bit to the tablegen emitter to specify that a given language option opts into this behavior. This allows us to more naturally specify that an attribute is a device-only attribute from Attr.td without adding logic in SemaDeclAttr.cpp to bail out in host mode (which looks like a bug due to the lack of an ignored attribute warning). As a drive-by, this also corrects a think-o with the [[intel::reqd_sub_group_size]] attribute in OpenCL mode, which was always being silently dropped.
1 parent 73b7da0 commit 5a6e060

File tree

3 files changed

+41
-61
lines changed

3 files changed

+41
-61
lines changed

clang/include/clang/Basic/Attr.td

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -317,10 +317,13 @@ class SubjectList<list<AttrSubject> subjects, SubjectDiag diag = WarnDiag,
317317
string CustomDiag = customDiag;
318318
}
319319

320-
class LangOpt<string name, code customCode = [{}]> {
320+
class LangOpt<string name, bit warn = 1, code customCode = [{}]> {
321321
// The language option to test; ignored when custom code is supplied.
322322
string Name = name;
323323

324+
// If set to 1, diagnose the attribute as being ignored if the test fails.
325+
bit Warn = warn;
326+
324327
// A custom predicate, written as an expression evaluated in a context with
325328
// "LangOpts" bound.
326329
code CustomCode = customCode;
@@ -329,19 +332,19 @@ def MicrosoftExt : LangOpt<"MicrosoftExt">;
329332
def Borland : LangOpt<"Borland">;
330333
def CUDA : LangOpt<"CUDA">;
331334
def HIP : LangOpt<"HIP">;
332-
def SYCLIsDevice : LangOpt<"SYCLIsDevice">;
333-
def SYCL : LangOpt<"SYCLIsDevice">;
334-
def SYCLIsHost : LangOpt<"SYCLIsHost">;
335+
def SYCL : LangOpt<"SYCL">;
336+
def SYCLIsDevice : LangOpt<"", 0, "(LangOpts.SYCL && LangOpts.SYCLIsDevice)">;
337+
def SYCLIsHost : LangOpt<"", 0, "(LangOpts.SYCL && LangOpts.SYCLIsHost)">;
335338
def SYCLExplicitSIMD : LangOpt<"SYCLExplicitSIMD">;
336-
def COnly : LangOpt<"", "!LangOpts.CPlusPlus">;
339+
def COnly : LangOpt<"", 1, "!LangOpts.CPlusPlus">;
337340
def CPlusPlus : LangOpt<"CPlusPlus">;
338341
def OpenCL : LangOpt<"OpenCL">;
339342
def RenderScript : LangOpt<"RenderScript">;
340343
def ObjC : LangOpt<"ObjC">;
341344
def BlocksSupported : LangOpt<"Blocks">;
342345
def ObjCAutoRefCount : LangOpt<"ObjCAutoRefCount">;
343346
def ObjCNonFragileRuntime
344-
: LangOpt<"", "LangOpts.ObjCRuntime.allowsClassStubs()">;
347+
: LangOpt<"", 1, "LangOpts.ObjCRuntime.allowsClassStubs()">;
345348

346349
// Language option for CMSE extensions
347350
def Cmse : LangOpt<"Cmse">;
@@ -1322,7 +1325,7 @@ def SYCLIntelNoGlobalWorkOffset : InheritableAttr {
13221325
let Spellings = [CXX11<"intelfpga","no_global_work_offset">,
13231326
CXX11<"intel","no_global_work_offset">];
13241327
let Args = [ExprArgument<"Value", /*optional*/1>];
1325-
let LangOpts = [SYCLIsDevice, SYCLIsHost];
1328+
let LangOpts = [SYCLIsDevice];
13261329
let Subjects = SubjectList<[Function], ErrorDiag>;
13271330
let Documentation = [SYCLIntelNoGlobalWorkOffsetAttrDocs];
13281331
}
@@ -1331,7 +1334,7 @@ def SYCLIntelLoopFuse : InheritableAttr {
13311334
let Spellings = [CXX11<"intel", "loop_fuse">,
13321335
CXX11<"intel", "loop_fuse_independent">];
13331336
let Args = [ExprArgument<"Value", /*optional=*/ 1>];
1334-
let LangOpts = [SYCLIsDevice, SYCLIsHost];
1337+
let LangOpts = [SYCLIsDevice];
13351338
let Subjects = SubjectList<[Function], ErrorDiag>;
13361339
let Accessors = [Accessor<"isIndependent",
13371340
[CXX11<"intel", "loop_fuse_independent">]>];
@@ -1946,7 +1949,7 @@ def IntelFPGADoublePump : Attr {
19461949
CXX11<"intel", "doublepump">];
19471950
let Subjects = SubjectList<[IntelFPGAConstVar, IntelFPGALocalOrStaticVar,
19481951
Field], ErrorDiag>;
1949-
let LangOpts = [SYCLIsDevice, SYCLIsHost];
1952+
let LangOpts = [SYCLIsDevice];
19501953
let Documentation = [IntelFPGADoublePumpAttrDocs];
19511954
}
19521955

@@ -1955,7 +1958,7 @@ def IntelFPGASinglePump : Attr {
19551958
CXX11<"intel", "singlepump">];
19561959
let Subjects = SubjectList<[IntelFPGAConstVar, IntelFPGALocalOrStaticVar,
19571960
Field], ErrorDiag>;
1958-
let LangOpts = [SYCLIsDevice, SYCLIsHost];
1961+
let LangOpts = [SYCLIsDevice];
19591962
let Documentation = [IntelFPGASinglePumpAttrDocs];
19601963
}
19611964

@@ -1976,7 +1979,7 @@ def IntelFPGAMemory : Attr {
19761979
}];
19771980
let Subjects = SubjectList<[IntelFPGAConstVar, IntelFPGALocalStaticSlaveMemVar,
19781981
Field], ErrorDiag>;
1979-
let LangOpts = [SYCLIsDevice, SYCLIsHost];
1982+
let LangOpts = [SYCLIsDevice];
19801983
let Documentation = [IntelFPGAMemoryAttrDocs];
19811984
}
19821985

@@ -1985,7 +1988,7 @@ def IntelFPGARegister : Attr {
19851988
CXX11<"intel", "fpga_register">];
19861989
let Subjects = SubjectList<[IntelFPGAConstVar, IntelFPGALocalOrStaticVar,
19871990
Field], ErrorDiag>;
1988-
let LangOpts = [SYCLIsDevice, SYCLIsHost];
1991+
let LangOpts = [SYCLIsDevice];
19891992
let Documentation = [IntelFPGARegisterAttrDocs];
19901993
}
19911994

@@ -1996,7 +1999,7 @@ def IntelFPGABankWidth : Attr {
19961999
let Args = [ExprArgument<"Value">];
19972000
let Subjects = SubjectList<[IntelFPGAConstVar, IntelFPGALocalStaticSlaveMemVar,
19982001
Field], ErrorDiag>;
1999-
let LangOpts = [SYCLIsDevice, SYCLIsHost];
2002+
let LangOpts = [SYCLIsDevice];
20002003
let Documentation = [IntelFPGABankWidthAttrDocs];
20012004
}
20022005

@@ -2006,15 +2009,15 @@ def IntelFPGANumBanks : Attr {
20062009
let Args = [ExprArgument<"Value">];
20072010
let Subjects = SubjectList<[IntelFPGAConstVar, IntelFPGALocalStaticSlaveMemVar,
20082011
Field], ErrorDiag>;
2009-
let LangOpts = [SYCLIsDevice, SYCLIsHost];
2012+
let LangOpts = [SYCLIsDevice];
20102013
let Documentation = [IntelFPGANumBanksAttrDocs];
20112014
}
20122015

20132016
def IntelFPGAPrivateCopies : InheritableAttr {
20142017
let Spellings = [CXX11<"intelfpga","private_copies">,
20152018
CXX11<"intel","private_copies">];
20162019
let Args = [ExprArgument<"Value">];
2017-
let LangOpts = [SYCLIsDevice, SYCLIsHost];
2020+
let LangOpts = [SYCLIsDevice];
20182021
let Subjects = SubjectList<[IntelFPGALocalNonConstVar, Field], ErrorDiag>;
20192022
let Documentation = [IntelFPGAPrivateCopiesAttrDocs];
20202023
}
@@ -2026,7 +2029,7 @@ def IntelFPGAMerge : Attr {
20262029
let Args = [StringArgument<"Name">, StringArgument<"Direction">];
20272030
let Subjects = SubjectList<[IntelFPGAConstVar, IntelFPGALocalOrStaticVar,
20282031
Field], ErrorDiag>;
2029-
let LangOpts = [SYCLIsDevice, SYCLIsHost];
2032+
let LangOpts = [SYCLIsDevice];
20302033
let Documentation = [IntelFPGAMergeAttrDocs];
20312034
}
20322035

@@ -2036,7 +2039,7 @@ def IntelFPGAMaxReplicates : Attr {
20362039
let Args = [ExprArgument<"Value">];
20372040
let Subjects = SubjectList<[IntelFPGAConstVar, IntelFPGALocalStaticSlaveMemVar,
20382041
Field], ErrorDiag>;
2039-
let LangOpts = [SYCLIsDevice, SYCLIsHost];
2042+
let LangOpts = [SYCLIsDevice];
20402043
let Documentation = [IntelFPGAMaxReplicatesAttrDocs];
20412044
}
20422045

@@ -2045,7 +2048,7 @@ def IntelFPGASimpleDualPort : Attr {
20452048
CXX11<"intel","simple_dual_port">];
20462049
let Subjects = SubjectList<[IntelFPGAConstVar, IntelFPGALocalStaticSlaveMemVar,
20472050
Field], ErrorDiag>;
2048-
let LangOpts = [SYCLIsDevice, SYCLIsHost];
2051+
let LangOpts = [SYCLIsDevice];
20492052
let Documentation = [IntelFPGASimpleDualPortAttrDocs];
20502053
}
20512054

@@ -2081,7 +2084,7 @@ def IntelFPGAForcePow2Depth : Attr {
20812084
let Args = [ExprArgument<"Value">];
20822085
let Subjects = SubjectList<[IntelFPGAConstVar, IntelFPGALocalStaticSlaveMemVar,
20832086
Field], ErrorDiag>;
2084-
let LangOpts = [SYCLIsDevice, SYCLIsHost];
2087+
let LangOpts = [SYCLIsDevice];
20852088
let Documentation = [IntelFPGAForcePow2DepthAttrDocs];
20862089
let AdditionalMembers = [{
20872090
static unsigned getMinValue() {

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 6 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3211,7 +3211,12 @@ static void handleWorkGroupSizeHint(Sema &S, Decl *D, const ParsedAttr &AL) {
32113211

32123212
// Handles intel_reqd_sub_group_size.
32133213
static void handleSubGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) {
3214-
if (S.LangOpts.SYCLIsHost)
3214+
// In SYCLIsHost mode, we want to ignore the attribute. In OpenCL or
3215+
// SYCLIsDevice mode, we want to process the attribute as normal. This cannot
3216+
// be handled in Attr.td unless ClangAttrEmitter.cpp gets smarter logic about
3217+
// when to suppress the "ignored attribute" warnings with a list of language
3218+
// options.
3219+
if (!S.LangOpts.SYCLIsDevice && !S.LangOpts.OpenCL)
32153220
return;
32163221

32173222
Expr *E = AL.getArgAsExpr(0);
@@ -3387,10 +3392,6 @@ void Sema::addSYCLIntelLoopFuseAttr(Decl *D, const AttributeCommonInfo &CI,
33873392
if (checkSYCLIntelLoopFuseArgument(*this, CI, E))
33883393
return;
33893394

3390-
// Attribute should not be added during host compilation.
3391-
if (getLangOpts().SYCLIsHost)
3392-
return;
3393-
33943395
SYCLIntelLoopFuseAttr *NewAttr = mergeSYCLIntelLoopFuseAttr(D, CI, E);
33953396

33963397
if (NewAttr)
@@ -5634,9 +5635,6 @@ static bool checkForDuplicateAttribute(Sema &S, Decl *D,
56345635

56355636
static void handleNoGlobalWorkOffsetAttr(Sema &S, Decl *D,
56365637
const ParsedAttr &A) {
5637-
if (S.LangOpts.SYCLIsHost)
5638-
return;
5639-
56405638
checkForDuplicateAttribute<SYCLIntelNoGlobalWorkOffsetAttr>(S, D, A);
56415639
S.CheckDeprecatedSYCLAttributeSpelling(A);
56425640

@@ -5653,9 +5651,6 @@ static void handleNoGlobalWorkOffsetAttr(Sema &S, Decl *D,
56535651
/// Both are incompatible with the __register__ attribute.
56545652
template <typename AttrType, typename IncompatAttrType>
56555653
static void handleIntelFPGAPumpAttr(Sema &S, Decl *D, const ParsedAttr &A) {
5656-
if (S.LangOpts.SYCLIsHost)
5657-
return;
5658-
56595654
checkForDuplicateAttribute<AttrType>(S, D, A);
56605655
if (checkAttrMutualExclusion<IncompatAttrType>(S, D, A))
56615656
return;
@@ -5676,10 +5671,6 @@ static void handleIntelFPGAPumpAttr(Sema &S, Decl *D, const ParsedAttr &A) {
56765671
/// This is incompatible with the [[intelfpga::register]] attribute.
56775672
static void handleIntelFPGAMemoryAttr(Sema &S, Decl *D,
56785673
const ParsedAttr &AL) {
5679-
5680-
if (S.LangOpts.SYCLIsHost)
5681-
return;
5682-
56835674
checkForDuplicateAttribute<IntelFPGAMemoryAttr>(S, D, AL);
56845675
if (checkAttrMutualExclusion<IntelFPGARegisterAttr>(S, D, AL))
56855676
return;
@@ -5749,10 +5740,6 @@ static bool checkIntelFPGARegisterAttrCompatibility(Sema &S, Decl *D,
57495740
/// Handle the [[intelfpga::register]] attribute.
57505741
/// This is incompatible with most of the other memory attributes.
57515742
static void handleIntelFPGARegisterAttr(Sema &S, Decl *D, const ParsedAttr &A) {
5752-
5753-
if (S.LangOpts.SYCLIsHost)
5754-
return;
5755-
57565743
checkForDuplicateAttribute<IntelFPGARegisterAttr>(S, D, A);
57575744
if (checkIntelFPGARegisterAttrCompatibility(S, D, A))
57585745
return;
@@ -5770,10 +5757,6 @@ static void handleIntelFPGARegisterAttr(Sema &S, Decl *D, const ParsedAttr &A) {
57705757
template <typename AttrType>
57715758
static void handleOneConstantPowerTwoValueAttr(Sema &S, Decl *D,
57725759
const ParsedAttr &A) {
5773-
5774-
if (S.LangOpts.SYCLIsHost)
5775-
return;
5776-
57775760
checkForDuplicateAttribute<AttrType>(S, D, A);
57785761
if (checkAttrMutualExclusion<IntelFPGARegisterAttr>(S, D, A))
57795762
return;
@@ -5785,9 +5768,6 @@ static void handleOneConstantPowerTwoValueAttr(Sema &S, Decl *D,
57855768

57865769
static void handleIntelFPGASimpleDualPortAttr(Sema &S, Decl *D,
57875770
const ParsedAttr &AL) {
5788-
if (S.LangOpts.SYCLIsHost)
5789-
return;
5790-
57915771
checkForDuplicateAttribute<IntelFPGASimpleDualPortAttr>(S, D, AL);
57925772

57935773
if (checkAttrMutualExclusion<IntelFPGARegisterAttr>(S, D, AL))
@@ -5805,9 +5785,6 @@ static void handleIntelFPGASimpleDualPortAttr(Sema &S, Decl *D,
58055785

58065786
static void handleIntelFPGAMaxReplicatesAttr(Sema &S, Decl *D,
58075787
const ParsedAttr &A) {
5808-
if (S.LangOpts.SYCLIsHost)
5809-
return;
5810-
58115788
checkForDuplicateAttribute<IntelFPGAMaxReplicatesAttr>(S, D, A);
58125789

58135790
if (checkAttrMutualExclusion<IntelFPGARegisterAttr>(S, D, A))
@@ -5825,9 +5802,6 @@ static void handleIntelFPGAMaxReplicatesAttr(Sema &S, Decl *D,
58255802
static void handleIntelFPGAMergeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
58265803
checkForDuplicateAttribute<IntelFPGAMergeAttr>(S, D, AL);
58275804

5828-
if (S.LangOpts.SYCLIsHost)
5829-
return;
5830-
58315805
if (checkAttrMutualExclusion<IntelFPGARegisterAttr>(S, D, AL))
58325806
return;
58335807

@@ -5946,9 +5920,6 @@ void Sema::AddIntelFPGABankBitsAttr(Decl *D, const AttributeCommonInfo &CI,
59465920

59475921
static void handleIntelFPGAPrivateCopiesAttr(Sema &S, Decl *D,
59485922
const ParsedAttr &A) {
5949-
if (S.LangOpts.SYCLIsHost)
5950-
return;
5951-
59525923
checkForDuplicateAttribute<IntelFPGAPrivateCopiesAttr>(S, D, A);
59535924
if (checkAttrMutualExclusion<IntelFPGARegisterAttr>(S, D, A))
59545925
return;
@@ -5960,9 +5931,6 @@ static void handleIntelFPGAPrivateCopiesAttr(Sema &S, Decl *D,
59605931

59615932
static void handleIntelFPGAForcePow2DepthAttr(Sema &S, Decl *D,
59625933
const ParsedAttr &A) {
5963-
if (S.LangOpts.SYCLIsHost)
5964-
return;
5965-
59665934
checkForDuplicateAttribute<IntelFPGAForcePow2DepthAttr>(S, D, A);
59675935

59685936
if (checkAttrMutualExclusion<IntelFPGARegisterAttr>(S, D, A))

clang/utils/TableGen/ClangAttrEmitter.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1992,13 +1992,19 @@ bool PragmaClangAttributeSupport::isAttributedSupported(
19921992
return true;
19931993
}
19941994

1995-
static std::string GenerateTestExpression(ArrayRef<Record *> LangOpts) {
1995+
static std::string GenerateTestExpression(ArrayRef<Record *> LangOpts,
1996+
bool *ShouldDiagnose = nullptr) {
19961997
std::string Test;
19971998

19981999
for (auto *E : LangOpts) {
19992000
if (!Test.empty())
20002001
Test += " || ";
20012002

2003+
// If any of the language options say "warn", then warn if any of the
2004+
// options fail.
2005+
if (ShouldDiagnose && E->getValueAsBit("Warn"))
2006+
*ShouldDiagnose = true;
2007+
20022008
const StringRef Code = E->getValueAsString("CustomCode");
20032009
if (!Code.empty()) {
20042010
Test += "(";
@@ -3638,10 +3644,13 @@ static void GenerateLangOptRequirements(const Record &R,
36383644
OS << "bool diagLangOpts(Sema &S, const ParsedAttr &Attr) ";
36393645
OS << "const override {\n";
36403646
OS << " auto &LangOpts = S.LangOpts;\n";
3641-
OS << " if (" << GenerateTestExpression(LangOpts) << ")\n";
3647+
bool Warn = false;
3648+
OS << " if (" << GenerateTestExpression(LangOpts, &Warn) << ")\n";
36423649
OS << " return true;\n\n";
3643-
OS << " S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) ";
3644-
OS << "<< Attr;\n";
3650+
if (Warn) {
3651+
OS << " S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) ";
3652+
OS << "<< Attr;\n";
3653+
}
36453654
OS << " return false;\n";
36463655
OS << "}\n\n";
36473656
}

0 commit comments

Comments
 (0)