This source file includes following definitions.
- HasArchDependentSize
- PrintTypeInfo
- HandleTopLevelDecl
- CreateASTConsumer
- ParseArgs
#include <cstdio>
#include <cstring>
#include <string>
#include "clang/AST/AST.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/Decl.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendPluginRegistry.h"
namespace {
const char* const kTypedefName = "Typedef";
const char* const kDelim = ",";
const char* const kArchDependent = "ArchDependentSize";
const char* const kNotArchDependent = "NotArchDependentSize";
class PrintNamesAndSizesConsumer : public clang::ASTConsumer {
public:
explicit PrintNamesAndSizesConsumer(clang::SourceManager* source_mgr)
: source_manager_(source_mgr) {}
private:
clang::SourceManager* source_manager_;
bool HasArchDependentSize(const clang::Type& type) {
if (type.isPointerType()) {
return true;
} else if (const clang::BuiltinType* builtin =
dyn_cast<clang::BuiltinType>(&type)) {
if ((builtin->getKind() == clang::BuiltinType::Long) ||
(builtin->getKind() == clang::BuiltinType::ULong)) {
return true;
}
} else if (const clang::ArrayType* array =
dyn_cast<clang::ArrayType>(&type)) {
return HasArchDependentSize(*(array->getElementType().getTypePtr()));
} else if (const clang::TypedefType* typedef_type =
dyn_cast<clang::TypedefType>(&type)) {
return HasArchDependentSize(*(typedef_type->desugar().getTypePtr()));
} else if (const clang::RecordType* record =
dyn_cast<clang::RecordType>(&type)) {
const clang::RecordDecl* decl = record->getDecl();
clang::RecordDecl::field_iterator iter(decl->field_begin());
clang::RecordDecl::field_iterator end(decl->field_end());
for (; iter != end; ++iter) {
if (HasArchDependentSize(*(iter->getType().getTypePtr()))) {
return true;
}
}
return false;
}
return false;
}
void PrintTypeInfo(const std::string& name, const clang::Type& type,
const std::string& kind, const clang::CharUnits& size,
const clang::SourceLocation& begin_loc,
const clang::SourceLocation& end_loc) {
clang::PresumedLoc presumed_begin(
source_manager_->getPresumedLoc(begin_loc));
clang::PresumedLoc presumed_end(source_manager_->getPresumedLoc(end_loc));
std::printf("%s,%s,%lu,%s,%s,%u,%u\n",
kind.c_str(),
name.c_str(),
size.getQuantity(),
HasArchDependentSize(type) ? kArchDependent : kNotArchDependent,
presumed_begin.getFilename(),
presumed_begin.getLine(),
presumed_end.getLine());
}
virtual void HandleTopLevelDecl(clang::DeclGroupRef decl_group) {
clang::DeclGroupRef::iterator iter(decl_group.begin());
clang::DeclGroupRef::iterator the_end(decl_group.end());
for (; iter != the_end; ++iter) {
const clang::Decl *decl = *iter;
if (const clang::TypeDecl* type_decl = dyn_cast<clang::TypeDecl>(decl)) {
std::string name(type_decl->getNameAsString());
clang::SourceLocation start_loc = type_decl->getLocStart();
clang::SourceLocation end_loc = type_decl->getLocEnd();
if (const clang::TagDecl* tag = dyn_cast<clang::TagDecl>(type_decl)) {
if (tag->isDefinition()) {
clang::Type* type = type_decl->getTypeForDecl();
clang::CharUnits size =
tag->getASTContext().getTypeSizeInChars(type);
PrintTypeInfo(name, *type, type->getTypeClassName(), size,
start_loc, end_loc);
}
} else if (const clang::TypedefDecl* td =
dyn_cast<clang::TypedefDecl>(type_decl)) {
clang::Type* type = td->getUnderlyingType().getTypePtr();
clang::CharUnits size = td->getASTContext().getTypeSizeInChars(type);
PrintTypeInfo(name, *type, kTypedefName, size, start_loc, end_loc);
}
}
}
}
};
class PrintNamesAndSizesAction : public clang::PluginASTAction {
public:
PrintNamesAndSizesAction() {}
private:
virtual clang::ASTConsumer *CreateASTConsumer(
clang::CompilerInstance &instance, llvm::StringRef ) {
return new PrintNamesAndSizesConsumer(
&(instance.getDiagnostics().getSourceManager()));
}
virtual bool ParseArgs(const clang::CompilerInstance& ,
const std::vector<std::string>& ) {
return true;
}
};
}
static clang::FrontendPluginRegistry::Add<PrintNamesAndSizesAction>
X("PrintNamesAndSizes",
"Print the names and sizes of classes, enums, and typedefs.");