diff options
author | Michael Han <Michael.Han@autodesk.com> | 2012-03-07 00:12:16 +0000 |
---|---|---|
committer | Michael Han <Michael.Han@autodesk.com> | 2012-03-07 00:12:16 +0000 |
commit | e53ac8aea2d9e8bbb11191398ea3cc2edb2d171a (patch) | |
tree | b89f8e7a367e6dceab83f73c21e1c00d69379ee5 /utils | |
parent | 29293cddc682091a16a71f513e605995473f7f45 (diff) |
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
Diffstat (limited to 'utils')
-rw-r--r-- | utils/TableGen/ClangAttrEmitter.cpp | 91 | ||||
-rw-r--r-- | utils/TableGen/ClangAttrEmitter.h | 26 | ||||
-rw-r--r-- | utils/TableGen/TableGen.cpp | 14 |
3 files changed, 131 insertions, 0 deletions
diff --git a/utils/TableGen/ClangAttrEmitter.cpp b/utils/TableGen/ClangAttrEmitter.cpp index 4d3daf605c..7951fc467d 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 @@ static std::string WritePCHRecord(StringRef type, StringRef name) { .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 @@ void ClangAttrTemplateInstantiateEmitter::run(raw_ostream &OS) { << "} // 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"; + } + } + } +} + + diff --git a/utils/TableGen/ClangAttrEmitter.h b/utils/TableGen/ClangAttrEmitter.h index 91ec754346..d119a094c1 100644 --- a/utils/TableGen/ClangAttrEmitter.h +++ b/utils/TableGen/ClangAttrEmitter.h @@ -122,6 +122,32 @@ class ClangAttrTemplateInstantiateEmitter : public TableGenBackend { void run(raw_ostream &OS); }; +/// ClangAttrParsedAttrListEmitter emits the list of parsed attributes +/// for clang. +class ClangAttrParsedAttrListEmitter : public TableGenBackend { + RecordKeeper &Records; + +public: + explicit ClangAttrParsedAttrListEmitter(RecordKeeper &R) + : Records(R) + {} + + void run(raw_ostream &OS); +}; + +/// ClangAttrParsedAttrKindsEmitter emits the kind list of parsed attributes +/// for clang. +class ClangAttrParsedAttrKindsEmitter : public TableGenBackend { + RecordKeeper &Records; + +public: + explicit ClangAttrParsedAttrKindsEmitter(RecordKeeper &R) + : Records(R) + {} + + void run(raw_ostream &OS); +}; + } #endif diff --git a/utils/TableGen/TableGen.cpp b/utils/TableGen/TableGen.cpp index 6462b3bb74..5ff88db301 100644 --- a/utils/TableGen/TableGen.cpp +++ b/utils/TableGen/TableGen.cpp @@ -37,6 +37,8 @@ enum ActionType { GenClangAttrSpellingList, GenClangAttrLateParsedList, GenClangAttrTemplateInstantiate, + GenClangAttrParsedAttrList, + GenClangAttrParsedAttrKinds, GenClangDiagsDefs, GenClangDiagGroups, GenClangDiagsIndexName, @@ -75,6 +77,12 @@ namespace { clEnumValN(GenClangAttrTemplateInstantiate, "gen-clang-attr-template-instantiate", "Generate a clang template instantiate code"), + clEnumValN(GenClangAttrParsedAttrList, + "gen-clang-attr-parsed-attr-list", + "Generate a clang parsed attribute list"), + clEnumValN(GenClangAttrParsedAttrKinds, + "gen-clang-attr-parsed-attr-kinds", + "Generate a clang parsed attribute kinds"), clEnumValN(GenClangDiagsDefs, "gen-clang-diags-defs", "Generate Clang diagnostics definitions"), clEnumValN(GenClangDiagGroups, "gen-clang-diag-groups", @@ -129,6 +137,12 @@ public: case GenClangAttrTemplateInstantiate: ClangAttrTemplateInstantiateEmitter(Records).run(OS); break; + case GenClangAttrParsedAttrList: + ClangAttrParsedAttrListEmitter(Records).run(OS); + break; + case GenClangAttrParsedAttrKinds: + ClangAttrParsedAttrKindsEmitter(Records).run(OS); + break; case GenClangDiagsDefs: ClangDiagsDefsEmitter(Records, ClangComponent).run(OS); break; |