From 663b4dd44efe005ebd0d07ffbd509e56c4f4d5cc Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Mon, 15 Sep 2014 15:14:13 +0000 Subject: [PATCH] When pretty printing attributes that have enumeration arguments, print the enumerator identifier (as a string literal) instead of the internal enumerator integral value. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@217771 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/SemaCXX/attr-print.cpp | 9 +++++ utils/TableGen/ClangAttrEmitter.cpp | 56 +++++++++++++++++++++++++---- 2 files changed, 59 insertions(+), 6 deletions(-) diff --git a/test/SemaCXX/attr-print.cpp b/test/SemaCXX/attr-print.cpp index a07eeff564..c430aeacfb 100644 --- a/test/SemaCXX/attr-print.cpp +++ b/test/SemaCXX/attr-print.cpp @@ -22,3 +22,12 @@ typedef int Small1 __attribute__((mode(byte))); // CHECK: int small __attribute__((mode(byte))); int small __attribute__((mode(byte))); + +// CHECK: int v __attribute__((visibility("hidden"))); +int v __attribute__((visibility("hidden"))); + +// FIXME: The attribute should be printed with the tag declaration. +class __attribute__((consumable(unknown))) AttrTester1 { + // CHECK: void callableWhen() __attribute__((callable_when("unconsumed", "consumed"))); + void callableWhen() __attribute__((callable_when("unconsumed", "consumed"))); +}; diff --git a/utils/TableGen/ClangAttrEmitter.cpp b/utils/TableGen/ClangAttrEmitter.cpp index cf04140eed..ce6f116af3 100644 --- a/utils/TableGen/ClangAttrEmitter.cpp +++ b/utils/TableGen/ClangAttrEmitter.cpp @@ -510,6 +510,12 @@ namespace { class VariadicArgument : public Argument { std::string Type, ArgName, ArgSizeName, RangeName; + protected: + // Assumed to receive a parameter: raw_ostream OS. + virtual void writeValueImpl(raw_ostream &OS) const { + OS << " OS << Val;\n"; + } + public: VariadicArgument(const Record &Arg, StringRef Attr, std::string T) : Argument(Arg, Attr), Type(T), ArgName(getLowerName().str() + "_"), @@ -589,9 +595,9 @@ namespace { OS << " bool isFirst = true;\n" << " for (const auto &Val : " << RangeName << "()) {\n" << " if (isFirst) isFirst = false;\n" - << " else OS << \", \";\n" - << " OS << Val;\n" - << " }\n"; + << " else OS << \", \";\n"; + writeValueImpl(OS); + OS << " }\n"; OS << " OS << \""; } void writeDump(raw_ostream &OS) const override { @@ -678,7 +684,8 @@ namespace { OS << "Record.push_back(SA->get" << getUpperName() << "());\n"; } void writeValue(raw_ostream &OS) const override { - OS << "\" << get" << getUpperName() << "() << \""; + OS << "\\\"\" << " << getAttrName() << "Attr::Convert" << type << "ToStr(get" + << getUpperName() << "()) << \"\\\""; } void writeDump(raw_ostream &OS) const override { OS << " switch(SA->get" << getUpperName() << "()) {\n"; @@ -703,13 +710,37 @@ namespace { OS << " if (R) {\n"; OS << " Out = *R;\n return true;\n }\n"; OS << " return false;\n"; - OS << " }\n"; + OS << " }\n\n"; + + // Mapping from enumeration values back to enumeration strings isn't + // trivial because some enumeration values have multiple named + // enumerators, such as type_visibility(internal) and + // type_visibility(hidden) both mapping to TypeVisibilityAttr::Hidden. + OS << " static const char *Convert" << type << "ToStr(" + << type << " Val) {\n" + << " switch(Val) {\n"; + std::set 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 << " }\n" + << " llvm_unreachable(\"No enumerator with that value\");\n" + << " }\n"; } }; class VariadicEnumArgument: public VariadicArgument { std::string type, QualifiedTypeName; std::vector values, enums, uniques; + + protected: + void writeValueImpl(raw_ostream &OS) const override { + OS << " OS << \"\\\"\" << " << getAttrName() << "Attr::Convert" << type + << "ToStr(Val)" << "<< \"\\\"\";\n"; + } + public: VariadicEnumArgument(const Record &Arg, StringRef Attr) : VariadicArgument(Arg, Attr, Arg.getValueAsString("Type")), @@ -785,7 +816,20 @@ namespace { OS << " if (R) {\n"; OS << " Out = *R;\n return true;\n }\n"; OS << " return false;\n"; - OS << " }\n"; + OS << " }\n\n"; + + OS << " static const char *Convert" << type << "ToStr(" + << type << " Val) {\n" + << " switch(Val) {\n"; + std::set 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 << " }\n" + << " llvm_unreachable(\"No enumerator with that value\");\n" + << " }\n"; } }; -- 2.40.0