summaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
authorDeLesley Hutchins <delesley@google.com>2013-10-04 21:28:06 +0000
committerDeLesley Hutchins <delesley@google.com>2013-10-04 21:28:06 +0000
commit66540857c08de7f1be9bea48381548d3942cf9d1 (patch)
treef7b37bfb773f09b0a81afe3745ae7702fb012b59 /utils
parent1cd6fab3930d5c058c201895654c6b0bd6ecb8c1 (diff)
downloadclang-66540857c08de7f1be9bea48381548d3942cf9d1.tar.gz
clang-66540857c08de7f1be9bea48381548d3942cf9d1.tar.bz2
clang-66540857c08de7f1be9bea48381548d3942cf9d1.tar.xz
Consumed Analysis: Change callable_when so that it can take a list of states
that a function can be called in. This reduced the total number of annotations needed and makes writing more complicated behaviour less burdensome. Patch by chriswails@gmail.com. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@191983 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'utils')
-rw-r--r--utils/TableGen/ClangAttrEmitter.cpp95
1 files changed, 94 insertions, 1 deletions
diff --git a/utils/TableGen/ClangAttrEmitter.cpp b/utils/TableGen/ClangAttrEmitter.cpp
index 7f42e455bd..6e44ac4146 100644
--- a/utils/TableGen/ClangAttrEmitter.cpp
+++ b/utils/TableGen/ClangAttrEmitter.cpp
@@ -136,6 +136,7 @@ namespace {
virtual void writeHasChildren(raw_ostream &OS) const { OS << "false"; }
virtual bool isEnumArg() const { return false; }
+ virtual bool isVariadicEnumArg() const { return false; }
};
class SimpleArgument : public Argument {
@@ -474,7 +475,7 @@ namespace {
<< ";\n";
OS << " " << getLowerName() << ".reserve(" << getLowerName()
<< "Size);\n";
- OS << " for (unsigned i = " << getLowerName() << "Size; i; --i)\n";
+ OS << " for (unsigned i = " << getLowerName() << "Size; i; --i)\n";
std::string read = ReadPCHRecord(type);
OS << " " << getLowerName() << ".push_back(" << read << ");\n";
@@ -604,6 +605,93 @@ namespace {
OS << " }\n";
}
};
+
+ class VariadicEnumArgument: public VariadicArgument {
+ std::string type, QualifiedTypeName;
+ std::vector<StringRef> values, enums, uniques;
+ public:
+ VariadicEnumArgument(Record &Arg, StringRef Attr)
+ : VariadicArgument(Arg, Attr, Arg.getValueAsString("Type")),
+ type(Arg.getValueAsString("Type")),
+ values(getValueAsListOfStrings(Arg, "Values")),
+ enums(getValueAsListOfStrings(Arg, "Enums")),
+ uniques(enums)
+ {
+ // Calculate the various enum values
+ std::sort(uniques.begin(), uniques.end());
+ uniques.erase(std::unique(uniques.begin(), uniques.end()), uniques.end());
+
+ QualifiedTypeName = getAttrName().str() + "Attr::" + type;
+
+ // FIXME: Emit a proper error
+ assert(!uniques.empty());
+ }
+
+ bool isVariadicEnumArg() const { return true; }
+
+ void writeDeclarations(raw_ostream &OS) const {
+ std::vector<StringRef>::const_iterator i = uniques.begin(),
+ e = uniques.end();
+ // 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";
+ OS << "private:\n";
+
+ VariadicArgument::writeDeclarations(OS);
+ }
+ void writeDump(raw_ostream &OS) const {
+ OS << " for (" << getAttrName() << "Attr::" << getLowerName()
+ << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->"
+ << getLowerName() << "_end(); I != E; ++I) {\n";
+ OS << " switch(*I) {\n";
+ for (std::vector<StringRef>::const_iterator UI = uniques.begin(),
+ UE = uniques.end(); UI != UE; ++UI) {
+ OS << " case " << getAttrName() << "Attr::" << *UI << ":\n";
+ OS << " OS << \" " << *UI << "\";\n";
+ OS << " break;\n";
+ }
+ OS << " }\n";
+ OS << " }\n";
+ }
+ void writePCHReadDecls(raw_ostream &OS) const {
+ OS << " unsigned " << getLowerName() << "Size = Record[Idx++];\n";
+ OS << " SmallVector<" << QualifiedTypeName << ", 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[Idx++]));\n";
+ }
+ void writePCHWrite(raw_ostream &OS) const{
+ OS << " Record.push_back(SA->" << getLowerName() << "_size());\n";
+ OS << " for (" << getAttrName() << "Attr::" << getLowerName()
+ << "_iterator i = SA->" << getLowerName() << "_begin(), e = SA->"
+ << getLowerName() << "_end(); i != e; ++i)\n";
+ OS << " " << WritePCHRecord(QualifiedTypeName, "(*i)");
+ }
+ void writeConversion(raw_ostream &OS) const {
+ OS << " static bool ConvertStrTo" << type << "(StringRef Val, ";
+ OS << type << " &Out) {\n";
+ OS << " Optional<" << type << "> R = llvm::StringSwitch<Optional<";
+ OS << type << "> >(Val)\n";
+ for (size_t I = 0; I < enums.size(); ++I) {
+ OS << " .Case(\"" << values[I] << "\", ";
+ OS << getAttrName() << "Attr::" << enums[I] << ")\n";
+ }
+ OS << " .Default(Optional<" << type << ">());\n";
+ OS << " if (R) {\n";
+ OS << " Out = *R;\n return true;\n }\n";
+ OS << " return false;\n";
+ OS << " }\n";
+ }
+ };
class VersionArgument : public Argument {
public:
@@ -768,6 +856,8 @@ static Argument *createArgument(Record &Arg, StringRef Attr,
Ptr = new SimpleArgument(Arg, Attr, "SourceLocation");
else if (ArgName == "VariadicUnsignedArgument")
Ptr = new VariadicArgument(Arg, Attr, "unsigned");
+ else if (ArgName == "VariadicEnumArgument")
+ Ptr = new VariadicEnumArgument(Arg, Attr);
else if (ArgName == "VariadicExprArgument")
Ptr = new VariadicExprArgument(Arg, Attr);
else if (ArgName == "VersionArgument")
@@ -1051,6 +1141,9 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
if ((*ai)->isEnumArg()) {
EnumArgument *EA = (EnumArgument *)*ai;
EA->writeConversion(OS);
+ } else if ((*ai)->isVariadicEnumArg()) {
+ VariadicEnumArgument *VEA = (VariadicEnumArgument *)*ai;
+ VEA->writeConversion(OS);
}
}