summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/slang-capability-generator/capability-generator-main.cpp38
-rw-r--r--tools/slang-capability-generator/slang-capability-diagnostic-defs.h1
2 files changed, 37 insertions, 2 deletions
diff --git a/tools/slang-capability-generator/capability-generator-main.cpp b/tools/slang-capability-generator/capability-generator-main.cpp
index e4a4885c6..711532273 100644
--- a/tools/slang-capability-generator/capability-generator-main.cpp
+++ b/tools/slang-capability-generator/capability-generator-main.cpp
@@ -258,6 +258,39 @@ struct CapabilityDefParser
return SLANG_OK;
}
+ void validateInternalAtomExternalAtomPair()
+ {
+ // All `_Internal` atoms must have an `External` atom.
+ // `External` atoms do not require to have an `_Internal` atom.
+ // The following behavior ensures that if we error with 'atom' instead of
+ // '_atom' a user may add the 'atom' capability to solve their error. This is
+ // important because '_Internal' will only be for 1 target, 'External' will alias
+ // to more than 1 target. We need to ensure users avoid 'Internal' when possible.
+
+ Dictionary<String, List<RefPtr<CapabilityDef>>> nameToInternalAndExternalAtom;
+ for(auto i : m_defs)
+ {
+ // 'abstract' atoms are not reported to a user and are ignored
+ if (i->flavor == CapabilityFlavor::Abstract)
+ continue;
+
+ // Try to pack `_atom` and `atom` into the same per key List
+ String name = i->name;
+ if(i->name.startsWith("_"))
+ name = name.subString(1, name.getLength()-1);
+ nameToInternalAndExternalAtom[name].add(i);
+ }
+ for(auto i : nameToInternalAndExternalAtom)
+ {
+ SLANG_ASSERT(i.second.getCount() <= 2);
+ if(i.second.getCount() != 2)
+ {
+ // If we only have a '_Internal' atom inside our name list there is a missing 'External' atom
+ if(i.second[0]->name.startsWith("_"))
+ m_sink->diagnose(i.second[0]->sourceLoc, Diagnostics::missingExternalInternalAtomPair, i.second[0]->name);
+ }
+ }
+ }
SlangResult parseDefs()
{
auto tokens = m_lexer->lexAllSemanticTokens();
@@ -337,6 +370,7 @@ struct CapabilityDefParser
def->sourceLoc = nameToken.loc;
}
+ validateInternalAtomExternalAtomPair();
return SLANG_OK;
}
};
@@ -856,12 +890,12 @@ SlangResult generateDefinitions(DiagnosticSink* sink, List<RefPtr<CapabilityDef>
{
if (!def)
{
- sbCpp << R"( { "Invalid", CapabilityNameFlavor::Concrete, CapabilityName::Invalid, 0, {nullptr, 0} },)" << "\n";
+ sbCpp << R"( { UnownedStringSlice::fromLiteral("Invalid"), CapabilityNameFlavor::Concrete, CapabilityName::Invalid, 0, {nullptr, 0} },)" << "\n";
continue;
}
// name.
- sbCpp << " { \"" << def->name << "\", ";
+ sbCpp << " { UnownedStringSlice::fromLiteral(\"" << def->name << "\"), ";
// flavor.
switch (def->flavor)
diff --git a/tools/slang-capability-generator/slang-capability-diagnostic-defs.h b/tools/slang-capability-generator/slang-capability-diagnostic-defs.h
index 1415b1f59..b6c4425a2 100644
--- a/tools/slang-capability-generator/slang-capability-diagnostic-defs.h
+++ b/tools/slang-capability-generator/slang-capability-diagnostic-defs.h
@@ -56,4 +56,5 @@ DIAGNOSTIC(20003, Error, undefinedIdentifier, "undefined identifier \"$0\".")
DIAGNOSTIC(20004, Error, redefinition, "capability redefinition: '$0'.")
DIAGNOSTIC(20005, Error, unionWithSameKeyAtomButNotSubset, "unioning ('|') capability sets which have incompatible atoms but compatible 'key atoms', this: '$0', other: '$1'")
DIAGNOSTIC(20006, Error, invalidJoinInGenerator, "joining ('+') capability sets which have incompatible 'key atoms'")
+DIAGNOSTIC(20007, Error, missingExternalInternalAtomPair, "All internal '_atom' require a corresponding external 'atom' atom meant for user's use. Offending atom: $0")
#undef DIAGNOSTIC