Emit TypeNodes.def with tblgen.
authorJohn McCall <rjmccall@apple.com>
Tue, 1 Oct 2019 23:13:03 +0000 (23:13 +0000)
committerJohn McCall <rjmccall@apple.com>
Tue, 1 Oct 2019 23:13:03 +0000 (23:13 +0000)
The primary goal here is to make the type node hierarchy available to
other tblgen backends, although it should also make it easier to generate
more selective x-macros in the future.

Because tblgen doesn't seem to allow backends to preserve the source
order of defs, this is not NFC because it significantly re-orders IDs.
I've fixed the one (fortunately obvious) place where we relied on
the old order.  Unfortunately, I wasn't able to share code with the
existing AST-node x-macro generators because the x-macro schema we use
for types is different in a number of ways.  The main loss is that
subclasses aren't ordered together, which doesn't seem important for
types because the hierarchy is generally very shallow with little
clustering.

llvm-svn: 373407

clang/include/clang/AST/CMakeLists.txt
clang/include/clang/AST/Type.h
clang/include/clang/AST/TypeNodes.def [deleted file]
clang/include/clang/Basic/TypeNodes.td [new file with mode: 0644]
clang/utils/TableGen/CMakeLists.txt
clang/utils/TableGen/ClangTypeNodesEmitter.cpp [new file with mode: 0644]
clang/utils/TableGen/TableGen.cpp
clang/utils/TableGen/TableGenBackends.h

index da16987..6035f91 100644 (file)
@@ -31,6 +31,10 @@ clang_tablegen(DeclNodes.inc -gen-clang-decl-nodes
   SOURCE ../Basic/DeclNodes.td
   TARGET ClangDeclNodes)
 
+clang_tablegen(TypeNodes.def -gen-clang-type-nodes
+  SOURCE ../Basic/TypeNodes.td
+  TARGET ClangTypeNodes)
+
 clang_tablegen(CommentNodes.inc -gen-clang-comment-nodes
   SOURCE ../Basic/CommentNodes.td
   TARGET ClangCommentNodes)
index 3968e1a..5c86509 100644 (file)
@@ -1437,10 +1437,9 @@ class alignas(8) Type : public ExtQualsTypeCommonBase {
 public:
   enum TypeClass {
 #define TYPE(Class, Base) Class,
-#define LAST_TYPE(Class) TypeLast = Class,
+#define LAST_TYPE(Class) TypeLast = Class
 #define ABSTRACT_TYPE(Class, Base)
 #include "clang/AST/TypeNodes.def"
-    TagFirst = Record, TagLast = Enum
   };
 
 private:
@@ -4436,7 +4435,7 @@ public:
   bool isBeingDefined() const;
 
   static bool classof(const Type *T) {
-    return T->getTypeClass() >= TagFirst && T->getTypeClass() <= TagLast;
+    return T->getTypeClass() == Enum || T->getTypeClass() == Record;
   }
 };
 
diff --git a/clang/include/clang/AST/TypeNodes.def b/clang/include/clang/AST/TypeNodes.def
deleted file mode 100644 (file)
index 58a5f88..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-//===-- TypeNodes.def - Metadata about Type AST nodes -----------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-//  This file defines the AST type info database. Each type node is
-//  enumerated by providing its name (e.g., "Builtin" or "Enum") and
-//  base class (e.g., "Type" or "TagType"). Depending on where in the
-//  abstract syntax tree the type will show up, the enumeration uses
-//  one of five different macros:
-//
-//    TYPE(Class, Base) - A type that can show up anywhere in the AST,
-//    and might be dependent, canonical, or non-canonical. All clients
-//    will need to understand these types.
-//
-//    ABSTRACT_TYPE(Class, Base) - An abstract class that shows up in
-//    the type hierarchy but has no concrete instances.
-//
-//    NON_CANONICAL_TYPE(Class, Base) - A type that can show up
-//    anywhere in the AST but will never be a part of a canonical
-//    type. Clients that only need to deal with canonical types
-//    (ignoring, e.g., typedefs and other type aliases used for
-//    pretty-printing) can ignore these types.
-//
-//    DEPENDENT_TYPE(Class, Base) - A type that will only show up
-//    within a C++ template that has not been instantiated, e.g., a
-//    type that is always dependent. Clients that do not need to deal
-//    with uninstantiated C++ templates can ignore these types.
-//
-//    NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) - A type that
-//    is non-canonical unless it is dependent.  Defaults to TYPE because
-//    it is neither reliably dependent nor reliably non-canonical.
-//
-//  There is a sixth macro, independent of the others.  Most clients
-//  will not need to use it.
-//
-//    LEAF_TYPE(Class) - A type that never has inner types.  Clients
-//    which can operate on such types more efficiently may wish to do so.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef ABSTRACT_TYPE
-#  define ABSTRACT_TYPE(Class, Base) TYPE(Class, Base)
-#endif
-
-#ifndef NON_CANONICAL_TYPE
-#  define NON_CANONICAL_TYPE(Class, Base) TYPE(Class, Base)
-#endif
-
-#ifndef DEPENDENT_TYPE
-#  define DEPENDENT_TYPE(Class, Base) TYPE(Class, Base)
-#endif
-
-#ifndef NON_CANONICAL_UNLESS_DEPENDENT_TYPE
-#  define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) TYPE(Class, Base)
-#endif
-
-TYPE(Builtin, Type)
-TYPE(Complex, Type)
-TYPE(Pointer, Type)
-TYPE(BlockPointer, Type)
-ABSTRACT_TYPE(Reference, Type)
-TYPE(LValueReference, ReferenceType)
-TYPE(RValueReference, ReferenceType)
-TYPE(MemberPointer, Type)
-ABSTRACT_TYPE(Array, Type)
-TYPE(ConstantArray, ArrayType)
-TYPE(IncompleteArray, ArrayType)
-TYPE(VariableArray, ArrayType)
-DEPENDENT_TYPE(DependentSizedArray, ArrayType)
-DEPENDENT_TYPE(DependentSizedExtVector, Type)
-DEPENDENT_TYPE(DependentAddressSpace, Type)
-TYPE(Vector, Type)
-DEPENDENT_TYPE(DependentVector, Type)
-TYPE(ExtVector, VectorType)
-ABSTRACT_TYPE(Function, Type)
-TYPE(FunctionProto, FunctionType)
-TYPE(FunctionNoProto, FunctionType)
-DEPENDENT_TYPE(UnresolvedUsing, Type)
-NON_CANONICAL_TYPE(Paren, Type)
-NON_CANONICAL_TYPE(Typedef, Type)
-NON_CANONICAL_TYPE(MacroQualified, Type)
-NON_CANONICAL_TYPE(Adjusted, Type)
-NON_CANONICAL_TYPE(Decayed, AdjustedType)
-NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TypeOfExpr, Type)
-NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TypeOf, Type)
-NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Decltype, Type)
-NON_CANONICAL_UNLESS_DEPENDENT_TYPE(UnaryTransform, Type)
-ABSTRACT_TYPE(Tag, Type)
-TYPE(Record, TagType)
-TYPE(Enum, TagType)
-NON_CANONICAL_TYPE(Elaborated, Type)
-NON_CANONICAL_TYPE(Attributed, Type)
-DEPENDENT_TYPE(TemplateTypeParm, Type)
-NON_CANONICAL_TYPE(SubstTemplateTypeParm, Type)
-DEPENDENT_TYPE(SubstTemplateTypeParmPack, Type)
-NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TemplateSpecialization, Type)
-ABSTRACT_TYPE(Deduced, Type)
-TYPE(Auto, DeducedType)
-TYPE(DeducedTemplateSpecialization, DeducedType)
-DEPENDENT_TYPE(InjectedClassName, Type)
-DEPENDENT_TYPE(DependentName, Type)
-DEPENDENT_TYPE(DependentTemplateSpecialization, Type)
-NON_CANONICAL_UNLESS_DEPENDENT_TYPE(PackExpansion, Type)
-NON_CANONICAL_TYPE(ObjCTypeParam, Type)
-TYPE(ObjCObject, Type)
-TYPE(ObjCInterface, ObjCObjectType)
-TYPE(ObjCObjectPointer, Type)
-TYPE(Pipe, Type)
-TYPE(Atomic, Type)
-
-#ifdef LAST_TYPE
-LAST_TYPE(Atomic)
-#undef LAST_TYPE
-#endif
-
-// These types are always leaves in the type hierarchy.
-#ifdef LEAF_TYPE
-LEAF_TYPE(Enum)
-LEAF_TYPE(Builtin)
-LEAF_TYPE(Record)
-LEAF_TYPE(InjectedClassName)
-LEAF_TYPE(ObjCInterface)
-LEAF_TYPE(TemplateTypeParm)
-#undef LEAF_TYPE
-#endif
-
-#undef NON_CANONICAL_UNLESS_DEPENDENT_TYPE
-#undef DEPENDENT_TYPE
-#undef NON_CANONICAL_TYPE
-#undef ABSTRACT_TYPE
-#undef TYPE
diff --git a/clang/include/clang/Basic/TypeNodes.td b/clang/include/clang/Basic/TypeNodes.td
new file mode 100644 (file)
index 0000000..b2554de
--- /dev/null
@@ -0,0 +1,106 @@
+class Type<bit abstract = 0> {
+  bit Abstract = abstract;
+} 
+
+class DerivedType<Type base, bit abstract = 0> : Type<abstract> {
+       Type Base = base;
+}
+
+/// A type node that is only used to represent dependent types in C++.  For
+/// example, DependentTemplateSpecializationType is used to represent types
+/// where the base template-id is dependent (such as `T::foo<U>`).  Code
+/// that only works with non-dependent types can ignore these type nodes.
+class AlwaysDependent {}
+
+/// A type node that is never used to represent a canonical type, which is to
+/// say that it always represents some sort of type "sugar" which can
+/// (supposedly) be erased without affecting the formal behavior of the
+/// language.  For example, in standard C/C++, typedefs do not introduce new
+/// types and do not affect the semantics of the program.  Code that only
+/// works with canonical types can ignore these type nodes.
+///
+/// Note that this simple story about non-canonical types is not the whole
+/// truth.  Languages and extensions often have formation rules which differ
+/// based on how a type is spelled and which therefore are not consistent
+/// with immediately stipping away type sugar.  More critically, attributes on
+/// typedefs can have semantic impacts in ways that are only reflected in our
+/// AST by preserving the typedef sugar; for example, we do not otherwise
+/// represent the alignment attribute on typedefs, and so it is necessary to
+/// preserve typedef structure into most parts of IR generation.
+class NeverCanonical {}
+
+/// A type node that only represents a canonical type in some dependent cases.
+/// For example, `std::vector<int>` (a TemplateSpecializationType) is
+/// considered to be a non-canonical representation for the RecordType
+/// referencing the concrete ClassTemplateSpecializationDecl; but
+/// `std::vector<T>` cannot be resolved to a concrete specialization
+/// and so remains canonical.  Code which only works with non-dependent
+/// canonical types can ignore these nodes.
+class NeverCanonicalUnlessDependent {}
+
+/// A type node which never has component type structure.  Some code may be
+/// able to operate on leaf types faster than they can on non-leaf types.
+///
+/// For example, the function type `void (int)` is not a leaf type because it
+/// is structurally composed of component types (`void` and `int`).
+///
+/// A struct type is a leaf type because its field types are not part of its
+/// type-expression.
+///
+/// Nodes like `TypedefType` which are syntactically leaves but can desugar
+/// to types that may not be leaves should not declare this.
+class LeafType {}
+
+def BuiltinType : Type, LeafType;
+def ComplexType : Type;
+def PointerType : Type;
+def BlockPointerType : Type;
+def ReferenceType : Type<1>;
+def LValueReferenceType : DerivedType<ReferenceType>;
+def RValueReferenceType : DerivedType<ReferenceType>;
+def MemberPointerType : Type;
+def ArrayType : Type<1>;
+def ConstantArrayType : DerivedType<ArrayType>;
+def IncompleteArrayType : DerivedType<ArrayType>;
+def VariableArrayType : DerivedType<ArrayType>;
+def DependentSizedArrayType : DerivedType<ArrayType>, AlwaysDependent;
+def DependentSizedExtVectorType : Type, AlwaysDependent;
+def DependentAddressSpaceType : Type, AlwaysDependent;
+def VectorType : Type;
+def DependentVectorType : Type, AlwaysDependent;
+def ExtVectorType : DerivedType<VectorType>;
+def FunctionType : Type<1>;
+def FunctionProtoType : DerivedType<FunctionType>;
+def FunctionNoProtoType : DerivedType<FunctionType>;
+def UnresolvedUsingType : Type, AlwaysDependent;
+def ParenType : Type, NeverCanonical;
+def TypedefType : Type, NeverCanonical;
+def MacroQualifiedType : Type, NeverCanonical;
+def AdjustedType : Type, NeverCanonical;
+def DecayedType : DerivedType<AdjustedType>, NeverCanonical;
+def TypeOfExprType : Type, NeverCanonicalUnlessDependent;
+def TypeOfType : Type, NeverCanonicalUnlessDependent;
+def DecltypeType : Type, NeverCanonicalUnlessDependent;
+def UnaryTransformType : Type, NeverCanonicalUnlessDependent;
+def TagType : Type<1>;
+def RecordType : DerivedType<TagType>, LeafType;
+def EnumType : DerivedType<TagType>, LeafType;
+def ElaboratedType : Type, NeverCanonical;
+def AttributedType : Type, NeverCanonical;
+def TemplateTypeParmType : Type, AlwaysDependent, LeafType;
+def SubstTemplateTypeParmType : Type, NeverCanonical;
+def SubstTemplateTypeParmPackType : Type, AlwaysDependent;
+def TemplateSpecializationType : Type, NeverCanonicalUnlessDependent;
+def DeducedType : Type<1>;
+def AutoType : DerivedType<DeducedType>;
+def DeducedTemplateSpecializationType : DerivedType<DeducedType>;
+def InjectedClassNameType : Type, AlwaysDependent, LeafType;
+def DependentNameType : Type, AlwaysDependent;
+def DependentTemplateSpecializationType : Type, AlwaysDependent;
+def PackExpansionType : Type, NeverCanonicalUnlessDependent;
+def ObjCTypeParamType : Type, NeverCanonical;
+def ObjCObjectType : Type;
+def ObjCInterfaceType : DerivedType<ObjCObjectType>, LeafType;
+def ObjCObjectPointerType : Type;
+def PipeType : Type;
+def AtomicType : Type;
index d33ede2..96b97a7 100644 (file)
@@ -12,6 +12,7 @@ add_tablegen(clang-tblgen CLANG
   ClangOpenCLBuiltinEmitter.cpp
   ClangOptionDocEmitter.cpp
   ClangSACheckersEmitter.cpp
+  ClangTypeNodesEmitter.cpp
   NeonEmitter.cpp
   TableGen.cpp
   )
diff --git a/clang/utils/TableGen/ClangTypeNodesEmitter.cpp b/clang/utils/TableGen/ClangTypeNodesEmitter.cpp
new file mode 100644 (file)
index 0000000..c9986c8
--- /dev/null
@@ -0,0 +1,220 @@
+//=== ClangTypeNodesEmitter.cpp - Generate type node tables -----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This tblgen backend emits the node table (the .def file) for Clang
+// type nodes.
+//
+// This file defines the AST type info database. Each type node is
+// enumerated by providing its name (e.g., "Builtin" or "Enum") and
+// base class (e.g., "Type" or "TagType"). Depending on where in the
+// abstract syntax tree the type will show up, the enumeration uses
+// one of five different macros:
+//
+//    TYPE(Class, Base) - A type that can show up anywhere in the AST,
+//    and might be dependent, canonical, or non-canonical. All clients
+//    will need to understand these types.
+//
+//    ABSTRACT_TYPE(Class, Base) - An abstract class that shows up in
+//    the type hierarchy but has no concrete instances.
+//
+//    NON_CANONICAL_TYPE(Class, Base) - A type that can show up
+//    anywhere in the AST but will never be a part of a canonical
+//    type. Clients that only need to deal with canonical types
+//    (ignoring, e.g., typedefs and other type aliases used for
+//    pretty-printing) can ignore these types.
+//
+//    DEPENDENT_TYPE(Class, Base) - A type that will only show up
+//    within a C++ template that has not been instantiated, e.g., a
+//    type that is always dependent. Clients that do not need to deal
+//    with uninstantiated C++ templates can ignore these types.
+//
+//    NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) - A type that
+//    is non-canonical unless it is dependent.  Defaults to TYPE because
+//    it is neither reliably dependent nor reliably non-canonical.
+//
+// There is a sixth macro, independent of the others.  Most clients
+// will not need to use it.
+//
+//    LEAF_TYPE(Class) - A type that never has inner types.  Clients
+//    which can operate on such types more efficiently may wish to do so.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/TableGenBackend.h"
+#include <set>
+#include <string>
+#include <vector>
+#include "TableGenBackends.h"
+
+using namespace llvm;
+
+// These are spellings in the generated output.
+#define TypeMacroName "TYPE"
+#define AbstractTypeMacroName "ABSTRACT_TYPE"
+#define DependentTypeMacroName "DEPENDENT_TYPE"
+#define NonCanonicalTypeMacroName "NON_CANONICAL_TYPE"
+#define NonCanonicalUnlessDependentTypeMacroName "NON_CANONICAL_UNLESS_DEPENDENT_TYPE"
+#define TypeMacroArgs "(Class, Base)"
+#define LastTypeMacroName "LAST_TYPE"
+#define LeafTypeMacroName "LEAF_TYPE"
+
+// These are spellings in the tblgen file.
+// (Type is also used for the spelling of the AST class.)
+#define TypeClassName "Type"
+#define DerivedTypeClassName "DerivedType"
+#define AlwaysDependentClassName "AlwaysDependent"
+#define NeverCanonicalClassName "NeverCanonical"
+#define NeverCanonicalUnlessDependentClassName "NeverCanonicalUnlessDependent"
+#define LeafTypeClassName "LeafType"
+#define AbstractFieldName "Abstract"
+#define BaseFieldName "Base"
+
+static StringRef getIdForType(Record *type) {
+       // The record name is expected to be the full C++ class name,
+       // including "Type".  Check for that and strip it off.
+       auto fullName = type->getName();
+       if (!fullName.endswith("Type"))
+               PrintFatalError(type->getLoc(), "name of Type node doesn't end in Type");
+       return fullName.drop_back(4);
+}
+
+namespace {
+class TypeNodeEmitter {
+       RecordKeeper &Records;
+       raw_ostream &Out;
+       const std::vector<Record*> Types;
+       std::vector<StringRef> MacrosToUndef;
+
+public:
+       TypeNodeEmitter(RecordKeeper &records, raw_ostream &out)
+               : Records(records), Out(out),
+                       Types(Records.getAllDerivedDefinitions("Type")) {
+       }
+
+       void emit();
+
+private:
+       void emitFallbackDefine(StringRef macroName, StringRef fallbackMacroName,
+                                                                                                       StringRef args);
+
+       void emitNodeInvocations();
+       void emitLastNodeInvocation();
+       void emitLeafNodeInvocations();
+
+       void addMacroToUndef(StringRef macroName);
+       void emitUndefs();
+};
+}
+
+void TypeNodeEmitter::emit() {
+       if (Types.empty())
+               PrintFatalError("no Type records in input!");
+
+       emitSourceFileHeader("An x-macro database of Clang type nodes", Out);
+
+       // Preamble
+       addMacroToUndef(TypeMacroName);
+       addMacroToUndef(AbstractTypeMacroName);
+       emitFallbackDefine(AbstractTypeMacroName, TypeMacroName, TypeMacroArgs);
+       emitFallbackDefine(NonCanonicalTypeMacroName, TypeMacroName, TypeMacroArgs);
+       emitFallbackDefine(DependentTypeMacroName, TypeMacroName, TypeMacroArgs);
+       emitFallbackDefine(NonCanonicalUnlessDependentTypeMacroName, TypeMacroName, 
+                                                                                TypeMacroArgs);
+
+       // Invocations.
+       emitNodeInvocations();
+       emitLastNodeInvocation();
+       emitLeafNodeInvocations();
+
+       // Postmatter
+       emitUndefs();
+}
+
+void TypeNodeEmitter::emitFallbackDefine(StringRef macroName,
+                                                                                                                                                                StringRef fallbackMacroName,
+                                                                                                                                                                StringRef args) {
+  Out << "#ifndef " << macroName << "\n";
+  Out << "#  define " << macroName << args
+         << " " << fallbackMacroName << args << "\n";
+  Out << "#endif\n";
+
+  addMacroToUndef(macroName);
+}
+
+void TypeNodeEmitter::emitNodeInvocations() {
+       for (auto type : Types) {
+               // The name with the Type suffix.
+               StringRef id = getIdForType(type);
+
+               // Figure out which macro to use.
+               StringRef macroName;
+               auto setMacroName = [&](StringRef newName) {
+                       if (!macroName.empty())
+                               PrintFatalError(type->getLoc(),
+                                                                                               Twine("conflict when computing macro name for "
+                                                                                                                       "Type node: trying to use both \"")
+                                                                                                       + macroName + "\" and \"" + newName + "\"");
+                       macroName = newName;
+               };
+               if (type->isSubClassOf(AlwaysDependentClassName))
+                       setMacroName(DependentTypeMacroName);
+               if (type->isSubClassOf(NeverCanonicalClassName))
+                       setMacroName(NonCanonicalTypeMacroName);
+               if (type->isSubClassOf(NeverCanonicalUnlessDependentClassName))
+                       setMacroName(NonCanonicalUnlessDependentTypeMacroName);
+               if (type->getValueAsBit(AbstractFieldName))
+                       setMacroName(AbstractTypeMacroName);
+               if (macroName.empty())
+                       macroName = TypeMacroName;
+
+               // Compute the base class.
+               StringRef baseName = TypeClassName;
+               if (type->isSubClassOf(DerivedTypeClassName))
+                       baseName = type->getValueAsDef(BaseFieldName)->getName();
+
+               // Generate the invocation line.
+               Out << macroName << "(" << id << ", " << baseName << ")\n";
+       }
+}
+
+void TypeNodeEmitter::emitLastNodeInvocation() {
+       // We check that this is non-empty earlier.
+       Out << "#ifdef " LastTypeMacroName "\n"
+              LastTypeMacroName "(" << getIdForType(Types.back()) << ")\n"
+                                "#undef " LastTypeMacroName "\n"
+                                "#endif\n";
+}
+
+void TypeNodeEmitter::emitLeafNodeInvocations() {
+       Out << "#ifdef " LeafTypeMacroName "\n";
+
+       for (auto type : Types) {
+               if (!type->isSubClassOf(LeafTypeClassName)) continue;
+               Out << LeafTypeMacroName "(" << getIdForType(type) << ")\n";
+       }
+
+       Out << "#undef " LeafTypeMacroName "\n"
+                                "#endif\n";
+}
+
+void TypeNodeEmitter::addMacroToUndef(StringRef macroName) {
+       MacrosToUndef.push_back(macroName);
+}
+
+void TypeNodeEmitter::emitUndefs() {
+       for (auto &macroName : MacrosToUndef) {
+               Out << "#undef " << macroName << "\n";
+       }
+}
+
+void clang::EmitClangTypeNodes(RecordKeeper &records, raw_ostream &out) {
+       TypeNodeEmitter(records, out).emit();
+}
index a923700..d0f8a75 100644 (file)
@@ -47,6 +47,7 @@ enum ActionType {
   GenClangCommentNodes,
   GenClangDeclNodes,
   GenClangStmtNodes,
+  GenClangTypeNodes,
   GenClangOpcodes,
   GenClangSACheckers,
   GenClangCommentHTMLTags,
@@ -130,6 +131,8 @@ cl::opt<ActionType> Action(
                    "Generate Clang AST declaration nodes"),
         clEnumValN(GenClangStmtNodes, "gen-clang-stmt-nodes",
                    "Generate Clang AST statement nodes"),
+        clEnumValN(GenClangTypeNodes, "gen-clang-type-nodes",
+                   "Generate Clang AST type nodes"),
         clEnumValN(GenClangOpcodes, "gen-clang-opcodes",
                    "Generate Clang constexpr interpreter opcodes"),
         clEnumValN(GenClangSACheckers, "gen-clang-sa-checkers",
@@ -254,6 +257,9 @@ bool ClangTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
   case GenClangStmtNodes:
     EmitClangASTNodes(Records, OS, "Stmt", "");
     break;
+  case GenClangTypeNodes:
+    EmitClangTypeNodes(Records, OS);
+    break;
   case GenClangOpcodes:
     EmitClangOpcodes(Records, OS);
     break;
index f9ee477..cdd492b 100644 (file)
@@ -27,6 +27,7 @@ namespace clang {
 void EmitClangDeclContext(llvm::RecordKeeper &RK, llvm::raw_ostream &OS);
 void EmitClangASTNodes(llvm::RecordKeeper &RK, llvm::raw_ostream &OS,
                        const std::string &N, const std::string &S);
+void EmitClangTypeNodes(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
 
 void EmitClangAttrParserStringSwitches(llvm::RecordKeeper &Records,
                                        llvm::raw_ostream &OS);