From a82d2fe94427f3122ecf94549b5f7f4c57b7b913 Mon Sep 17 00:00:00 2001 From: John McCall Date: Tue, 1 Oct 2019 23:13:03 +0000 Subject: [PATCH] Emit TypeNodes.def with tblgen. 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 | 4 + clang/include/clang/AST/Type.h | 5 +- clang/include/clang/AST/TypeNodes.def | 135 --------------- clang/include/clang/Basic/TypeNodes.td | 106 ++++++++++++ clang/utils/TableGen/CMakeLists.txt | 1 + clang/utils/TableGen/ClangTypeNodesEmitter.cpp | 220 +++++++++++++++++++++++++ clang/utils/TableGen/TableGen.cpp | 6 + clang/utils/TableGen/TableGenBackends.h | 1 + 8 files changed, 340 insertions(+), 138 deletions(-) delete mode 100644 clang/include/clang/AST/TypeNodes.def create mode 100644 clang/include/clang/Basic/TypeNodes.td create mode 100644 clang/utils/TableGen/ClangTypeNodesEmitter.cpp diff --git a/clang/include/clang/AST/CMakeLists.txt b/clang/include/clang/AST/CMakeLists.txt index da16987..6035f91 100644 --- a/clang/include/clang/AST/CMakeLists.txt +++ b/clang/include/clang/AST/CMakeLists.txt @@ -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) diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 3968e1a..5c86509 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -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 index 58a5f88..0000000 --- a/clang/include/clang/AST/TypeNodes.def +++ /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 index 0000000..b2554de --- /dev/null +++ b/clang/include/clang/Basic/TypeNodes.td @@ -0,0 +1,106 @@ +class Type { + bit Abstract = abstract; +} + +class DerivedType : Type { + 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`). 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` (a TemplateSpecializationType) is +/// considered to be a non-canonical representation for the RecordType +/// referencing the concrete ClassTemplateSpecializationDecl; but +/// `std::vector` 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; +def RValueReferenceType : DerivedType; +def MemberPointerType : Type; +def ArrayType : Type<1>; +def ConstantArrayType : DerivedType; +def IncompleteArrayType : DerivedType; +def VariableArrayType : DerivedType; +def DependentSizedArrayType : DerivedType, AlwaysDependent; +def DependentSizedExtVectorType : Type, AlwaysDependent; +def DependentAddressSpaceType : Type, AlwaysDependent; +def VectorType : Type; +def DependentVectorType : Type, AlwaysDependent; +def ExtVectorType : DerivedType; +def FunctionType : Type<1>; +def FunctionProtoType : DerivedType; +def FunctionNoProtoType : DerivedType; +def UnresolvedUsingType : Type, AlwaysDependent; +def ParenType : Type, NeverCanonical; +def TypedefType : Type, NeverCanonical; +def MacroQualifiedType : Type, NeverCanonical; +def AdjustedType : Type, NeverCanonical; +def DecayedType : DerivedType, NeverCanonical; +def TypeOfExprType : Type, NeverCanonicalUnlessDependent; +def TypeOfType : Type, NeverCanonicalUnlessDependent; +def DecltypeType : Type, NeverCanonicalUnlessDependent; +def UnaryTransformType : Type, NeverCanonicalUnlessDependent; +def TagType : Type<1>; +def RecordType : DerivedType, LeafType; +def EnumType : DerivedType, 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; +def DeducedTemplateSpecializationType : DerivedType; +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, LeafType; +def ObjCObjectPointerType : Type; +def PipeType : Type; +def AtomicType : Type; diff --git a/clang/utils/TableGen/CMakeLists.txt b/clang/utils/TableGen/CMakeLists.txt index d33ede2..96b97a7 100644 --- a/clang/utils/TableGen/CMakeLists.txt +++ b/clang/utils/TableGen/CMakeLists.txt @@ -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 index 0000000..c9986c8 --- /dev/null +++ b/clang/utils/TableGen/ClangTypeNodesEmitter.cpp @@ -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 +#include +#include +#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 Types; + std::vector 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 ¯oName : MacrosToUndef) { + Out << "#undef " << macroName << "\n"; + } +} + +void clang::EmitClangTypeNodes(RecordKeeper &records, raw_ostream &out) { + TypeNodeEmitter(records, out).emit(); +} diff --git a/clang/utils/TableGen/TableGen.cpp b/clang/utils/TableGen/TableGen.cpp index a923700..d0f8a75 100644 --- a/clang/utils/TableGen/TableGen.cpp +++ b/clang/utils/TableGen/TableGen.cpp @@ -47,6 +47,7 @@ enum ActionType { GenClangCommentNodes, GenClangDeclNodes, GenClangStmtNodes, + GenClangTypeNodes, GenClangOpcodes, GenClangSACheckers, GenClangCommentHTMLTags, @@ -130,6 +131,8 @@ cl::opt 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; diff --git a/clang/utils/TableGen/TableGenBackends.h b/clang/utils/TableGen/TableGenBackends.h index f9ee477..cdd492b 100644 --- a/clang/utils/TableGen/TableGenBackends.h +++ b/clang/utils/TableGen/TableGenBackends.h @@ -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); -- 2.7.4