diff --git a/clang/utils/TableGen/ClangOptionDocEmitter.cpp b/clang/utils/TableGen/ClangOptionDocEmitter.cpp --- a/clang/utils/TableGen/ClangOptionDocEmitter.cpp +++ b/clang/utils/TableGen/ClangOptionDocEmitter.cpp @@ -31,13 +31,41 @@ struct Documentation { std::vector Groups; std::vector Options; + + bool empty() { + return Groups.empty() && Options.empty(); + } }; struct DocumentedGroup : Documentation { Record *Group; }; +bool hasFlag(const Record *Option, StringRef OptionFlag) { + for (const Record *Flag : Option->getValueAsListOfDefs("Flags")) + if (Flag->getName() == OptionFlag) + return true; + if (const DefInit *DI = dyn_cast(Option->getValueInit("Group"))) + for (const Record *Flag : DI->getDef()->getValueAsListOfDefs("Flags")) + if (Flag->getName() == OptionFlag) + return true; + return false; +} + +bool isOptionVisible(const Record *Option, const Record *DocInfo) { + for (StringRef Exclusion : DocInfo->getValueAsListOfStrings("ExcludedFlags")) + if (hasFlag(Option, Exclusion)) + return false; + if (!DocInfo->getValue("IncludedFlags")) + return true; + for (StringRef Inclusion : DocInfo->getValueAsListOfStrings("IncludedFlags")) + if (hasFlag(Option, Inclusion)) + return true; + return false; +} + // Reorganize the records into a suitable form for emitting documentation. -Documentation extractDocumentation(RecordKeeper &Records) { +Documentation extractDocumentation(RecordKeeper &Records, + const Record *DocInfo) { Documentation Result; // Build the tree of groups. The root in the tree is the fake option group @@ -124,12 +152,15 @@ D.Groups.back().Group = G; Documentation &Base = D.Groups.back(); Base = DocumentationForGroup(G); + if (Base.empty()) + D.Groups.pop_back(); } auto &Options = OptionsInGroup[R]; llvm::sort(Options, CompareByName); for (Record *O : Options) - D.Options.push_back(DocumentationForOption(O)); + if (isOptionVisible(O, DocInfo)) + D.Options.push_back(DocumentationForOption(O)); return D; }; @@ -161,44 +192,6 @@ .Default(0); } -bool hasFlag(const Record *OptionOrGroup, StringRef OptionFlag) { - for (const Record *Flag : OptionOrGroup->getValueAsListOfDefs("Flags")) - if (Flag->getName() == OptionFlag) - return true; - return false; -} - -bool isIncluded(const Record *OptionOrGroup, const Record *DocInfo) { - assert(DocInfo->getValue("IncludedFlags") && "Missing includeFlags"); - for (StringRef Inclusion : DocInfo->getValueAsListOfStrings("IncludedFlags")) - if (hasFlag(OptionOrGroup, Inclusion)) - return true; - return false; -} - -bool isGroupIncluded(const DocumentedGroup &Group, const Record *DocInfo) { - if (isIncluded(Group.Group, DocInfo)) - return true; - for (auto &O : Group.Options) - if (isIncluded(O.Option, DocInfo)) - return true; - for (auto &G : Group.Groups) { - if (isIncluded(G.Group, DocInfo)) - return true; - if (isGroupIncluded(G, DocInfo)) - return true; - } - return false; -} - -bool isExcluded(const Record *OptionOrGroup, const Record *DocInfo) { - // FIXME: Provide a flag to specify the set of exclusions. - for (StringRef Exclusion : DocInfo->getValueAsListOfStrings("ExcludedFlags")) - if (hasFlag(OptionOrGroup, Exclusion)) - return true; - return false; -} - std::string escapeRST(StringRef Str) { std::string Out; for (auto K : Str) { @@ -319,16 +312,13 @@ F(Option.Option); for (auto *Alias : Option.Aliases) - if (!isExcluded(Alias, DocInfo) && canSphinxCopeWithOption(Option.Option)) + if (isOptionVisible(Alias, DocInfo) && + canSphinxCopeWithOption(Option.Option)) F(Alias); } void emitOption(const DocumentedOption &Option, const Record *DocInfo, raw_ostream &OS) { - if (isExcluded(Option.Option, DocInfo)) - return; - if (DocInfo->getValue("IncludedFlags") && !isIncluded(Option.Option, DocInfo)) - return; if (Option.Option->getValueAsDef("Kind")->getName() == "KIND_UNKNOWN" || Option.Option->getValueAsDef("Kind")->getName() == "KIND_INPUT") return; @@ -401,12 +391,6 @@ void emitGroup(int Depth, const DocumentedGroup &Group, const Record *DocInfo, raw_ostream &OS) { - if (isExcluded(Group.Group, DocInfo)) - return; - - if (DocInfo->getValue("IncludedFlags") && !isGroupIncluded(Group, DocInfo)) - return; - emitHeading(Depth, getRSTStringWithTextFallback(Group.Group, "DocName", "Name"), OS); @@ -440,5 +424,5 @@ OS << DocInfo->getValueAsString("Intro") << "\n"; OS << ".. program:: " << DocInfo->getValueAsString("Program") << "\n"; - emitDocumentation(0, extractDocumentation(Records), DocInfo, OS); + emitDocumentation(0, extractDocumentation(Records, DocInfo), DocInfo, OS); }