r201732 - Refactored the way attribute category headers are handled so that it is possible to use custom categories. This allows for moving the consumable attributes (consumable, callable_when, return_typestate, etc) to be grouped together, with a content heading, like they were in the language extensions documentation. Moved the consumable attribute documentation from the language extensions into the attribute documentation table.

Aaron Ballman aaron at aaronballman.com
Wed Feb 19 14:59:32 PST 2014


Author: aaronballman
Date: Wed Feb 19 16:59:32 2014
New Revision: 201732

URL: http://llvm.org/viewvc/llvm-project?rev=201732&view=rev
Log:
Refactored the way attribute category headers are handled so that it is possible to use custom categories. This allows for moving the consumable attributes (consumable, callable_when, return_typestate, etc) to be grouped together, with a content heading, like they were in the language extensions documentation. Moved the consumable attribute documentation from the language extensions into the attribute documentation table.

Modified:
    cfe/trunk/docs/LanguageExtensions.rst
    cfe/trunk/include/clang/Basic/Attr.td
    cfe/trunk/include/clang/Basic/AttrDocs.td
    cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp

Modified: cfe/trunk/docs/LanguageExtensions.rst
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/LanguageExtensions.rst?rev=201732&r1=201731&r2=201732&view=diff
==============================================================================
--- cfe/trunk/docs/LanguageExtensions.rst (original)
+++ cfe/trunk/docs/LanguageExtensions.rst Wed Feb 19 16:59:32 2014
@@ -1697,64 +1697,6 @@ The complete list of thread safety attri
 frequently asked questions, can be found in the main documentation: see 
 :doc:`ThreadSafetyAnalysis`.
 
-
-Consumed Annotation Checking
-============================
-
-Clang supports additional attributes for checking basic resource management
-properties, specifically for unique objects that have a single owning reference.
-The following attributes are currently supported, although **the implementation
-for these annotations is currently in development and are subject to change.**
-
-``consumable``
---------------
-
-Each class that uses any of the following annotations must first be marked
-using the consumable attribute.  Failure to do so will result in a warning.
-
-``set_typestate(new_state)``
-----------------------------
-
-Annotate methods that transition an object into a new state with
-``__attribute__((set_typestate(new_state)))``.  The new new state must be
-unconsumed, consumed, or unknown.
-
-``callable_when(...)``
-----------------------
-
-Use ``__attribute__((callable_when(...)))`` to indicate what states a method
-may be called in.  Valid states are unconsumed, consumed, or unknown.  Each
-argument to this attribute must be a quoted string.  E.g.:
-
-``__attribute__((callable_when("unconsumed", "unknown")))``
-
-``tests_typestate(tested_state)``
----------------------------------
-
-Use ``__attribute__((tests_typestate(tested_state)))`` to indicate that a method
-returns true if the object is in the specified state..
-
-``param_typestate(expected_state)``
------------------------------------
-
-This attribute specifies expectations about function parameters.  Calls to an
-function with annotated parameters will issue a warning if the corresponding
-argument isn't in the expected state.  The attribute is also used to set the
-initial state of the parameter when analyzing the function's body.
-
-``return_typestate(ret_state)``
--------------------------------
-
-The ``return_typestate`` attribute can be applied to functions or parameters.
-When applied to a function the attribute specifies the state of the returned
-value.  The function's body is checked to ensure that it always returns a value
-in the specified state.  On the caller side, values returned by the annotated
-function are initialized to the given state.
-
-If the attribute is applied to a function parameter it modifies the state of
-an argument after a call to the function returns.  The function's body is
-checked to ensure that the parameter is in the expected state before returning. 
-
 Type Safety Checking
 ====================
 

Modified: cfe/trunk/include/clang/Basic/Attr.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=201732&r1=201731&r2=201732&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Attr.td (original)
+++ cfe/trunk/include/clang/Basic/Attr.td Wed Feb 19 16:59:32 2014
@@ -11,11 +11,12 @@
 // specific documentation that is collated within the larger document.
 class DocumentationCategory<string name> {
   string Name = name;
+  code Content = [{}];
 }
-def DocCatFunction : DocumentationCategory<"Functions">;
-def DocCatVariable : DocumentationCategory<"Variables">;
-def DocCatType : DocumentationCategory<"Types">;
-def DocCatStmt : DocumentationCategory<"Statements">;
+def DocCatFunction : DocumentationCategory<"Function Attributes">;
+def DocCatVariable : DocumentationCategory<"Variable Attributes">;
+def DocCatType : DocumentationCategory<"Type Attributes">;
+def DocCatStmt : DocumentationCategory<"Statement Attributes">;
 // Attributes listed under the Undocumented category do not generate any public
 // documentation. Ideally, this category should be used for internal-only
 // attributes which contain no spellings.
@@ -1484,7 +1485,7 @@ def Consumable : InheritableAttr {
   let Args = [EnumArgument<"DefaultState", "ConsumedState",
                            ["unknown", "consumed", "unconsumed"],
                            ["Unknown", "Consumed", "Unconsumed"]>];
-  let Documentation = [Undocumented];
+  let Documentation = [ConsumableDocs];
 }
 
 def ConsumableAutoCast : InheritableAttr {
@@ -1505,7 +1506,7 @@ def CallableWhen : InheritableAttr {
   let Args = [VariadicEnumArgument<"CallableState", "ConsumedState",
                                    ["unknown", "consumed", "unconsumed"],
                                    ["Unknown", "Consumed", "Unconsumed"]>];
-  let Documentation = [Undocumented];
+  let Documentation = [CallableWhenDocs];
 }
 
 def ParamTypestate : InheritableAttr {
@@ -1514,7 +1515,7 @@ def ParamTypestate : InheritableAttr {
   let Args = [EnumArgument<"ParamState", "ConsumedState",
                            ["unknown", "consumed", "unconsumed"],
                            ["Unknown", "Consumed", "Unconsumed"]>];
-  let Documentation = [Undocumented];
+  let Documentation = [ParamTypestateDocs];
 }
 
 def ReturnTypestate : InheritableAttr {
@@ -1523,7 +1524,7 @@ def ReturnTypestate : InheritableAttr {
   let Args = [EnumArgument<"State", "ConsumedState",
                            ["unknown", "consumed", "unconsumed"],
                            ["Unknown", "Consumed", "Unconsumed"]>];
-  let Documentation = [Undocumented];
+  let Documentation = [ReturnTypestateDocs];
 }
 
 def SetTypestate : InheritableAttr {
@@ -1532,7 +1533,7 @@ def SetTypestate : InheritableAttr {
   let Args = [EnumArgument<"NewState", "ConsumedState",
                            ["unknown", "consumed", "unconsumed"],
                            ["Unknown", "Consumed", "Unconsumed"]>];
-  let Documentation = [Undocumented];
+  let Documentation = [SetTypestateDocs];
 }
 
 def TestTypestate : InheritableAttr {
@@ -1541,7 +1542,7 @@ def TestTypestate : InheritableAttr {
   let Args = [EnumArgument<"TestState", "ConsumedState",
                            ["consumed", "unconsumed"],
                            ["Consumed", "Unconsumed"]>];
-  let Documentation = [Undocumented];
+  let Documentation = [TestTypestateDocs];
 }
 
 // Type safety attributes for `void *' pointers and type tags.

Modified: cfe/trunk/include/clang/Basic/AttrDocs.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/AttrDocs.td?rev=201732&r1=201731&r2=201732&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/AttrDocs.td (original)
+++ cfe/trunk/include/clang/Basic/AttrDocs.td Wed Feb 19 16:59:32 2014
@@ -498,3 +498,76 @@ The semantics are as follows:
   a sequence equivalent to "movs pc, lr" will be used.
   }];
 }
+
+def DocCatConsumed : DocumentationCategory<"Consumed Annotation Checking"> {
+  let Content = [{
+Clang supports additional attributes for checking basic resource management
+properties, specifically for unique objects that have a single owning reference.
+The following attributes are currently supported, although **the implementation
+for these annotations is currently in development and are subject to change.**
+  }];
+}
+
+def SetTypestateDocs : Documentation {
+  let Category = DocCatConsumed;
+  let Content = [{
+Annotate methods that transition an object into a new state with
+``__attribute__((set_typestate(new_state)))``.  The new new state must be
+unconsumed, consumed, or unknown.
+  }];
+}
+
+def CallableWhenDocs : Documentation {
+  let Category = DocCatConsumed;
+  let Content = [{
+Use ``__attribute__((callable_when(...)))`` to indicate what states a method
+may be called in.  Valid states are unconsumed, consumed, or unknown.  Each
+argument to this attribute must be a quoted string.  E.g.:
+
+``__attribute__((callable_when("unconsumed", "unknown")))``
+  }];
+}
+
+def TestTypestateDocs : Documentation {
+  let Category = DocCatConsumed;
+  let Content = [{
+Use ``__attribute__((test_typestate(tested_state)))`` to indicate that a method
+returns true if the object is in the specified state..
+  }];
+}
+
+def ParamTypestateDocs : Documentation {
+  let Category = DocCatConsumed;
+  let Content = [{
+This attribute specifies expectations about function parameters.  Calls to an
+function with annotated parameters will issue a warning if the corresponding
+argument isn't in the expected state.  The attribute is also used to set the
+initial state of the parameter when analyzing the function's body.
+  }];
+}
+
+def ReturnTypestateDocs : Documentation {
+  let Category = DocCatConsumed;
+  let Content = [{
+The ``return_typestate`` attribute can be applied to functions or parameters.
+When applied to a function the attribute specifies the state of the returned
+value.  The function's body is checked to ensure that it always returns a value
+in the specified state.  On the caller side, values returned by the annotated
+function are initialized to the given state.
+
+When applied to a function parameter it modifies the state of an argument after
+a call to the function returns.  The function's body is checked to ensure that
+the parameter is in the expected state before returning.
+  }];
+}
+
+def ConsumableDocs : Documentation {
+  let Category = DocCatConsumed;
+  let Content = [{
+Each ``class`` that uses any of the typestate annotations must first be marked
+using the ``consumable`` attribute.  Failure to do so will result in a warning.
+
+This attribute accepts a single parameter that must be one of the following:
+``unknown``, ``consumed``, or ``unconsumed``.
+  }];
+}

Modified: cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp?rev=201732&r1=201731&r2=201732&view=diff
==============================================================================
--- cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp (original)
+++ cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp Wed Feb 19 16:59:32 2014
@@ -2648,49 +2648,32 @@ void EmitClangAttrParserStringSwitches(R
 
 class DocumentationData {
 public:
-  enum DocCategory {
-    Function,
-    Variable,
-    Type,
-    Statement,
-    Undocumented
-  };
-
-  DocCategory Category;
   const Record *Documentation;
   const Record *Attribute;
 
-  DocumentationData(DocCategory Category, const Record &Documentation,
-                    const Record &Attribute)
-      : Category(Category), Documentation(&Documentation),
-        Attribute(&Attribute) {}
+  DocumentationData(const Record &Documentation, const Record &Attribute)
+      : Documentation(&Documentation), Attribute(&Attribute) {}
 };
 
-static void WriteCategoryHeader(DocumentationData::DocCategory Category,
+static void WriteCategoryHeader(const Record *DocCategory,
                                 raw_ostream &OS) {
-  OS << "\n";
-  switch (Category) {
-    case DocumentationData::Undocumented:
-      assert(false && "Undocumented attributes are not documented!");
-      break;
-    case DocumentationData::Function:
-      OS << "Function Attributes\n";
-      OS << "===================\n";
-      break;
-    case DocumentationData::Variable:
-      OS << "Variable Attributes\n";
-      OS << "===================\n";
-      break;
-    case DocumentationData::Type:
-      OS << "Type Attributes\n";
-      OS << "===============\n";
-      break;
-    case DocumentationData::Statement:
-      OS << "Statement Attributes\n";
-      OS << "====================\n";
-      break;
+  const std::string &Name = DocCategory->getValueAsString("Name");
+  OS << Name << "\n" << std::string(Name.length(), '=') << "\n";
+
+  // If there is content, print that as well.
+  std::string ContentStr = DocCategory->getValueAsString("Content");
+  if (!ContentStr.empty()) {
+    // Trim leading and trailing newlines and spaces.
+    StringRef Content(ContentStr);
+    while (Content.startswith("\r") || Content.startswith("\n") ||
+           Content.startswith(" ") || Content.startswith("\t"))
+           Content = Content.substr(1);
+    while (Content.endswith("\r") || Content.endswith("\n") ||
+           Content.endswith(" ") || Content.endswith("\t"))
+           Content = Content.substr(0, Content.size() - 1);
+    OS << Content;
   }
-  OS << "\n";
+  OS << "\n\n";
 }
 
 enum SpellingKind {
@@ -2828,9 +2811,9 @@ void EmitClangAttrDocs(RecordKeeper &Rec
     return;
   }
 
-  OS << Documentation->getValueAsString("Intro");
+  OS << Documentation->getValueAsString("Intro") << "\n";
 
-  typedef std::map<DocumentationData::DocCategory,
+  typedef std::map<const Record *,
                    std::vector<DocumentationData> > CategoryMap;
   CategoryMap SplitDocs;
 
@@ -2844,26 +2827,19 @@ void EmitClangAttrDocs(RecordKeeper &Rec
     for (std::vector<Record *>::const_iterator DI = Docs.begin(),
          DE = Docs.end(); DI != DE; ++DI) {
       const Record &Doc = **DI;
-      DocumentationData::DocCategory Cat =
-          StringSwitch<DocumentationData::DocCategory>(
-              Doc.getValueAsDef("Category")->getValueAsString("Name"))
-              .Case("Functions", DocumentationData::Function)
-              .Case("Variables", DocumentationData::Variable)
-              .Case("Types", DocumentationData::Type)
-              .Case("Statements", DocumentationData::Statement)
-              .Case("Undocumented", DocumentationData::Undocumented);
-
+      const Record *Category = Doc.getValueAsDef("Category");
       // If the category is "undocumented", then there cannot be any other
       // documentation categories (otherwise, the attribute would become
       // documented).
-      bool Undocumented = DocumentationData::Undocumented == Cat;
+      std::string Cat = Category->getValueAsString("Name");
+      bool Undocumented = Cat == "Undocumented";
       if (Undocumented && Docs.size() > 1)
         PrintFatalError(Doc.getLoc(),
                         "Attribute is \"Undocumented\", but has multiple "
                         "documentation categories");      
 
       if (!Undocumented)
-        SplitDocs[Cat].push_back(DocumentationData(Cat, Doc, Attr));
+        SplitDocs[Category].push_back(DocumentationData(Doc, Attr));
     }
   }
 





More information about the cfe-commits mailing list