r200041 - 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).

Aaron Ballman aaron at aaronballman.com
Fri Jan 24 13:32:49 PST 2014


Author: aaronballman
Date: Fri Jan 24 15:32:49 2014
New Revision: 200041

URL: http://llvm.org/viewvc/llvm-project?rev=200041&view=rev
Log:
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).

Modified:
    cfe/trunk/include/clang/Sema/AttributeList.h
    cfe/trunk/lib/Sema/AttributeList.cpp
    cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp

Modified: cfe/trunk/include/clang/Sema/AttributeList.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/AttributeList.h?rev=200041&r1=200040&r2=200041&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/AttributeList.h (original)
+++ cfe/trunk/include/clang/Sema/AttributeList.h Fri Jan 24 15:32:49 2014
@@ -495,6 +495,13 @@ public:
   bool diagnoseLangOpts(class Sema &S) const;
   bool existsInTarget(llvm::Triple T) const;
   bool canAppearOnFunctionDefinition() const;
+
+  /// \brief If the parsed attribute has a semantic equivalent, and it would
+  /// have a semantic Spelling enumeration (due to having semantically-distinct
+  /// spelling variations), return the value of that semantic spelling. If the
+  /// parsed attribute does not have a semantic equivalent, or would not have
+  /// a Spelling enumeration, the value UINT_MAX is returned.
+  unsigned getSemanticSpelling() const;
 };
 
 /// A factory, from which one makes pools, from which one creates

Modified: cfe/trunk/lib/Sema/AttributeList.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/AttributeList.cpp?rev=200041&r1=200040&r2=200041&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/AttributeList.cpp (original)
+++ cfe/trunk/lib/Sema/AttributeList.cpp Fri Jan 24 15:32:49 2014
@@ -156,6 +156,7 @@ struct ParsedAttrInfo {
                                const Decl *);
   bool (*DiagLangOpts)(Sema &S, const AttributeList &Attr);
   bool (*ExistsInTarget)(llvm::Triple T);
+  unsigned (*SpellingIndexToSemanticSpelling)(const AttributeList &Attr);
 };
 
 namespace {
@@ -201,3 +202,7 @@ bool AttributeList::existsInTarget(llvm:
 bool AttributeList::canAppearOnFunctionDefinition() const {
   return getInfo(*this).CanAppearOnFuncDef;
 }
+
+unsigned AttributeList::getSemanticSpelling() const {
+  return getInfo(*this).SpellingIndexToSemanticSpelling(*this);
+}

Modified: cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp?rev=200041&r1=200040&r2=200041&view=diff
==============================================================================
--- cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp (original)
+++ cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp Fri Jan 24 15:32:49 2014
@@ -1140,6 +1140,65 @@ static bool SpellingNamesAreCommon(const
   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 &Re
     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);
+    // This maps spelling index values to semantic Spelling enumerants.
+    SemanticSpellingMap SemanticToSyntacticMap;
 
-        OS << "    " << EnumName;
-      }
-      OS << "\n  };\n\n";
-    }
+    if (!ElideSpelling)
+      OS << CreateSemanticSpellings(Spellings, SemanticToSyntacticMap);
 
     OS << "  static " << R.getName() << "Attr *CreateImplicit(";
     OS << "ASTContext &Ctx";
@@ -1327,6 +1354,14 @@ void EmitClangAttrClass(RecordKeeper &Re
     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 GenerateTargetRequire
   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(RecordK
   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(RecordK
     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)





More information about the cfe-commits mailing list