@@ -12744,11 +12744,11 @@ static void _propagateRequirement(
12744
12744
// if stmt inside parent, set the provenance tracker to the calling function
12745
12745
if (!decl)
12746
12746
decl = visitor->getParentFuncOfVisitor();
12747
- if (referencedDecl && decl)
12747
+ if (referencedNode && decl)
12748
12748
{
12749
12749
// Here we store a childDecl that added/removed capabilities from a parentDecl
12750
12750
decl->capabilityRequirementProvenance.add(
12751
- DeclReferenceWithLoc{referencedDecl , referenceLoc});
12751
+ ProvenenceNodeWithLoc{referencedNode , referenceLoc});
12752
12752
}
12753
12753
};
12754
12754
@@ -12977,15 +12977,19 @@ CapabilitySet SemanticsDeclCapabilityVisitor::getDeclaredCapabilitySet(Decl* dec
12977
12977
// The requirement for `foo` should be glsl+glsl_ext_1 | spirv.
12978
12978
//
12979
12979
CapabilitySet declaredCaps;
12980
+ CapabilityAtom stageToJoin = CapabilityAtom::Invalid;
12980
12981
for (Decl* parent = decl; parent; parent = getParentDecl(parent))
12981
12982
{
12982
12983
CapabilitySet localDeclaredCaps;
12983
12984
bool shouldBreak = false;
12984
12985
if (!as<AggTypeDeclBase>(parent) || parent->inferredCapabilityRequirements.isEmpty())
12985
12986
{
12986
- for (auto decoration : parent->getModifiersOfType<RequireCapabilityAttribute>() )
12987
+ for (auto mod : parent->modifiers )
12987
12988
{
12988
- localDeclaredCaps.unionWith(decoration->capabilitySet);
12989
+ if (auto decoration = as<RequireCapabilityAttribute>(mod))
12990
+ localDeclaredCaps.unionWith(decoration->capabilitySet);
12991
+ else if (auto entrypoint = as<EntryPointAttribute>(mod))
12992
+ stageToJoin = entrypoint->capabilitySet.getTargetStage();
12989
12993
}
12990
12994
}
12991
12995
else
@@ -13001,6 +13005,8 @@ CapabilitySet SemanticsDeclCapabilityVisitor::getDeclaredCapabilitySet(Decl* dec
13001
13005
if (shouldBreak)
13002
13006
break;
13003
13007
}
13008
+ if (!declaredCaps.isEmpty() && stageToJoin != CapabilityAtom::Invalid)
13009
+ declaredCaps.join(CapabilitySet((CapabilityName)stageToJoin));
13004
13010
return declaredCaps;
13005
13011
}
13006
13012
@@ -13298,63 +13304,83 @@ void diagnoseMissingCapabilityProvenance(
13298
13304
Decl* decl,
13299
13305
CapabilitySet& setToFind)
13300
13306
{
13301
- HashSet<Decl *> checkedDecls;
13302
- DeclReferenceWithLoc declWithRef ;
13303
- declWithRef.referencedDecl = decl;
13304
- declWithRef .referenceLoc = (decl) ? decl->loc : SourceLoc();
13307
+ HashSet<NodeBase *> checkedDecls;
13308
+ ProvenenceNodeWithLoc provNode ;
13309
+ provNode.referencedNode = decl;
13310
+ provNode .referenceLoc = (decl) ? decl->loc : SourceLoc();
13305
13311
bool bottomOfProvenanceStack = false;
13306
13312
// Find the bottom of the atom provenance stack which fails to contain `setToFind`
13307
- while (!bottomOfProvenanceStack && declWithRef.referencedDecl )
13313
+ while (!bottomOfProvenanceStack && provNode.referencedNode )
13308
13314
{
13309
13315
bottomOfProvenanceStack = true;
13310
- for (auto& i : declWithRef.referencedDecl->capabilityRequirementProvenance )
13316
+ if (auto referencedDecl = as<Decl>(provNode.referencedNode) )
13311
13317
{
13312
- if (checkedDecls.contains(i.referencedDecl))
13313
- continue;
13314
- checkedDecls.add(i.referencedDecl);
13315
-
13316
- if (!i.referencedDecl->inferredCapabilityRequirements.implies(setToFind))
13318
+ for (auto& i : referencedDecl->capabilityRequirementProvenance)
13317
13319
{
13318
- // We found a source of the incompatible capability, follow this
13319
- // element inside the provenance stack until we are at the bottom
13320
- declWithRef = i;
13321
- bottomOfProvenanceStack = false;
13322
- break;
13320
+ if (checkedDecls.contains(i.referencedNode))
13321
+ continue;
13322
+ checkedDecls.add(i.referencedNode);
13323
+ auto innerReferencedDecl = as<Decl>(i.referencedNode);
13324
+ if (!innerReferencedDecl ||
13325
+ !innerReferencedDecl->inferredCapabilityRequirements.implies(setToFind))
13326
+ {
13327
+ // We found a source of the incompatible capability, follow this
13328
+ // element inside the provenance stack until we are at the bottom
13329
+ provNode = i;
13330
+ bottomOfProvenanceStack = false;
13331
+ break;
13332
+ }
13323
13333
}
13324
13334
}
13335
+ else
13336
+ {
13337
+ bottomOfProvenanceStack = true;
13338
+ }
13325
13339
}
13326
13340
13327
- if (!declWithRef.referencedDecl )
13341
+ if (!provNode.referencedNode )
13328
13342
return;
13329
13343
13330
- // Diagnose the use-site
13331
- maybeDiagnose(
13332
- sink,
13333
- optionSet,
13334
- DiagnosticCategory::Capability,
13335
- declWithRef.referenceLoc,
13336
- Diagnostics::seeUsingOf,
13337
- declWithRef.referencedDecl);
13338
- // Diagnose the definition as the problem
13339
- maybeDiagnose(
13340
- sink,
13341
- optionSet,
13342
- DiagnosticCategory::Capability,
13343
- declWithRef.referencedDecl->loc,
13344
- Diagnostics::seeDefinitionOf,
13345
- declWithRef.referencedDecl);
13346
-
13347
- // If we find a 'require' modifier, this is contributing to the overall capability
13348
- // incompatibility. We should hint to the user that this declaration is problematic.
13349
- if (auto requireCapabilityAttribute =
13350
- declWithRef.referencedDecl->findModifier<RequireCapabilityAttribute>())
13344
+ if (auto referencedDecl = as<Decl>(provNode.referencedNode))
13345
+ {
13346
+ // Diagnose the use-site
13351
13347
maybeDiagnose(
13352
13348
sink,
13353
13349
optionSet,
13354
13350
DiagnosticCategory::Capability,
13355
- requireCapabilityAttribute->loc,
13356
- Diagnostics::seeDeclarationOf,
13357
- requireCapabilityAttribute);
13351
+ provNode.referenceLoc,
13352
+ Diagnostics::seeUsingOf,
13353
+ referencedDecl);
13354
+ // Diagnose the definition as the problem
13355
+ maybeDiagnose(
13356
+ sink,
13357
+ optionSet,
13358
+ DiagnosticCategory::Capability,
13359
+ referencedDecl->loc,
13360
+ Diagnostics::seeDefinitionOf,
13361
+ referencedDecl);
13362
+ // If we find a 'require' modifier, this is contributing to the overall capability
13363
+ // incompatibility. We should hint to the user that this declaration is problematic.
13364
+ if (auto requireCapabilityAttribute =
13365
+ referencedDecl->findModifier<RequireCapabilityAttribute>())
13366
+ maybeDiagnose(
13367
+ sink,
13368
+ optionSet,
13369
+ DiagnosticCategory::Capability,
13370
+ requireCapabilityAttribute->loc,
13371
+ Diagnostics::seeDeclarationOf,
13372
+ requireCapabilityAttribute);
13373
+ }
13374
+ else
13375
+ {
13376
+ maybeDiagnose(
13377
+ sink,
13378
+ optionSet,
13379
+ DiagnosticCategory::Capability,
13380
+ provNode.referenceLoc,
13381
+ Diagnostics::seeUsingOf,
13382
+ provNode.referencedNode->astNodeType);
13383
+ }
13358
13384
}
13359
13385
13360
13386
void diagnoseCapabilityProvenance(
@@ -13372,16 +13398,29 @@ void diagnoseCapabilityProvenance(
13372
13398
printedDecls.add(declToPrint);
13373
13399
for (auto& provenance : declToPrint->capabilityRequirementProvenance)
13374
13400
{
13375
- if (!provenance.referencedDecl->inferredCapabilityRequirements.implies(atomToFind))
13401
+ auto referencedDecl = as<Decl>(provenance.referencedNode);
13402
+ if (!referencedDecl)
13403
+ {
13404
+ maybeDiagnose(
13405
+ sink,
13406
+ optionSet,
13407
+ DiagnosticCategory::Capability,
13408
+ provenance.referenceLoc,
13409
+ Diagnostics::seeUsingOf,
13410
+ provenance.referencedNode->astNodeType);
13411
+ break;
13412
+ }
13413
+
13414
+ if (!referencedDecl->inferredCapabilityRequirements.implies(atomToFind))
13376
13415
continue;
13377
13416
maybeDiagnose(
13378
13417
sink,
13379
13418
optionSet,
13380
13419
DiagnosticCategory::Capability,
13381
13420
provenance.referenceLoc,
13382
13421
Diagnostics::seeUsingOf,
13383
- provenance. referencedDecl);
13384
- declToPrint = provenance. referencedDecl;
13422
+ referencedDecl);
13423
+ declToPrint = referencedDecl;
13385
13424
if (printedDecls.contains(declToPrint))
13386
13425
break;
13387
13426
if (declToPrint->findModifier<RequireCapabilityAttribute>())
@@ -13487,14 +13526,30 @@ void SemanticsDeclCapabilityVisitor::diagnoseUndeclaredCapability(
13487
13526
for (auto i : simplifiedFailedAtomsSet)
13488
13527
{
13489
13528
CapabilityAtom formattedAtom = asAtom(i);
13490
- maybeDiagnose(
13491
- getSink(),
13492
- this->getOptionSet(),
13493
- DiagnosticCategory::Capability,
13494
- decl->loc,
13495
- diagnosticInfo,
13496
- decl,
13497
- formattedAtom);
13529
+ CapabilityName canonicalName;
13530
+ if (isStageAtom((CapabilityName)formattedAtom, canonicalName))
13531
+ {
13532
+ // Provide a more friendly message if atom is a stage.
13533
+ maybeDiagnose(
13534
+ getSink(),
13535
+ this->getOptionSet(),
13536
+ DiagnosticCategory::Capability,
13537
+ decl->loc,
13538
+ Diagnostics::declHasDependenciesNotCompatibleOnStage,
13539
+ decl,
13540
+ formattedAtom);
13541
+ }
13542
+ else
13543
+ {
13544
+ maybeDiagnose(
13545
+ getSink(),
13546
+ this->getOptionSet(),
13547
+ DiagnosticCategory::Capability,
13548
+ decl->loc,
13549
+ diagnosticInfo,
13550
+ decl,
13551
+ formattedAtom);
13552
+ }
13498
13553
// Print provenances.
13499
13554
diagnoseCapabilityProvenance(
13500
13555
this->getOptionSet(),
0 commit comments