From: Douglas Gregor Date: Mon, 15 Jun 2009 19:02:54 +0000 (+0000) Subject: More XML output support, from Olaf Krzikalla! X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=038f75abf5abd1e35736dd5c751ba20df1158aaa;p=clang More XML output support, from Olaf Krzikalla! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@73402 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/TypeVisitor.h b/include/clang/AST/TypeVisitor.h new file mode 100644 index 0000000000..a02e39b3f3 --- /dev/null +++ b/include/clang/AST/TypeVisitor.h @@ -0,0 +1,50 @@ +//===--- TypeVisitor.h - Visitor for Stmt subclasses ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the TypeVisitor interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_TYPEVISITOR_H +#define LLVM_CLANG_AST_TYPEVISITOR_H + +#include "clang/AST/Type.h" + +namespace clang { + +#define DISPATCH(CLASS) \ + return static_cast(this)->Visit ## CLASS(static_cast(T)) + +template +class TypeVisitor { +public: + RetTy Visit(Type *T) { + // Top switch stmt: dispatch to VisitFooStmt for each FooStmt. + switch (T->getTypeClass()) { + default: assert(0 && "Unknown type class!"); +#define ABSTRACT_TYPE(CLASS, PARENT) +#define TYPE(CLASS, PARENT) case Type::CLASS: DISPATCH(CLASS##Type); +#include "clang/AST/TypeNodes.def" + } + } + + // If the implementation chooses not to implement a certain visit method, fall + // back on superclass. +#define TYPE(CLASS, PARENT) RetTy Visit##CLASS##Type(CLASS##Type *T) { DISPATCH(PARENT); } +#include "clang/AST/TypeNodes.def" + + // Base case, ignore it. :) + RetTy VisitType(Type*) { return RetTy(); } +}; + +#undef DISPATCH + +} // end namespace clang + +#endif diff --git a/include/clang/Frontend/DeclContextXML.def b/include/clang/Frontend/DeclContextXML.def new file mode 100644 index 0000000000..39ed5f9432 --- /dev/null +++ b/include/clang/Frontend/DeclContextXML.def @@ -0,0 +1,113 @@ +//===-- DeclContextXML.def - Metadata about Context XML nodes ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the XML context info database as written in the +// / sub-nodes of the XML document. Type nodes +// are referred by "context" reference attributes throughout the document. +// A context node never contains sub-nodes. +// The semantics of the attributes and enums are mostly self-documenting +// by looking at the appropriate internally used functions and values. +// The following macros are used: +// +// NODE_XML( CLASS, NAME ) - A node of name NAME denotes a concrete +// context of class CLASS where CLASS is a class name used internally by clang. +// After a NODE_XML the definition of all (optional) attributes of that context +// node and possible sub-nodes follows. +// +// END_NODE_XML - Closes the attribute definition of the current node. +// +// ID_ATTRIBUTE_XML - Context nodes have an "id" attribute containing a +// string, which value uniquely identify that statement. Other nodes may refer +// by "context" attributes to this value. +// +// TYPE_ATTRIBUTE_XML( FN ) - Context nodes may refer to the ids of type +// nodes by a "type" attribute, if they create a type during declaration. +// For instance 'struct S;' creates both a context 'S::' and a type 'S'. +// Contexts and types always have different ids, however declarations and +// contexts may share the same ids. FN is internally used by clang. +// +// ATTRIBUTE_XML( FN, NAME ) - An attribute named NAME. FN is internally +// used by clang. A boolean attribute have the values "0" or "1". +// +// ATTRIBUTE_ENUM[_OPT]_XML( FN, NAME ) - An attribute named NAME. The value +// is an enumeration defined with ENUM_XML macros immediately following after +// that macro. An optional attribute is ommited, if the particular enum is the +// empty string. FN is internally used by clang. +// +// ENUM_XML( VALUE, NAME ) - An enumeration element named NAME. VALUE is +// internally used by clang. +// +// END_ENUM_XML - Closes the enumeration definition of the current attribute. +// +//===----------------------------------------------------------------------===// + +#ifndef TYPE_ATTRIBUTE_XML +# define TYPE_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "type") +#endif + +#ifndef CONTEXT_ATTRIBUTE_XML +# define CONTEXT_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "context") +#endif + +NODE_XML(TranslationUnitDecl, "TranslationUnit") + ID_ATTRIBUTE_XML +END_NODE_XML + +NODE_XML(FunctionDecl, "Function") + ID_ATTRIBUTE_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_XML(getNameAsString(), "name") + TYPE_ATTRIBUTE_XML(getType()->getAsFunctionType()) +END_NODE_XML + +NODE_XML(NamespaceDecl, "Namespace") + ID_ATTRIBUTE_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_XML(getNameAsString(), "name") +END_NODE_XML + +NODE_XML(RecordDecl, "Record") + ID_ATTRIBUTE_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_XML(getNameAsString(), "name") + TYPE_ATTRIBUTE_XML(getTypeForDecl()) +END_NODE_XML + +NODE_XML(EnumDecl, "Enum") + ID_ATTRIBUTE_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_XML(getNameAsString(), "name") + TYPE_ATTRIBUTE_XML(getTypeForDecl()) +END_NODE_XML + +NODE_XML(LinkageSpecDecl, "LinkageSpec") + ID_ATTRIBUTE_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_ENUM_OPT_XML(getLanguage(), "lang") + ENUM_XML(LinkageSpecDecl::lang_c, "C") + ENUM_XML(LinkageSpecDecl::lang_cxx, "CXX") + END_ENUM_XML +END_NODE_XML + +//===----------------------------------------------------------------------===// +#undef NODE_XML +#undef ID_ATTRIBUTE_XML +#undef TYPE_ATTRIBUTE_XML +#undef ATTRIBUTE_XML +#undef ATTRIBUTE_SPECIAL_XML +#undef ATTRIBUTE_OPT_XML +#undef ATTRIBUTE_ENUM_XML +#undef ATTRIBUTE_ENUM_OPT_XML +#undef ATTRIBUTE_FILE_LOCATION_XML +#undef ENUM_XML +#undef END_ENUM_XML +#undef END_NODE_XML +#undef SUB_NODE_XML +#undef SUB_NODE_SEQUENCE_XML +#undef SUB_NODE_OPT_XML diff --git a/include/clang/Frontend/DeclXML.def b/include/clang/Frontend/DeclXML.def new file mode 100644 index 0000000000..956d9719f9 --- /dev/null +++ b/include/clang/Frontend/DeclXML.def @@ -0,0 +1,250 @@ +//===-- DeclXML.def - Metadata about Decl XML nodes ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the XML statement database structure as written in +// sub-nodes of the XML document. +// The semantics of the attributes and enums are mostly self-documenting +// by looking at the appropriate internally used functions and values. +// The following macros are used: +// +// NODE_XML( CLASS, NAME ) - A node of name NAME denotes a concrete +// statement of class CLASS where CLASS is a class name used internally by clang. +// After a NODE_XML the definition of all (optional) attributes of that statement +// node and possible sub-nodes follows. +// +// END_NODE_XML - Closes the attribute definition of the current node. +// +// ID_ATTRIBUTE_XML - Some statement nodes have an "id" attribute containing a +// string, which value uniquely identify that statement. Other nodes may refer +// by reference attributes to this value (currently used only for Label). +// +// TYPE_ATTRIBUTE_XML( FN ) - Type nodes refer to the result type id of an +// expression by a "type" attribute. FN is internally used by clang. +// +// ATTRIBUTE_XML( FN, NAME ) - An attribute named NAME. FN is internally +// used by clang. A boolean attribute have the values "0" or "1". +// +// ATTRIBUTE_SPECIAL_XML( FN, NAME ) - An attribute named NAME which deserves +// a special handling. See the appropriate documentations. +// +// ATTRIBUTE_FILE_LOCATION_XML - A bunch of attributes denoting the location of +// a statement in the source file(s). +// +// ATTRIBUTE_OPT_XML( FN, NAME ) - An optional attribute named NAME. +// Optional attributes are omitted for boolean types, if the value is false, +// for integral types, if the value is null and for strings, +// if the value is the empty string. FN is internally used by clang. +// +// ATTRIBUTE_ENUM[_OPT]_XML( FN, NAME ) - An attribute named NAME. The value +// is an enumeration defined with ENUM_XML macros immediately following after +// that macro. An optional attribute is ommited, if the particular enum is the +// empty string. FN is internally used by clang. +// +// ENUM_XML( VALUE, NAME ) - An enumeration element named NAME. VALUE is +// internally used by clang. +// +// END_ENUM_XML - Closes the enumeration definition of the current attribute. +// +// SUB_NODE_XML( CLASS ) - A mandatory sub-node of class CLASS or its sub-classes. +// +// SUB_NODE_OPT_XML( CLASS ) - An optional sub-node of class CLASS or its sub-classes. +// +// SUB_NODE_SEQUENCE_XML( CLASS ) - Zero or more sub-nodes of class CLASS or +// its sub-classes. +// +//===----------------------------------------------------------------------===// + +#ifndef ATTRIBUTE_FILE_LOCATION_XML +# define ATTRIBUTE_FILE_LOCATION_XML \ + ATTRIBUTE_XML(getFilename(), "file") \ + ATTRIBUTE_XML(getLine(), "line") \ + ATTRIBUTE_XML(getColumn(), "col") \ + ATTRIBUTE_OPT_XML(getFilename(), "endfile") \ + ATTRIBUTE_OPT_XML(getLine(), "endline") \ + ATTRIBUTE_OPT_XML(getColumn(), "endcol") +#endif + +#ifndef TYPE_ATTRIBUTE_XML +# define TYPE_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "type") +#endif + +#ifndef CONTEXT_ATTRIBUTE_XML +# define CONTEXT_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "context") +#endif + +//NODE_XML(TranslationUnitDecl, "TranslationUnit") +// SUB_NODE_SEQUENCE_XML(Decl) +//END_NODE_XML + +NODE_XML(Decl, "FIXME_Decl") + ATTRIBUTE_FILE_LOCATION_XML +END_NODE_XML + +NODE_XML(FunctionDecl, "Function") + ID_ATTRIBUTE_XML + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_XML(getNameAsString(), "name") + TYPE_ATTRIBUTE_XML(getType()->getAsFunctionType()->getResultType()) + ATTRIBUTE_XML(getType()->getAsFunctionType(), "function_type") + ATTRIBUTE_ENUM_OPT_XML(getStorageClass(), "storage_class") + ENUM_XML(FunctionDecl::None, "") + ENUM_XML(FunctionDecl::Extern, "extern") + ENUM_XML(FunctionDecl::Static, "static") + ENUM_XML(FunctionDecl::PrivateExtern, "__private_extern__") + END_ENUM_XML + ATTRIBUTE_OPT_XML(isInline(), "inline") + //ATTRIBUTE_OPT_XML(isVariadic(), "variadic") // in the type reference + ATTRIBUTE_XML(getNumParams(), "num_args") + SUB_NODE_SEQUENCE_XML(ParmVarDecl) + //SUB_NODE_OPT_XML("Body") +END_NODE_XML + +NODE_XML(CXXMethodDecl, "CXXMethodDecl") + ID_ATTRIBUTE_XML + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_XML(getNameAsString(), "name") + TYPE_ATTRIBUTE_XML(getType()->getAsFunctionType()->getResultType()) + ATTRIBUTE_XML(getType()->getAsFunctionType(), "function_type") + ATTRIBUTE_OPT_XML(isInline(), "inline") + ATTRIBUTE_OPT_XML(isStatic(), "static") + ATTRIBUTE_OPT_XML(isVirtual(), "virtual") + ATTRIBUTE_XML(getNumParams(), "num_args") + SUB_NODE_SEQUENCE_XML(ParmVarDecl) + //SUB_NODE_OPT_XML("Body") +END_NODE_XML + +//NODE_XML("Body") +// SUB_NODE_XML(Stmt) +//END_NODE_XML + +NODE_XML(NamespaceDecl, "Namespace") + ID_ATTRIBUTE_XML + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_XML(getNameAsString(), "name") +END_NODE_XML + +NODE_XML(UsingDirectiveDecl, "UsingDirective") + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_XML(getNameAsString(), "name") + ATTRIBUTE_XML(getNominatedNamespace(), "ref") +END_NODE_XML + +NODE_XML(NamespaceAliasDecl, "NamespaceAlias") + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_XML(getNameAsString(), "name") + ATTRIBUTE_XML(getNamespace(), "ref") +END_NODE_XML + +NODE_XML(RecordDecl, "Record") + ID_ATTRIBUTE_XML + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_XML(getNameAsString(), "name") + ATTRIBUTE_OPT_XML(isDefinition() == false, "forward") + ATTRIBUTE_XML(getTypeForDecl(), "type") // refers to the type this decl creates + SUB_NODE_SEQUENCE_XML(FieldDecl) +END_NODE_XML + +NODE_XML(EnumDecl, "Enum") + ID_ATTRIBUTE_XML + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_XML(getNameAsString(), "name") + ATTRIBUTE_OPT_XML(isDefinition() == false, "forward") + ATTRIBUTE_SPECIAL_XML(getIntegerType(), "type") // is NULL in pure declarations thus deserves special handling + SUB_NODE_SEQUENCE_XML(EnumConstantDecl) // only present in definition +END_NODE_XML + +NODE_XML(EnumConstantDecl, "EnumConstant") + ID_ATTRIBUTE_XML + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_XML(getNameAsString(), "name") + TYPE_ATTRIBUTE_XML(getType()) + ATTRIBUTE_XML(getInitVal().toString(10, true), "value") // integer + SUB_NODE_OPT_XML(Expr) // init expr of this constant +END_NODE_XML + +NODE_XML(FieldDecl, "Field") + ID_ATTRIBUTE_XML + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_XML(getNameAsString(), "name") + TYPE_ATTRIBUTE_XML(getType()) + ATTRIBUTE_OPT_XML(isMutable(), "mutable") + ATTRIBUTE_OPT_XML(isBitField(), "bitfield") + SUB_NODE_OPT_XML(Expr) // init expr of a bit field +END_NODE_XML + +NODE_XML(TypedefDecl, "Typedef") + ID_ATTRIBUTE_XML + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_XML(getNameAsString(), "name") + TYPE_ATTRIBUTE_XML(getUnderlyingType()) +END_NODE_XML + +NODE_XML(VarDecl, "Var") + ID_ATTRIBUTE_XML + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_XML(getNameAsString(), "name") + TYPE_ATTRIBUTE_XML(getType()) + ATTRIBUTE_ENUM_OPT_XML(getStorageClass(), "storage_class") + ENUM_XML(VarDecl::None, "") + ENUM_XML(VarDecl::Auto, "auto") + ENUM_XML(VarDecl::Register, "register") + ENUM_XML(VarDecl::Extern, "extern") + ENUM_XML(VarDecl::Static, "static") + ENUM_XML(VarDecl::PrivateExtern, "__private_extern__") + END_ENUM_XML + SUB_NODE_OPT_XML(Expr) // init expr +END_NODE_XML + +NODE_XML(ParmVarDecl, "ParmVar") + ID_ATTRIBUTE_XML + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_XML(getNameAsString(), "name") + TYPE_ATTRIBUTE_XML(getType()) + SUB_NODE_OPT_XML(Expr) // default argument expression +END_NODE_XML + +NODE_XML(LinkageSpecDecl, "LinkageSpec") + ID_ATTRIBUTE_XML + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_ENUM_OPT_XML(getLanguage(), "lang") + ENUM_XML(LinkageSpecDecl::lang_c, "C") + ENUM_XML(LinkageSpecDecl::lang_cxx, "CXX") + END_ENUM_XML +END_NODE_XML + + +//===----------------------------------------------------------------------===// +#undef NODE_XML +#undef ID_ATTRIBUTE_XML +#undef TYPE_ATTRIBUTE_XML +#undef ATTRIBUTE_XML +#undef ATTRIBUTE_SPECIAL_XML +#undef ATTRIBUTE_OPT_XML +#undef ATTRIBUTE_ENUM_XML +#undef ATTRIBUTE_ENUM_OPT_XML +#undef ATTRIBUTE_FILE_LOCATION_XML +#undef ENUM_XML +#undef END_ENUM_XML +#undef END_NODE_XML +#undef SUB_NODE_XML +#undef SUB_NODE_SEQUENCE_XML +#undef SUB_NODE_OPT_XML diff --git a/include/clang/Frontend/DocumentXML.def b/include/clang/Frontend/DocumentXML.def new file mode 100644 index 0000000000..4c52bd8442 --- /dev/null +++ b/include/clang/Frontend/DocumentXML.def @@ -0,0 +1,75 @@ +//===-- DocumentXML.def - Metadata about Document XML nodes -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the XML root database structure as written in +// an AST XML document. +// The following macros are used: +// +// NODE_XML( CLASS, NAME ) - A node of name NAME denotes a concrete +// statement of class CLASS where CLASS is a class name used internally by clang. +// After a NODE_XML the definition of all (optional) attributes of that statement +// node and possible sub-nodes follows. +// +// END_NODE_XML - Closes the attribute definition of the current node. +// +// ID_ATTRIBUTE_XML - Some nodes have an "id" attribute containing a +// string, which value uniquely identify the entity represented by that node. +// Other nodes may refer by reference attributes to this value. +// +// ATTRIBUTE_SPECIAL_XML( FN, NAME ) - An attribute named NAME which deserves +// a special handling. See the appropriate documentations. +// +// SUB_NODE_XML( CLASS ) - A mandatory sub-node of class CLASS or its sub-classes. +// +// SUB_NODE_SEQUENCE_XML( CLASS ) - Zero or more sub-nodes of class CLASS or +// its sub-classes. +// +//===----------------------------------------------------------------------===// + +ROOT_NODE_XML("CLANG_XML") + ATTRIBUTE_SPECIAL_XML(ignore, "version") // special retrieving needed + SUB_NODE_XML("TranslationUnit") + SUB_NODE_XML("ReferenceSection") +END_NODE_XML + +NODE_XML("TranslationUnit") + SUB_NODE_SEQUENCE_XML(Decl) +END_NODE_XML + +NODE_XML("ReferenceSection") + SUB_NODE_XML("Types") + SUB_NODE_XML("Contexts") + SUB_NODE_XML("Files") +END_NODE_XML + +NODE_XML("Types") + SUB_NODE_SEQUENCE_XML(Type) +END_NODE_XML + +NODE_XML("Contexts") + SUB_NODE_SEQUENCE_XML(DeclContext) +END_NODE_XML + +NODE_XML("Files") + SUB_NODE_SEQUENCE_XML("File") +END_NODE_XML + +NODE_XML("File") + ID_ATTRIBUTE_XML + ATTRIBUTE_SPECIAL_XML(ignore, "name") // special retrieving needed, denotes the source file name +END_NODE_XML + + +//===----------------------------------------------------------------------===// +#undef NODE_XML +#undef ID_ATTRIBUTE_XML +#undef ATTRIBUTE_SPECIAL_XML +#undef END_NODE_XML +#undef SUB_NODE_XML +#undef SUB_NODE_SEQUENCE_XML diff --git a/include/clang/Frontend/DocumentXML.h b/include/clang/Frontend/DocumentXML.h index 99db717190..4ed11e153c 100644 --- a/include/clang/Frontend/DocumentXML.h +++ b/include/clang/Frontend/DocumentXML.h @@ -17,6 +17,7 @@ #include #include +#include #include "clang/AST/Type.h" #include "clang/AST/TypeOrdering.h" #include "llvm/Support/raw_ostream.h" @@ -30,6 +31,7 @@ class Decl; class NamedDecl; class FunctionDecl; class ASTContext; +class LabelStmt; //--------------------------------------------------------- namespace XML @@ -50,26 +52,37 @@ class DocumentXML { public: DocumentXML(const std::string& rootName, llvm::raw_ostream& out); - ~DocumentXML(); void initialize(ASTContext &Context); void PrintDecl(Decl *D); void PrintStmt(const Stmt *S); // defined in StmtXML.cpp - void finalize(); DocumentXML& addSubNode(const std::string& name); // also enters the sub node, returns *this DocumentXML& toParent(); // returns *this + void addAttribute(const char* pName, const QualType& pType); + void addAttribute(const char* pName, bool value); + + template + void addAttribute(const char* pName, const T* value) + { + addPtrAttribute(pName, value); + } + + template + void addAttribute(const char* pName, T* value) + { + addPtrAttribute(pName, value); + } + template void addAttribute(const char* pName, const T& value); - void addTypeAttribute(const QualType& pType); - void addRefAttribute(const NamedDecl* D); + template + void addAttributeOptional(const char* pName, const T& value); - enum tContextUsage { CONTEXT_AS_CONTEXT, CONTEXT_AS_ID }; - void addContextAttribute(const DeclContext *DC, tContextUsage usage = CONTEXT_AS_CONTEXT); void addSourceFileAttribute(const std::string& fileName); PresumedLoc addLocation(const SourceLocation& Loc); @@ -81,13 +94,9 @@ private: DocumentXML(const DocumentXML&); // not defined DocumentXML& operator=(const DocumentXML&); // not defined - struct NodeXML; - - NodeXML* Root; - NodeXML* CurrentNode; // always after Root + std::stack NodeStack; llvm::raw_ostream& Out; ASTContext *Ctx; - int CurrentIndent; bool HasCurrentNodeSubNodes; @@ -96,15 +105,38 @@ private: XML::IdMap BasicTypes; XML::IdMap SourceFiles; XML::IdMap Decls; + XML::IdMap Labels; void addContextsRecursively(const DeclContext *DC); - void addBasicTypeRecursively(const Type* pType); + void addTypeRecursively(const Type* pType); void addTypeRecursively(const QualType& pType); - void PrintFunctionDecl(FunctionDecl *FD); - void addDeclIdAttribute(const NamedDecl* D); - void addTypeIdAttribute(const Type* pType); void Indent(); + + // forced pointer dispatch: + void addPtrAttribute(const char* pName, const Type* pType); + void addPtrAttribute(const char* pName, const NamedDecl* D); + void addPtrAttribute(const char* pName, const DeclContext* D); + void addPtrAttribute(const char* pName, const NamespaceDecl* D); // disambiguation + void addPtrAttribute(const char* pName, const LabelStmt* L); + void addPtrAttribute(const char* pName, const char* text); + + // defined in TypeXML.cpp: + void addParentTypes(const Type* pType); + void writeTypeToXML(const Type* pType); + void writeTypeToXML(const QualType& pType); + class TypeAdder; + friend class TypeAdder; + + // defined in DeclXML.cpp: + void writeDeclToXML(Decl *D); + class DeclPrinter; + friend class DeclPrinter; + + // for addAttributeOptional: + static bool isDefault(unsigned value) { return value == 0; } + static bool isDefault(bool value) { return !value; } + static bool isDefault(const std::string& value) { return value.empty(); } }; //--------------------------------------------------------- inlines @@ -121,6 +153,28 @@ inline void DocumentXML::addAttribute(const char* pName, const T& value) Out << ' ' << pName << "=\"" << value << "\""; } +//--------------------------------------------------------- +inline void DocumentXML::addPtrAttribute(const char* pName, const char* text) +{ + Out << ' ' << pName << "=\"" << text << "\""; +} + +//--------------------------------------------------------- +inline void DocumentXML::addAttribute(const char* pName, bool value) +{ + addPtrAttribute(pName, value ? "1" : "0"); +} + +//--------------------------------------------------------- +template +inline void DocumentXML::addAttributeOptional(const char* pName, const T& value) +{ + if (!isDefault(value)) + { + addAttribute(pName, value); + } +} + //--------------------------------------------------------- } //namespace clang diff --git a/include/clang/Frontend/StmtXML.def b/include/clang/Frontend/StmtXML.def new file mode 100644 index 0000000000..26430f740d --- /dev/null +++ b/include/clang/Frontend/StmtXML.def @@ -0,0 +1,517 @@ +//===-- StmtXML.def - Metadata about Stmt XML nodes ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the XML statement database structure as written in +// sub-nodes of the XML document. +// The semantics of the attributes and enums are mostly self-documenting +// by looking at the appropriate internally used functions and values. +// The following macros are used: +// +// NODE_XML( CLASS, NAME ) - A node of name NAME denotes a concrete +// statement of class CLASS where CLASS is a class name used internally by clang. +// After a NODE_XML the definition of all (optional) attributes of that statement +// node and possible sub-nodes follows. +// +// END_NODE_XML - Closes the attribute definition of the current node. +// +// ID_ATTRIBUTE_XML - Some statement nodes have an "id" attribute containing a +// string, which value uniquely identify that statement. Other nodes may refer +// by reference attributes to this value (currently used only for Label). +// +// TYPE_ATTRIBUTE_XML( FN ) - Type nodes refer to the result type id of an +// expression by a "type" attribute. FN is internally used by clang. +// +// ATTRIBUTE_XML( FN, NAME ) - An attribute named NAME. FN is internally +// used by clang. A boolean attribute have the values "0" or "1". +// +// ATTRIBUTE_SPECIAL_XML( FN, NAME ) - An attribute named NAME which deserves +// a special handling. See the appropriate documentations. +// +// ATTRIBUTE_FILE_LOCATION_XML - A bunch of attributes denoting the location of +// a statement in the source file(s). +// +// ATTRIBUTE_OPT_XML( FN, NAME ) - An optional attribute named NAME. +// Optional attributes are omitted for boolean types, if the value is false, +// for integral types, if the value is null and for strings, +// if the value is the empty string. FN is internally used by clang. +// +// ATTRIBUTE_ENUM[_OPT]_XML( FN, NAME ) - An attribute named NAME. The value +// is an enumeration defined with ENUM_XML macros immediately following after +// that macro. An optional attribute is ommited, if the particular enum is the +// empty string. FN is internally used by clang. +// +// ENUM_XML( VALUE, NAME ) - An enumeration element named NAME. VALUE is +// internally used by clang. +// +// END_ENUM_XML - Closes the enumeration definition of the current attribute. +// +// SUB_NODE_XML( CLASS ) - A mandatory sub-node of class CLASS or its sub-classes. +// +// SUB_NODE_OPT_XML( CLASS ) - An optional sub-node of class CLASS or its sub-classes. +// +// SUB_NODE_SEQUENCE_XML( CLASS ) - Zero or more sub-nodes of class CLASS or +// its sub-classes. +// +//===----------------------------------------------------------------------===// + +#ifndef ATTRIBUTE_FILE_LOCATION_XML +# define ATTRIBUTE_FILE_LOCATION_XML \ + ATTRIBUTE_XML(getFilename(), "file") \ + ATTRIBUTE_XML(getLine(), "line") \ + ATTRIBUTE_XML(getColumn(), "col") \ + ATTRIBUTE_OPT_XML(getFilename(), "endfile") \ + ATTRIBUTE_OPT_XML(getLine(), "endline") \ + ATTRIBUTE_OPT_XML(getColumn(), "endcol") +#endif + +#ifndef TYPE_ATTRIBUTE_XML +# define TYPE_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "type") +#endif + +#ifndef CONTEXT_ATTRIBUTE_XML +# define CONTEXT_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "context") +#endif + + +NODE_XML(NullStmt, "NullStmt") + ATTRIBUTE_FILE_LOCATION_XML +END_NODE_XML + +NODE_XML(CompoundStmt, "CompoundStmt") + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(size(), "num_stmts") + SUB_NODE_SEQUENCE_XML(Stmt) +END_NODE_XML + +NODE_XML(CaseStmt, "CaseStmt") // case expr: body; + ATTRIBUTE_FILE_LOCATION_XML + SUB_NODE_XML(Stmt) // body + SUB_NODE_XML(Expr) // expr + SUB_NODE_XML(Expr) // rhs expr in gc extension: case expr .. expr: body; +END_NODE_XML + +NODE_XML(DefaultStmt, "DefaultStmt") // default: body; + ATTRIBUTE_FILE_LOCATION_XML + SUB_NODE_XML(Stmt) // body +END_NODE_XML + +NODE_XML(LabelStmt, "LabelStmt") // Label: body; + ID_ATTRIBUTE_XML + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(getName(), "name") // string + SUB_NODE_XML(Stmt) // body +END_NODE_XML + +NODE_XML(IfStmt, "IfStmt") // if (cond) stmt1; else stmt2; + ATTRIBUTE_FILE_LOCATION_XML + SUB_NODE_XML(Expr) // cond + SUB_NODE_XML(Stmt) // stmt1 + SUB_NODE_XML(Stmt) // stmt2 +END_NODE_XML + +NODE_XML(SwitchStmt, "SwitchStmt") // switch (cond) body; + ATTRIBUTE_FILE_LOCATION_XML + SUB_NODE_XML(Expr) // cond + SUB_NODE_XML(Stmt) // body +END_NODE_XML + +NODE_XML(WhileStmt, "WhileStmt") // while (cond) body; + ATTRIBUTE_FILE_LOCATION_XML + SUB_NODE_XML(Expr) // cond + SUB_NODE_XML(Stmt) // body +END_NODE_XML + +NODE_XML(DoStmt, "DoStmt") // do body while (cond); + ATTRIBUTE_FILE_LOCATION_XML + SUB_NODE_XML(Expr) // cond + SUB_NODE_XML(Stmt) // body +END_NODE_XML + +NODE_XML(ForStmt, "ForStmt") // for (init; cond; inc) body; + ATTRIBUTE_FILE_LOCATION_XML + SUB_NODE_XML(Stmt) // init + SUB_NODE_XML(Expr) // cond + SUB_NODE_XML(Expr) // inc + SUB_NODE_XML(Stmt) // body +END_NODE_XML + +NODE_XML(GotoStmt, "GotoStmt") // goto label; + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(getLabel()->getName(), "name") // informal string + ATTRIBUTE_XML(getLabel(), "ref") // id string +END_NODE_XML + +NODE_XML(IndirectGotoStmt, "IndirectGotoStmt") // goto expr; + ATTRIBUTE_FILE_LOCATION_XML + SUB_NODE_XML(Expr) // expr +END_NODE_XML + +NODE_XML(ContinueStmt, "ContinueStmt") // continue + ATTRIBUTE_FILE_LOCATION_XML +END_NODE_XML + +NODE_XML(BreakStmt, "BreakStmt") // break + ATTRIBUTE_FILE_LOCATION_XML +END_NODE_XML + +NODE_XML(ReturnStmt, "ReturnStmt") // return expr; + ATTRIBUTE_FILE_LOCATION_XML + SUB_NODE_XML(Expr) // expr +END_NODE_XML + +NODE_XML(AsmStmt, "AsmStmt") // GNU inline-assembly statement extension + ATTRIBUTE_FILE_LOCATION_XML + // FIXME +END_NODE_XML + +NODE_XML(DeclStmt, "DeclStmt") // a declaration statement + ATTRIBUTE_FILE_LOCATION_XML + SUB_NODE_SEQUENCE_XML(Decl) +END_NODE_XML + +// C++ statements +NODE_XML(CXXTryStmt, "CXXTryStmt") // try CompoundStmt CXXCatchStmt1 CXXCatchStmt2 .. + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(getNumHandlers(), "num_handlers") + SUB_NODE_XML(CompoundStmt) + SUB_NODE_SEQUENCE_XML(CXXCatchStmt) +END_NODE_XML + +NODE_XML(CXXCatchStmt, "CXXCatchStmt") // catch (decl) Stmt + ATTRIBUTE_FILE_LOCATION_XML + SUB_NODE_XML(VarDecl) + SUB_NODE_XML(Stmt) +END_NODE_XML + +// Expressions +NODE_XML(PredefinedExpr, "PredefinedExpr") + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + ATTRIBUTE_ENUM_XML(getIdentType(), "kind") + ENUM_XML(PredefinedExpr::Func, "__func__") + ENUM_XML(PredefinedExpr::Function, "__FUNCTION__") + ENUM_XML(PredefinedExpr::PrettyFunction, "__PRETTY_FUNCTION__") + END_ENUM_XML +END_NODE_XML + +NODE_XML(DeclRefExpr, "DeclRefExpr") // an expression referring to a declared entity + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + ATTRIBUTE_XML(getDecl(), "ref") // id string of the declaration + ATTRIBUTE_XML(getDecl()->getNameAsString(), "name") // informal + //ATTRIBUTE_ENUM_XML(getDecl()->getKind(), "kind") // really needed here? +END_NODE_XML + +NODE_XML(IntegerLiteral, "IntegerLiteral") + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + ATTRIBUTE_XML(getValue(), "value") // (signed) integer +END_NODE_XML + +NODE_XML(CharacterLiteral, "CharacterLiteral") + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + ATTRIBUTE_XML(getValue(), "value") // unsigned +END_NODE_XML + +NODE_XML(FloatingLiteral, "FloatingLiteral") + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + // FIXME: output float as written in source (no approximation or the like) + //ATTRIBUTE_XML(getValueAsApproximateDouble(), "value") // float +END_NODE_XML + +NODE_XML(StringLiteral, "StringLiteral") + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + ATTRIBUTE_SPECIAL_XML(getStrData(), "value") // string, special handling for escaping needed + ATTRIBUTE_OPT_XML(isWide(), "is_wide") // boolean +END_NODE_XML + +NODE_XML(UnaryOperator, "UnaryOperator") // op(expr) or (expr)op + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + ATTRIBUTE_ENUM_XML(getOpcode(), "kind") + ENUM_XML(UnaryOperator::PostInc, "postinc") + ENUM_XML(UnaryOperator::PostDec, "postdec") + ENUM_XML(UnaryOperator::PreInc, "preinc") + ENUM_XML(UnaryOperator::PreDec, "predec") + ENUM_XML(UnaryOperator::AddrOf, "addrof") + ENUM_XML(UnaryOperator::Deref, "deref") + ENUM_XML(UnaryOperator::Plus, "plus") + ENUM_XML(UnaryOperator::Minus, "minus") + ENUM_XML(UnaryOperator::Not, "not") // bitwise not + ENUM_XML(UnaryOperator::LNot, "lnot") // boolean not + ENUM_XML(UnaryOperator::Real, "__real") + ENUM_XML(UnaryOperator::Imag, "__imag") + ENUM_XML(UnaryOperator::Extension, "__extension__") + ENUM_XML(UnaryOperator::OffsetOf, "__builtin_offsetof") + END_ENUM_XML + SUB_NODE_XML(Expr) // expr +END_NODE_XML + +NODE_XML(BinaryOperator, "BinaryOperator") // (expr1) op (expr2) + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + ATTRIBUTE_ENUM_XML(getOpcode(), "kind") + ENUM_XML(BinaryOperator::PtrMemD , "ptrmemd") + ENUM_XML(BinaryOperator::PtrMemI , "ptrmemi") + ENUM_XML(BinaryOperator::Mul , "mul") + ENUM_XML(BinaryOperator::Div , "div") + ENUM_XML(BinaryOperator::Rem , "rem") + ENUM_XML(BinaryOperator::Add , "add") + ENUM_XML(BinaryOperator::Sub , "sub") + ENUM_XML(BinaryOperator::Shl , "shl") + ENUM_XML(BinaryOperator::Shr , "shr") + ENUM_XML(BinaryOperator::LT , "lt") + ENUM_XML(BinaryOperator::GT , "gt") + ENUM_XML(BinaryOperator::LE , "le") + ENUM_XML(BinaryOperator::GE , "ge") + ENUM_XML(BinaryOperator::EQ , "eq") + ENUM_XML(BinaryOperator::NE , "ne") + ENUM_XML(BinaryOperator::And , "and") // bitwise and + ENUM_XML(BinaryOperator::Xor , "xor") + ENUM_XML(BinaryOperator::Or , "or") // bitwise or + ENUM_XML(BinaryOperator::LAnd , "land") // boolean and + ENUM_XML(BinaryOperator::LOr , "lor") // boolean or + ENUM_XML(BinaryOperator::Assign , "assign") + ENUM_XML(BinaryOperator::MulAssign, "mulassign") + ENUM_XML(BinaryOperator::DivAssign, "divassign") + ENUM_XML(BinaryOperator::RemAssign, "remassign") + ENUM_XML(BinaryOperator::AddAssign, "addassign") + ENUM_XML(BinaryOperator::SubAssign, "subassign") + ENUM_XML(BinaryOperator::ShlAssign, "shlassign") + ENUM_XML(BinaryOperator::ShrAssign, "shrassign") + ENUM_XML(BinaryOperator::AndAssign, "andassign") + ENUM_XML(BinaryOperator::XorAssign, "xorassign") + ENUM_XML(BinaryOperator::OrAssign , "orassign") + ENUM_XML(BinaryOperator::Comma , "comma") + END_ENUM_XML + SUB_NODE_XML(Expr) // expr1 + SUB_NODE_XML(Expr) // expr2 +END_NODE_XML + +// FIXME: is there a special class needed or is BinaryOperator sufficient? +//NODE_XML(CompoundAssignOperator, "CompoundAssignOperator") + +NODE_XML(ConditionalOperator, "ConditionalOperator") // expr1 ? expr2 : expr3 + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + SUB_NODE_XML(Expr) // expr1 + SUB_NODE_XML(Expr) // expr2 + SUB_NODE_XML(Expr) // expr3 +END_NODE_XML + +NODE_XML(SizeOfAlignOfExpr, "SizeOfAlignOfExpr") // sizeof(expr) or alignof(expr) + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + ATTRIBUTE_XML(isSizeOf(), "is_sizeof") + ATTRIBUTE_XML(isArgumentType(), "is_type") // "1" if expr denotes a type + ATTRIBUTE_SPECIAL_XML(getArgumentType(), "type_ref") // optional, denotes the type of expr, if is_type=="1", special handling needed since getArgumentType() could assert + SUB_NODE_OPT_XML(Expr) // expr, if is_type=="0" +END_NODE_XML + +NODE_XML(ArraySubscriptExpr, "ArraySubscriptExpr") // expr1[expr2] + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + SUB_NODE_XML(Expr) // expr1 + SUB_NODE_XML(Expr) // expr2 +END_NODE_XML + +NODE_XML(CallExpr, "CallExpr") // fnexpr(arg1, arg2, ...) + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + ATTRIBUTE_XML(getNumArgs(), "num_args") // unsigned + SUB_NODE_XML(Expr) // fnexpr + SUB_NODE_SEQUENCE_XML(Expr) // arg1..argN +END_NODE_XML + +NODE_XML(MemberExpr, "MemberExpr") // expr->F or expr.F + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + ATTRIBUTE_XML(isArrow(), "is_deref") + ATTRIBUTE_XML(getMemberDecl(), "ref") // refers to F + ATTRIBUTE_XML(getMemberDecl()->getNameAsString(), "name") // informal + SUB_NODE_XML(Expr) // expr +END_NODE_XML + +NODE_XML(CStyleCastExpr, "CStyleCastExpr") // (type)expr + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + ATTRIBUTE_XML(getTypeAsWritten(), "type_ref") // denotes the type as written in the source code + SUB_NODE_XML(Expr) // expr +END_NODE_XML + +NODE_XML(ImplicitCastExpr, "ImplicitCastExpr") + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + SUB_NODE_XML(Expr) +END_NODE_XML + +NODE_XML(CompoundLiteralExpr, "CompoundLiteralExpr") // [C99 6.5.2.5] + SUB_NODE_XML(Expr) // init +END_NODE_XML + +NODE_XML(ExtVectorElementExpr, "ExtVectorElementExpr") + SUB_NODE_XML(Expr) // base +END_NODE_XML + +NODE_XML(InitListExpr, "InitListExpr") // struct foo x = { expr1, { expr2, expr3 } }; + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + ATTRIBUTE_OPT_XML(getInitializedFieldInUnion(), "field_ref") // if a union is initialized, this refers to the initialized union field id + ATTRIBUTE_XML(getNumInits(), "num_inits") // unsigned + SUB_NODE_SEQUENCE_XML(Expr) // expr1..exprN +END_NODE_XML + +NODE_XML(DesignatedInitExpr, "DesignatedInitExpr") + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) +END_NODE_XML + +NODE_XML(ImplicitValueInitExpr, "ImplicitValueInitExpr") // Implicit value initializations occur within InitListExpr + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) +END_NODE_XML + +NODE_XML(VAArgExpr, "VAArgExpr") // used for the builtin function __builtin_va_start(expr) + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + SUB_NODE_XML(Expr) // expr +END_NODE_XML + +NODE_XML(ParenExpr, "ParenExpr") // this represents a parethesized expression "(expr)". Only formed if full location information is requested. + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + SUB_NODE_XML(Expr) // expr +END_NODE_XML + +// GNU Extensions +NODE_XML(AddrLabelExpr, "AddrLabelExpr") // the GNU address of label extension, representing &&label. + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + ATTRIBUTE_XML(getLabel(), "ref") // id string + SUB_NODE_XML(LabelStmt) // expr +END_NODE_XML + +NODE_XML(StmtExpr, "StmtExpr") // StmtExpr contains a single CompoundStmt node, which it evaluates and takes the value of the last subexpression. + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + SUB_NODE_XML(CompoundStmt) +END_NODE_XML + +NODE_XML(TypesCompatibleExpr, "TypesCompatibleExpr") // GNU builtin-in function __builtin_types_compatible_p + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + ATTRIBUTE_XML(getArgType1(), "type1_ref") // id of type1 + ATTRIBUTE_XML(getArgType2(), "type2_ref") // id of type2 +END_NODE_XML + +NODE_XML(ChooseExpr, "ChooseExpr") // GNU builtin-in function __builtin_choose_expr(expr1, expr2, expr3) + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + SUB_NODE_XML(Expr) // expr1 + SUB_NODE_XML(Expr) // expr2 + SUB_NODE_XML(Expr) // expr3 +END_NODE_XML + +NODE_XML(GNUNullExpr, "GNUNullExpr") // GNU __null extension + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) +END_NODE_XML + +// C++ Expressions +NODE_XML(CXXOperatorCallExpr, "CXXOperatorCallExpr") // fnexpr(arg1, arg2, ...) + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + ATTRIBUTE_XML(getNumArgs(), "num_args") // unsigned + SUB_NODE_XML(Expr) // fnexpr + SUB_NODE_SEQUENCE_XML(Expr) // arg1..argN +END_NODE_XML + +NODE_XML(CXXNamedCastExpr, "CXXNamedCastExpr") // xxx_cast(expr) + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + ATTRIBUTE_ENUM_XML(getStmtClass(), "kind") + ENUM_XML(Stmt::CXXStaticCastExprClass, "static_cast") + ENUM_XML(Stmt::CXXDynamicCastExprClass, "dynamic_cast") + ENUM_XML(Stmt::CXXReinterpretCastExprClass, "reinterpret_cast") + ENUM_XML(Stmt::CXXConstCastExprClass, "const_cast") + END_ENUM_XML + ATTRIBUTE_XML(getTypeAsWritten(), "type_ref") // denotes the type as written in the source code + SUB_NODE_XML(Expr) // expr +END_NODE_XML + +NODE_XML(CXXMemberCallExpr, "CXXMemberCallExpr") // fnexpr(arg1, arg2, ...) + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + ATTRIBUTE_XML(getNumArgs(), "num_args") // unsigned + SUB_NODE_XML(Expr) // fnexpr + SUB_NODE_SEQUENCE_XML(Expr) // arg1..argN +END_NODE_XML + +NODE_XML(CXXBoolLiteralExpr, "CXXBoolLiteralExpr") + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + ATTRIBUTE_XML(getValue(), "value") // boolean +END_NODE_XML + +NODE_XML(CXXNullPtrLiteralExpr, "CXXNullPtrLiteralExpr") // [C++0x 2.14.7] C++ Pointer Literal + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) +END_NODE_XML + +NODE_XML(CXXTypeidExpr, "CXXTypeidExpr") // typeid(expr) + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + ATTRIBUTE_XML(isTypeOperand(), "is_type") // "1" if expr denotes a type + ATTRIBUTE_SPECIAL_XML(getTypeOperand(), "type_ref") // optional, denotes the type of expr, if is_type=="1", special handling needed since getTypeOperand() could assert + SUB_NODE_OPT_XML(Expr) // expr, if is_type=="0" +END_NODE_XML + +NODE_XML(CXXThisExpr, "CXXThisExpr") // this + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) +END_NODE_XML + +NODE_XML(CXXThrowExpr, "CXXThrowExpr") // throw (expr); + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + SUB_NODE_XML(Expr) // NULL in case of "throw;" +END_NODE_XML + +NODE_XML(CXXDefaultArgExpr, "CXXDefaultArgExpr") + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + ATTRIBUTE_XML(getParam(), "ref") // id of the parameter declaration (the expression is a subnode of the declaration) +END_NODE_XML + +NODE_XML(CXXConditionDeclExpr, "CXXConditionDeclExpr") + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + SUB_NODE_XML(VarDecl) // a CXXConditionDeclExpr owns the declaration +END_NODE_XML + + +//===----------------------------------------------------------------------===// +#undef NODE_XML +#undef ID_ATTRIBUTE_XML +#undef TYPE_ATTRIBUTE_XML +#undef ATTRIBUTE_XML +#undef ATTRIBUTE_SPECIAL_XML +#undef ATTRIBUTE_OPT_XML +#undef ATTRIBUTE_ENUM_XML +#undef ATTRIBUTE_ENUM_OPT_XML +#undef ATTRIBUTE_FILE_LOCATION_XML +#undef ENUM_XML +#undef END_ENUM_XML +#undef END_NODE_XML +#undef SUB_NODE_XML +#undef SUB_NODE_SEQUENCE_XML +#undef SUB_NODE_OPT_XML diff --git a/include/clang/Frontend/TypeXML.def b/include/clang/Frontend/TypeXML.def new file mode 100644 index 0000000000..fd9d08adff --- /dev/null +++ b/include/clang/Frontend/TypeXML.def @@ -0,0 +1,277 @@ +//===-- TypeXML.def - Metadata about Type XML nodes ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the XML type info database as written in the +// / sub-nodes of the XML document. Type nodes +// are referred by "type" reference attributes throughout the document. +// A type node never contains sub-nodes. +// The semantics of the attributes and enums are mostly self-documenting +// by looking at the appropriate internally used functions and values. +// The following macros are used: +// +// NODE_XML( CLASS, NAME ) - A node of name NAME denotes a concrete +// type of class CLASS where CLASS is a class name used internally by clang. +// After a NODE_XML the definition of all (optional) attributes of that type +// node follows. +// +// END_NODE_XML - Closes the attribute definition of the current node. +// +// ID_ATTRIBUTE_XML - Each type node has an "id" attribute containing a +// string, which value uniquely identify the type. Other nodes may refer +// by "type" reference attributes to this value. +// +// TYPE_ATTRIBUTE_XML( FN ) - Type nodes may refer to the ids of other type +// nodes by a "type" attribute. FN is internally used by clang. +// +// CONTEXT_ATTRIBUTE_XML( FN ) - Type nodes may refer to the ids of their +// declaration contexts by a "context" attribute. FN is internally used by +// clang. +// +// ATTRIBUTE_XML( FN, NAME ) - An attribute named NAME. FN is internally +// used by clang. A boolean attribute have the values "0" or "1". +// +// ATTRIBUTE_OPT_XML( FN, NAME ) - An optional attribute named NAME. +// Optional attributes are omitted for boolean types, if the value is false, +// for integral types, if the value is null and for strings, +// if the value is the empty string. FN is internally used by clang. +// +// ATTRIBUTE_ENUM[_OPT]_XML( FN, NAME ) - An attribute named NAME. The value +// is an enumeration defined with ENUM_XML macros immediately following after +// that macro. An optional attribute is ommited, if the particular enum is the +// empty string. FN is internally used by clang. +// +// ENUM_XML( VALUE, NAME ) - An enumeration element named NAME. VALUE is +// internally used by clang. +// +// END_ENUM_XML - Closes the enumeration definition of the current attribute. +// +//===----------------------------------------------------------------------===// + +#ifndef TYPE_ATTRIBUTE_XML +# define TYPE_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "type") +#endif + +#ifndef CONTEXT_ATTRIBUTE_XML +# define CONTEXT_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "context") +#endif + + +NODE_XML(QualType, "CvQualifiedType") + ID_ATTRIBUTE_XML + TYPE_ATTRIBUTE_XML(getTypePtr()) // the qualified type, e.g. for 'T* const' it's 'T*' + ATTRIBUTE_OPT_XML(isConstQualified(), "const") // boolean + ATTRIBUTE_OPT_XML(isVolatileQualified(), "volatile") // boolean + ATTRIBUTE_OPT_XML(isRestrictQualified(), "restrict") // boolean +END_NODE_XML + +NODE_XML(ExtQualType, "ExtQualType") + ID_ATTRIBUTE_XML + TYPE_ATTRIBUTE_XML(getBaseType()) + ATTRIBUTE_OPT_XML(getAddressSpace(), "adress_space") // unsigned: Address Space ID - The address space ID this type is qualified with. + ATTRIBUTE_ENUM_OPT_XML(getObjCGCAttr(), "objc_gc") // GC __weak/__strong attributes + ENUM_XML(QualType::GCNone, "") + ENUM_XML(QualType::Weak, "weak") + ENUM_XML(QualType::Strong, "strong") + END_ENUM_XML +END_NODE_XML + +NODE_XML(BuiltinType, "FundamentalType") + ID_ATTRIBUTE_XML + ATTRIBUTE_ENUM_XML(getKind(), "kind") + ENUM_XML(BuiltinType::Void, "void") + ENUM_XML(BuiltinType::Bool, "bool") + ENUM_XML(BuiltinType::Char_U, "char") // not explicitely qualified char, depends on target platform + ENUM_XML(BuiltinType::Char_S, "char") // not explicitely qualified char, depends on target platform + ENUM_XML(BuiltinType::SChar, "signed char") + ENUM_XML(BuiltinType::Short, "short"); + ENUM_XML(BuiltinType::Int, "int"); + ENUM_XML(BuiltinType::Long, "long"); + ENUM_XML(BuiltinType::LongLong, "long long"); + ENUM_XML(BuiltinType::Int128, "__int128_t"); + ENUM_XML(BuiltinType::UChar, "unsigned char"); + ENUM_XML(BuiltinType::UShort, "unsigned short"); + ENUM_XML(BuiltinType::UInt, "unsigned int"); + ENUM_XML(BuiltinType::ULong, "unsigned long"); + ENUM_XML(BuiltinType::ULongLong, "unsigned long long"); + ENUM_XML(BuiltinType::UInt128, "__uint128_t"); + ENUM_XML(BuiltinType::Float, "float"); + ENUM_XML(BuiltinType::Double, "double"); + ENUM_XML(BuiltinType::LongDouble, "long double"); + ENUM_XML(BuiltinType::WChar, "wchar_t"); + ENUM_XML(BuiltinType::NullPtr, "nullptr_t"); // This is the type of C++0x 'nullptr'. + ENUM_XML(BuiltinType::Overload, "overloaded"); + ENUM_XML(BuiltinType::Dependent, "dependent"); + END_ENUM_XML +END_NODE_XML + +NODE_XML(FixedWidthIntType, "FixedWidthIntType") + ID_ATTRIBUTE_XML + ATTRIBUTE_XML(getWidth(), "width") // unsigned + ATTRIBUTE_XML(isSigned(), "is_signed") // boolean +END_NODE_XML + +NODE_XML(PointerType, "PointerType") + ID_ATTRIBUTE_XML + TYPE_ATTRIBUTE_XML(getPointeeType()) +END_NODE_XML + +NODE_XML(LValueReferenceType, "ReferenceType") + ID_ATTRIBUTE_XML + TYPE_ATTRIBUTE_XML(getPointeeType()) +END_NODE_XML + +NODE_XML(RValueReferenceType, "ReferenceType") + ID_ATTRIBUTE_XML + TYPE_ATTRIBUTE_XML(getPointeeType()) +END_NODE_XML + +NODE_XML(FunctionNoProtoType, "FunctionNoProtoType") + ID_ATTRIBUTE_XML +END_NODE_XML + +NODE_XML(FunctionProtoType, "FunctionType") + ID_ATTRIBUTE_XML + ATTRIBUTE_XML(getResultType(), "result_type") + ATTRIBUTE_OPT_XML(isVariadic(), "variadic") +END_NODE_XML + +NODE_XML(TypedefType, "Typedef") + ID_ATTRIBUTE_XML + TYPE_ATTRIBUTE_XML(getDecl()->getUnderlyingType()) + ATTRIBUTE_XML(getDecl()->getNameAsString(), "name") // string + CONTEXT_ATTRIBUTE_XML(getDecl()->getDeclContext()) +END_NODE_XML + +NODE_XML(ComplexType, "ComplexType") // C99 complex types (_Complex float etc) + ID_ATTRIBUTE_XML + TYPE_ATTRIBUTE_XML(getElementType()) +END_NODE_XML + +NODE_XML(BlockPointerType, "BlockPointerType") + ID_ATTRIBUTE_XML + TYPE_ATTRIBUTE_XML(getPointeeType()) // alway refers to a function type +END_NODE_XML + +NODE_XML(MemberPointerType, "MemberPointerType") + ID_ATTRIBUTE_XML + TYPE_ATTRIBUTE_XML(getPointeeType()) + ATTRIBUTE_XML(getClass(), "class_type") // refers to the class type id of which the pointee is a member +END_NODE_XML + +NODE_XML(ConstantArrayType, "ArrayType") + ID_ATTRIBUTE_XML + TYPE_ATTRIBUTE_XML(getElementType()) + ATTRIBUTE_XML(getSize(), "size") // unsigned + ATTRIBUTE_ENUM_OPT_XML(getSizeModifier(), "size_modifier") + ENUM_XML(ArrayType::Normal, "") + ENUM_XML(ArrayType::Static, "static") + ENUM_XML(ArrayType::Star, "star") + END_ENUM_XML + ATTRIBUTE_OPT_XML(getIndexTypeQualifier(), "index_type_qualifier") // unsigned +END_NODE_XML + +NODE_XML(IncompleteArrayType, "IncompleteArrayType") + ID_ATTRIBUTE_XML + TYPE_ATTRIBUTE_XML(getElementType()) +END_NODE_XML + +NODE_XML(VariableArrayType, "VariableArrayType") + ID_ATTRIBUTE_XML + TYPE_ATTRIBUTE_XML(getElementType()) + // note: the size expression is print at the point of declaration +END_NODE_XML + +NODE_XML(DependentSizedArrayType, "DependentSizedArrayType") + ID_ATTRIBUTE_XML + TYPE_ATTRIBUTE_XML(getElementType()) + // FIXME: how to deal with size expression? +END_NODE_XML + +NODE_XML(VectorType, "VectorType") + ID_ATTRIBUTE_XML + TYPE_ATTRIBUTE_XML(getElementType()) + ATTRIBUTE_XML(getNumElements(), "size") // unsigned +END_NODE_XML + +NODE_XML(ExtVectorType, "ExtVectorType") + ID_ATTRIBUTE_XML + TYPE_ATTRIBUTE_XML(getElementType()) + ATTRIBUTE_XML(getNumElements(), "size") // unsigned +END_NODE_XML + +NODE_XML(TypeOfExprType, "TypeOfExprType") + ID_ATTRIBUTE_XML + // note: the typeof expression is print at the point of use +END_NODE_XML + +NODE_XML(TypeOfType, "TypeOfType") + ID_ATTRIBUTE_XML + TYPE_ATTRIBUTE_XML(getUnderlyingType()) +END_NODE_XML + + +NODE_XML(RecordType, "Record") + ID_ATTRIBUTE_XML + ATTRIBUTE_XML(getDecl()->getNameAsString(), "name") // string + ATTRIBUTE_ENUM_XML(getDecl()->getTagKind(), "kind") + ENUM_XML(TagDecl::TK_struct, "struct") + ENUM_XML(TagDecl::TK_union, "union") + ENUM_XML(TagDecl::TK_class, "class") + END_ENUM_XML + CONTEXT_ATTRIBUTE_XML(getDecl()->getDeclContext()) +END_NODE_XML + +NODE_XML(EnumType, "Enum") + ID_ATTRIBUTE_XML + ATTRIBUTE_XML(getDecl()->getNameAsString(), "name") // string + CONTEXT_ATTRIBUTE_XML(getDecl()->getDeclContext()) +END_NODE_XML + +NODE_XML(TemplateTypeParmType, "TemplateTypeParmType") + ID_ATTRIBUTE_XML +END_NODE_XML + +NODE_XML(TemplateSpecializationType, "TemplateSpecializationType") + ID_ATTRIBUTE_XML +END_NODE_XML + +NODE_XML(QualifiedNameType, "QualifiedNameType") + ID_ATTRIBUTE_XML + TYPE_ATTRIBUTE_XML(getNamedType()) +END_NODE_XML + +NODE_XML(TypenameType, "TypenameType") + ID_ATTRIBUTE_XML +END_NODE_XML + +NODE_XML(ObjCInterfaceType, "ObjCInterfaceType") + ID_ATTRIBUTE_XML +END_NODE_XML + +NODE_XML(ObjCQualifiedInterfaceType, "ObjCQualifiedInterfaceType") + ID_ATTRIBUTE_XML +END_NODE_XML + +NODE_XML(ObjCQualifiedIdType, "ObjCQualifiedIdType") + ID_ATTRIBUTE_XML +END_NODE_XML + + +//===----------------------------------------------------------------------===// +#undef NODE_XML +#undef ID_ATTRIBUTE_XML +#undef TYPE_ATTRIBUTE_XML +#undef CONTEXT_ATTRIBUTE_XML +#undef ATTRIBUTE_XML +#undef ATTRIBUTE_OPT_XML +#undef ATTRIBUTE_ENUM_XML +#undef ATTRIBUTE_ENUM_OPT_XML +#undef ENUM_XML +#undef END_ENUM_XML +#undef END_NODE_XML diff --git a/lib/Frontend/CMakeLists.txt b/lib/Frontend/CMakeLists.txt index 649f9dae37..72d9a7ead9 100644 --- a/lib/Frontend/CMakeLists.txt +++ b/lib/Frontend/CMakeLists.txt @@ -5,6 +5,7 @@ add_clang_library(clangFrontend ASTConsumers.cpp Backend.cpp CacheTokens.cpp + DeclXML.cpp DependencyFile.cpp DiagChecker.cpp DocumentXML.cpp @@ -31,5 +32,6 @@ add_clang_library(clangFrontend StmtXML.cpp TextDiagnosticBuffer.cpp TextDiagnosticPrinter.cpp + TypeXML.cpp Warnings.cpp ) diff --git a/lib/Frontend/DeclXML.cpp b/lib/Frontend/DeclXML.cpp new file mode 100644 index 0000000000..5c21999bfa --- /dev/null +++ b/lib/Frontend/DeclXML.cpp @@ -0,0 +1,161 @@ +//===--- DeclXML.cpp - XML implementation for Decl ASTs -------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the XML document class, which provides the means to +// dump out the AST in a XML form that exposes type details and other fields. +// +//===----------------------------------------------------------------------===// + +#include "clang/Frontend/DocumentXML.h" +#include "clang/AST/DeclVisitor.h" +#include "clang/AST/Expr.h" + +namespace clang { + +//--------------------------------------------------------- +class DocumentXML::DeclPrinter : public DeclVisitor +{ + DocumentXML& Doc; + + void addSubNodes(FunctionDecl* FD) + { + for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) + { + Visit(FD->getParamDecl(i)); + Doc.toParent(); + } + } + + void addSubNodes(RecordDecl* RD) + { + for (RecordDecl::field_iterator i = RD->field_begin(*Doc.Ctx), e = RD->field_end(*Doc.Ctx); i != e; ++i) + { + Visit(*i); + Doc.toParent(); + } + } + + void addSubNodes(EnumDecl* ED) + { + for (EnumDecl::enumerator_iterator i = ED->enumerator_begin(*Doc.Ctx), e = ED->enumerator_end(*Doc.Ctx); i != e; ++i) + { + Visit(*i); + Doc.toParent(); + } + } + + void addSubNodes(EnumConstantDecl* ECD) + { + if (ECD->getInitExpr()) + { + Doc.PrintStmt(ECD->getInitExpr()); + } + } + + void addSubNodes(FieldDecl* FdD) + { + if (FdD->isBitField()) + { + Doc.PrintStmt(FdD->getBitWidth()); + } + } + + void addSubNodes(VarDecl* V) + { + if (V->getInit()) + { + Doc.PrintStmt(V->getInit()); + } + } + + void addSubNodes(ParmVarDecl* argDecl) + { + if (argDecl->getDefaultArg()) + { + Doc.PrintStmt(argDecl->getDefaultArg()); + } + } + + void addSpecialAttribute(const char* pName, EnumDecl* ED) + { + const QualType& enumType = ED->getIntegerType(); + if (!enumType.isNull()) + { + Doc.addAttribute(pName, enumType); + } + } + + void addIdAttribute(LinkageSpecDecl* ED) + { + Doc.addAttribute("id", ED); + } + + void addIdAttribute(NamedDecl* ND) + { + Doc.addAttribute("id", ND); + } + +public: + DeclPrinter(DocumentXML& doc) : Doc(doc) {} + +#define NODE_XML( CLASS, NAME ) \ + void Visit##CLASS(CLASS* T) \ + { \ + Doc.addSubNode(NAME); + +#define ID_ATTRIBUTE_XML addIdAttribute(T); +#define ATTRIBUTE_XML( FN, NAME ) Doc.addAttribute(NAME, T->FN); +#define ATTRIBUTE_OPT_XML( FN, NAME ) Doc.addAttributeOptional(NAME, T->FN); +#define ATTRIBUTE_FILE_LOCATION_XML Doc.addLocation(T->getLocation()); +#define ATTRIBUTE_SPECIAL_XML( FN, NAME ) addSpecialAttribute(NAME, T); + +#define ATTRIBUTE_ENUM_XML( FN, NAME ) \ + { \ + const char* pAttributeName = NAME; \ + const bool optional = false; \ + switch (T->FN) { \ + default: assert(0 && "unknown enum value"); + +#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME ) \ + { \ + const char* pAttributeName = NAME; \ + const bool optional = true; \ + switch (T->FN) { \ + default: assert(0 && "unknown enum value"); + +#define ENUM_XML( VALUE, NAME ) case VALUE: if ((!optional) || NAME[0]) Doc.addAttribute(pAttributeName, NAME); break; +#define END_ENUM_XML } } +#define END_NODE_XML } + +#define SUB_NODE_XML( CLASS ) addSubNodes(T); +#define SUB_NODE_SEQUENCE_XML( CLASS ) addSubNodes(T); +#define SUB_NODE_OPT_XML( CLASS ) addSubNodes(T); + +#include "clang/Frontend/DeclXML.def" +}; + + +//--------------------------------------------------------- +void DocumentXML::writeDeclToXML(Decl *D) +{ + DeclPrinter(*this).Visit(D); + if (FunctionDecl *FD = dyn_cast(D)) + { + if (Stmt *Body = FD->getBody(*Ctx)) { + addSubNode("Body"); + PrintStmt(Body); + toParent(); + } + } + toParent(); +} + +//--------------------------------------------------------- +} // NS clang + diff --git a/lib/Frontend/DocumentXML.cpp b/lib/Frontend/DocumentXML.cpp index 7562d2ae87..19a757303f 100644 --- a/lib/Frontend/DocumentXML.cpp +++ b/lib/Frontend/DocumentXML.cpp @@ -14,44 +14,22 @@ #include "clang/Frontend/DocumentXML.h" #include "clang/AST/Decl.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/Expr.h" +#include "clang/AST/ASTContext.h" #include "clang/Basic/SourceManager.h" #include "llvm/ADT/StringExtras.h" namespace clang { -//--------------------------------------------------------- -struct DocumentXML::NodeXML -{ - std::string Name; - NodeXML* Parent; - - NodeXML(const std::string& name, NodeXML* parent) : - Name(name), - Parent(parent) - {} -}; - //--------------------------------------------------------- DocumentXML::DocumentXML(const std::string& rootName, llvm::raw_ostream& out) : - Root(new NodeXML(rootName, 0)), - CurrentNode(Root), Out(out), Ctx(0), - CurrentIndent(0), HasCurrentNodeSubNodes(false) { + NodeStack.push(rootName); Out << "\n<" << rootName; } -//--------------------------------------------------------- -DocumentXML::~DocumentXML() -{ - assert(CurrentNode == Root && "not completely backtracked"); - delete Root; -} - //--------------------------------------------------------- DocumentXML& DocumentXML::addSubNode(const std::string& name) { @@ -59,47 +37,43 @@ DocumentXML& DocumentXML::addSubNode(const std::string& name) { Out << ">\n"; } - CurrentNode = new NodeXML(name, CurrentNode); + NodeStack.push(name); HasCurrentNodeSubNodes = false; - CurrentIndent += 2; Indent(); - Out << "<" << CurrentNode->Name; + Out << "<" << NodeStack.top(); return *this; } //--------------------------------------------------------- void DocumentXML::Indent() { - for (int i = 0; i < CurrentIndent; ++i) + for (size_t i = 0, e = (NodeStack.size() - 1) * 2; i < e; ++i) Out << ' '; } //--------------------------------------------------------- DocumentXML& DocumentXML::toParent() { - assert(CurrentNode != Root && "to much backtracking"); + assert(NodeStack.size() > 1 && "to much backtracking"); if (HasCurrentNodeSubNodes) { Indent(); - Out << "Name << ">\n"; + Out << "\n"; } else { Out << "/>\n"; } - NodeXML* NodeToDelete = CurrentNode; - CurrentNode = CurrentNode->Parent; - delete NodeToDelete; + NodeStack.pop(); HasCurrentNodeSubNodes = true; - CurrentIndent -= 2; return *this; } //--------------------------------------------------------- namespace { -enum tIdType { ID_NORMAL, ID_FILE, ID_LAST }; +enum tIdType { ID_NORMAL, ID_FILE, ID_LABEL, ID_LAST }; unsigned getNewId(tIdType idType) { @@ -110,7 +84,7 @@ unsigned getNewId(tIdType idType) //--------------------------------------------------------- inline std::string getPrefixedId(unsigned uId, tIdType idType) { - static const char idPrefix[ID_LAST] = { '_', 'f' }; + static const char idPrefix[ID_LAST] = { '_', 'f', 'l' }; char buffer[20]; char* BufPtr = llvm::utohex_buffer(uId, buffer + 20); *--BufPtr = idPrefix[idType]; @@ -132,6 +106,7 @@ bool addToMap(T& idMap, const V& value, tIdType idType = ID_NORMAL) } // anon NS + //--------------------------------------------------------- std::string DocumentXML::escapeString(const char* pStr, std::string::size_type len) { @@ -170,7 +145,7 @@ std::string DocumentXML::escapeString(const char* pStr, std::string::size_type l //--------------------------------------------------------- void DocumentXML::finalize() { - assert(CurrentNode == Root && "not completely backtracked"); + assert(NodeStack.size() == 1 && "not completely backtracked"); addSubNode("ReferenceSection"); addSubNode("Types"); @@ -179,71 +154,15 @@ void DocumentXML::finalize() { if (i->first.getCVRQualifiers() != 0) { - addSubNode("CvQualifiedType"); + writeTypeToXML(i->first); addAttribute("id", getPrefixedId(i->second, ID_NORMAL)); - addAttribute("type", getPrefixedId(BasicTypes[i->first.getTypePtr()], ID_NORMAL)); - if (i->first.isConstQualified()) addAttribute("const", "1"); - if (i->first.isVolatileQualified()) addAttribute("volatile", "1"); - if (i->first.isRestrictQualified()) addAttribute("restrict", "1"); toParent(); } } for (XML::IdMap::iterator i = BasicTypes.begin(), e = BasicTypes.end(); i != e; ++i) { - // don't use the get methods as they strip of typedef infos - if (const BuiltinType *BT = dyn_cast(i->first)) { - addSubNode("FundamentalType"); - addAttribute("name", BT->getName(Ctx->getLangOptions().CPlusPlus)); - } - else if (const PointerType *PT = dyn_cast(i->first)) { - addSubNode("PointerType"); - addTypeAttribute(PT->getPointeeType()); - } - else if (dyn_cast(i->first) != 0) { - addSubNode("FunctionType"); - } - else if (const ReferenceType *RT = dyn_cast(i->first)) { - addSubNode("ReferenceType"); - addTypeAttribute(RT->getPointeeType()); - } - else if (const TypedefType * TT = dyn_cast(i->first)) { - addSubNode("Typedef"); - addAttribute("name", TT->getDecl()->getNameAsString()); - addTypeAttribute(TT->getDecl()->getUnderlyingType()); - addContextAttribute(TT->getDecl()->getDeclContext()); - } - else if (const QualifiedNameType *QT = dyn_cast(i->first)) { - addSubNode("QualifiedNameType"); - addTypeAttribute(QT->getNamedType()); - } - else if (const ConstantArrayType *CAT = dyn_cast(i->first)) { - addSubNode("ArrayType"); - addAttribute("min", 0); - addAttribute("max", (CAT->getSize() - 1).toString(10, false)); - addTypeAttribute(CAT->getElementType()); - } - else if (const VariableArrayType *VAT = dyn_cast(i->first)) { - addSubNode("VariableArrayType"); - addTypeAttribute(VAT->getElementType()); - } - else if (const TagType *RET = dyn_cast(i->first)) { - const TagDecl *tagDecl = RET->getDecl(); - std::string tagKind = tagDecl->getKindName(); - tagKind[0] = std::toupper(tagKind[0]); - addSubNode(tagKind); - addAttribute("name", tagDecl->getNameAsString()); - addContextAttribute(tagDecl->getDeclContext()); - } - else if (const VectorType* VT = dyn_cast(i->first)) { - addSubNode("VectorType"); - addTypeAttribute(VT->getElementType()); - addAttribute("num_elements", VT->getNumElements()); - } - else - { - addSubNode("FIXMEType"); - } + writeTypeToXML(i->first); addAttribute("id", getPrefixedId(i->second, ID_NORMAL)); toParent(); } @@ -267,7 +186,7 @@ void DocumentXML::finalize() if (const DeclContext* parent = i->first->getParent()) { - addContextAttribute(parent); + addAttribute("context", parent); } toParent(); } @@ -285,21 +204,21 @@ void DocumentXML::finalize() toParent().toParent(); // write the root closing node (which has always subnodes) - Out << "Name << ">\n"; + Out << "\n"; } //--------------------------------------------------------- -void DocumentXML::addTypeAttribute(const QualType& pType) +void DocumentXML::addAttribute(const char* pAttributeName, const QualType& pType) { addTypeRecursively(pType); - addAttribute("type", getPrefixedId(Types[pType], ID_NORMAL)); + addAttribute(pAttributeName, getPrefixedId(Types[pType], ID_NORMAL)); } //--------------------------------------------------------- -void DocumentXML::addTypeIdAttribute(const Type* pType) +void DocumentXML::addPtrAttribute(const char* pAttributeName, const Type* pType) { - addBasicTypeRecursively(pType); - addAttribute("id", getPrefixedId(BasicTypes[pType], ID_NORMAL)); + addTypeRecursively(pType); + addAttribute(pAttributeName, getPrefixedId(BasicTypes[pType], ID_NORMAL)); } //--------------------------------------------------------- @@ -307,7 +226,7 @@ void DocumentXML::addTypeRecursively(const QualType& pType) { if (addToMap(Types, pType)) { - addBasicTypeRecursively(pType.getTypePtr()); + addTypeRecursively(pType.getTypePtr()); // beautifier: a non-qualified type shall be transparent if (pType.getCVRQualifiers() == 0) { @@ -317,43 +236,49 @@ void DocumentXML::addTypeRecursively(const QualType& pType) } //--------------------------------------------------------- -void DocumentXML::addBasicTypeRecursively(const Type* pType) +void DocumentXML::addTypeRecursively(const Type* pType) { if (addToMap(BasicTypes, pType)) { - if (const PointerType *PT = dyn_cast(pType)) { - addTypeRecursively(PT->getPointeeType()); - } - else if (const ReferenceType *RT = dyn_cast(pType)) { - addTypeRecursively(RT->getPointeeType()); - } - else if (const TypedefType *TT = dyn_cast(pType)) { - addTypeRecursively(TT->getDecl()->getUnderlyingType()); - addContextsRecursively(TT->getDecl()->getDeclContext()); - } - else if (const QualifiedNameType *QT = dyn_cast(pType)) { - addTypeRecursively(QT->getNamedType()); - // FIXME: what to do with NestedNameSpecifier or shall this type be transparent? - } - else if (const ArrayType *AT = dyn_cast(pType)) { - addTypeRecursively(AT->getElementType()); - // FIXME: doesn't work in the immediate streaming approach - /*if (const VariableArrayType *VAT = dyn_cast(AT)) - { - addSubNode("VariableArraySizeExpression"); - PrintStmt(VAT->getSizeExpr()); - toParent(); - }*/ + addParentTypes(pType); +/* + // FIXME: doesn't work in the immediate streaming approach + if (const VariableArrayType *VAT = dyn_cast(pType)) + { + addSubNode("VariableArraySizeExpression"); + PrintStmt(VAT->getSizeExpr()); + toParent(); } +*/ } } //--------------------------------------------------------- -void DocumentXML::addContextAttribute(const DeclContext *DC, tContextUsage usage) +void DocumentXML::addPtrAttribute(const char* pName, const DeclContext* DC) { addContextsRecursively(DC); - const char* pAttributeTags[2] = { "context", "id" }; - addAttribute(pAttributeTags[usage], getPrefixedId(Contexts[DC], ID_NORMAL)); + addAttribute(pName, getPrefixedId(Contexts[DC], ID_NORMAL)); +} + +//--------------------------------------------------------- +void DocumentXML::addPtrAttribute(const char* pAttributeName, const NamedDecl* D) +{ + if (const DeclContext* DC = dyn_cast(D)) + { + addContextsRecursively(DC); + addAttribute(pAttributeName, getPrefixedId(Contexts[DC], ID_NORMAL)); + } + else + { + addToMap(Decls, D); + addAttribute(pAttributeName, getPrefixedId(Decls[D], ID_NORMAL)); + } +} + +//--------------------------------------------------------- +void DocumentXML::addPtrAttribute(const char* pName, const NamespaceDecl* D) +{ + addPtrAttribute(pName, static_cast(D)); } //--------------------------------------------------------- @@ -372,6 +297,15 @@ void DocumentXML::addSourceFileAttribute(const std::string& fileName) addAttribute("file", getPrefixedId(SourceFiles[fileName], ID_FILE)); } + +//--------------------------------------------------------- +void DocumentXML::addPtrAttribute(const char* pName, const LabelStmt* L) +{ + addToMap(Labels, L, ID_LABEL); + addAttribute(pName, getPrefixedId(Labels[L], ID_LABEL)); +} + + //--------------------------------------------------------- PresumedLoc DocumentXML::addLocation(const SourceLocation& Loc) { @@ -416,162 +350,10 @@ void DocumentXML::addLocationRange(const SourceRange& R) } } -//--------------------------------------------------------- -void DocumentXML::PrintFunctionDecl(FunctionDecl *FD) -{ - switch (FD->getStorageClass()) { - default: assert(0 && "Unknown storage class"); - case FunctionDecl::None: break; - case FunctionDecl::Extern: addAttribute("storage_class", "extern"); break; - case FunctionDecl::Static: addAttribute("storage_class", "static"); break; - case FunctionDecl::PrivateExtern: addAttribute("storage_class", "__private_extern__"); break; - } - - if (FD->isInline()) - addAttribute("inline", "1"); - - const FunctionType *AFT = FD->getType()->getAsFunctionType(); - addTypeAttribute(AFT->getResultType()); - addBasicTypeRecursively(AFT); - - if (const FunctionProtoType *FT = dyn_cast(AFT)) { - addAttribute("num_args", FD->getNumParams()); - for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) { - addSubNode("Argument"); - ParmVarDecl *argDecl = FD->getParamDecl(i); - addAttribute("name", argDecl->getNameAsString()); - addTypeAttribute(FT->getArgType(i)); - addDeclIdAttribute(argDecl); - if (argDecl->getDefaultArg()) - { - addAttribute("default_arg", "1"); - PrintStmt(argDecl->getDefaultArg()); - } - toParent(); - } - - if (FT->isVariadic()) { - addSubNode("Ellipsis").toParent(); - } - } else { - assert(isa(AFT)); - } -} - -//--------------------------------------------------------- -void DocumentXML::addRefAttribute(const NamedDecl* D) -{ - // FIXME: in case of CXX inline member functions referring to a member defined - // after the function it needs to be tested, if the ids are already there - // (should work, but I couldn't test it) - if (const DeclContext* DC = dyn_cast(D)) - { - addAttribute("ref", getPrefixedId(Contexts[DC], ID_NORMAL)); - } - else - { - addAttribute("ref", getPrefixedId(Decls[D], ID_NORMAL)); - } -} - -//--------------------------------------------------------- -void DocumentXML::addDeclIdAttribute(const NamedDecl* D) -{ - addToMap(Decls, D); - addAttribute("id", getPrefixedId(Decls[D], ID_NORMAL)); -} - //--------------------------------------------------------- void DocumentXML::PrintDecl(Decl *D) { - addSubNode(D->getDeclKindName()); - addContextAttribute(D->getDeclContext()); - addLocation(D->getLocation()); - if (DeclContext* DC = dyn_cast(D)) - { - addContextAttribute(DC, CONTEXT_AS_ID); - } - - if (NamedDecl *ND = dyn_cast(D)) { - addAttribute("name", ND->getNameAsString()); - - if (FunctionDecl *FD = dyn_cast(D)) { - PrintFunctionDecl(FD); - if (Stmt *Body = FD->getBody(*Ctx)) { - addSubNode("Body"); - PrintStmt(Body); - toParent(); - } - } else if (RecordDecl *RD = dyn_cast(D)) { - addBasicTypeRecursively(RD->getTypeForDecl()); - addAttribute("type", getPrefixedId(BasicTypes[RD->getTypeForDecl()], ID_NORMAL)); - if (!RD->isDefinition()) - { - addAttribute("forward", "1"); - } - - for (RecordDecl::field_iterator i = RD->field_begin(*Ctx), e = RD->field_end(*Ctx); i != e; ++i) - { - PrintDecl(*i); - } - } else if (EnumDecl *ED = dyn_cast(D)) { - const QualType& enumType = ED->getIntegerType(); - if (!enumType.isNull()) - { - addTypeAttribute(enumType); - for (EnumDecl::enumerator_iterator i = ED->enumerator_begin(*Ctx), e = ED->enumerator_end(*Ctx); i != e; ++i) - { - PrintDecl(*i); - } - } - } else if (EnumConstantDecl* ECD = dyn_cast(D)) { - addTypeAttribute(ECD->getType()); - addAttribute("value", ECD->getInitVal().toString(10, true)); - if (ECD->getInitExpr()) - { - PrintStmt(ECD->getInitExpr()); - } - } else if (FieldDecl *FdD = dyn_cast(D)) { - addTypeAttribute(FdD->getType()); - addDeclIdAttribute(ND); - if (FdD->isMutable()) - addAttribute("mutable", "1"); - if (FdD->isBitField()) - { - addAttribute("bitfield", "1"); - PrintStmt(FdD->getBitWidth()); - } - } else if (TypedefDecl *TD = dyn_cast(D)) { - addTypeIdAttribute(Ctx->getTypedefType(TD).getTypePtr()); - addTypeAttribute(TD->getUnderlyingType()); - } else if (ValueDecl *VD = dyn_cast(D)) { - addTypeAttribute(VD->getType()); - addDeclIdAttribute(ND); - - VarDecl *V = dyn_cast(VD); - if (V && V->getStorageClass() != VarDecl::None) - { - addAttribute("storage_class", VarDecl::getStorageClassSpecifierString(V->getStorageClass())); - } - - if (V && V->getInit()) - { - PrintStmt(V->getInit()); - } - } - } else if (LinkageSpecDecl* LSD = dyn_cast(D)) { - switch (LSD->getLanguage()) - { - case LinkageSpecDecl::lang_c: addAttribute("lang", "C"); break; - case LinkageSpecDecl::lang_cxx: addAttribute("lang", "CXX"); break; - default: assert(0 && "Unexpected lang id"); - } - } else if (isa(D)) { - // FIXME: Implement this - } else { - assert(0 && "Unexpected decl"); - } - toParent(); + writeDeclToXML(D); } //--------------------------------------------------------- diff --git a/lib/Frontend/StmtXML.cpp b/lib/Frontend/StmtXML.cpp index c861881486..6ba0a28c7d 100644 --- a/lib/Frontend/StmtXML.cpp +++ b/lib/Frontend/StmtXML.cpp @@ -28,8 +28,31 @@ namespace { class VISIBILITY_HIDDEN StmtXML : public StmtVisitor { DocumentXML& Doc; - static const char *getOpcodeStr(UnaryOperator::Opcode Op); - static const char *getOpcodeStr(BinaryOperator::Opcode Op); + //static const char *getOpcodeStr(UnaryOperator::Opcode Op); + //static const char *getOpcodeStr(BinaryOperator::Opcode Op); + + + void addSpecialAttribute(const char* pName, StringLiteral* Str) + { + Doc.addAttribute(pName, Doc.escapeString(Str->getStrData(), Str->getByteLength())); + } + + void addSpecialAttribute(const char* pName, SizeOfAlignOfExpr* S) + { + if (S->isArgumentType()) + { + Doc.addAttribute(pName, S->getArgumentType()); + } + } + + void addSpecialAttribute(const char* pName, CXXTypeidExpr* S) + { + if (S->isTypeOperand()) + { + Doc.addAttribute(pName, S->getTypeOperand()); + } + } + public: StmtXML(DocumentXML& doc) @@ -39,12 +62,21 @@ namespace { void DumpSubTree(Stmt *S) { if (S) { - Doc.addSubNode(S->getStmtClassName()); - Doc.addLocationRange(S->getSourceRange()); - if (DeclStmt* DS = dyn_cast(S)) { - VisitDeclStmt(DS); - } else { - Visit(S); + Visit(S); + if (DeclStmt* DS = dyn_cast(S)) + { + for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end(); + DI != DE; ++DI) + { + Doc.PrintDecl(*DI); + } + } + else + { + if (CXXConditionDeclExpr* CCDE = dyn_cast(S)) + { + Doc.PrintDecl(CCDE->getVarDecl()); + } for (Stmt::child_iterator i = S->child_begin(), e = S->child_end(); i != e; ++i) { DumpSubTree(*i); @@ -56,17 +88,46 @@ namespace { } } - void DumpTypeExpr(const QualType& T) - { - Doc.addSubNode("TypeExpr"); - Doc.addTypeAttribute(T); - Doc.toParent(); - } - void DumpExpr(const Expr *Node) { - Doc.addTypeAttribute(Node->getType()); - } +#define NODE_XML( CLASS, NAME ) \ + void Visit##CLASS(CLASS* S) \ + { \ + typedef CLASS tStmtType; \ + Doc.addSubNode(NAME); + +#define ATTRIBUTE_XML( FN, NAME ) Doc.addAttribute(NAME, S->FN); +#define TYPE_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "type") +#define ATTRIBUTE_OPT_XML( FN, NAME ) Doc.addAttributeOptional(NAME, S->FN); +#define ATTRIBUTE_SPECIAL_XML( FN, NAME ) addSpecialAttribute(NAME, S); +#define ATTRIBUTE_FILE_LOCATION_XML Doc.addLocationRange(S->getSourceRange()); + +#define ATTRIBUTE_ENUM_XML( FN, NAME ) \ + { \ + const char* pAttributeName = NAME; \ + const bool optional = false; \ + switch (S->FN) { \ + default: assert(0 && "unknown enum value"); + +#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME ) \ + { \ + const char* pAttributeName = NAME; \ + const bool optional = true; \ + switch (S->FN) { \ + default: assert(0 && "unknown enum value"); + +#define ENUM_XML( VALUE, NAME ) case VALUE: if ((!optional) || NAME[0]) Doc.addAttribute(pAttributeName, NAME); break; +#define END_ENUM_XML } } +#define END_NODE_XML } + +#define ID_ATTRIBUTE_XML Doc.addAttribute("id", S); +#define SUB_NODE_XML( CLASS ) +#define SUB_NODE_SEQUENCE_XML( CLASS ) +#define SUB_NODE_OPT_XML( CLASS ) + +#include "clang/Frontend/StmtXML.def" + +#if (0) // Stmts. void VisitStmt(Stmt *Node); void VisitDeclStmt(DeclStmt *Node); @@ -105,13 +166,14 @@ namespace { void VisitObjCKVCRefExpr(ObjCKVCRefExpr *Node); void VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node); void VisitObjCSuperExpr(ObjCSuperExpr *Node); +#endif }; } //===----------------------------------------------------------------------===// // Stmt printing methods. //===----------------------------------------------------------------------===// - +#if (0) void StmtXML::VisitStmt(Stmt *Node) { // nothing special to do @@ -396,7 +458,7 @@ void StmtXML::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) { if (Node->isFreeIvar()) Doc.addAttribute("isFreeIvar", "1"); } - +#endif //===----------------------------------------------------------------------===// // Stmt method implementations //===----------------------------------------------------------------------===// diff --git a/lib/Frontend/TypeXML.cpp b/lib/Frontend/TypeXML.cpp new file mode 100644 index 0000000000..f32fbbd241 --- /dev/null +++ b/lib/Frontend/TypeXML.cpp @@ -0,0 +1,127 @@ +//===--- DocumentXML.cpp - XML document for ASTs --------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the XML document class, which provides the means to +// dump out the AST in a XML form that exposes type details and other fields. +// +//===----------------------------------------------------------------------===// + +#include "clang/Frontend/DocumentXML.h" +#include "clang/AST/TypeVisitor.h" +#include "clang/AST/Type.h" +#include "clang/AST/Decl.h" + +namespace clang { + namespace XML { + namespace { + +//--------------------------------------------------------- +class TypeWriter : public TypeVisitor +{ + DocumentXML& Doc; + +public: + TypeWriter(DocumentXML& doc) : Doc(doc) {} + +#define NODE_XML( CLASS, NAME ) \ + void Visit##CLASS(CLASS* T) \ + { \ + Doc.addSubNode(NAME); + +#define ID_ATTRIBUTE_XML // done by the Document class itself +#define ATTRIBUTE_XML( FN, NAME ) Doc.addAttribute(NAME, T->FN); +#define TYPE_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "type") +#define CONTEXT_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "context") +#define ATTRIBUTE_OPT_XML( FN, NAME ) Doc.addAttributeOptional(NAME, T->FN); + +#define ATTRIBUTE_ENUM_XML( FN, NAME ) \ + { \ + const char* pAttributeName = NAME; \ + const bool optional = false; \ + switch (T->FN) { \ + default: assert(0 && "unknown enum value"); + +#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME ) \ + { \ + const char* pAttributeName = NAME; \ + const bool optional = true; \ + switch (T->FN) { \ + default: assert(0 && "unknown enum value"); + +#define ENUM_XML( VALUE, NAME ) case VALUE: if ((!optional) || NAME[0]) Doc.addAttribute(pAttributeName, NAME); break; +#define END_ENUM_XML } } +#define END_NODE_XML } + +#include "clang/Frontend/TypeXML.def" + +}; + +//--------------------------------------------------------- + } // anon clang + } // NS XML + +//--------------------------------------------------------- +class DocumentXML::TypeAdder : public TypeVisitor +{ + DocumentXML& Doc; + + void addIfType(const Type* pType) + { + Doc.addTypeRecursively(pType); + } + + void addIfType(const QualType& pType) + { + Doc.addTypeRecursively(pType); + } + + template void addIfType(T) {} + +public: + TypeAdder(DocumentXML& doc) : Doc(doc) {} + +#define NODE_XML( CLASS, NAME ) \ + void Visit##CLASS(CLASS* T) \ + { + +#define ID_ATTRIBUTE_XML +#define TYPE_ATTRIBUTE_XML( FN ) Doc.addTypeRecursively(T->FN); +#define CONTEXT_ATTRIBUTE_XML( FN ) +#define ATTRIBUTE_XML( FN, NAME ) addIfType(T->FN); +#define ATTRIBUTE_OPT_XML( FN, NAME ) +#define ATTRIBUTE_ENUM_XML( FN, NAME ) +#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME ) +#define ENUM_XML( VALUE, NAME ) +#define END_ENUM_XML +#define END_NODE_XML } + +#include "clang/Frontend/TypeXML.def" +}; + +//--------------------------------------------------------- +void DocumentXML::addParentTypes(const Type* pType) +{ + TypeAdder(*this).Visit(const_cast(pType)); +} + +//--------------------------------------------------------- +void DocumentXML::writeTypeToXML(const Type* pType) +{ + XML::TypeWriter(*this).Visit(const_cast(pType)); +} + +//--------------------------------------------------------- +void DocumentXML::writeTypeToXML(const QualType& pType) +{ + XML::TypeWriter(*this).VisitQualType(const_cast(&pType)); +} + +//--------------------------------------------------------- +} // NS clang +