Refactor Clang sema attribute handling.

This submission improves Clang sema handling by using Clang tablegen
to generate common boilerplate code. As a start, it implements AttributeList
enumerator generation and case statements for AttributeList::getKind.

A new field "SemaHandler" is introduced in Attr.td and by default set to 1
as most of attributes in Attr.td have semantic checking in Sema. For a small
number of attributes that don't appear in Sema, the value is set to 0.

Also there are a small number of attributes that only appear in Sema but not
in Attr.td. Currently these attributes are still hardcoded in Sema AttributeList.

Reviewed by Delesley Hutchins.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@152169 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/utils/TableGen/ClangAttrEmitter.cpp b/utils/TableGen/ClangAttrEmitter.cpp
index 4d3daf6..7951fc4 100644
--- a/utils/TableGen/ClangAttrEmitter.cpp
+++ b/utils/TableGen/ClangAttrEmitter.cpp
@@ -16,6 +16,7 @@
 #include "llvm/TableGen/Record.h"
 #include <algorithm>
 #include <cctype>
+#include <set>
 
 using namespace llvm;
 
@@ -65,6 +66,30 @@
     .Default("Record.push_back(" + std::string(name) + ");\n");
 }
 
+// Normalize attribute name by removing leading and trailing
+// underscores. For example, __foo, foo__, __foo__ would
+// become foo.
+static StringRef NormalizeAttrName(StringRef AttrName) {
+  if (AttrName.startswith("__"))
+    AttrName = AttrName.substr(2, AttrName.size());
+
+  if (AttrName.endswith("__"))
+    AttrName = AttrName.substr(0, AttrName.size() - 2);
+
+  return AttrName;
+}
+
+// Normalize attribute spelling only if the spelling has both leading
+// and trailing underscores. For example, __ms_struct__ will be 
+// normalized to "ms_struct"; __cdecl will remain intact.
+static StringRef NormalizeAttrSpelling(StringRef AttrSpelling) {
+  if (AttrSpelling.startswith("__") && AttrSpelling.endswith("__")) {
+    AttrSpelling = AttrSpelling.substr(2, AttrSpelling.size() - 4);
+  }
+
+  return AttrSpelling;
+}
+
 namespace {
   class Argument {
     std::string lowerName, upperName;
@@ -999,3 +1024,69 @@
      << "} // end namespace clang\n";
 }
 
+void ClangAttrParsedAttrListEmitter::run(raw_ostream &OS) {
+  OS << "// This file is generated by TableGen. Do not edit.\n\n";
+  
+  OS << "#ifndef PARSED_ATTR\n";
+  OS << "#define PARSED_ATTR(NAME) NAME\n";
+  OS << "#endif\n\n";
+  
+  std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
+  std::set<StringRef> ProcessedAttrs;
+
+  for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
+       I != E; ++I) {
+    Record &Attr = **I;
+    
+    bool SemaHandler = Attr.getValueAsBit("SemaHandler");
+    
+    if (SemaHandler) {
+      std::vector<StringRef> Spellings =
+        getValueAsListOfStrings(Attr, "Spellings");
+      
+      for (std::vector<StringRef>::const_iterator I = Spellings.begin(),
+           E = Spellings.end(); I != E; ++I) {
+        StringRef AttrName = *I;
+
+        AttrName = NormalizeAttrName(AttrName);
+        // skip if a normalized version has been processed.
+        if (ProcessedAttrs.find(AttrName) != ProcessedAttrs.end())
+          continue;
+        else
+          ProcessedAttrs.insert(AttrName);
+
+        OS << "PARSED_ATTR(" << AttrName << ")\n";
+      }
+    }
+  }
+}
+
+void ClangAttrParsedAttrKindsEmitter::run(raw_ostream &OS) {
+  OS << "// This file is generated by TableGen. Do not edit.\n\n";
+
+  std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
+
+  for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
+       I != E; ++I) {
+    Record &Attr = **I;
+    
+    bool SemaHandler = Attr.getValueAsBit("SemaHandler");
+    
+    if (SemaHandler) {
+      std::vector<StringRef> Spellings =
+        getValueAsListOfStrings(Attr, "Spellings");
+
+      for (std::vector<StringRef>::const_iterator I = Spellings.begin(),
+           E = Spellings.end(); I != E; ++I) {
+       StringRef AttrName = *I, Spelling = *I;
+       
+       AttrName = NormalizeAttrName(AttrName);
+       Spelling = NormalizeAttrSpelling(Spelling);
+
+       OS << ".Case(\"" << Spelling << "\", " << "AT_" << AttrName << ")\n";
+      }
+    }
+  }
+}
+
+