diff --git a/lib/modules/Tools.pmod/AutoDoc.pmod/PikeObjects.pmod b/lib/modules/Tools.pmod/AutoDoc.pmod/PikeObjects.pmod
index fc0fb121ad819503654cc5181c56183eceb8f683..106ef7b961532b95822a98934e4d5ec3a1c4dc6b 100644
--- a/lib/modules/Tools.pmod/AutoDoc.pmod/PikeObjects.pmod
+++ b/lib/modules/Tools.pmod/AutoDoc.pmod/PikeObjects.pmod
@@ -821,11 +821,15 @@ class Constant {
   //!
   constant objtype = "constant";
 
+  //! The type of the constant, if known.
+  Type type;
+
   //! Typedef @[Type] if it is a typedef.
   Type typedefType = 0;
 
   string xml() {
     return standardStart() + standardTags()
+      + (type ? xmltag ("type", type->xml()) : "")
       + (typedefType ? xmltag("typevalue", typedefType->xml()) : "")
       + standardEnd();
   }
diff --git a/lib/modules/Tools.pmod/AutoDoc.pmod/PikeParser.pike b/lib/modules/Tools.pmod/AutoDoc.pmod/PikeParser.pike
index 00c16e1252889d3dd7df7c4aa586f4ce94029ff7..e477220a25210aaad374d249f74ba033b3b78821 100644
--- a/lib/modules/Tools.pmod/AutoDoc.pmod/PikeParser.pike
+++ b/lib/modules/Tools.pmod/AutoDoc.pmod/PikeParser.pike
@@ -680,6 +680,33 @@ void|string parseLiteral() {
   return 0;
 }
 
+Type literalType (string literal)
+//! Returns the type of a literal. Currently only recognizes the top
+//! level type. Currently does not thoroughly check that the literal
+//! is syntactically valid.
+{
+  if (sizeof (literal))
+    switch (literal[0]) {
+      case '\'': return IntType(); // Character constant.
+      case '"': return StringType();
+      case '(':
+	if (sizeof (literal) > 1)
+	  switch (literal[1]) {
+	    case '{': return ArrayType();
+	    case '[': return MappingType();
+	    case '<': return MultisetType();
+	  }
+	break;
+      default:
+	if (sscanf (literal, "%*D%*c") == 1)
+	  return IntType();
+	if (sscanf (literal, "%*f%*c") == 1)
+	  return FloatType();
+    }
+  // Unrecognized format. Add an option to trig a parse error instead?
+  return 0;
+}
+
 //! Expect a literal constant.
 //!
 //! @seealso
@@ -731,9 +758,22 @@ PikeObject|array(PikeObject) parseDecl(mapping|void args) {
     c->position = position;
     c->modifiers = modifiers;
     readToken();
+    int save_pos = tokenPtr;
+    mixed err = catch (c->type = parseOrType());
+    if (err && (!objectp (err) || !err->is_pike_parse_error))
+      throw (err);
+    if (err || (<"=", ";", EOF>)[peekToken()]) {
+      c->type = 0;
+      tokenPtr = save_pos;
+    }
     c->name = eatIdentifier();
     if (peekToken() == "=") {
       eat("=");
+      if (string l = parseLiteral())
+	// It's intentional that literalType doesn't return too
+	// specific types for integers, i.e. it's int instead of e.g.
+	// int(4711..4711).
+	c->type = literalType (l);
       // TODO: parse the expression ???
       //   added parsing only of types...
       //   a constant value will just be ignored.
diff --git a/refdoc/keywords.txt b/refdoc/keywords.txt
index 955c93947677457ec3797a58e5b70b30473b9a0a..109cf6f4d6170fa488e7ad28acf32882c83a2246 100644
--- a/refdoc/keywords.txt
+++ b/refdoc/keywords.txt
@@ -83,6 +83,12 @@ Description:  Declare a Pike entity and state that the current
                 2. All @decl's in the block are methods with the same
                    name as that method. (look at the last example
                    below)
+
+	      The rest of the line after @decl should follow real pike
+	      syntax, but the ending semicolon is optional. There are
+	      some differences though, notably it allows a type to be
+	      specified for constants.
+
 Arguments:    <declaration>
               Where:
                 <declaration> is a valid Pike declaration. A trailing
@@ -101,6 +107,9 @@ Examples:
               //!  This is how to document a "polymorph" function.
               float|int cube(float|int x) { /* body */ }
 
+	      //! @decl constant int bitmask
+	      //!  A constant which has a public type but private value.
+
 _______________________________________________________________________________
 
 Keyword:      @endclass
diff --git a/refdoc/presentation/make_html.pike b/refdoc/presentation/make_html.pike
index 5efbe1b4fec843159355a7d1e30097e46777e92d..ef8bf0f8af8881335b2bbbec7e9aee20aebd3657 100644
--- a/refdoc/presentation/make_html.pike
+++ b/refdoc/presentation/make_html.pike
@@ -1100,6 +1100,8 @@ string parse_not_doc(Node n) {
     case "constant":
       if(const++) ret += "<br />\n";
       ret += "<tt>constant ";
+      if (Node type = c->get_first_element ("type"))
+	ret += parse_type (get_first_element (type), "constant") + " ";
       ret += c->get_attributes()->class_path;
       ret += "<font color='#F000F0'>" + c->get_attributes()->name + "</font>";
       cc = c->get_first_element("typevalue");
diff --git a/refdoc/xml.txt b/refdoc/xml.txt
index 409c12cb587f95ef5fbd665ae384581e64dc0c86..6cd0899a29bedac07834ab44bfc7ad20737fedf3 100644
--- a/refdoc/xml.txt
+++ b/refdoc/xml.txt
@@ -200,7 +200,8 @@ entities:
      </class>
  
 <constant>
-   Only has a name. The element is empty (or has a <source-position> child.)
+   Has a name attribute. Contains optional <type> and
+   <source-position> child elements.
 
 <enum>
    Works as a container. Has a <doc> child element with the documentation of