diff options
Diffstat (limited to 'utils/TableGen/ClangAttrEmitter.cpp')
| -rw-r--r-- | utils/TableGen/ClangAttrEmitter.cpp | 297 |
1 files changed, 220 insertions, 77 deletions
diff --git a/utils/TableGen/ClangAttrEmitter.cpp b/utils/TableGen/ClangAttrEmitter.cpp index b0e2ddd91362a..0bf7a07cf6e14 100644 --- a/utils/TableGen/ClangAttrEmitter.cpp +++ b/utils/TableGen/ClangAttrEmitter.cpp @@ -87,6 +87,8 @@ GetFlattenedSpellings(const Record &Attr) { } else if (Variety == "Clang") { Ret.emplace_back("GNU", Name, "", false); Ret.emplace_back("CXX11", Name, "clang", false); + if (Spelling->getValueAsBit("AllowInC")) + Ret.emplace_back("C2x", Name, "clang", false); } else Ret.push_back(FlattenedSpelling(*Spelling)); } @@ -102,6 +104,7 @@ static std::string ReadPCHRecord(StringRef type) { .Case("Expr *", "Record.readExpr()") .Case("IdentifierInfo *", "Record.getIdentifierInfo()") .Case("StringRef", "Record.readString()") + .Case("ParamIdx", "ParamIdx::deserialize(Record.readInt())") .Default("Record.readInt()"); } @@ -120,6 +123,7 @@ static std::string WritePCHRecord(StringRef type, StringRef name) { .Case("Expr *", "AddStmt(" + std::string(name) + ");\n") .Case("IdentifierInfo *", "AddIdentifierRef(" + std::string(name) + ");\n") .Case("StringRef", "AddString(" + std::string(name) + ");\n") + .Case("ParamIdx", "push_back(" + std::string(name) + ".serialize());\n") .Default("push_back(" + std::string(name) + ");\n"); } @@ -229,6 +233,7 @@ namespace { virtual void writePCHReadArgs(raw_ostream &OS) const = 0; virtual void writePCHReadDecls(raw_ostream &OS) const = 0; virtual void writePCHWrite(raw_ostream &OS) const = 0; + virtual std::string getIsOmitted() const { return "false"; } virtual void writeValue(raw_ostream &OS) const = 0; virtual void writeDump(raw_ostream &OS) const = 0; virtual void writeDumpChildren(raw_ostream &OS) const {} @@ -296,23 +301,29 @@ namespace { std::string(getUpperName()) + "()"); } + std::string getIsOmitted() const override { + if (type == "IdentifierInfo *") + return "!get" + getUpperName().str() + "()"; + if (type == "ParamIdx") + return "!get" + getUpperName().str() + "().isValid()"; + return "false"; + } + void writeValue(raw_ostream &OS) const override { - if (type == "FunctionDecl *") { + if (type == "FunctionDecl *") OS << "\" << get" << getUpperName() << "()->getNameInfo().getAsString() << \""; - } else if (type == "IdentifierInfo *") { - OS << "\";\n"; - if (isOptional()) - OS << " if (get" << getUpperName() << "()) "; - else - OS << " "; - OS << "OS << get" << getUpperName() << "()->getName();\n"; - OS << " OS << \""; - } else if (type == "TypeSourceInfo *") { + else if (type == "IdentifierInfo *") + // Some non-optional (comma required) identifier arguments can be the + // empty string but are then recorded as a nullptr. + OS << "\" << (get" << getUpperName() << "() ? get" << getUpperName() + << "()->getName() : \"\") << \""; + else if (type == "TypeSourceInfo *") OS << "\" << get" << getUpperName() << "().getAsString() << \""; - } else { + else if (type == "ParamIdx") + OS << "\" << get" << getUpperName() << "().getSourceIndex() << \""; + else OS << "\" << get" << getUpperName() << "() << \""; - } } void writeDump(raw_ostream &OS) const override { @@ -320,9 +331,10 @@ namespace { OS << " OS << \" \";\n"; OS << " dumpBareDeclRef(SA->get" << getUpperName() << "());\n"; } else if (type == "IdentifierInfo *") { - if (isOptional()) - OS << " if (SA->get" << getUpperName() << "())\n "; - OS << " OS << \" \" << SA->get" << getUpperName() + // Some non-optional (comma required) identifier arguments can be the + // empty string but are then recorded as a nullptr. + OS << " if (SA->get" << getUpperName() << "())\n" + << " OS << \" \" << SA->get" << getUpperName() << "()->getName();\n"; } else if (type == "TypeSourceInfo *") { OS << " OS << \" \" << SA->get" << getUpperName() @@ -332,6 +344,11 @@ namespace { << getUpperName() << "\";\n"; } else if (type == "int" || type == "unsigned") { OS << " OS << \" \" << SA->get" << getUpperName() << "();\n"; + } else if (type == "ParamIdx") { + if (isOptional()) + OS << " if (SA->get" << getUpperName() << "().isValid())\n "; + OS << " OS << \" \" << SA->get" << getUpperName() + << "().getSourceIndex();\n"; } else { llvm_unreachable("Unknown SimpleArgument type!"); } @@ -574,12 +591,15 @@ namespace { << "Type());\n"; } + std::string getIsOmitted() const override { + return "!is" + getLowerName().str() + "Expr || !" + getLowerName().str() + + "Expr"; + } + void writeValue(raw_ostream &OS) const override { OS << "\";\n"; - // The aligned attribute argument expression is optional. - OS << " if (is" << getLowerName() << "Expr && " - << getLowerName() << "Expr)\n"; - OS << " " << getLowerName() << "Expr->printPretty(OS, nullptr, Policy);\n"; + OS << " " << getLowerName() + << "Expr->printPretty(OS, nullptr, Policy);\n"; OS << " OS << \""; } @@ -606,6 +626,10 @@ namespace { virtual void writeValueImpl(raw_ostream &OS) const { OS << " OS << Val;\n"; } + // Assumed to receive a parameter: raw_ostream OS. + virtual void writeDumpImpl(raw_ostream &OS) const { + OS << " OS << \" \" << Val;\n"; + } public: VariadicArgument(const Record &Arg, StringRef Attr, std::string T) @@ -732,7 +756,22 @@ namespace { void writeDump(raw_ostream &OS) const override { OS << " for (const auto &Val : SA->" << RangeName << "())\n"; - OS << " OS << \" \" << Val;\n"; + writeDumpImpl(OS); + } + }; + + class VariadicParamIdxArgument : public VariadicArgument { + public: + VariadicParamIdxArgument(const Record &Arg, StringRef Attr) + : VariadicArgument(Arg, Attr, "ParamIdx") {} + + public: + void writeValueImpl(raw_ostream &OS) const override { + OS << " OS << Val.getSourceIndex();\n"; + } + + void writeDumpImpl(raw_ostream &OS) const override { + OS << " OS << \" \" << Val.getSourceIndex();\n"; } }; @@ -1134,6 +1173,13 @@ namespace { } }; + class VariadicIdentifierArgument : public VariadicArgument { + public: + VariadicIdentifierArgument(const Record &Arg, StringRef Attr) + : VariadicArgument(Arg, Attr, "IdentifierInfo *") + {} + }; + class VariadicStringArgument : public VariadicArgument { public: VariadicStringArgument(const Record &Arg, StringRef Attr) @@ -1235,6 +1281,12 @@ createArgument(const Record &Arg, StringRef Attr, Ptr = llvm::make_unique<VariadicEnumArgument>(Arg, Attr); else if (ArgName == "VariadicExprArgument") Ptr = llvm::make_unique<VariadicExprArgument>(Arg, Attr); + else if (ArgName == "VariadicParamIdxArgument") + Ptr = llvm::make_unique<VariadicParamIdxArgument>(Arg, Attr); + else if (ArgName == "ParamIdxArgument") + Ptr = llvm::make_unique<SimpleArgument>(Arg, Attr, "ParamIdx"); + else if (ArgName == "VariadicIdentifierArgument") + Ptr = llvm::make_unique<VariadicIdentifierArgument>(Arg, Attr); else if (ArgName == "VersionArgument") Ptr = llvm::make_unique<VersionArgument>(Arg, Attr); @@ -1366,7 +1418,7 @@ writePrettyPrintFunction(Record &R, " OS << \"" << Prefix << Spelling; if (Variety == "Pragma") { - OS << " \";\n"; + OS << "\";\n"; OS << " printPrettyPragma(OS, Policy);\n"; OS << " OS << \"\\n\";"; OS << " break;\n"; @@ -1374,33 +1426,83 @@ writePrettyPrintFunction(Record &R, continue; } - // Fake arguments aren't part of the parsed form and should not be - // pretty-printed. - bool hasNonFakeArgs = llvm::any_of( - Args, [](const std::unique_ptr<Argument> &A) { return !A->isFake(); }); - - // FIXME: always printing the parenthesis isn't the correct behavior for - // attributes which have optional arguments that were not provided. For - // instance: __attribute__((aligned)) will be pretty printed as - // __attribute__((aligned())). The logic should check whether there is only - // a single argument, and if it is optional, whether it has been provided. - if (hasNonFakeArgs) - OS << "("; if (Spelling == "availability") { + OS << "("; writeAvailabilityValue(OS); + OS << ")"; } else if (Spelling == "deprecated" || Spelling == "gnu::deprecated") { - writeDeprecatedAttrValue(OS, Variety); + OS << "("; + writeDeprecatedAttrValue(OS, Variety); + OS << ")"; } else { - unsigned index = 0; + // To avoid printing parentheses around an empty argument list or + // printing spurious commas at the end of an argument list, we need to + // determine where the last provided non-fake argument is. + unsigned NonFakeArgs = 0; + unsigned TrailingOptArgs = 0; + bool FoundNonOptArg = false; + for (const auto &arg : llvm::reverse(Args)) { + if (arg->isFake()) + continue; + ++NonFakeArgs; + if (FoundNonOptArg) + continue; + // FIXME: arg->getIsOmitted() == "false" means we haven't implemented + // any way to detect whether the argument was omitted. + if (!arg->isOptional() || arg->getIsOmitted() == "false") { + FoundNonOptArg = true; + continue; + } + if (!TrailingOptArgs++) + OS << "\";\n" + << " unsigned TrailingOmittedArgs = 0;\n"; + OS << " if (" << arg->getIsOmitted() << ")\n" + << " ++TrailingOmittedArgs;\n"; + } + if (TrailingOptArgs) + OS << " OS << \""; + if (TrailingOptArgs < NonFakeArgs) + OS << "("; + else if (TrailingOptArgs) + OS << "\";\n" + << " if (TrailingOmittedArgs < " << NonFakeArgs << ")\n" + << " OS << \"(\";\n" + << " OS << \""; + unsigned ArgIndex = 0; for (const auto &arg : Args) { - if (arg->isFake()) continue; - if (index++) OS << ", "; + if (arg->isFake()) + continue; + if (ArgIndex) { + if (ArgIndex >= NonFakeArgs - TrailingOptArgs) + OS << "\";\n" + << " if (" << ArgIndex << " < " << NonFakeArgs + << " - TrailingOmittedArgs)\n" + << " OS << \", \";\n" + << " OS << \""; + else + OS << ", "; + } + std::string IsOmitted = arg->getIsOmitted(); + if (arg->isOptional() && IsOmitted != "false") + OS << "\";\n" + << " if (!(" << IsOmitted << ")) {\n" + << " OS << \""; arg->writeValue(OS); + if (arg->isOptional() && IsOmitted != "false") + OS << "\";\n" + << " }\n" + << " OS << \""; + ++ArgIndex; } + if (TrailingOptArgs < NonFakeArgs) + OS << ")"; + else if (TrailingOptArgs) + OS << "\";\n" + << " if (TrailingOmittedArgs < " << NonFakeArgs << ")\n" + << " OS << \")\";\n" + << " OS << \""; } - if (hasNonFakeArgs) - OS << ")"; OS << Suffix + "\";\n"; OS << @@ -1414,7 +1516,7 @@ writePrettyPrintFunction(Record &R, OS << "}\n\n"; } -/// \brief Return the index of a spelling in a spelling list. +/// Return the index of a spelling in a spelling list. static unsigned getSpellingListIndex(const std::vector<FlattenedSpelling> &SpellingList, const FlattenedSpelling &Spelling) { @@ -1963,7 +2065,7 @@ static void forEachUniqueSpelling(const Record &Attr, Fn &&F) { } } -/// \brief Emits the first-argument-is-type property for attributes. +/// Emits the first-argument-is-type property for attributes. static void emitClangAttrTypeArgList(RecordKeeper &Records, raw_ostream &OS) { OS << "#if defined(CLANG_ATTR_TYPE_ARG_LIST)\n"; std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr"); @@ -1985,7 +2087,7 @@ static void emitClangAttrTypeArgList(RecordKeeper &Records, raw_ostream &OS) { OS << "#endif // CLANG_ATTR_TYPE_ARG_LIST\n\n"; } -/// \brief Emits the parse-arguments-in-unevaluated-context property for +/// Emits the parse-arguments-in-unevaluated-context property for /// attributes. static void emitClangAttrArgContextList(RecordKeeper &Records, raw_ostream &OS) { OS << "#if defined(CLANG_ATTR_ARG_CONTEXT_LIST)\n"; @@ -2013,6 +2115,34 @@ static bool isIdentifierArgument(Record *Arg) { .Default(false); } +static bool isVariadicIdentifierArgument(Record *Arg) { + return !Arg->getSuperClasses().empty() && + llvm::StringSwitch<bool>( + Arg->getSuperClasses().back().first->getName()) + .Case("VariadicIdentifierArgument", true) + .Default(false); +} + +static void emitClangAttrVariadicIdentifierArgList(RecordKeeper &Records, + raw_ostream &OS) { + OS << "#if defined(CLANG_ATTR_VARIADIC_IDENTIFIER_ARG_LIST)\n"; + std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr"); + for (const auto *A : Attrs) { + // Determine whether the first argument is a variadic identifier. + std::vector<Record *> Args = A->getValueAsListOfDefs("Args"); + if (Args.empty() || !isVariadicIdentifierArgument(Args[0])) + continue; + + // All these spellings take an identifier argument. + forEachUniqueSpelling(*A, [&](const FlattenedSpelling &S) { + OS << ".Case(\"" << S.name() << "\", " + << "true" + << ")\n"; + }); + } + OS << "#endif // CLANG_ATTR_VARIADIC_IDENTIFIER_ARG_LIST\n\n"; +} + // Emits the first-argument-is-identifier property for attributes. static void emitClangAttrIdentifierArgList(RecordKeeper &Records, raw_ostream &OS) { OS << "#if defined(CLANG_ATTR_IDENTIFIER_ARG_LIST)\n"; @@ -2063,10 +2193,14 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) { ArrayRef<std::pair<Record *, SMRange>> Supers = R.getSuperClasses(); assert(!Supers.empty() && "Forgot to specify a superclass for the attr"); std::string SuperName; + bool Inheritable = false; for (const auto &Super : llvm::reverse(Supers)) { const Record *R = Super.first; - if (R->getName() != "TargetSpecificAttr" && SuperName.empty()) + if (R->getName() != "TargetSpecificAttr" && + R->getName() != "DeclOrTypeAttr" && SuperName.empty()) SuperName = R->getName(); + if (R->getName() == "InheritableAttr") + Inheritable = true; } OS << "class " << R.getName() << "Attr : public " << SuperName << " {\n"; @@ -2160,8 +2294,13 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) { OS << " )\n"; OS << " : " << SuperName << "(attr::" << R.getName() << ", R, SI, " - << ( R.getValueAsBit("LateParsed") ? "true" : "false" ) << ", " - << ( R.getValueAsBit("DuplicatesAllowedWhileMerging") ? "true" : "false" ) << ")\n"; + << ( R.getValueAsBit("LateParsed") ? "true" : "false" ); + if (Inheritable) { + OS << ", " + << (R.getValueAsBit("InheritEvenIfAlreadyPresent") ? "true" + : "false"); + } + OS << ")\n"; for (auto const &ai : Args) { OS << " , "; @@ -3030,7 +3169,7 @@ static void emitArgInfo(const Record &R, raw_ostream &OS) { } static void GenerateDefaultAppertainsTo(raw_ostream &OS) { - OS << "static bool defaultAppertainsTo(Sema &, const AttributeList &,"; + OS << "static bool defaultAppertainsTo(Sema &, const ParsedAttr &,"; OS << "const Decl *) {\n"; OS << " return true;\n"; OS << "}\n\n"; @@ -3168,7 +3307,7 @@ static std::string GenerateAppertainsTo(const Record &Attr, raw_ostream &OS) { // name of that check to the caller. std::string FnName = "check" + Attr.getName().str() + "AppertainsTo"; std::stringstream SS; - SS << "static bool " << FnName << "(Sema &S, const AttributeList &Attr, "; + SS << "static bool " << FnName << "(Sema &S, const ParsedAttr &Attr, "; SS << "const Decl *D) {\n"; SS << " if ("; for (auto I = Subjects.begin(), E = Subjects.end(); I != E; ++I) { @@ -3240,7 +3379,7 @@ emitAttributeMatchRules(PragmaClangAttributeSupport &PragmaAttributeSupport, static void GenerateDefaultLangOptRequirements(raw_ostream &OS) { OS << "static bool defaultDiagnoseLangOpts(Sema &, "; - OS << "const AttributeList &) {\n"; + OS << "const ParsedAttr &) {\n"; OS << " return true;\n"; OS << "}\n\n"; } @@ -3279,7 +3418,7 @@ static std::string GenerateLangOptRequirements(const Record &R, if (I != CustomLangOptsSet.end()) return *I; - OS << "static bool " << FnName << "(Sema &S, const AttributeList &Attr) {\n"; + OS << "static bool " << FnName << "(Sema &S, const ParsedAttr &Attr) {\n"; OS << " if (" << Test << ")\n"; OS << " return true;\n\n"; OS << " S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) "; @@ -3312,7 +3451,7 @@ static std::string GenerateTargetRequirements(const Record &Attr, // If there are other attributes which share the same parsed attribute kind, // such as target-specific attributes with a shared spelling, collapse the // duplicate architectures. This is required because a shared target-specific - // attribute has only one AttributeList::Kind enumeration value, but it + // attribute has only one ParsedAttr::Kind enumeration value, but it // applies to multiple target architectures. In order for the attribute to be // considered valid, all of its architectures need to be included. if (!Attr.isValueUnset("ParseKind")) { @@ -3349,7 +3488,7 @@ static std::string GenerateTargetRequirements(const Record &Attr, static void GenerateDefaultSpellingIndexToSemanticSpelling(raw_ostream &OS) { OS << "static unsigned defaultSpellingIndexToSemanticSpelling(" - << "const AttributeList &Attr) {\n"; + << "const ParsedAttr &Attr) {\n"; OS << " return UINT_MAX;\n"; OS << "}\n\n"; } @@ -3372,7 +3511,7 @@ static std::string GenerateSpellingIndexToSemanticSpelling(const Record &Attr, std::string Enum = CreateSemanticSpellings(Spellings, SemanticToSyntacticMap); std::string Name = Attr.getName().str() + "AttrSpellingMap"; - OS << "static unsigned " << Name << "(const AttributeList &Attr) {\n"; + OS << "static unsigned " << Name << "(const ParsedAttr &Attr) {\n"; OS << Enum; OS << " unsigned Idx = Attr.getAttributeSpellingListIndex();\n"; WriteSemanticSpellingSwitch("Idx", SemanticToSyntacticMap, OS); @@ -3422,12 +3561,14 @@ void EmitClangAttrParsedAttrImpl(RecordKeeper &Records, raw_ostream &OS) { // the spellings are identical, and custom parsing rules match, etc. // We need to generate struct instances based off ParsedAttrInfo from - // AttributeList.cpp. + // ParsedAttr.cpp. SS << " { "; emitArgInfo(*I->second, SS); SS << ", " << I->second->getValueAsBit("HasCustomParsing"); SS << ", " << I->second->isSubClassOf("TargetSpecificAttr"); - SS << ", " << I->second->isSubClassOf("TypeAttr"); + SS << ", " + << (I->second->isSubClassOf("TypeAttr") || + I->second->isSubClassOf("DeclOrTypeAttr")); SS << ", " << I->second->isSubClassOf("StmtAttr"); SS << ", " << IsKnownToGCC(*I->second); SS << ", " << PragmaAttributeSupport.isAttributedSupported(*I->second); @@ -3445,7 +3586,8 @@ void EmitClangAttrParsedAttrImpl(RecordKeeper &Records, raw_ostream &OS) { SS << " // AT_" << I->first << "\n"; } - OS << "static const ParsedAttrInfo AttrInfoMap[AttributeList::UnknownAttribute + 1] = {\n"; + OS << "static const ParsedAttrInfo AttrInfoMap[ParsedAttr::UnknownAttribute " + "+ 1] = {\n"; OS << SS.str(); OS << "};\n\n"; @@ -3473,7 +3615,7 @@ void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) { // specific attribute, or MSP430-specific attribute. Additionally, an // attribute can be spelled GNU<"dllexport"> and Declspec<"dllexport"> // for the same semantic attribute. Ultimately, we need to map each of - // these to a single AttributeList::Kind value, but the StringMatcher + // these to a single ParsedAttr::Kind value, but the StringMatcher // class cannot handle duplicate match strings. So we generate a list of // string to match based on the syntax, and emit multiple string matchers // depending on the syntax used. @@ -3520,34 +3662,34 @@ void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) { Spelling += RawSpelling; if (SemaHandler) - Matches->push_back(StringMatcher::StringPair(Spelling, - "return AttributeList::AT_" + AttrName + ";")); + Matches->push_back(StringMatcher::StringPair( + Spelling, "return ParsedAttr::AT_" + AttrName + ";")); else - Matches->push_back(StringMatcher::StringPair(Spelling, - "return AttributeList::IgnoredAttribute;")); + Matches->push_back(StringMatcher::StringPair( + Spelling, "return ParsedAttr::IgnoredAttribute;")); } } } - - OS << "static AttributeList::Kind getAttrKind(StringRef Name, "; - OS << "AttributeList::Syntax Syntax) {\n"; - OS << " if (AttributeList::AS_GNU == Syntax) {\n"; + + OS << "static ParsedAttr::Kind getAttrKind(StringRef Name, "; + OS << "ParsedAttr::Syntax Syntax) {\n"; + OS << " if (ParsedAttr::AS_GNU == Syntax) {\n"; StringMatcher("Name", GNU, OS).Emit(); - OS << " } else if (AttributeList::AS_Declspec == Syntax) {\n"; + OS << " } else if (ParsedAttr::AS_Declspec == Syntax) {\n"; StringMatcher("Name", Declspec, OS).Emit(); - OS << " } else if (AttributeList::AS_Microsoft == Syntax) {\n"; + OS << " } else if (ParsedAttr::AS_Microsoft == Syntax) {\n"; StringMatcher("Name", Microsoft, OS).Emit(); - OS << " } else if (AttributeList::AS_CXX11 == Syntax) {\n"; + OS << " } else if (ParsedAttr::AS_CXX11 == Syntax) {\n"; StringMatcher("Name", CXX11, OS).Emit(); - OS << " } else if (AttributeList::AS_C2x == Syntax) {\n"; + OS << " } else if (ParsedAttr::AS_C2x == Syntax) {\n"; StringMatcher("Name", C2x, OS).Emit(); - OS << " } else if (AttributeList::AS_Keyword == Syntax || "; - OS << "AttributeList::AS_ContextSensitiveKeyword == Syntax) {\n"; + OS << " } else if (ParsedAttr::AS_Keyword == Syntax || "; + OS << "ParsedAttr::AS_ContextSensitiveKeyword == Syntax) {\n"; StringMatcher("Name", Keywords, OS).Emit(); - OS << " } else if (AttributeList::AS_Pragma == Syntax) {\n"; + OS << " } else if (ParsedAttr::AS_Pragma == Syntax) {\n"; StringMatcher("Name", Pragma, OS).Emit(); OS << " }\n"; - OS << " return AttributeList::UnknownAttribute;\n" + OS << " return ParsedAttr::UnknownAttribute;\n" << "}\n"; } @@ -3592,6 +3734,7 @@ void EmitClangAttrParserStringSwitches(RecordKeeper &Records, emitSourceFileHeader("Parser-related llvm::StringSwitch cases", OS); emitClangAttrArgContextList(Records, OS); emitClangAttrIdentifierArgList(Records, OS); + emitClangAttrVariadicIdentifierArgList(Records, OS); emitClangAttrTypeArgList(Records, OS); emitClangAttrLateParsedList(Records, OS); } @@ -3753,8 +3896,8 @@ static void WriteDocumentation(RecordKeeper &Records, const Record &Deprecated = *Doc.Documentation->getValueAsDef("Deprecated"); const StringRef Replacement = Deprecated.getValueAsString("Replacement"); if (!Replacement.empty()) - OS << " This attribute has been superseded by ``" - << Replacement << "``."; + OS << " This attribute has been superseded by ``" << Replacement + << "``."; OS << "\n\n"; } @@ -3807,9 +3950,9 @@ void EmitClangAttrDocs(RecordKeeper &Records, raw_ostream &OS) { for (auto &I : SplitDocs) { WriteCategoryHeader(I.first, OS); - std::sort(I.second.begin(), I.second.end(), - [](const DocumentationData &D1, const DocumentationData &D2) { - return D1.Heading < D2.Heading; + llvm::sort(I.second.begin(), I.second.end(), + [](const DocumentationData &D1, const DocumentationData &D2) { + return D1.Heading < D2.Heading; }); // Walk over each of the attributes in the category and write out their |
