aboutsummaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
authorAaron Ballman <aaron@aaronballman.com>2014-01-24 21:32:49 +0000
committerAaron Ballman <aaron@aaronballman.com>2014-01-24 21:32:49 +0000
commitb4aad1b48dcb1407091cd72645d78b773b315d23 (patch)
treec8da204a7dbe9ba5da1515a3f628e34fc91f009b /utils
parent38cdf2a5abaaf91bee1d2132fbd19d0e8d28cf56 (diff)
downloadclang_35a-b4aad1b48dcb1407091cd72645d78b773b315d23.tar.gz
Adds a getSemanticSpelling function to semantic attribute subclasses which have a meaningful semantic spelling. Adds a sibling function to parsed attribtues (via AttributeList) for getting the semantic spelling, if one were to exist. This can be used for cleaner code that deals directly with the semantic spellings (such as the MSInheritance attribute).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@200041 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'utils')
-rw-r--r--utils/TableGen/ClangAttrEmitter.cpp149
1 files changed, 110 insertions, 39 deletions
diff --git a/utils/TableGen/ClangAttrEmitter.cpp b/utils/TableGen/ClangAttrEmitter.cpp
index f06a1cb746..6a8c73d370 100644
--- a/utils/TableGen/ClangAttrEmitter.cpp
+++ b/utils/TableGen/ClangAttrEmitter.cpp
@@ -1140,6 +1140,65 @@ static bool SpellingNamesAreCommon(const std::vector<Record *>& Spellings) {
return true;
}
+typedef std::map<unsigned, std::string> SemanticSpellingMap;
+static std::string
+CreateSemanticSpellings(const std::vector<Record *> &Spellings,
+ SemanticSpellingMap &Map) {
+ // The enumerants are automatically generated based on the variety,
+ // namespace (if present) and name for each attribute spelling. However,
+ // care is taken to avoid trampling on the reserved namespace due to
+ // underscores.
+ std::string Ret(" enum Spelling {\n");
+ std::set<std::string> Uniques;
+ unsigned Idx = 0;
+ for (std::vector<Record *>::const_iterator I = Spellings.begin(),
+ E = Spellings.end(); I != E; ++I, ++Idx) {
+ const Record &S = **I;
+ std::string Variety = S.getValueAsString("Variety");
+ std::string Spelling = S.getValueAsString("Name");
+ std::string Namespace = "";
+ std::string EnumName = "";
+
+ if (Variety == "CXX11")
+ Namespace = S.getValueAsString("Namespace");
+
+ EnumName += (Variety + "_");
+ if (!Namespace.empty())
+ EnumName += (NormalizeNameForSpellingComparison(Namespace).str() +
+ "_");
+ EnumName += NormalizeNameForSpellingComparison(Spelling);
+
+ // Even if the name is not unique, this spelling index corresponds to a
+ // particular enumerant name that we've calculated.
+ Map[Idx] = EnumName;
+
+ // Since we have been stripping underscores to avoid trampling on the
+ // reserved namespace, we may have inadvertently created duplicate
+ // enumerant names. These duplicates are not considered part of the
+ // semantic spelling, and can be elided.
+ if (Uniques.find(EnumName) != Uniques.end())
+ continue;
+
+ Uniques.insert(EnumName);
+ if (I != Spellings.begin())
+ Ret += ",\n";
+ Ret += " " + EnumName;
+ }
+ Ret += "\n };\n\n";
+ return Ret;
+}
+
+void WriteSemanticSpellingSwitch(const std::string &VarName,
+ const SemanticSpellingMap &Map,
+ raw_ostream &OS) {
+ OS << " switch (" << VarName << ") {\n default: "
+ << "llvm_unreachable(\"Unknown spelling list index\");\n";
+ for (SemanticSpellingMap::const_iterator I = Map.begin(), E = Map.end();
+ I != E; ++I)
+ OS << " case " << I->first << ": return " << I->second << ";\n";
+ OS << " }\n";
+}
+
namespace clang {
// Emits the class definitions for attributes.
@@ -1199,43 +1258,11 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
bool ElideSpelling = (Spellings.size() <= 1) ||
SpellingNamesAreCommon(Spellings);
- if (!ElideSpelling) {
- // The enumerants are automatically generated based on the variety,
- // namespace (if present) and name for each attribute spelling. However,
- // care is taken to avoid trampling on the reserved namespace due to
- // underscores.
- OS << " enum Spelling {\n";
- std::set<std::string> Uniques;
- for (std::vector<Record *>::const_iterator I = Spellings.begin(),
- E = Spellings.end(); I != E; ++I) {
- if (I != Spellings.begin())
- OS << ",\n";
- const Record &S = **I;
- std::string Variety = S.getValueAsString("Variety");
- std::string Spelling = S.getValueAsString("Name");
- std::string Namespace = "";
- std::string EnumName = "";
-
- if (Variety == "CXX11")
- Namespace = S.getValueAsString("Namespace");
-
- EnumName += (Variety + "_");
- if (!Namespace.empty())
- EnumName += (NormalizeNameForSpellingComparison(Namespace).str() +
- "_");
- EnumName += NormalizeNameForSpellingComparison(Spelling);
-
- // Since we have been stripping underscores to avoid trampling on the
- // reserved namespace, we may have inadvertently created duplicate
- // enumerant names. Unique the name if required.
- while (Uniques.find(EnumName) != Uniques.end())
- EnumName += "_alternate";
- Uniques.insert(EnumName);
-
- OS << " " << EnumName;
- }
- OS << "\n };\n\n";
- }
+ // This maps spelling index values to semantic Spelling enumerants.
+ SemanticSpellingMap SemanticToSyntacticMap;
+
+ if (!ElideSpelling)
+ OS << CreateSemanticSpellings(Spellings, SemanticToSyntacticMap);
OS << " static " << R.getName() << "Attr *CreateImplicit(";
OS << "ASTContext &Ctx";
@@ -1327,6 +1354,14 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
OS << " virtual void printPretty(raw_ostream &OS,\n"
<< " const PrintingPolicy &Policy) const;\n";
OS << " virtual const char *getSpelling() const;\n";
+
+ if (!ElideSpelling) {
+ assert(!SemanticToSyntacticMap.empty() && "Empty semantic mapping list");
+ OS << " Spelling getSemanticSpelling() const {\n";
+ WriteSemanticSpellingSwitch("SpellingListIndex", SemanticToSyntacticMap,
+ OS);
+ OS << " }\n";
+ }
writeAttrAccessorDefinition(R, OS);
@@ -2317,6 +2352,40 @@ static std::string GenerateTargetRequirements(const Record &Attr,
return FnName;
}
+static void GenerateDefaultSpellingIndexToSemanticSpelling(raw_ostream &OS) {
+ OS << "static unsigned defaultSpellingIndexToSemanticSpelling("
+ << "const AttributeList &Attr) {\n";
+ OS << " return UINT_MAX;\n";
+ OS << "}\n\n";
+}
+
+static std::string GenerateSpellingIndexToSemanticSpelling(const Record &Attr,
+ raw_ostream &OS) {
+ // If the attribute does not have a semantic form, we can bail out early.
+ if (!Attr.getValueAsBit("ASTNode"))
+ return "defaultSpellingIndexToSemanticSpelling";
+
+ std::vector<Record *> Spellings = Attr.getValueAsListOfDefs("Spellings");
+
+ // If there are zero or one spellings, or all of the spellings share the same
+ // name, we can also bail out early.
+ if (Spellings.size() <= 1 || SpellingNamesAreCommon(Spellings))
+ return "defaultSpellingIndexToSemanticSpelling";
+
+ // Generate the enumeration we will use for the mapping.
+ SemanticSpellingMap SemanticToSyntacticMap;
+ std::string Enum = CreateSemanticSpellings(Spellings, SemanticToSyntacticMap);
+ std::string Name = Attr.getName() + "AttrSpellingMap";
+
+ OS << "static unsigned " << Name << "(const AttributeList &Attr) {\n";
+ OS << Enum;
+ OS << " unsigned Idx = Attr.getAttributeSpellingListIndex();\n";
+ WriteSemanticSpellingSwitch("Idx", SemanticToSyntacticMap, OS);
+ OS << "}\n\n";
+
+ return Name;
+}
+
static bool CanAppearOnFuncDef(const Record &Attr) {
// Look at the subjects this function appertains to; if a FunctionDefinition
// appears in the list, then this attribute can appear on a function
@@ -2344,11 +2413,12 @@ void EmitClangAttrParsedAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
ParsedAttrMap Dupes;
ParsedAttrMap Attrs = getParsedAttrList(Records, &Dupes);
- // Generate the default appertainsTo, target and language option diagnostic
- // methods.
+ // Generate the default appertainsTo, target and language option diagnostic,
+ // and spelling list index mapping methods.
GenerateDefaultAppertainsTo(OS);
GenerateDefaultLangOptRequirements(OS);
GenerateDefaultTargetRequirements(OS);
+ GenerateDefaultSpellingIndexToSemanticSpelling(OS);
// Generate the appertainsTo diagnostic methods and write their names into
// another mapping. At the same time, generate the AttrInfoMap object
@@ -2374,6 +2444,7 @@ void EmitClangAttrParsedAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
SS << ", " << GenerateAppertainsTo(*I->second, OS);
SS << ", " << GenerateLangOptRequirements(*I->second, OS);
SS << ", " << GenerateTargetRequirements(*I->second, Dupes, OS);
+ SS << ", " << GenerateSpellingIndexToSemanticSpelling(*I->second, OS);
SS << " }";
if (I + 1 != E)