[clang] [Clang] Improve EmitClangAttrSpellingListIndex (PR #114899)
Erich Keane via cfe-commits
cfe-commits at lists.llvm.org
Tue Nov 5 06:17:05 PST 2024
================
@@ -3841,19 +3842,110 @@ void EmitClangAttrSpellingListIndex(const RecordKeeper &Records,
const Record &R = *I.second;
std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
OS << " case AT_" << I.first << ": {\n";
- for (unsigned I = 0; I < Spellings.size(); ++ I) {
- OS << " if (Name == \"" << Spellings[I].name() << "\" && "
- << "getSyntax() == AttributeCommonInfo::AS_" << Spellings[I].variety()
- << " && Scope == \"" << Spellings[I].nameSpace() << "\")\n"
- << " return " << I << ";\n";
+
+ // If there are none or one spelling to check, resort to the default
+ // behavior of returning index as 0.
+ if (Spellings.size() <= 1) {
+ OS << " return 0;\n"
+ << " break;\n"
+ << " }\n";
+ continue;
}
- OS << " break;\n";
- OS << " }\n";
+ bool HasSingleUniqueSpellingName = true;
+ StringMap<std::vector<const FlattenedSpelling *>> SpellingMap;
+
+ StringRef FirstName = Spellings.front().name();
----------------
erichkeane wrote:
This does a ton of work in a way that is pretty difficult. Really what you're trying to find is that all of the names are the same, plus information about the names. I think something like:
```
std::vector<StringRef> Names;
llvm::transform(Spellings, std::back_inserter(Names), [](const FlattenedSpelling &FS) { return FS.name(); });
llvm::sort(Names);
llvm::erase(llvm::unique(Names), Names.end());
```
Would give you a lot of information that would be necessary/useful later.
First, you can check:
`Names.size() ==1` <= Means that all of the names are the same name, so you can skip the name check entirely.
`Names.end() == std::adjacent_find(Names.begin(), Names.end(), [](StringRef LHS, StringRef RHS){ return LHS.size() == RHS.size(); });`
If THAT is true, all you have to do is check 'size', since all of them have a unique length.
THOUGH, you probably want to do this on a 'size' of name basis, so if you do that in the loop of the current `FlattenedSpelling` (and add to the condition in the `adjacent_find` that the size is the current `FS.name().size()`), if you don't find one, you can do just the size check.
Alternatively, you can do just a `copy_if` from that based on the current `FlattenedSpelling` name's size, which would give you the bits to tell which actual characters to check. So something like:
```
for (const FlattenedSpelling &FS : Spellings) {
std::vector<StringRef> SameLenNames;
llvm::copy_if(Names, std::back_inserter(SameLenNames), [&](StringRef N) { return N.size() == FS.name().size(); });
// insert print size check here
-- Since Names.size() > 1 above, we actually have to check the sizes. THOUGH, IMO, you can be a little smarter about combining it into here too, and only doing the copy_if that is necessary (so we only do the loop on Spellings once).
if (SameLenNames.size() > 1) {
// if size > 1 we have to check individual characters, else we could just do size + scope/etc
// print with just the size check.
for(StringRef SLN : SameLenNames) {
if (SLN == FS.name()) continue; // don't check same name!
auto [CurItr, OtherItr] = std::mismatch(FS.name().begin(), FS.name().end(), SLN.begin());
// NOW you know which character to check to make sure we're unique. so something like:
OS << "Name[" << std::distance(FS.name().begin(), CurItr) << "] == '" << *CurItr << "'';
}
}
}
```
THOUGH, like i said, you can probably combine the `Names.size() ==1` condition inside of that loop as well. And probably the `adjacent_find` test can be skipped with the loop I just wrote above.
https://github.com/llvm/llvm-project/pull/114899
More information about the cfe-commits
mailing list