Commit 313e846d authored by dmichael@chromium.org's avatar dmichael@chromium.org

PPAPI: Remove clang plugins from ppapi/tests/clang

We don't use these anymore, and they have bitrotted and probably don't
even build with recent Clang. If we want them back, we can get them back
out of SVN/git.

R=teravest@chromium.org
BUG=

Review URL: https://codereview.chromium.org/297963003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@272639 0039d316-1c4b-4281-b951-d872f2087c98
parent c14c19c6
# Copyright (c) 2010 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# Makefile to build the PPAPI Clang plugins
.PHONY: all clean
PLUGINS = PrintNamesAndSizes FindAffectedInterfaces
all: $(foreach plugin,$(PLUGINS),$(plugin))
clean: $(foreach plugin,$(PLUGINS),clean_$(plugin))
# This makefile assumes that you checked out llvm in a subdirectory of your
# home directory called 'llvm'. The source of llvm itself should be one level
# deeper at ~/llvm/llvm. It also assumes that you also have the clang component
# of llvm installed.
# It further assumes that clang has been built in Debug mode following the
# usual instructions, with a build directory parallel to the llvm directory.
# See instructions here: http://clang.llvm.org/get_started.html
# If you didn't configure Clang this way, you can set environment variables
# appropriately to work with your configuration of Clang and LLVM.
LLVM_ROOT ?= ~/llvm
LLVM_SOURCE_ROOT ?= $(LLVM_ROOT)/llvm
LLVM_BUILD_ROOT?=$(LLVM_ROOT)/build
LLVM_INCLUDES?=-I$(LLVM_BUILD_ROOT)/include -I$(LLVM_SOURCE_ROOT)/include
LLVM_LIB_PATHS?=-L$(LLVM_BUILD_ROOT)/Debug+Asserts/lib
CLANG_ROOT=$(LLVM_SOURCE_ROOT)/tools/clang
CLANG_BUILD_ROOT=$(LLVM_BUILD_ROOT)/tools/clang
CLANG_INCLUDES=-I$(CLANG_ROOT)/include -I$(CLANG_BUILD_ROOT)/include
INCLUDES=$(LLVM_INCLUDES) $(CLANG_INCLUDES) -I.
CLANG_DEFINITIONS=-D_DEBUG -D_GNU_SOURCE -D__STDC_LIMIT_MACROS\
-D__STDC_CONSTANT_MACROS
COMMON_CCFLAGS=-fno-exceptions -fno-rtti -fPIC -Woverloaded-virtual -Wcast-qual\
-fno-strict-aliasing -pedantic -Wno-long-long -Wall -W -Wno-unused-parameter\
-Wwrite-strings
CCFLAGS=$(INCLUDES) $(CLANG_DEFINITIONS) $(COMMON_CCFLAGS) -O2
LDFLAGS = -Wl,-R $(LLVM_LIB_PATHS) -lpthread -ldl -lm -shared
CPP=g++
%.o: %.cc
$(CPP) $(CCFLAGS) -c -o $@ $<
PRINT_NAMES_AND_SIZES_OBJECTS=print_names_and_sizes.o
PrintNamesAndSizes: $(PRINT_NAMES_AND_SIZES_OBJECTS)
$(CPP) $^ $(LDFLAGS) -o libPrintNamesAndSizes.so
clean_PrintNamesAndSizes:
rm -f $(PRINT_NAMES_AND_SIZES_OBJECTS) libPrintNamesAndSizes.so
FIND_AFFECTED_INTERFACES_OBJECTS=find_affected_interfaces.o
FindAffectedInterfaces: $(FIND_AFFECTED_INTERFACES_OBJECTS)
$(CPP) $^ $(LDFLAGS) -o libFindAffectedInterfaces.so
clean_FindAffectedInterfaces:
rm -f $(FIND_AFFECTED_INTERFACES_OBJECTS) libFindAffectedInterfaces.so
This is a directory for Clang plugins that are designed to do analysis and/or
manipulation of PPAPI code. Clang is an open-source C front-end that allows
you to parse C, C++, or Objective-C code in to an abstract syntax tree (or AST)
for processing. This README assumes that you are working in a check-out of
chromium.
To use these plugins, you will need to get Clang. Clang is rapidly changing,
so you may want to download and build it yourself. See the instructions here:
- http://clang.llvm.org/get_started.html
To build the plugins, use the Makefile in this directory. If you want the
provided Makefile to work out-of-the-box, in step 2 of the instructions at the
above URL, you should do the following:
> mkdir ~/llvm
> cd ~/llvm
Now continue with the svn co command to check out llvm in ~/llvm/llvm. If you
choose to build llvm in another location, you can use environment variables to
force the Makefile to find your build of clang. See the Makefile for details.
To run a plugin, use clang with the -cc1 -load and -plugin flags and an
otherwise normal build line. For example, to run liBPrintNamesAndSizes.so, if
you currently build like this:
g++ (build_options)
Run this from the command-line instead:
clang -cc1 -load ppapi/tests/clang/libPrintNamesAndSizes.so \
-plugin PrintNamesAndSizes (build_options)
Plugins:
PrintNamesAndSizes : print_names_and_sizes.cc
Print information about all top-level type definitions. You probably won't
need to run it by itself; instead see generate_ppapi_size_checks.py, which
uses the plugin. See print_names_and_sizes.cc for more detail on the plugin.
Example command-line:
python generate_ppapi_size_checks.py \
--ppapi-root=/usr/local/google/chrome_build/src/ppapi
python generate_ppapi_size_checks.py --help
FindAffectedInterfaces : find_affected_interfaces.cc
Given typenames as parameters, print out all types that are affected
(including function pointer types and structs containing affected function
pointer types) if the given type(s) change. This is meant to be used for
determining what interfaces are affected by a change to a struct.
Example command-line:
clang -cc1 -load ppapi/tests/clang/libFindAffectedInterfaces.so \
-plugin FindAffectedInterfaces -I. ppapi/tests/all_includes.h \
-plugin-arg-FindAffectedInterfaces \
"struct PP_VideoCompressedDataBuffer_Dev"
clang -cc1 -load tests/clang/libFindAffectedInterfaces.so \
-plugin FindAffectedInterfaces -I../ tests/all_c_includes.h \
-plugin-arg-FindAffectedInterfaces \
"struct PP_VideoCompressedDataBuffer_Dev,struct PP_Var"
(This assumes that clang is in your path and you are running the plugin from
the ppapi subdirectory in a chrome checkout).
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Clang plugin which finds types that are affected if the types listed in the
// plugin parameters are changed. This is for use in determining what PPAPI
// C-level interfaces are affected if one or more PPAPI C structs are changed.
#include <algorithm>
#include <cstdio>
#include <map>
#include <sstream>
#include <string>
#include <vector>
#include "clang/AST/AST.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/CharUnits.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendPluginRegistry.h"
namespace {
typedef std::vector<std::string> StringVec;
class FindAffectedInterfacesConsumer : public clang::ASTConsumer {
public:
explicit FindAffectedInterfacesConsumer(const StringVec& changed_classes) {
StringVec::const_iterator iter(changed_classes.begin());
StringVec::const_iterator the_end(changed_classes.end());
for (; iter != the_end; ++iter) {
class_is_affected_map_[*iter] = true;
}
}
private:
typedef std::map<std::string, bool> StringBoolMap;
StringBoolMap class_is_affected_map_;
bool IsAffected(const clang::Type& type_to_check) {
std::string type_string(
type_to_check.getCanonicalTypeInternal().getAsString());
std::pair<StringBoolMap::iterator, bool> iter_success_pair =
class_is_affected_map_.insert(
StringBoolMap::value_type(type_string, false));
StringBoolMap::iterator iter(iter_success_pair.first);
bool successfully_inserted(iter_success_pair.second);
// If we were able to insert, then we haven't yet seen this type. Compute
// IsAffected and put it at the newly inserted location in the map.
if (successfully_inserted) {
if (type_to_check.isPointerType()) {
const clang::PointerType* pointer_type =
dyn_cast<clang::PointerType>(&type_to_check);
// Recurse to the pointee type.
iter->second = IsAffected(*pointer_type->getPointeeType().getTypePtr());
} else if (type_to_check.isFunctionProtoType()) {
const clang::FunctionProtoType* func_type =
dyn_cast<clang::FunctionProtoType>(&type_to_check);
// Recurse to the return type and parameter types.
iter->second = IsAffected(*func_type->getResultType().getTypePtr());
if (!iter->second) {
clang::FunctionProtoType::arg_type_iterator arg_iter =
func_type->arg_type_begin();
clang::FunctionProtoType::arg_type_iterator arg_end =
func_type->arg_type_end();
for (; (arg_iter != arg_end) && (!iter->second); ++arg_iter) {
iter->second = IsAffected(*(arg_iter->getTypePtr()));
}
}
} else if (type_to_check.isRecordType()) {
// For records (unions, structs), recurse to the fields.
const clang::RecordType* record =
dyn_cast<clang::RecordType>(&type_to_check);
const clang::RecordDecl* decl = record->getDecl();
clang::RecordDecl::field_iterator field_iter(decl->field_begin());
clang::RecordDecl::field_iterator field_end(decl->field_end());
for (; (field_iter != field_end) && (!iter->second); ++field_iter) {
iter->second = IsAffected(*(field_iter->getType().getTypePtr()));
}
}
}
// By this point, the bool in the map at the location referenced by iter has
// the correct value. Either it was cached, or we computed & inserted it.
return iter->second;
}
// Virtual function to consume top-level declarations. For each one, we check
// to see if it is a type definition. If it is, we print information about
// it.
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());
// TagDecl covers structs, enums, unions, and classes.
if (const clang::TagDecl* tag = dyn_cast<clang::TagDecl>(type_decl)) {
// Only print out info when we find the definition; ignore forward
// references.
if (tag->isDefinition()) {
clang::Type* type = type_decl->getTypeForDecl();
if (IsAffected(*type)) {
std::printf("%s\n", name.c_str());
}
}
} else if (const clang::TypedefDecl* td =
dyn_cast<clang::TypedefDecl>(type_decl)) {
clang::Type* type = td->getUnderlyingType().getTypePtr();
if (IsAffected(*type)) {
std::printf("%s\n", name.c_str());
}
}
}
}
}
};
class FindAffectedInterfacesAction : public clang::PluginASTAction {
public:
FindAffectedInterfacesAction() {}
private:
StringVec types_;
virtual clang::ASTConsumer *CreateASTConsumer(
clang::CompilerInstance &instance, llvm::StringRef /*input_file*/) {
return new FindAffectedInterfacesConsumer(types_);
}
virtual bool ParseArgs(const clang::CompilerInstance& /*instance*/,
const std::vector<std::string>& args) {
// Every argument is interpreted as a comma-delimited list of names of types
// that have been changed.
StringVec::const_iterator iter(args.begin()), end(args.end());
for (; iter != end; ++iter) {
std::stringstream stream(*iter);
std::string type_name;
while (std::getline(stream, type_name, ',')) {
types_.push_back(type_name);
}
}
return true;
}
};
} // namespace
static clang::FrontendPluginRegistry::Add<FindAffectedInterfacesAction>
X("FindAffectedInterfaces",
"Find interfaces affected by changes to the passes classes.");
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Clang plugin which prints the names and sizes of all the top-level
// structs, enums, and typedefs in the input file.
#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";
// This class consumes a Clang-parsed AST and prints out information about types
// defined in the global namespace. Specifically, for each type definition
// encountered, it prints:
// "kind,name,size,arch_dependent,source_file,first_line,last_line\n"
// Where:
// - kind: The Clang TypeClassName (Record, Enum, Typedef, Union, etc)
// - name: The unmangled string name of the type.
// - size: The size in bytes of the type.
// - arch_dependent: 'ArchDependentSize' if the type has architecture-dependent
// size, NotArchDependentSize otherwise.
// - source_file: The source file in which the type is defined.
// - first_line: The first line of the definition (counting from 0).
// - last_line: The last line of the definition (counting from 0).
class PrintNamesAndSizesConsumer : public clang::ASTConsumer {
public:
explicit PrintNamesAndSizesConsumer(clang::SourceManager* source_mgr)
: source_manager_(source_mgr) {}
private:
// SourceManager has information about source code locations, to help us know
// where definitions appear. We do not own this pointer, so we must not
// delete it.
clang::SourceManager* source_manager_;
// Return true if the type contains types that differ in size between 32-bit
// and 64-bit architectures. This is true for types that are typedefed to a
// pointer, long, or unsigned long and also any types that contain an
// architecture-dependent type. Note that this is a bit overly restrictive;
// some unions may be consistent size on 32-bit and 64-bit architectures
// despite containing one of these types. But it's not an important enough
// issue to warrant coding the special case.
// Structs, enums, and unions that do NOT contain arch-dependent types are
// crafted to be the same size on 32-bit and 64-bit platforms by convention.
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)) {
// If it's an array, it has architecture-dependent size if its elements
// do.
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)) {
// If it's a struct or union, iterate through the fields. If any of them
// has architecture-dependent size, then we do too.
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;
}
}
// It's a struct or union, but contains no architecture-dependent members.
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 function to consume top-level declarations. For each one, we check
// to see if it is a type definition. If it is, we print information about
// it.
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();
// TagDecl covers structs, enums, unions, and classes.
if (const clang::TagDecl* tag = dyn_cast<clang::TagDecl>(type_decl)) {
// Only print out info when we find the definition; ignore forward
// references.
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 /*input_file*/) {
return new PrintNamesAndSizesConsumer(
&(instance.getDiagnostics().getSourceManager()));
}
// We don't accept any arguments, but ParseArgs is pure-virtual.
virtual bool ParseArgs(const clang::CompilerInstance& /*instance*/,
const std::vector<std::string>& /*args*/) {
return true;
}
};
} // namespace
static clang::FrontendPluginRegistry::Add<PrintNamesAndSizesAction>
X("PrintNamesAndSizes",
"Print the names and sizes of classes, enums, and typedefs.");
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment