Merge "Add a command line option to suppress compilation errors"

am: 419ef1bf8e

Change-Id: I47a7612b5000ead27229108f2efac1269be26008
This commit is contained in:
Hsin-Yi Chen
2018-11-06 23:39:56 -08:00
committed by android-build-merger
11 changed files with 200 additions and 52 deletions

View File

@@ -55,6 +55,7 @@ cc_binary_host {
srcs: [ srcs: [
"header-abi-dumper/src/abi_wrappers.cpp", "header-abi-dumper/src/abi_wrappers.cpp",
"header-abi-dumper/src/ast_processing.cpp", "header-abi-dumper/src/ast_processing.cpp",
"header-abi-dumper/src/diagnostic_consumer.cpp",
"header-abi-dumper/src/fixed_argv.cpp", "header-abi-dumper/src/fixed_argv.cpp",
"header-abi-dumper/src/frontend_action.cpp", "header-abi-dumper/src/frontend_action.cpp",
"header-abi-dumper/src/frontend_action_factory.cpp", "header-abi-dumper/src/frontend_action_factory.cpp",

View File

@@ -47,6 +47,10 @@ HeaderASTVisitor::HeaderASTVisitor(
ast_caches_(ast_caches) {} ast_caches_(ast_caches) {}
bool HeaderASTVisitor::VisitRecordDecl(const clang::RecordDecl *decl) { bool HeaderASTVisitor::VisitRecordDecl(const clang::RecordDecl *decl) {
// Avoid segmentation fault in getASTRecordLayout.
if (decl->isInvalidDecl()) {
return true;
}
// Skip forward declarations, dependent records. Also skip anonymous records // Skip forward declarations, dependent records. Also skip anonymous records
// as they will be traversed through record fields. // as they will be traversed through record fields.
if (!decl->isThisDeclarationADefinition() || if (!decl->isThisDeclarationADefinition() ||
@@ -176,14 +180,8 @@ bool HeaderASTVisitor::TraverseDecl(clang::Decl *decl) {
} }
HeaderASTConsumer::HeaderASTConsumer( HeaderASTConsumer::HeaderASTConsumer(
clang::CompilerInstance *compiler_instancep, clang::CompilerInstance *compiler_instancep, HeaderCheckerOptions &options)
const std::string &out_dump_name, : cip_(compiler_instancep), options_(options) {}
std::set<std::string> &exported_headers,
abi_util::TextFormatIR text_format)
: cip_(compiler_instancep),
out_dump_name_(out_dump_name),
exported_headers_(exported_headers),
text_format_(text_format) {}
void HeaderASTConsumer::HandleTranslationUnit(clang::ASTContext &ctx) { void HeaderASTConsumer::HandleTranslationUnit(clang::ASTContext &ctx) {
clang::PrintingPolicy policy(ctx.getPrintingPolicy()); clang::PrintingPolicy policy(ctx.getPrintingPolicy());
@@ -198,13 +196,15 @@ void HeaderASTConsumer::HandleTranslationUnit(clang::ASTContext &ctx) {
const std::string &translation_unit_source = const std::string &translation_unit_source =
ABIWrapper::GetDeclSourceFile(translation_unit, cip_); ABIWrapper::GetDeclSourceFile(translation_unit, cip_);
ast_util::ASTCaches ast_caches(translation_unit_source); ast_util::ASTCaches ast_caches(translation_unit_source);
if (!exported_headers_.empty()) { if (!options_.exported_headers_.empty()) {
exported_headers_.insert(translation_unit_source); options_.exported_headers_.insert(translation_unit_source);
} }
std::unique_ptr<abi_util::IRDumper> ir_dumper = std::unique_ptr<abi_util::IRDumper> ir_dumper =
abi_util::IRDumper::CreateIRDumper(text_format_, out_dump_name_); abi_util::IRDumper::CreateIRDumper(options_.text_format_,
HeaderASTVisitor v(mangle_contextp.get(), &ctx, cip_, exported_headers_, options_.dump_name_);
translation_unit, ir_dumper.get(), &ast_caches); HeaderASTVisitor v(mangle_contextp.get(), &ctx, cip_,
options_.exported_headers_, translation_unit,
ir_dumper.get(), &ast_caches);
if (!v.TraverseDecl(translation_unit) || !ir_dumper->Dump()) { if (!v.TraverseDecl(translation_unit) || !ir_dumper->Dump()) {
llvm::errs() << "Serialization to ostream failed\n"; llvm::errs() << "Serialization to ostream failed\n";

View File

@@ -16,7 +16,7 @@
#define AST_PROCESSING_H_ #define AST_PROCESSING_H_
#include "ast_util.h" #include "ast_util.h"
#include "ir_representation.h" #include "header_checker.h"
#include <clang/AST/AST.h> #include <clang/AST/AST.h>
#include <clang/AST/ASTConsumer.h> #include <clang/AST/ASTConsumer.h>
@@ -69,17 +69,13 @@ class HeaderASTVisitor
class HeaderASTConsumer : public clang::ASTConsumer { class HeaderASTConsumer : public clang::ASTConsumer {
public: public:
HeaderASTConsumer(clang::CompilerInstance *compiler_instancep, HeaderASTConsumer(clang::CompilerInstance *compiler_instancep,
const std::string &out_dump_name, HeaderCheckerOptions &options);
std::set<std::string> &exported_headers,
abi_util::TextFormatIR text_format);
void HandleTranslationUnit(clang::ASTContext &ctx) override; void HandleTranslationUnit(clang::ASTContext &ctx) override;
private: private:
clang::CompilerInstance *cip_; clang::CompilerInstance *cip_;
const std::string &out_dump_name_; HeaderCheckerOptions &options_;
std::set<std::string> &exported_headers_;
abi_util::TextFormatIR text_format_;
}; };
#endif // AST_PROCESSING_H_ #endif // AST_PROCESSING_H_

View File

@@ -0,0 +1,64 @@
// Copyright (C) 2018 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "diagnostic_consumer.h"
#include <clang/Basic/DiagnosticCategories.h>
#include <clang/Basic/DiagnosticIDs.h>
#include <clang/Lex/LexDiagnostic.h>
HeaderCheckerDiagnosticConsumer::HeaderCheckerDiagnosticConsumer(
std::unique_ptr<clang::DiagnosticConsumer> wrapped)
: wrapped_(std::move(wrapped)) {}
void HeaderCheckerDiagnosticConsumer::clear() {
// Default implementation resets warning/error count.
DiagnosticConsumer::clear();
wrapped_->clear();
}
void HeaderCheckerDiagnosticConsumer::BeginSourceFile(
const clang::LangOptions &lang_opts,
const clang::Preprocessor *preprocessor) {
wrapped_->BeginSourceFile(lang_opts, preprocessor);
}
void HeaderCheckerDiagnosticConsumer::EndSourceFile() {
wrapped_->EndSourceFile();
}
void HeaderCheckerDiagnosticConsumer::finish() { wrapped_->finish(); }
bool HeaderCheckerDiagnosticConsumer::IncludeInDiagnosticCounts() const {
return false;
}
void HeaderCheckerDiagnosticConsumer::HandleDiagnostic(
clang::DiagnosticsEngine::Level level, const clang::Diagnostic &info) {
if (level < clang::DiagnosticsEngine::Level::Error) {
return;
}
unsigned id = info.getID();
if (id == clang::diag::err_pp_hash_error ||
id == clang::diag::fatal_too_many_errors) {
return;
}
unsigned category = clang::DiagnosticIDs::getCategoryNumberForDiag(id);
if (category == clang::diag::DiagCat_Semantic_Issue) {
return;
}
// Default implementation increases warning/error count.
DiagnosticConsumer::HandleDiagnostic(level, info);
wrapped_->HandleDiagnostic(level, info);
}

View File

@@ -0,0 +1,37 @@
// Copyright (C) 2018 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef DIAGNOSTIC_CONSUMER_H_
#define DIAGNOSTIC_CONSUMER_H_
#include <clang/Basic/Diagnostic.h>
class HeaderCheckerDiagnosticConsumer : public clang::DiagnosticConsumer {
private:
std::unique_ptr<clang::DiagnosticConsumer> wrapped_;
public:
HeaderCheckerDiagnosticConsumer(
std::unique_ptr<clang::DiagnosticConsumer> wrapped);
void clear() override;
void BeginSourceFile(const clang::LangOptions &lang_opts,
const clang::Preprocessor *preprocessor) override;
void EndSourceFile() override;
void finish() override;
bool IncludeInDiagnosticCounts() const override;
void HandleDiagnostic(clang::DiagnosticsEngine::Level level,
const clang::Diagnostic &info) override;
};
#endif // DIAGNOSTIC_CONSUMER_H_

View File

@@ -15,6 +15,7 @@
#include "frontend_action.h" #include "frontend_action.h"
#include "ast_processing.h" #include "ast_processing.h"
#include "diagnostic_consumer.h"
#include "header_abi_util.h" #include "header_abi_util.h"
#include "ir_representation.h" #include "ir_representation.h"
@@ -25,15 +26,29 @@
#include <llvm/ADT/STLExtras.h> #include <llvm/ADT/STLExtras.h>
HeaderCheckerFrontendAction::HeaderCheckerFrontendAction( HeaderCheckerFrontendAction::HeaderCheckerFrontendAction(
const std::string &dump_name, std::set<std::string> &exported_headers, HeaderCheckerOptions &options)
abi_util::TextFormatIR text_format) : options_(options) {}
: dump_name_(dump_name), exported_headers_(exported_headers),
text_format_(text_format) {}
std::unique_ptr<clang::ASTConsumer> std::unique_ptr<clang::ASTConsumer>
HeaderCheckerFrontendAction::CreateASTConsumer(clang::CompilerInstance &ci, HeaderCheckerFrontendAction::CreateASTConsumer(clang::CompilerInstance &ci,
llvm::StringRef header_file) { llvm::StringRef header_file) {
// Create AST consumers. // Create AST consumers.
return llvm::make_unique<HeaderASTConsumer>(&ci, dump_name_, return llvm::make_unique<HeaderASTConsumer>(&ci, options_);
exported_headers_, text_format_); }
bool HeaderCheckerFrontendAction::BeginInvocation(clang::CompilerInstance &ci) {
if (options_.suppress_errors_) {
clang::DiagnosticsEngine &diagnostics = ci.getDiagnostics();
diagnostics.setClient(
new HeaderCheckerDiagnosticConsumer(diagnostics.takeClient()),
/* ShouldOwnClient */ true);
}
return true;
}
bool HeaderCheckerFrontendAction::BeginSourceFileAction(
clang::CompilerInstance &ci) {
ci.getPreprocessor().SetSuppressIncludeNotFoundError(
options_.suppress_errors_);
return true;
} }

View File

@@ -15,7 +15,7 @@
#ifndef FRONTEND_ACTION_H_ #ifndef FRONTEND_ACTION_H_
#define FRONTEND_ACTION_H_ #define FRONTEND_ACTION_H_
#include "ir_representation.h" #include "header_checker.h"
#include <clang/Frontend/FrontendAction.h> #include <clang/Frontend/FrontendAction.h>
#include <llvm/ADT/StringRef.h> #include <llvm/ADT/StringRef.h>
@@ -32,19 +32,17 @@ namespace clang {
class HeaderCheckerFrontendAction : public clang::ASTFrontendAction { class HeaderCheckerFrontendAction : public clang::ASTFrontendAction {
private: private:
const std::string &dump_name_; HeaderCheckerOptions &options_;
std::set<std::string> &exported_headers_;
abi_util::TextFormatIR text_format_;
public: public:
HeaderCheckerFrontendAction( HeaderCheckerFrontendAction(HeaderCheckerOptions &options);
const std::string &dump_name,
std::set<std::string> &exported_headers,
abi_util::TextFormatIR text_format);
protected: protected:
std::unique_ptr<clang::ASTConsumer> CreateASTConsumer( std::unique_ptr<clang::ASTConsumer> CreateASTConsumer(
clang::CompilerInstance &ci, llvm::StringRef header_file) override; clang::CompilerInstance &ci, llvm::StringRef header_file) override;
bool BeginInvocation(clang::CompilerInstance &ci) override;
bool BeginSourceFileAction(clang::CompilerInstance &ci) override;
}; };
#endif // FRONTEND_ACTION_H_ #endif // FRONTEND_ACTION_H_

View File

@@ -19,13 +19,9 @@
#include <clang/Frontend/FrontendActions.h> #include <clang/Frontend/FrontendActions.h>
HeaderCheckerFrontendActionFactory::HeaderCheckerFrontendActionFactory( HeaderCheckerFrontendActionFactory::HeaderCheckerFrontendActionFactory(
const std::string &dump_name, HeaderCheckerOptions &options)
std::set<std::string> &exported_headers, : options_(options) {}
abi_util::TextFormatIR text_format)
: dump_name_(dump_name), exported_headers_(exported_headers),
text_format_(text_format) {}
clang::FrontendAction *HeaderCheckerFrontendActionFactory::create() { clang::FrontendAction *HeaderCheckerFrontendActionFactory::create() {
return new HeaderCheckerFrontendAction(dump_name_, exported_headers_, return new HeaderCheckerFrontendAction(options_);
text_format_);
} }

View File

@@ -15,6 +15,7 @@
#ifndef FRONTEND_ACTION_FACTORY_H_ #ifndef FRONTEND_ACTION_FACTORY_H_
#define FRONTEND_ACTION_FACTORY_H_ #define FRONTEND_ACTION_FACTORY_H_
#include "frontend_action.h"
#include "ir_representation.h" #include "ir_representation.h"
#include <clang/Tooling/Tooling.h> #include <clang/Tooling/Tooling.h>
@@ -24,15 +25,10 @@
class HeaderCheckerFrontendActionFactory class HeaderCheckerFrontendActionFactory
: public clang::tooling::FrontendActionFactory { : public clang::tooling::FrontendActionFactory {
private: private:
const std::string &dump_name_; HeaderCheckerOptions &options_;
std::set<std::string> &exported_headers_;
abi_util::TextFormatIR text_format_;
public: public:
HeaderCheckerFrontendActionFactory( HeaderCheckerFrontendActionFactory(HeaderCheckerOptions &options);
const std::string &dump_name,
std::set<std::string> &exported_headers,
abi_util::TextFormatIR text_format);
clang::FrontendAction *create() override; clang::FrontendAction *create() override;
}; };

View File

@@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include "header_checker.h"
#include "fixed_argv.h" #include "fixed_argv.h"
#include "frontend_action_factory.h" #include "frontend_action_factory.h"
#include "header_abi_util.h" #include "header_abi_util.h"
@@ -50,6 +52,11 @@ static llvm::cl::opt<bool> no_filter(
"no-filter", llvm::cl::desc("Do not filter any abi"), llvm::cl::Optional, "no-filter", llvm::cl::desc("Do not filter any abi"), llvm::cl::Optional,
llvm::cl::cat(header_checker_category)); llvm::cl::cat(header_checker_category));
static llvm::cl::opt<bool> suppress_errors(
"suppress-errors",
llvm::cl::desc("Suppress preprocess and semantic errors"),
llvm::cl::Optional, llvm::cl::cat(header_checker_category));
static llvm::cl::opt<abi_util::TextFormatIR> output_format( static llvm::cl::opt<abi_util::TextFormatIR> output_format(
"output-format", llvm::cl::desc("Specify format of output dump file"), "output-format", llvm::cl::desc("Specify format of output dump file"),
llvm::cl::values(clEnumValN(abi_util::TextFormatIR::ProtobufTextFormat, llvm::cl::values(clEnumValN(abi_util::TextFormatIR::ProtobufTextFormat,
@@ -72,7 +79,6 @@ static void HideIrrelevantCommandLineOptions() {
} }
} }
int main(int argc, const char **argv) { int main(int argc, const char **argv) {
HideIrrelevantCommandLineOptions(); HideIrrelevantCommandLineOptions();
@@ -124,11 +130,11 @@ int main(int argc, const char **argv) {
// Initialize clang tools and run front-end action. // Initialize clang tools and run front-end action.
std::vector<std::string> header_files{ header_file }; std::vector<std::string> header_files{ header_file };
HeaderCheckerOptions options(out_dump, std::move(exported_headers),
output_format, suppress_errors);
clang::tooling::ClangTool tool(*compilations, header_files); clang::tooling::ClangTool tool(*compilations, header_files);
std::unique_ptr<clang::tooling::FrontendActionFactory> factory( std::unique_ptr<clang::tooling::FrontendActionFactory> factory(
new HeaderCheckerFrontendActionFactory(out_dump, exported_headers, new HeaderCheckerFrontendActionFactory(options));
output_format));
return tool.run(factory.get()); return tool.run(factory.get());
} }

View File

@@ -0,0 +1,39 @@
// Copyright (C) 2018 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef HEADER_CHECKER_H_
#define HEADER_CHECKER_H_
#include "ir_representation.h"
#include <set>
#include <string>
class HeaderCheckerOptions {
public:
std::string dump_name_;
std::set<std::string> exported_headers_;
abi_util::TextFormatIR text_format_;
bool suppress_errors_;
public:
HeaderCheckerOptions(std::string dump_name,
std::set<std::string> exported_headers,
abi_util::TextFormatIR text_format, bool suppress_errors)
: dump_name_(std::move(dump_name)),
exported_headers_(std::move(exported_headers)),
text_format_(text_format), suppress_errors_(suppress_errors) {}
};
#endif // HEADER_CHECKER_H_