[clang] 1c6c01f - [Attributes][HLSL] Teach EnumArgument to refer to an external enum (#70835)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Nov 1 11:24:52 PDT 2023
Author: Justin Bogner
Date: 2023-11-01T11:24:48-07:00
New Revision: 1c6c01fbde87171457a5bce7b147fa5bcbaddae7
URL: https://github.com/llvm/llvm-project/commit/1c6c01fbde87171457a5bce7b147fa5bcbaddae7
DIFF: https://github.com/llvm/llvm-project/commit/1c6c01fbde87171457a5bce7b147fa5bcbaddae7.diff
LOG: [Attributes][HLSL] Teach EnumArgument to refer to an external enum (#70835)
Rather than write a bunch of logic to shepherd between enums with the
same sets of values, add the ability for EnumArgument to refer to an
external enum in the first place.
Added:
Modified:
clang-tools-extra/modularize/ModularizeUtilities.cpp
clang/include/clang/AST/Attr.h
clang/include/clang/Basic/Attr.td
clang/lib/CodeGen/CGHLSLRuntime.cpp
clang/lib/Sema/HLSLExternalSemaSource.cpp
clang/unittests/Sema/SemaNoloadLookupTest.cpp
clang/utils/TableGen/ClangAttrEmitter.cpp
Removed:
################################################################################
diff --git a/clang-tools-extra/modularize/ModularizeUtilities.cpp b/clang-tools-extra/modularize/ModularizeUtilities.cpp
index 043f6f5b20b80f2..089f52f52ec4d34 100644
--- a/clang-tools-extra/modularize/ModularizeUtilities.cpp
+++ b/clang-tools-extra/modularize/ModularizeUtilities.cpp
@@ -322,7 +322,7 @@ std::error_code ModularizeUtilities::loadModuleMap(
// Walks the modules and collects referenced headers into
// HeaderFileNames.
bool ModularizeUtilities::collectModuleMapHeaders(clang::ModuleMap *ModMap) {
- SmallVector<std::pair<StringRef, const Module *>, 0> Vec;
+ SmallVector<std::pair<StringRef, const clang::Module *>, 0> Vec;
for (auto &M : ModMap->modules())
Vec.emplace_back(M.first(), M.second);
llvm::sort(Vec, llvm::less_first());
@@ -349,14 +349,14 @@ bool ModularizeUtilities::collectModuleHeaders(const clang::Module &Mod) {
for (auto *Submodule : Mod.submodules())
collectModuleHeaders(*Submodule);
- if (std::optional<Module::Header> UmbrellaHeader =
+ if (std::optional<clang::Module::Header> UmbrellaHeader =
Mod.getUmbrellaHeaderAsWritten()) {
std::string HeaderPath = getCanonicalPath(UmbrellaHeader->Entry.getName());
// Collect umbrella header.
HeaderFileNames.push_back(HeaderPath);
// FUTURE: When needed, umbrella header header collection goes here.
- } else if (std::optional<Module::DirectoryName> UmbrellaDir =
+ } else if (std::optional<clang::Module::DirectoryName> UmbrellaDir =
Mod.getUmbrellaDirAsWritten()) {
// If there normal headers, assume these are umbrellas and skip collection.
if (Mod.Headers->size() == 0) {
diff --git a/clang/include/clang/AST/Attr.h b/clang/include/clang/AST/Attr.h
index 793732cd26b02ff..8884bd5a90de198 100644
--- a/clang/include/clang/AST/Attr.h
+++ b/clang/include/clang/AST/Attr.h
@@ -19,11 +19,12 @@
#include "clang/AST/Type.h"
#include "clang/Basic/AttrKinds.h"
#include "clang/Basic/AttributeCommonInfo.h"
-#include "clang/Basic/LangOptions.h"
#include "clang/Basic/LLVM.h"
+#include "clang/Basic/LangOptions.h"
#include "clang/Basic/OpenMPKinds.h"
#include "clang/Basic/Sanitizers.h"
#include "clang/Basic/SourceLocation.h"
+#include "llvm/Frontend/HLSL/HLSLResource.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/VersionTuple.h"
#include "llvm/Support/raw_ostream.h"
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index 25231c5b82b907c..60b549999c155e5 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -277,23 +277,28 @@ class DefaultIntArgument<string name, int default> : IntArgument<name, 1> {
int Default = default;
}
-// This argument is more complex, it includes the enumerator type name,
-// a list of strings to accept, and a list of enumerators to map them to.
+// This argument is more complex, it includes the enumerator type
+// name, whether the enum type is externally defined, a list of
+// strings to accept, and a list of enumerators to map them to.
class EnumArgument<string name, string type, list<string> values,
- list<string> enums, bit opt = 0, bit fake = 0>
+ list<string> enums, bit opt = 0, bit fake = 0,
+ bit isExternalType = 0>
: Argument<name, opt, fake> {
string Type = type;
list<string> Values = values;
list<string> Enums = enums;
+ bit IsExternalType = isExternalType;
}
// FIXME: There should be a VariadicArgument type that takes any other type
// of argument and generates the appropriate type.
class VariadicEnumArgument<string name, string type, list<string> values,
- list<string> enums> : Argument<name, 1> {
+ list<string> enums, bit isExternalType = 0>
+ : Argument<name, 1> {
string Type = type;
list<string> Values = values;
list<string> Enums = enums;
+ bit IsExternalType = isExternalType;
}
// This handles one spelling of an attribute.
@@ -4182,26 +4187,26 @@ def HLSLResource : InheritableAttr {
let Spellings = [];
let Subjects = SubjectList<[Struct]>;
let LangOpts = [HLSL];
- let Args = [EnumArgument<"ResourceType", "ResourceClass",
+ let Args = [EnumArgument<"ResourceClass", "llvm::hlsl::ResourceClass",
["SRV", "UAV", "CBuffer", "Sampler"],
- ["SRV", "UAV", "CBuffer", "Sampler"]
- >,
- EnumArgument<"ResourceShape", "ResourceKind",
+ ["SRV", "UAV", "CBuffer", "Sampler"],
+ /*opt=*/0, /*fake=*/0, /*isExternalType=*/1>,
+ EnumArgument<"ResourceKind", "llvm::hlsl::ResourceKind",
["Texture1D", "Texture2D", "Texture2DMS",
"Texture3D", "TextureCube", "Texture1DArray",
"Texture2DArray", "Texture2DMSArray",
"TextureCubeArray", "TypedBuffer", "RawBuffer",
- "StructuredBuffer", "CBufferKind", "SamplerKind",
- "TBuffer", "RTAccelerationStructure", "FeedbackTexture2D",
- "FeedbackTexture2DArray"],
+ "StructuredBuffer", "CBuffer", "Sampler",
+ "TBuffer", "RTAccelerationStructure",
+ "FeedbackTexture2D", "FeedbackTexture2DArray"],
["Texture1D", "Texture2D", "Texture2DMS",
"Texture3D", "TextureCube", "Texture1DArray",
"Texture2DArray", "Texture2DMSArray",
"TextureCubeArray", "TypedBuffer", "RawBuffer",
- "StructuredBuffer", "CBufferKind", "SamplerKind",
- "TBuffer", "RTAccelerationStructure", "FeedbackTexture2D",
- "FeedbackTexture2DArray"]
- >
+ "StructuredBuffer", "CBuffer", "Sampler",
+ "TBuffer", "RTAccelerationStructure",
+ "FeedbackTexture2D", "FeedbackTexture2DArray"],
+ /*opt=*/0, /*fake=*/0, /*isExternalType=*/1>
];
let Documentation = [InternalOnly];
}
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp
index e9fa273f21cc8d0..c239bc17ef267e8 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.cpp
+++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp
@@ -223,56 +223,6 @@ void CGHLSLRuntime::addBufferResourceAnnotation(llvm::GlobalVariable *GV,
ResourceMD->addOperand(Res.getMetadata());
}
-static llvm::hlsl::ResourceKind
-castResourceShapeToResourceKind(HLSLResourceAttr::ResourceKind RK) {
- switch (RK) {
- case HLSLResourceAttr::ResourceKind::Texture1D:
- return llvm::hlsl::ResourceKind::Texture1D;
- case HLSLResourceAttr::ResourceKind::Texture2D:
- return llvm::hlsl::ResourceKind::Texture2D;
- case HLSLResourceAttr::ResourceKind::Texture2DMS:
- return llvm::hlsl::ResourceKind::Texture2DMS;
- case HLSLResourceAttr::ResourceKind::Texture3D:
- return llvm::hlsl::ResourceKind::Texture3D;
- case HLSLResourceAttr::ResourceKind::TextureCube:
- return llvm::hlsl::ResourceKind::TextureCube;
- case HLSLResourceAttr::ResourceKind::Texture1DArray:
- return llvm::hlsl::ResourceKind::Texture1DArray;
- case HLSLResourceAttr::ResourceKind::Texture2DArray:
- return llvm::hlsl::ResourceKind::Texture2DArray;
- case HLSLResourceAttr::ResourceKind::Texture2DMSArray:
- return llvm::hlsl::ResourceKind::Texture2DMSArray;
- case HLSLResourceAttr::ResourceKind::TextureCubeArray:
- return llvm::hlsl::ResourceKind::TextureCubeArray;
- case HLSLResourceAttr::ResourceKind::TypedBuffer:
- return llvm::hlsl::ResourceKind::TypedBuffer;
- case HLSLResourceAttr::ResourceKind::RawBuffer:
- return llvm::hlsl::ResourceKind::RawBuffer;
- case HLSLResourceAttr::ResourceKind::StructuredBuffer:
- return llvm::hlsl::ResourceKind::StructuredBuffer;
- case HLSLResourceAttr::ResourceKind::CBufferKind:
- return llvm::hlsl::ResourceKind::CBuffer;
- case HLSLResourceAttr::ResourceKind::SamplerKind:
- return llvm::hlsl::ResourceKind::Sampler;
- case HLSLResourceAttr::ResourceKind::TBuffer:
- return llvm::hlsl::ResourceKind::TBuffer;
- case HLSLResourceAttr::ResourceKind::RTAccelerationStructure:
- return llvm::hlsl::ResourceKind::RTAccelerationStructure;
- case HLSLResourceAttr::ResourceKind::FeedbackTexture2D:
- return llvm::hlsl::ResourceKind::FeedbackTexture2D;
- case HLSLResourceAttr::ResourceKind::FeedbackTexture2DArray:
- return llvm::hlsl::ResourceKind::FeedbackTexture2DArray;
- }
- // Make sure to update HLSLResourceAttr::ResourceKind when add new Kind to
- // hlsl::ResourceKind. Assume FeedbackTexture2DArray is the last enum for
- // HLSLResourceAttr::ResourceKind.
- static_assert(
- static_cast<uint32_t>(
- HLSLResourceAttr::ResourceKind::FeedbackTexture2DArray) ==
- (static_cast<uint32_t>(llvm::hlsl::ResourceKind::NumEntries) - 2));
- llvm_unreachable("all switch cases should be covered");
-}
-
void CGHLSLRuntime::annotateHLSLResource(const VarDecl *D, GlobalVariable *GV) {
const Type *Ty = D->getType()->getPointeeOrArrayElementType();
if (!Ty)
@@ -284,15 +234,12 @@ void CGHLSLRuntime::annotateHLSLResource(const VarDecl *D, GlobalVariable *GV) {
if (!Attr)
return;
- HLSLResourceAttr::ResourceClass RC = Attr->getResourceType();
- llvm::hlsl::ResourceKind RK =
- castResourceShapeToResourceKind(Attr->getResourceShape());
+ llvm::hlsl::ResourceClass RC = Attr->getResourceClass();
+ llvm::hlsl::ResourceKind RK = Attr->getResourceKind();
QualType QT(Ty, 0);
BufferResBinding Binding(D->getAttr<HLSLResourceBindingAttr>());
- addBufferResourceAnnotation(GV, QT.getAsString(),
- static_cast<llvm::hlsl::ResourceClass>(RC), RK,
- Binding);
+ addBufferResourceAnnotation(GV, QT.getAsString(), RC, RK, Binding);
}
CGHLSLRuntime::BufferResBinding::BufferResBinding(
diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp
index fd86a5f8b49c0a1..0be76d4b36e046c 100644
--- a/clang/lib/Sema/HLSLExternalSemaSource.cpp
+++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp
@@ -115,9 +115,8 @@ struct BuiltinTypeDeclBuilder {
return addMemberVariable("h", Ty, Access);
}
- BuiltinTypeDeclBuilder &
- annotateResourceClass(HLSLResourceAttr::ResourceClass RC,
- HLSLResourceAttr::ResourceKind RK) {
+ BuiltinTypeDeclBuilder &annotateResourceClass(ResourceClass RC,
+ ResourceKind RK) {
if (Record->isCompleteDefinition())
return *this;
Record->addAttr(
@@ -503,7 +502,6 @@ void HLSLExternalSemaSource::completeBufferType(CXXRecordDecl *Record) {
.addHandleMember()
.addDefaultHandleConstructor(*SemaPtr, ResourceClass::UAV)
.addArraySubscriptOperators()
- .annotateResourceClass(HLSLResourceAttr::UAV,
- HLSLResourceAttr::TypedBuffer)
+ .annotateResourceClass(ResourceClass::UAV, ResourceKind::TypedBuffer)
.completeDefinition();
}
diff --git a/clang/unittests/Sema/SemaNoloadLookupTest.cpp b/clang/unittests/Sema/SemaNoloadLookupTest.cpp
index 2e74ad3a30a93b6..b24c72cba407f3a 100644
--- a/clang/unittests/Sema/SemaNoloadLookupTest.cpp
+++ b/clang/unittests/Sema/SemaNoloadLookupTest.cpp
@@ -118,7 +118,7 @@ class NoloadLookupConsumer : public SemaConsumer {
if (!ID)
return true;
- Module *M = ID->getImportedModule();
+ clang::Module *M = ID->getImportedModule();
assert(M);
if (M->Name != "R")
return true;
diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp
index 45e2fa7b283e18d..4231bcbb362539d 100644
--- a/clang/utils/TableGen/ClangAttrEmitter.cpp
+++ b/clang/utils/TableGen/ClangAttrEmitter.cpp
@@ -898,15 +898,25 @@ namespace {
}
class EnumArgument : public Argument {
- std::string type;
+ std::string fullType;
+ StringRef shortType;
std::vector<StringRef> values, enums, uniques;
+ bool isExternal;
public:
EnumArgument(const Record &Arg, StringRef Attr)
- : Argument(Arg, Attr), type(std::string(Arg.getValueAsString("Type"))),
- values(Arg.getValueAsListOfStrings("Values")),
+ : Argument(Arg, Attr), values(Arg.getValueAsListOfStrings("Values")),
enums(Arg.getValueAsListOfStrings("Enums")),
- uniques(uniqueEnumsInOrder(enums)) {
+ uniques(uniqueEnumsInOrder(enums)),
+ isExternal(Arg.getValueAsBit("IsExternalType")) {
+ StringRef Type = Arg.getValueAsString("Type");
+ shortType = isExternal ? Type.rsplit("::").second : Type;
+ // If shortType didn't contain :: at all rsplit will give us an empty
+ // string.
+ if (shortType.empty())
+ shortType = Type;
+ fullType = isExternal ? Type : (getAttrName() + "Attr::" + Type).str();
+
// FIXME: Emit a proper error
assert(!uniques.empty());
}
@@ -914,7 +924,7 @@ namespace {
bool isEnumArg() const override { return true; }
void writeAccessors(raw_ostream &OS) const override {
- OS << " " << type << " get" << getUpperName() << "() const {\n";
+ OS << " " << fullType << " get" << getUpperName() << "() const {\n";
OS << " return " << getLowerName() << ";\n";
OS << " }";
}
@@ -930,30 +940,32 @@ namespace {
OS << getLowerName() << "(" << getUpperName() << ")";
}
void writeCtorDefaultInitializers(raw_ostream &OS) const override {
- OS << getLowerName() << "(" << type << "(0))";
+ OS << getLowerName() << "(" << fullType << "(0))";
}
void writeCtorParameters(raw_ostream &OS) const override {
- OS << type << " " << getUpperName();
+ OS << fullType << " " << getUpperName();
}
void writeDeclarations(raw_ostream &OS) const override {
- auto i = uniques.cbegin(), e = uniques.cend();
- // The last one needs to not have a comma.
- --e;
+ if (!isExternal) {
+ auto i = uniques.cbegin(), e = uniques.cend();
+ // The last one needs to not have a comma.
+ --e;
+
+ OS << "public:\n";
+ OS << " enum " << shortType << " {\n";
+ for (; i != e; ++i)
+ OS << " " << *i << ",\n";
+ OS << " " << *e << "\n";
+ OS << " };\n";
+ }
- OS << "public:\n";
- OS << " enum " << type << " {\n";
- for (; i != e; ++i)
- OS << " " << *i << ",\n";
- OS << " " << *e << "\n";
- OS << " };\n";
OS << "private:\n";
- OS << " " << type << " " << getLowerName() << ";";
+ OS << " " << fullType << " " << getLowerName() << ";";
}
void writePCHReadDecls(raw_ostream &OS) const override {
- OS << " " << getAttrName() << "Attr::" << type << " " << getLowerName()
- << "(static_cast<" << getAttrName() << "Attr::" << type
- << ">(Record.readInt()));\n";
+ OS << " " << fullType << " " << getLowerName() << "(static_cast<"
+ << fullType << ">(Record.readInt()));\n";
}
void writePCHReadArgs(raw_ostream &OS) const override {
@@ -961,46 +973,50 @@ namespace {
}
void writePCHWrite(raw_ostream &OS) const override {
- OS << "Record.push_back(SA->get" << getUpperName() << "());\n";
+ OS << "Record.push_back(static_cast<uint64_t>(SA->get" << getUpperName()
+ << "()));\n";
}
void writeValue(raw_ostream &OS) const override {
// FIXME: this isn't 100% correct -- some enum arguments require printing
// as a string literal, while others require printing as an identifier.
// Tablegen currently does not distinguish between the two forms.
- OS << "\\\"\" << " << getAttrName() << "Attr::Convert" << type << "ToStr(get"
- << getUpperName() << "()) << \"\\\"";
+ OS << "\\\"\" << " << getAttrName() << "Attr::Convert" << shortType
+ << "ToStr(get" << getUpperName() << "()) << \"\\\"";
}
void writeDump(raw_ostream &OS) const override {
OS << " switch(SA->get" << getUpperName() << "()) {\n";
for (const auto &I : uniques) {
- OS << " case " << getAttrName() << "Attr::" << I << ":\n";
+ OS << " case " << fullType << "::" << I << ":\n";
OS << " OS << \" " << I << "\";\n";
OS << " break;\n";
}
+ if (isExternal) {
+ OS << " default:\n";
+ OS << " llvm_unreachable(\"Invalid attribute value\");\n";
+ }
OS << " }\n";
}
void writeConversion(raw_ostream &OS, bool Header) const {
if (Header) {
- OS << " static bool ConvertStrTo" << type << "(StringRef Val, " << type
- << " &Out);\n";
- OS << " static const char *Convert" << type << "ToStr(" << type
- << " Val);\n";
+ OS << " static bool ConvertStrTo" << shortType << "(StringRef Val, "
+ << fullType << " &Out);\n";
+ OS << " static const char *Convert" << shortType << "ToStr("
+ << fullType << " Val);\n";
return;
}
- OS << "bool " << getAttrName() << "Attr::ConvertStrTo" << type
- << "(StringRef Val, " << type << " &Out) {\n";
- OS << " std::optional<" << type
- << "> R = llvm::StringSwitch<std::optional<";
- OS << type << ">>(Val)\n";
+ OS << "bool " << getAttrName() << "Attr::ConvertStrTo" << shortType
+ << "(StringRef Val, " << fullType << " &Out) {\n";
+ OS << " std::optional<" << fullType << "> "
+ << "R = llvm::StringSwitch<std::optional<" << fullType << ">>(Val)\n";
for (size_t I = 0; I < enums.size(); ++I) {
OS << " .Case(\"" << values[I] << "\", ";
- OS << getAttrName() << "Attr::" << enums[I] << ")\n";
+ OS << fullType << "::" << enums[I] << ")\n";
}
- OS << " .Default(std::optional<" << type << ">());\n";
+ OS << " .Default(std::optional<" << fullType << ">());\n";
OS << " if (R) {\n";
OS << " Out = *R;\n return true;\n }\n";
OS << " return false;\n";
@@ -1010,14 +1026,17 @@ namespace {
// trivial because some enumeration values have multiple named
// enumerators, such as type_visibility(internal) and
// type_visibility(hidden) both mapping to TypeVisibilityAttr::Hidden.
- OS << "const char *" << getAttrName() << "Attr::Convert" << type
- << "ToStr(" << type << " Val) {\n"
+ OS << "const char *" << getAttrName() << "Attr::Convert" << shortType
+ << "ToStr(" << fullType << " Val) {\n"
<< " switch(Val) {\n";
SmallDenseSet<StringRef, 8> Uniques;
for (size_t I = 0; I < enums.size(); ++I) {
if (Uniques.insert(enums[I]).second)
- OS << " case " << getAttrName() << "Attr::" << enums[I]
- << ": return \"" << values[I] << "\";\n";
+ OS << " case " << fullType << "::" << enums[I] << ": return \""
+ << values[I] << "\";\n";
+ }
+ if (isExternal) {
+ OS << " default: llvm_unreachable(\"Invalid attribute value\");\n";
}
OS << " }\n"
<< " llvm_unreachable(\"No enumerator with that value\");\n"
@@ -1026,27 +1045,36 @@ namespace {
};
class VariadicEnumArgument: public VariadicArgument {
- std::string type, QualifiedTypeName;
+ std::string fullType;
+ StringRef shortType;
std::vector<StringRef> values, enums, uniques;
+ bool isExternal;
protected:
void writeValueImpl(raw_ostream &OS) const override {
// FIXME: this isn't 100% correct -- some enum arguments require printing
// as a string literal, while others require printing as an identifier.
// Tablegen currently does not distinguish between the two forms.
- OS << " OS << \"\\\"\" << " << getAttrName() << "Attr::Convert" << type
- << "ToStr(Val)" << "<< \"\\\"\";\n";
+ OS << " OS << \"\\\"\" << " << getAttrName() << "Attr::Convert"
+ << shortType << "ToStr(Val)"
+ << "<< \"\\\"\";\n";
}
public:
VariadicEnumArgument(const Record &Arg, StringRef Attr)
: VariadicArgument(Arg, Attr,
std::string(Arg.getValueAsString("Type"))),
- type(std::string(Arg.getValueAsString("Type"))),
values(Arg.getValueAsListOfStrings("Values")),
enums(Arg.getValueAsListOfStrings("Enums")),
- uniques(uniqueEnumsInOrder(enums)) {
- QualifiedTypeName = getAttrName().str() + "Attr::" + type;
+ uniques(uniqueEnumsInOrder(enums)),
+ isExternal(Arg.getValueAsBit("IsExternalType")) {
+ StringRef Type = Arg.getValueAsString("Type");
+ shortType = isExternal ? Type.rsplit("::").second : Type;
+ // If shortType didn't contain :: at all rsplit will give us an empty
+ // string.
+ if (shortType.empty())
+ shortType = Type;
+ fullType = isExternal ? Type : (getAttrName() + "Attr::" + Type).str();
// FIXME: Emit a proper error
assert(!uniques.empty());
@@ -1055,16 +1083,18 @@ namespace {
bool isVariadicEnumArg() const override { return true; }
void writeDeclarations(raw_ostream &OS) const override {
- auto i = uniques.cbegin(), e = uniques.cend();
- // The last one needs to not have a comma.
- --e;
-
- OS << "public:\n";
- OS << " enum " << type << " {\n";
- for (; i != e; ++i)
- OS << " " << *i << ",\n";
- OS << " " << *e << "\n";
- OS << " };\n";
+ if (!isExternal) {
+ auto i = uniques.cbegin(), e = uniques.cend();
+ // The last one needs to not have a comma.
+ --e;
+
+ OS << "public:\n";
+ OS << " enum " << shortType << " {\n";
+ for (; i != e; ++i)
+ OS << " " << *i << ",\n";
+ OS << " " << *e << "\n";
+ OS << " };\n";
+ }
OS << "private:\n";
VariadicArgument::writeDeclarations(OS);
@@ -1076,7 +1106,7 @@ namespace {
<< getLowerName() << "_end(); I != E; ++I) {\n";
OS << " switch(*I) {\n";
for (const auto &UI : uniques) {
- OS << " case " << getAttrName() << "Attr::" << UI << ":\n";
+ OS << " case " << fullType << "::" << UI << ":\n";
OS << " OS << \" " << UI << "\";\n";
OS << " break;\n";
}
@@ -1086,13 +1116,13 @@ namespace {
void writePCHReadDecls(raw_ostream &OS) const override {
OS << " unsigned " << getLowerName() << "Size = Record.readInt();\n";
- OS << " SmallVector<" << QualifiedTypeName << ", 4> " << getLowerName()
+ OS << " SmallVector<" << fullType << ", 4> " << getLowerName()
<< ";\n";
OS << " " << getLowerName() << ".reserve(" << getLowerName()
<< "Size);\n";
OS << " for (unsigned i = " << getLowerName() << "Size; i; --i)\n";
- OS << " " << getLowerName() << ".push_back(" << "static_cast<"
- << QualifiedTypeName << ">(Record.readInt()));\n";
+ OS << " " << getLowerName() << ".push_back("
+ << "static_cast<" << fullType << ">(Record.readInt()));\n";
}
void writePCHWrite(raw_ostream &OS) const override {
@@ -1100,42 +1130,42 @@ namespace {
OS << " for (" << getAttrName() << "Attr::" << getLowerName()
<< "_iterator i = SA->" << getLowerName() << "_begin(), e = SA->"
<< getLowerName() << "_end(); i != e; ++i)\n";
- OS << " " << WritePCHRecord(QualifiedTypeName, "(*i)");
+ OS << " " << WritePCHRecord(fullType, "(*i)");
}
void writeConversion(raw_ostream &OS, bool Header) const {
if (Header) {
- OS << " static bool ConvertStrTo" << type << "(StringRef Val, " << type
- << " &Out);\n";
- OS << " static const char *Convert" << type << "ToStr(" << type
- << " Val);\n";
+ OS << " static bool ConvertStrTo" << shortType << "(StringRef Val, "
+ << fullType << " &Out);\n";
+ OS << " static const char *Convert" << shortType << "ToStr("
+ << fullType << " Val);\n";
return;
}
- OS << "bool " << getAttrName() << "Attr::ConvertStrTo" << type
+ OS << "bool " << getAttrName() << "Attr::ConvertStrTo" << shortType
<< "(StringRef Val, ";
- OS << type << " &Out) {\n";
- OS << " std::optional<" << type
+ OS << fullType << " &Out) {\n";
+ OS << " std::optional<" << fullType
<< "> R = llvm::StringSwitch<std::optional<";
- OS << type << ">>(Val)\n";
+ OS << fullType << ">>(Val)\n";
for (size_t I = 0; I < enums.size(); ++I) {
OS << " .Case(\"" << values[I] << "\", ";
- OS << getAttrName() << "Attr::" << enums[I] << ")\n";
+ OS << fullType << "::" << enums[I] << ")\n";
}
- OS << " .Default(std::optional<" << type << ">());\n";
+ OS << " .Default(std::optional<" << fullType << ">());\n";
OS << " if (R) {\n";
OS << " Out = *R;\n return true;\n }\n";
OS << " return false;\n";
OS << "}\n\n";
- OS << "const char *" << getAttrName() << "Attr::Convert" << type
- << "ToStr(" << type << " Val) {\n"
+ OS << "const char *" << getAttrName() << "Attr::Convert" << shortType
+ << "ToStr(" << fullType << " Val) {\n"
<< " switch(Val) {\n";
SmallDenseSet<StringRef, 8> Uniques;
for (size_t I = 0; I < enums.size(); ++I) {
if (Uniques.insert(enums[I]).second)
- OS << " case " << getAttrName() << "Attr::" << enums[I]
- << ": return \"" << values[I] << "\";\n";
+ OS << " case " << fullType << "::" << enums[I] << ": return \""
+ << values[I] << "\";\n";
}
OS << " }\n"
<< " llvm_unreachable(\"No enumerator with that value\");\n"
More information about the cfe-commits
mailing list