Enable warnings in llvm_rs_cc
- Fixed a bug that prevented llvm_rs_cc from emitting many warnings.
- Add support so that we can do Wno-error (needed to avoid deprecation warnings
from breaking the build).
- Add test to verify deprecated warning works.
- Simplified slang top level to clean up handling of 32/64 bit compilation handling.
Change-Id: Ibacfa7d3d9708cb39a33b71da9621aee2718f758
diff --git a/RSCCOptions.td b/RSCCOptions.td
index 1277c3a..96cdaa8 100644
--- a/RSCCOptions.td
+++ b/RSCCOptions.td
@@ -91,7 +91,7 @@
HelpText<"package name for referencing RS classes">;
def rs_package_name_EQ : Joined<["-"], "rs-package-name=">, Alias<rs_package_name>;
-def W : Joined<["-"], "W">;
+def W : Joined<["-"], "W">, HelpText<"Enable the specified warning">;
def w : Flag<["-"], "w">, HelpText<"Suppress all warnings">;
//===----------------------------------------------------------------------===//
diff --git a/llvm-rs-cc.cpp b/llvm-rs-cc.cpp
index fea818b..c860c9e 100644
--- a/llvm-rs-cc.cpp
+++ b/llvm-rs-cc.cpp
@@ -17,6 +17,8 @@
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
+#include "clang/Frontend/CompilerInvocation.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Frontend/Utils.h"
@@ -24,11 +26,11 @@
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/Option/OptTable.h"
-#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Signals.h"
#include "llvm/Target/TargetMachine.h"
#include "rs_cc_options.h"
@@ -133,20 +135,15 @@
* 32-bit and 64-bit bitcode outputs to be included in the final reflected
* source code that is emitted.
*/
-static int compileFiles(NamePairList *IOFiles, NamePairList *IOFiles32,
+static void makeFileList(NamePairList *IOFiles, NamePairList *DepFiles,
const llvm::SmallVector<const char*, 16> &Inputs, slang::RSCCOptions &Opts,
- clang::DiagnosticsEngine *DiagEngine, slang::DiagnosticBuffer *DiagClient,
StringSet *SavedStrings) {
- NamePairList DepFiles;
std::string PathSuffix = "";
- bool CompileSecondTimeFor64Bit = false;
-
// In our mixed 32/64-bit path, we need to suffix our files differently for
// both 32-bit and 64-bit versions.
if (Opts.mEmit3264) {
if (Opts.mBitWidth == 64) {
PathSuffix = "bc64";
- CompileSecondTimeFor64Bit = true;
} else {
PathSuffix = "bc32";
}
@@ -172,18 +169,11 @@
OutputFile = DepOutputFile;
}
- DepFiles.push_back(std::make_pair(BCOutputFile, DepOutputFile));
+ DepFiles->push_back(std::make_pair(BCOutputFile, DepOutputFile));
}
IOFiles->push_back(std::make_pair(InputFile, OutputFile));
}
-
- std::unique_ptr<slang::Slang> Compiler(new slang::Slang());
- Compiler->init(Opts.mBitWidth, DiagEngine, DiagClient);
- int CompileFailed = !Compiler->compile(*IOFiles, *IOFiles32, DepFiles, Opts);
- // We suppress warnings (via reset) if we are doing a second compilation.
- Compiler->reset(CompileSecondTimeFor64Bit);
- return CompileFailed;
}
#define str(s) #s
@@ -205,74 +195,94 @@
#undef wrap_str
#undef str
+static void LLVMErrorHandler(void *UserData, const std::string &Message,
+ bool GenCrashDialog) {
+ clang::DiagnosticsEngine *DiagEngine =
+ static_cast<clang::DiagnosticsEngine *>(UserData);
+
+ DiagEngine->Report(clang::diag::err_fe_error_backend) << Message;
+
+ // Run the interrupt handlers to make sure any special cleanups get done, in
+ // particular that we remove files registered with RemoveFileOnSignal.
+ llvm::sys::RunInterruptHandlers();
+
+ exit(1);
+}
+
int main(int argc, const char **argv) {
- llvm::llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+ llvm::llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+ LLVMInitializeARMTargetInfo();
+ LLVMInitializeARMTarget();
+ LLVMInitializeARMAsmPrinter();
- // Populate a vector with the command line arguments, expanding command files
- // that have been included by via the '@' argument.
- llvm::SmallVector<const char*, 256> ArgVector;
- StringSet SavedStrings; // Keeps track of strings to be destroyed at the end.
- const auto& ArgsIn(llvm::makeArrayRef(argv, argc));
- ArgVector.append(ArgsIn.begin(), ArgsIn.end());
- llvm::cl::ExpandResponseFiles(SavedStrings, llvm::cl::TokenizeGNUCommandLine,
- ArgVector, false);
+ StringSet SavedStrings; // Keeps track of strings to be destroyed at the end.
- const std::string Argv0 = llvm::sys::path::stem(ArgVector[0]);
-
- // Setup diagnostic engine
- slang::DiagnosticBuffer *DiagClient = new slang::DiagnosticBuffer();
-
- llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> DiagIDs(
- new clang::DiagnosticIDs());
-
- llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> DiagOpts(
- new clang::DiagnosticOptions());
- clang::DiagnosticsEngine DiagEngine(DiagIDs, &*DiagOpts, DiagClient, true);
-
- slang::Slang::GlobalInitialization();
-
+ // Parse the command line arguments and respond to show help & version
+ // commands.
+ llvm::SmallVector<const char *, 16> Inputs;
slang::RSCCOptions Opts;
- llvm::SmallVector<const char*, 16> Inputs;
- slang::ParseArguments(ArgVector, Inputs, Opts, DiagEngine);
-
- // Exits when there's any error occurred during parsing the arguments
- if (DiagEngine.hasErrorOccurred()) {
- llvm::errs() << DiagClient->str();
+ llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> DiagOpts =
+ new clang::DiagnosticOptions();
+ if (!slang::ParseArguments(llvm::makeArrayRef(argv, argc), Inputs, Opts,
+ *DiagOpts, SavedStrings)) {
+ // Exits when there's any error occurred during parsing the arguments
return 1;
}
-
if (Opts.mShowHelp) {
std::unique_ptr<llvm::opt::OptTable> OptTbl(slang::createRSCCOptTable());
+ const std::string Argv0 = llvm::sys::path::stem(argv[0]);
OptTbl->PrintHelp(llvm::outs(), Argv0.c_str(),
"Renderscript source compiler");
return 0;
}
-
if (Opts.mShowVersion) {
llvm_rs_cc_VersionPrinter();
return 0;
}
- // No input file
+ // Initialize the diagnostic objects
+ llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> DiagIDs(
+ new clang::DiagnosticIDs());
+ slang::DiagnosticBuffer DiagsBuffer;
+ clang::DiagnosticsEngine DiagEngine(DiagIDs, &*DiagOpts, &DiagsBuffer, false);
+ clang::ProcessWarningOptions(DiagEngine, *DiagOpts);
+ (void)DiagEngine.setSeverityForGroup(clang::diag::Flavor::WarningOrError,
+ "implicit-function-declaration",
+ clang::diag::Severity::Error);
+
+ // Report error if no input file
if (Inputs.empty()) {
DiagEngine.Report(clang::diag::err_drv_no_input_files);
- llvm::errs() << DiagClient->str();
+ llvm::errs() << DiagsBuffer.str();
return 1;
}
- // Prepare input data for RS compiler.
- NamePairList IOFiles64;
- NamePairList IOFiles32;
+ llvm::install_fatal_error_handler(LLVMErrorHandler, &DiagEngine);
- int CompileFailed = compileFiles(&IOFiles32, &IOFiles32, Inputs, Opts,
- &DiagEngine, DiagClient, &SavedStrings);
+ // Compile the 32 bit version
+ NamePairList IOFiles32;
+ NamePairList DepFiles32;
+ makeFileList(&IOFiles32, &DepFiles32, Inputs, Opts, &SavedStrings);
+
+ std::unique_ptr<slang::Slang> Compiler(
+ new slang::Slang(32, &DiagEngine, &DiagsBuffer));
+ int CompileFailed =
+ !Compiler->compile(IOFiles32, IOFiles32, DepFiles32, Opts, *DiagOpts);
// Handle the 64-bit case too!
if (Opts.mEmit3264 && !CompileFailed) {
Opts.mBitWidth = 64;
- CompileFailed = compileFiles(&IOFiles64, &IOFiles32, Inputs, Opts,
- &DiagEngine, DiagClient, &SavedStrings);
+ NamePairList IOFiles64;
+ NamePairList DepFiles64;
+ makeFileList(&IOFiles64, &DepFiles64, Inputs, Opts, &SavedStrings);
+
+ std::unique_ptr<slang::Slang> Compiler(
+ new slang::Slang(64, &DiagEngine, &DiagsBuffer));
+ CompileFailed =
+ !Compiler->compile(IOFiles64, IOFiles32, DepFiles64, Opts, *DiagOpts);
}
+ llvm::errs() << DiagsBuffer.str();
+ llvm::remove_fatal_error_handler();
return CompileFailed;
}
diff --git a/rs_cc_options.cpp b/rs_cc_options.cpp
index ff37dd0..94d1453 100644
--- a/rs_cc_options.cpp
+++ b/rs_cc_options.cpp
@@ -23,6 +23,7 @@
#include "llvm/Option/ArgList.h"
#include "llvm/Option/Option.h"
#include "llvm/Option/OptTable.h"
+#include "llvm/Support/CommandLine.h"
#include "rs_cc_options.h"
#include "slang.h"
@@ -76,168 +77,193 @@
};
}
-llvm::opt::OptTable *slang::createRSCCOptTable() { return new RSCCOptTable(); }
+namespace slang {
-void slang::ParseArguments(llvm::SmallVectorImpl<const char *> &ArgVector,
- llvm::SmallVectorImpl<const char *> &Inputs,
- slang::RSCCOptions &Opts,
- clang::DiagnosticsEngine &DiagEngine) {
- if (ArgVector.size() > 1) {
- const char **ArgBegin = ArgVector.data() + 1;
- const char **ArgEnd = ArgVector.data() + ArgVector.size();
- unsigned MissingArgIndex, MissingArgCount;
- std::unique_ptr<llvm::opt::OptTable> OptParser(slang::createRSCCOptTable());
- std::unique_ptr<llvm::opt::InputArgList> Args(OptParser->ParseArgs(
- ArgBegin, ArgEnd, MissingArgIndex, MissingArgCount));
+llvm::opt::OptTable *createRSCCOptTable() { return new RSCCOptTable(); }
- // Check for missing argument error.
- if (MissingArgCount)
- DiagEngine.Report(clang::diag::err_drv_missing_argument)
- << Args->getArgString(MissingArgIndex) << MissingArgCount;
+// This function is similar to
+// clang/lib/Frontend/CompilerInvocation::CreateFromArgs.
+bool ParseArguments(const llvm::ArrayRef<const char *> &ArgsIn,
+ llvm::SmallVectorImpl<const char *> &Inputs,
+ RSCCOptions &Opts, clang::DiagnosticOptions &DiagOpts,
+ llvm::cl::StringSaver &StringSaver) {
+ // We use a different diagnostic engine for argument parsing from the rest of
+ // the work. This mimics what's done in clang. I believe it is so the
+ // argument parsing errors are well formatted while the full errors can be
+ // influenced by command line arguments.
+ llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> ArgumentParseDiagOpts(
+ new clang::DiagnosticOptions());
+ llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> DiagIDs(
+ new clang::DiagnosticIDs());
+ DiagnosticBuffer DiagsBuffer;
+ clang::DiagnosticsEngine DiagEngine(DiagIDs, &*ArgumentParseDiagOpts,
+ &DiagsBuffer, false);
- clang::DiagnosticOptions DiagOpts;
- DiagOpts.IgnoreWarnings = Args->hasArg(OPT_w);
- DiagOpts.Warnings = Args->getAllArgValues(OPT_W);
- clang::ProcessWarningOptions(DiagEngine, DiagOpts);
+ // Populate a vector with the command line arguments, expanding command files
+ // that have been included via the '@' argument.
+ llvm::SmallVector<const char *, 256> ArgVector;
+ ArgVector.append(ArgsIn.begin(), ArgsIn.end());
+ llvm::cl::ExpandResponseFiles(StringSaver, llvm::cl::TokenizeGNUCommandLine,
+ ArgVector, false);
- // Issue errors on unknown arguments.
- for (llvm::opt::arg_iterator it = Args->filtered_begin(OPT_UNKNOWN),
- ie = Args->filtered_end();
- it != ie; ++it)
- DiagEngine.Report(clang::diag::err_drv_unknown_argument)
- << (*it)->getAsString(*Args);
+ std::unique_ptr<llvm::opt::OptTable> OptParser(createRSCCOptTable());
+ unsigned MissingArgIndex = 0;
+ unsigned MissingArgCount = 0;
+ std::unique_ptr<llvm::opt::InputArgList> Args(
+ OptParser->ParseArgs(ArgVector.begin() + 1, ArgVector.end(),
+ MissingArgIndex, MissingArgCount));
- for (llvm::opt::ArgList::const_iterator it = Args->begin(),
- ie = Args->end();
- it != ie; ++it) {
- const llvm::opt::Arg *A = *it;
- if (A->getOption().getKind() == llvm::opt::Option::InputClass)
- Inputs.push_back(A->getValue());
+ // Check for missing argument error.
+ if (MissingArgCount) {
+ DiagEngine.Report(clang::diag::err_drv_missing_argument)
+ << Args->getArgString(MissingArgIndex) << MissingArgCount;
+ }
+
+ // Issue errors on unknown arguments.
+ for (llvm::opt::arg_iterator it = Args->filtered_begin(OPT_UNKNOWN),
+ ie = Args->filtered_end();
+ it != ie; ++it) {
+ DiagEngine.Report(clang::diag::err_drv_unknown_argument)
+ << (*it)->getAsString(*Args);
+ }
+
+ DiagOpts.IgnoreWarnings = Args->hasArg(OPT_w);
+ DiagOpts.Warnings = Args->getAllArgValues(OPT_W);
+
+ for (llvm::opt::ArgList::const_iterator it = Args->begin(), ie = Args->end();
+ it != ie; ++it) {
+ const llvm::opt::Arg *A = *it;
+ if (A->getOption().getKind() == llvm::opt::Option::InputClass)
+ Inputs.push_back(A->getValue());
+ }
+
+ Opts.mIncludePaths = Args->getAllArgValues(OPT_I);
+
+ Opts.mBitcodeOutputDir = Args->getLastArgValue(OPT_o);
+
+ if (const llvm::opt::Arg *A = Args->getLastArg(OPT_M_Group)) {
+ switch (A->getOption().getID()) {
+ case OPT_M: {
+ Opts.mEmitDependency = true;
+ Opts.mOutputType = Slang::OT_Dependency;
+ break;
}
-
- Opts.mIncludePaths = Args->getAllArgValues(OPT_I);
-
- Opts.mBitcodeOutputDir = Args->getLastArgValue(OPT_o);
-
- if (const llvm::opt::Arg *A = Args->getLastArg(OPT_M_Group)) {
- switch (A->getOption().getID()) {
- case OPT_M: {
- Opts.mEmitDependency = true;
- Opts.mOutputType = slang::Slang::OT_Dependency;
- break;
- }
- case OPT_MD: {
- Opts.mEmitDependency = true;
- Opts.mOutputType = slang::Slang::OT_Bitcode;
- break;
- }
- default: { slangAssert(false && "Invalid option in M group!"); }
- }
+ case OPT_MD: {
+ Opts.mEmitDependency = true;
+ Opts.mOutputType = Slang::OT_Bitcode;
+ break;
}
-
- if (const llvm::opt::Arg *A = Args->getLastArg(OPT_Output_Type_Group)) {
- switch (A->getOption().getID()) {
- case OPT_emit_asm: {
- Opts.mOutputType = slang::Slang::OT_Assembly;
- break;
- }
- case OPT_emit_llvm: {
- Opts.mOutputType = slang::Slang::OT_LLVMAssembly;
- break;
- }
- case OPT_emit_bc: {
- Opts.mOutputType = slang::Slang::OT_Bitcode;
- break;
- }
- case OPT_emit_nothing: {
- Opts.mOutputType = slang::Slang::OT_Nothing;
- break;
- }
- default: {
- slangAssert(false && "Invalid option in output type group!");
- }
- }
- }
-
- if (Opts.mEmitDependency &&
- ((Opts.mOutputType != slang::Slang::OT_Bitcode) &&
- (Opts.mOutputType != slang::Slang::OT_Dependency)))
- DiagEngine.Report(clang::diag::err_drv_argument_not_allowed_with)
- << Args->getLastArg(OPT_M_Group)->getAsString(*Args)
- << Args->getLastArg(OPT_Output_Type_Group)->getAsString(*Args);
-
- Opts.mAllowRSPrefix = Args->hasArg(OPT_allow_rs_prefix);
-
- Opts.mJavaReflectionPathBase =
- Args->getLastArgValue(OPT_java_reflection_path_base);
- Opts.mJavaReflectionPackageName =
- Args->getLastArgValue(OPT_java_reflection_package_name);
-
- Opts.mRSPackageName = Args->getLastArgValue(OPT_rs_package_name);
-
- llvm::StringRef BitcodeStorageValue =
- Args->getLastArgValue(OPT_bitcode_storage);
- if (BitcodeStorageValue == "ar")
- Opts.mBitcodeStorage = slang::BCST_APK_RESOURCE;
- else if (BitcodeStorageValue == "jc")
- Opts.mBitcodeStorage = slang::BCST_JAVA_CODE;
- else if (!BitcodeStorageValue.empty())
- DiagEngine.Report(clang::diag::err_drv_invalid_value)
- << OptParser->getOptionName(OPT_bitcode_storage)
- << BitcodeStorageValue;
-
- llvm::opt::Arg *lastBitwidthArg = Args->getLastArg(OPT_m32, OPT_m64);
- if (Args->hasArg(OPT_reflect_cpp)) {
- Opts.mBitcodeStorage = slang::BCST_CPP_CODE;
- // mJavaReflectionPathBase can be set for C++ reflected builds.
- // Set it to the standard mBitcodeOutputDir (via -o) by default.
- if (Opts.mJavaReflectionPathBase.empty()) {
- Opts.mJavaReflectionPathBase = Opts.mBitcodeOutputDir;
- }
-
- // Check for bitwidth arguments.
- if (lastBitwidthArg) {
- if (lastBitwidthArg->getOption().matches(OPT_m32)) {
- Opts.mBitWidth = 32;
- } else {
- Opts.mBitWidth = 64;
- }
- }
- } else if (lastBitwidthArg) {
- // -m32/-m64 are forbidden for non-C++ reflection paths.
- DiagEngine.Report(DiagEngine.getCustomDiagID(
- clang::DiagnosticsEngine::Error,
- "cannot use -m32/-m64 without specifying C++ reflection (-reflect-c++)"));
- }
-
- Opts.mDependencyOutputDir =
- Args->getLastArgValue(OPT_output_dep_dir, Opts.mBitcodeOutputDir);
- Opts.mAdditionalDepTargets =
- Args->getAllArgValues(OPT_additional_dep_target);
-
- Opts.mShowHelp = Args->hasArg(OPT_help);
- Opts.mShowVersion = Args->hasArg(OPT_version);
- Opts.mDebugEmission = Args->hasArg(OPT_emit_g);
- Opts.mVerbose = Args->hasArg(OPT_verbose);
-
- // If we are emitting both 32-bit and 64-bit bitcode, we must embed it.
-
- size_t OptLevel =
- clang::getLastArgIntValue(*Args, OPT_optimization_level, 3, DiagEngine);
-
- Opts.mOptimizationLevel =
- OptLevel == 0 ? llvm::CodeGenOpt::None : llvm::CodeGenOpt::Aggressive;
-
- Opts.mTargetAPI = clang::getLastArgIntValue(*Args, OPT_target_api,
- RS_VERSION, DiagEngine);
-
- if (Opts.mTargetAPI == 0) {
- Opts.mTargetAPI = UINT_MAX;
- }
-
- Opts.mEmit3264 = (Opts.mTargetAPI >= 21) && (Opts.mBitcodeStorage != slang::BCST_CPP_CODE);
- if (Opts.mEmit3264) {
- Opts.mBitcodeStorage = slang::BCST_JAVA_CODE;
+ default: { slangAssert(false && "Invalid option in M group!"); }
}
}
+
+ if (const llvm::opt::Arg *A = Args->getLastArg(OPT_Output_Type_Group)) {
+ switch (A->getOption().getID()) {
+ case OPT_emit_asm: {
+ Opts.mOutputType = Slang::OT_Assembly;
+ break;
+ }
+ case OPT_emit_llvm: {
+ Opts.mOutputType = Slang::OT_LLVMAssembly;
+ break;
+ }
+ case OPT_emit_bc: {
+ Opts.mOutputType = Slang::OT_Bitcode;
+ break;
+ }
+ case OPT_emit_nothing: {
+ Opts.mOutputType = Slang::OT_Nothing;
+ break;
+ }
+ default: { slangAssert(false && "Invalid option in output type group!"); }
+ }
+ }
+
+ if (Opts.mEmitDependency && ((Opts.mOutputType != Slang::OT_Bitcode) &&
+ (Opts.mOutputType != Slang::OT_Dependency)))
+ DiagEngine.Report(clang::diag::err_drv_argument_not_allowed_with)
+ << Args->getLastArg(OPT_M_Group)->getAsString(*Args)
+ << Args->getLastArg(OPT_Output_Type_Group)->getAsString(*Args);
+
+ Opts.mAllowRSPrefix = Args->hasArg(OPT_allow_rs_prefix);
+
+ Opts.mJavaReflectionPathBase =
+ Args->getLastArgValue(OPT_java_reflection_path_base);
+ Opts.mJavaReflectionPackageName =
+ Args->getLastArgValue(OPT_java_reflection_package_name);
+
+ Opts.mRSPackageName = Args->getLastArgValue(OPT_rs_package_name);
+
+ llvm::StringRef BitcodeStorageValue =
+ Args->getLastArgValue(OPT_bitcode_storage);
+ if (BitcodeStorageValue == "ar")
+ Opts.mBitcodeStorage = BCST_APK_RESOURCE;
+ else if (BitcodeStorageValue == "jc")
+ Opts.mBitcodeStorage = BCST_JAVA_CODE;
+ else if (!BitcodeStorageValue.empty())
+ DiagEngine.Report(clang::diag::err_drv_invalid_value)
+ << OptParser->getOptionName(OPT_bitcode_storage) << BitcodeStorageValue;
+
+ llvm::opt::Arg *lastBitwidthArg = Args->getLastArg(OPT_m32, OPT_m64);
+ if (Args->hasArg(OPT_reflect_cpp)) {
+ Opts.mBitcodeStorage = BCST_CPP_CODE;
+ // mJavaReflectionPathBase can be set for C++ reflected builds.
+ // Set it to the standard mBitcodeOutputDir (via -o) by default.
+ if (Opts.mJavaReflectionPathBase.empty()) {
+ Opts.mJavaReflectionPathBase = Opts.mBitcodeOutputDir;
+ }
+
+ // Check for bitwidth arguments.
+ if (lastBitwidthArg) {
+ if (lastBitwidthArg->getOption().matches(OPT_m32)) {
+ Opts.mBitWidth = 32;
+ } else {
+ Opts.mBitWidth = 64;
+ }
+ }
+ } else if (lastBitwidthArg) {
+ // -m32/-m64 are forbidden for non-C++ reflection paths.
+ DiagEngine.Report(
+ DiagEngine.getCustomDiagID(clang::DiagnosticsEngine::Error,
+ "cannot use -m32/-m64 without specifying "
+ "C++ reflection (-reflect-c++)"));
+ }
+
+ Opts.mDependencyOutputDir =
+ Args->getLastArgValue(OPT_output_dep_dir, Opts.mBitcodeOutputDir);
+ Opts.mAdditionalDepTargets = Args->getAllArgValues(OPT_additional_dep_target);
+
+ Opts.mShowHelp = Args->hasArg(OPT_help);
+ Opts.mShowVersion = Args->hasArg(OPT_version);
+ Opts.mDebugEmission = Args->hasArg(OPT_emit_g);
+ Opts.mVerbose = Args->hasArg(OPT_verbose);
+
+ // If we are emitting both 32-bit and 64-bit bitcode, we must embed it.
+
+ size_t OptLevel =
+ clang::getLastArgIntValue(*Args, OPT_optimization_level, 3, DiagEngine);
+
+ Opts.mOptimizationLevel =
+ OptLevel == 0 ? llvm::CodeGenOpt::None : llvm::CodeGenOpt::Aggressive;
+
+ Opts.mTargetAPI =
+ clang::getLastArgIntValue(*Args, OPT_target_api, RS_VERSION, DiagEngine);
+
+ if (Opts.mTargetAPI == 0) {
+ Opts.mTargetAPI = UINT_MAX;
+ }
+
+ Opts.mEmit3264 =
+ (Opts.mTargetAPI >= 21) && (Opts.mBitcodeStorage != BCST_CPP_CODE);
+ if (Opts.mEmit3264) {
+ Opts.mBitcodeStorage = BCST_JAVA_CODE;
+ }
+
+ if (DiagEngine.hasErrorOccurred()) {
+ llvm::errs() << DiagsBuffer.str();
+ return false;
+ }
+
+ return true;
+}
}
diff --git a/rs_cc_options.h b/rs_cc_options.h
index 8bdd7bc..e45dae0 100644
--- a/rs_cc_options.h
+++ b/rs_cc_options.h
@@ -28,6 +28,9 @@
#include <vector>
namespace llvm {
+namespace cl {
+class StringSaver;
+}
namespace opt {
class OptTable;
}
@@ -125,10 +128,12 @@
* \param Opts - returned options after command line has been processed
* \param DiagEngine - input for issuing warnings/errors on arguments
*/
-void ParseArguments(llvm::SmallVectorImpl<const char *> &ArgVector,
- llvm::SmallVectorImpl<const char *> &Inputs,
- RSCCOptions &Opts, clang::DiagnosticsEngine &DiagEngine);
-} // namespace slang
+bool ParseArguments(const llvm::ArrayRef<const char *> &ArgsIn,
+ llvm::SmallVectorImpl<const char *> &Inputs,
+ RSCCOptions &Opts, clang::DiagnosticOptions &DiagOpts,
+ llvm::cl::StringSaver &StringSaver);
+
+} // namespace slang
#endif // _FRAMEWORKS_COMPILE_SLANG_RS_CC_OPTIONS_H_
diff --git a/slang.cpp b/slang.cpp
index f372250..3431eb0 100644
--- a/slang.cpp
+++ b/slang.cpp
@@ -32,13 +32,11 @@
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/FileSystemOptions.h"
-#include "clang/Basic/LangOptions.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TargetOptions.h"
-#include "clang/Frontend/CodeGenOptions.h"
#include "clang/Frontend/DependencyOutputOptions.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/FrontendOptions.h"
@@ -78,7 +76,6 @@
#include "slang_assert.h"
#include "slang_backend.h"
-#include "slang_backend.h"
#include "slang_rs_context.h"
#include "slang_rs_export_type.h"
@@ -121,14 +118,6 @@
RS_HEADER_ENTRY(rs_vector_math) \
-bool Slang::GlobalInitialized = false;
-
-// Language option (define the language feature for compiler such as C99)
-clang::LangOptions Slang::LangOpts;
-
-// Code generation option for the compiler
-clang::CodeGenOptions Slang::CodeGenOpts;
-
// The named of metadata node that pragma resides (should be synced with
// bcc.cpp)
const llvm::StringRef Slang::PragmaMetadataName = "#pragma";
@@ -157,36 +146,6 @@
return nullptr;
}
-void Slang::GlobalInitialization() {
- if (!GlobalInitialized) {
-
- LLVMInitializeARMTargetInfo();
- LLVMInitializeARMTarget();
- LLVMInitializeARMAsmPrinter();
-
- // Please refer to include/clang/Basic/LangOptions.h to setup
- // the options.
- LangOpts.RTTI = 0; // Turn off the RTTI information support
- LangOpts.C99 = 1;
- LangOpts.Renderscript = 1;
- LangOpts.LaxVectorConversions = 0; // Do not bitcast vectors!
- LangOpts.CharIsSigned = 1; // Signed char is our default.
-
- CodeGenOpts.OptimizationLevel = 3;
-
- GlobalInitialized = true;
- }
-}
-
-void Slang::LLVMErrorHandler(void *UserData, const std::string &Message,
- bool GenCrashDialog) {
- clang::DiagnosticsEngine* DiagEngine =
- static_cast<clang::DiagnosticsEngine *>(UserData);
-
- DiagEngine->Report(clang::diag::err_fe_error_backend) << Message;
- exit(1);
-}
-
void Slang::createTarget(uint32_t BitWidth) {
std::vector<std::string> features;
@@ -268,18 +227,32 @@
clang::ASTConsumer *
Slang::createBackend(const clang::CodeGenOptions &CodeGenOpts,
- llvm::raw_ostream *OS, Slang::OutputType OT) {
+ llvm::raw_ostream *OS, OutputType OT) {
return new Backend(mRSContext, &getDiagnostics(), CodeGenOpts,
getTargetOptions(), &mPragmas, OS, OT, getSourceManager(),
mAllowRSPrefix, mIsFilterscript);
}
-Slang::Slang()
- : mInitialized(false), mDiagClient(nullptr),
+Slang::Slang(uint32_t BitWidth, clang::DiagnosticsEngine *DiagEngine,
+ DiagnosticBuffer *DiagClient)
+ : mDiagEngine(DiagEngine), mDiagClient(DiagClient),
mTargetOpts(new clang::TargetOptions()), mOT(OT_Default),
mRSContext(nullptr), mAllowRSPrefix(false), mTargetAPI(0),
mVerbose(false), mIsFilterscript(false) {
- GlobalInitialization();
+ // Please refer to include/clang/Basic/LangOptions.h to setup
+ // the options.
+ LangOpts.RTTI = 0; // Turn off the RTTI information support
+ LangOpts.LineComment = 1;
+ LangOpts.C99 = 1;
+ LangOpts.Renderscript = 1;
+ LangOpts.LaxVectorConversions = 0; // Do not bitcast vectors!
+ LangOpts.CharIsSigned = 1; // Signed char is our default.
+
+ CodeGenOpts.OptimizationLevel = 3;
+
+ createTarget(BitWidth);
+ createFileManager();
+ createSourceManager();
}
Slang::~Slang() {
@@ -291,24 +264,6 @@
}
}
-void Slang::init(uint32_t BitWidth, clang::DiagnosticsEngine *DiagEngine,
- DiagnosticBuffer *DiagClient) {
- if (mInitialized)
- return;
-
- mDiagEngine = DiagEngine;
- mDiagClient = DiagClient;
- mDiag.reset(new clang::Diagnostic(mDiagEngine));
- initDiagnostic();
- llvm::install_fatal_error_handler(LLVMErrorHandler, mDiagEngine);
-
- createTarget(BitWidth);
- createFileManager();
- createSourceManager();
-
- mInitialized = true;
-}
-
clang::ModuleLoadResult Slang::loadModule(
clang::SourceLocation ImportLoc,
clang::ModuleIdPath Path,
@@ -474,30 +429,6 @@
CodeGenOpts.OptimizationLevel = OptimizationLevel;
}
-void Slang::reset(bool SuppressWarnings) {
- delete mRSContext;
- mRSContext = nullptr;
- mGeneratedFileNames.clear();
-
- // Always print diagnostics if we had an error occur, but don't print
- // warnings if we suppressed them (i.e. we are doing the 64-bit compile after
- // an existing 32-bit compile).
- //
- // TODO: This should really be removing duplicate identical warnings between
- // the 32-bit and 64-bit compiles, but that is a more substantial feature.
- // Bug: 17052573
- if (!SuppressWarnings || mDiagEngine->hasErrorOccurred()) {
- llvm::errs() << mDiagClient->str();
- }
- mDiagEngine->Reset();
- mDiagClient->reset();
-
- // remove fatal error handler. slang::init needs to be called before another
- // compilation, which will re-install the error handler.
- llvm::remove_fatal_error_handler();
-}
-
-// Returns true if \p Filename ends in ".fs".
bool Slang::isFilterscript(const char *Filename) {
const char *c = strrchr(Filename, '.');
if (c && !strncmp(FS_SUFFIX, c + 1, strlen(FS_SUFFIX) + 1)) {
@@ -513,8 +444,8 @@
RSSlangReflectUtils::BitCodeAccessorContext BCAccessorContext;
BCAccessorContext.rsFileName = getInputFileName().c_str();
- BCAccessorContext.bc32FileName = getOutput32FileName().c_str();
- BCAccessorContext.bc64FileName = getOutputFileName().c_str();
+ BCAccessorContext.bc32FileName = mOutput32FileName.c_str();
+ BCAccessorContext.bc64FileName = mOutputFileName.c_str();
BCAccessorContext.reflectPath = OutputPathBase.c_str();
BCAccessorContext.packageName = PackageName.c_str();
BCAccessorContext.licenseNote = LicenseNote;
@@ -589,9 +520,13 @@
}
if (!PassODR) {
- getDiagnostics().Report(mDiagErrorODR) << Reflected->getName()
- << getInputFileName()
- << RD->getValue().second;
+ unsigned DiagID = mDiagEngine->getCustomDiagID(
+ clang::DiagnosticsEngine::Error,
+ "type '%0' in different translation unit (%1 v.s. %2) "
+ "has incompatible type definition");
+ getDiagnostics().Report(DiagID) << Reflected->getName()
+ << getInputFileName()
+ << RD->getValue().second;
return false;
}
} else {
@@ -609,39 +544,6 @@
return true;
}
-void Slang::initDiagnostic() {
- clang::DiagnosticsEngine &DiagEngine = getDiagnostics();
- const auto Flavor = clang::diag::Flavor::WarningOrError;
-
- if (DiagEngine.setSeverityForGroup(Flavor, "implicit-function-declaration",
- clang::diag::Severity::Error)) {
- DiagEngine.Report(clang::diag::warn_unknown_diag_option)
- << /* clang::diag::Flavor::WarningOrError */ 0
- << "implicit-function-declaration";
- }
-
- DiagEngine.setSeverity(
- clang::diag::ext_typecheck_convert_discards_qualifiers,
- clang::diag::Severity::Error,
- clang::SourceLocation());
-
- mDiagErrorInvalidOutputDepParameter =
- DiagEngine.getCustomDiagID(
- clang::DiagnosticsEngine::Error,
- "invalid parameter for output dependencies files.");
-
- mDiagErrorODR =
- DiagEngine.getCustomDiagID(
- clang::DiagnosticsEngine::Error,
- "type '%0' in different translation unit (%1 v.s. %2) "
- "has incompatible type definition");
-
- mDiagErrorTargetAPIRange =
- DiagEngine.getCustomDiagID(
- clang::DiagnosticsEngine::Error,
- "target API level '%0' is out of range ('%1' - '%2')");
-}
-
void Slang::initPreprocessor() {
clang::Preprocessor &PP = getPreprocessor();
@@ -687,12 +589,16 @@
const std::list<std::pair<const char*, const char*> > &IOFiles64,
const std::list<std::pair<const char*, const char*> > &IOFiles32,
const std::list<std::pair<const char*, const char*> > &DepFiles,
- const RSCCOptions &Opts) {
+ const RSCCOptions &Opts,
+ clang::DiagnosticOptions &DiagOpts) {
if (IOFiles32.empty())
return true;
if (Opts.mEmitDependency && (DepFiles.size() != IOFiles32.size())) {
- getDiagnostics().Report(mDiagErrorInvalidOutputDepParameter);
+ unsigned DiagID = mDiagEngine->getCustomDiagID(
+ clang::DiagnosticsEngine::Error,
+ "invalid parameter for output dependencies files.");
+ getDiagnostics().Report(DiagID);
return false;
}
@@ -705,10 +611,6 @@
const char *InputFile, *Output64File, *Output32File, *BCOutputFile,
*DepOutputFile;
- std::list<std::pair<const char*, const char*> >::const_iterator
- IOFile64Iter = IOFiles64.begin(),
- IOFile32Iter = IOFiles32.begin(),
- DepFileIter = DepFiles.begin();
setIncludePaths(Opts.mIncludePaths);
setOutputType(Opts.mOutputType);
@@ -726,8 +628,11 @@
if (mTargetAPI != SLANG_DEVELOPMENT_TARGET_API &&
(mTargetAPI < SLANG_MINIMUM_TARGET_API ||
mTargetAPI > SLANG_MAXIMUM_TARGET_API)) {
- getDiagnostics().Report(mDiagErrorTargetAPIRange) << mTargetAPI
- << SLANG_MINIMUM_TARGET_API << SLANG_MAXIMUM_TARGET_API;
+ unsigned DiagID = mDiagEngine->getCustomDiagID(
+ clang::DiagnosticsEngine::Error,
+ "target API level '%0' is out of range ('%1' - '%2')");
+ getDiagnostics().Report(DiagID) << mTargetAPI << SLANG_MINIMUM_TARGET_API
+ << SLANG_MAXIMUM_TARGET_API;
return false;
}
@@ -737,23 +642,25 @@
// a single pass over the input file.
bool SuppressAllWarnings = (Opts.mOutputType != Slang::OT_Dependency);
- bool CompileSecondTimeFor64Bit = Opts.mEmit3264 && Opts.mBitWidth == 64;
+ std::list<std::pair<const char*, const char*> >::const_iterator
+ IOFile64Iter = IOFiles64.begin(),
+ IOFile32Iter = IOFiles32.begin(),
+ DepFileIter = DepFiles.begin();
for (unsigned i = 0, e = IOFiles32.size(); i != e; i++) {
InputFile = IOFile64Iter->first;
Output64File = IOFile64Iter->second;
Output32File = IOFile32Iter->second;
- // We suppress warnings (via reset) if we are doing a second compilation.
- reset(CompileSecondTimeFor64Bit);
-
if (!setInputSource(InputFile))
return false;
if (!setOutput(Output64File))
return false;
- setOutput32(Output32File);
+ // For use with 64-bit compilation/reflection. This only sets the filename of
+ // the 32-bit bitcode file, and doesn't actually verify it already exists.
+ mOutput32FileName = Output32File;
mIsFilterscript = isFilterscript(InputFile);
@@ -776,7 +683,7 @@
if (Opts.mBitcodeStorage == BCST_CPP_CODE) {
const std::string &outputFileName = (Opts.mBitWidth == 64) ?
- getOutputFileName() : getOutput32FileName();
+ mOutputFileName : mOutput32FileName;
RSReflectionCpp R(mRSContext, Opts.mJavaReflectionPathBase,
getInputFileName(), outputFileName);
if (!R.reflect()) {
@@ -790,7 +697,7 @@
std::vector<std::string> generatedFileNames;
RSReflectionJava R(mRSContext, &generatedFileNames,
Opts.mJavaReflectionPathBase, getInputFileName(),
- getOutputFileName(),
+ mOutputFileName,
Opts.mBitcodeStorage == BCST_JAVA_CODE);
if (!R.reflect()) {
// TODO Is this needed or will the error message have been printed
@@ -848,7 +755,6 @@
IOFile64Iter++;
IOFile32Iter++;
}
-
return true;
}
diff --git a/slang.h b/slang.h
index 2b40adb..c220beb 100644
--- a/slang.h
+++ b/slang.h
@@ -32,7 +32,9 @@
#include "llvm/ADT/IntrusiveRefCntPtr.h"
using llvm::RefCountedBase;
+#include "clang/Basic/LangOptions.h"
#include "clang/Basic/TargetOptions.h"
+#include "clang/Frontend/CodeGenOptions.h"
#include "clang/Lex/ModuleLoader.h"
#include "llvm/ADT/StringRef.h"
@@ -81,22 +83,14 @@
};
private:
- static clang::LangOptions LangOpts;
- static clang::CodeGenOptions CodeGenOpts;
-
- static bool GlobalInitialized;
-
- static void LLVMErrorHandler(void *UserData, const std::string &Message,
- bool GenCrashDialog);
+ // Language options (define the language feature for compiler such as C99)
+ clang::LangOptions LangOpts;
+ // Code generation options for the compiler
+ clang::CodeGenOptions CodeGenOpts;
// Returns true if this is a Filterscript file.
static bool isFilterscript(const char *Filename);
- bool mInitialized;
-
- // Diagnostics Mediator (An interface for both Producer and Consumer)
- std::unique_ptr<clang::Diagnostic> mDiag;
-
// Diagnostics Engine (Producer and Diagnostics Reporter)
clang::DiagnosticsEngine *mDiagEngine;
@@ -159,11 +153,6 @@
bool mIsFilterscript;
- // Custom diagnostic identifiers
- unsigned mDiagErrorInvalidOutputDepParameter;
- unsigned mDiagErrorODR;
- unsigned mDiagErrorTargetAPIRange;
-
// Collect generated filenames (without the .java) for dependency generation
std::vector<std::string> mGeneratedFileNames;
@@ -197,13 +186,12 @@
inline clang::TargetOptions const &getTargetOptions() const
{ return *mTargetOpts.get(); }
- void initDiagnostic();
void initPreprocessor();
void initASTContext();
clang::ASTConsumer *createBackend(const clang::CodeGenOptions &CodeGenOpts,
llvm::raw_ostream *OS,
- Slang::OutputType OT);
+ OutputType OT);
public:
static const llvm::StringRef PragmaMetadataName;
@@ -217,11 +205,10 @@
static bool IsLocInRSHeaderFile(const clang::SourceLocation &Loc,
const clang::SourceManager &SourceMgr);
- Slang();
- virtual ~Slang();
+ Slang(uint32_t BitWidth, clang::DiagnosticsEngine *DiagEngine,
+ DiagnosticBuffer *DiagClient);
- void init(uint32_t BitWidth, clang::DiagnosticsEngine *DiagEngine,
- DiagnosticBuffer *DiagClient);
+ virtual ~Slang();
bool setInputSource(llvm::StringRef InputFile);
@@ -235,20 +222,6 @@
bool setOutput(const char *OutputFile);
- // For use with 64-bit compilation/reflection. This only sets the filename of
- // the 32-bit bitcode file, and doesn't actually verify it already exists.
- void setOutput32(const char *OutputFile) {
- mOutput32FileName = OutputFile;
- }
-
- std::string const &getOutputFileName() const {
- return mOutputFileName;
- }
-
- std::string const &getOutput32FileName() const {
- return mOutput32FileName;
- }
-
bool setDepOutput(const char *OutputFile);
void setDepTargetBC(const char *TargetBCFile) {
@@ -274,10 +247,6 @@
void setOptimizationLevel(llvm::CodeGenOpt::Level OptimizationLevel);
- // Reset the slang compiler state such that it can be reused to compile
- // another file
- void reset(bool SuppressWarnings = false);
-
// Compile bunch of RS files given in the llvm-rs-cc arguments. Return true if
// all given input files are successfully compiled without errors.
//
@@ -292,7 +261,8 @@
compile(const std::list<std::pair<const char *, const char *>> &IOFiles64,
const std::list<std::pair<const char *, const char *>> &IOFiles32,
const std::list<std::pair<const char *, const char *>> &DepFiles,
- const RSCCOptions &Opts);
+ const RSCCOptions &Opts,
+ clang::DiagnosticOptions &DiagOpts);
clang::ModuleLoadResult loadModule(clang::SourceLocation ImportLoc,
clang::ModuleIdPath Path,
diff --git a/slang_diagnostic_buffer.cpp b/slang_diagnostic_buffer.cpp
index 5b7adaf..d6afabf 100644
--- a/slang_diagnostic_buffer.cpp
+++ b/slang_diagnostic_buffer.cpp
@@ -29,12 +29,6 @@
: mSOS(new llvm::raw_string_ostream(mDiags)) {
}
-DiagnosticBuffer::DiagnosticBuffer(DiagnosticBuffer const &src)
- : clang::DiagnosticConsumer(src),
- mDiags(src.mDiags),
- mSOS(new llvm::raw_string_ostream(mDiags)) {
-}
-
DiagnosticBuffer::~DiagnosticBuffer() {
}
@@ -43,43 +37,45 @@
clang::Diagnostic const &Info) {
clang::SourceLocation const &SrcLoc = Info.getLocation();
- // 100 is enough for storing general diagnosis message
- llvm::SmallString<100> Buf;
+ std::string Message;
+ llvm::raw_string_ostream stream(Message);
if (SrcLoc.isValid()) {
- SrcLoc.print(*mSOS, Info.getSourceManager());
- (*mSOS) << ": ";
+ SrcLoc.print(stream, Info.getSourceManager());
+ stream << ": ";
}
switch (DiagLevel) {
case clang::DiagnosticsEngine::Note: {
- (*mSOS) << "note: ";
+ stream << "note: ";
break;
}
case clang::DiagnosticsEngine::Warning: {
- (*mSOS) << "warning: ";
+ stream << "warning: ";
break;
}
case clang::DiagnosticsEngine::Error: {
- (*mSOS) << "error: ";
+ stream << "error: ";
break;
}
case clang::DiagnosticsEngine::Fatal: {
- (*mSOS) << "fatal: ";
+ stream << "fatal: ";
break;
}
default: {
slangAssert(0 && "Diagnostic not handled during diagnostic buffering!");
}
}
-
+ // 100 is enough for storing general diagnosis Message
+ llvm::SmallString<100> Buf;
Info.FormatDiagnostic(Buf);
- (*mSOS) << Buf.str() << '\n';
-}
+ stream << Buf.str() << '\n';
+ stream.flush();
-clang::DiagnosticConsumer *
-DiagnosticBuffer::clone(clang::DiagnosticsEngine &Diags) const {
- return new DiagnosticBuffer(*this);
+ if (mIncludedMessages.find(Message) == mIncludedMessages.end()) {
+ mIncludedMessages.insert(Message);
+ (*mSOS) << Message;
+ }
}
} // namespace slang
diff --git a/slang_diagnostic_buffer.h b/slang_diagnostic_buffer.h
index 56fa0a0..500f345 100644
--- a/slang_diagnostic_buffer.h
+++ b/slang_diagnostic_buffer.h
@@ -17,6 +17,7 @@
#ifndef _FRAMEWORKS_COMPILE_SLANG_SLANG_DIAGNOSTIC_BUFFER_H_ // NOLINT
#define _FRAMEWORKS_COMPILE_SLANG_SLANG_DIAGNOSTIC_BUFFER_H_
+#include <set>
#include <string>
#include "clang/Basic/Diagnostic.h"
@@ -31,22 +32,20 @@
// The diagnostics consumer instance (for reading the processed diagnostics)
class DiagnosticBuffer : public clang::DiagnosticConsumer {
- private:
+private:
+ // We keed track of the messages that have been already added to this
+ // diagnostic buffer, to avoid duplicates. This can happen because for a
+ // given script we'll usually compile for both 32 and 64 bit targets.
+ std::set<std::string> mIncludedMessages;
std::string mDiags;
std::unique_ptr<llvm::raw_string_ostream> mSOS;
- public:
+public:
DiagnosticBuffer();
-
- explicit DiagnosticBuffer(DiagnosticBuffer const &src);
-
virtual ~DiagnosticBuffer();
virtual void HandleDiagnostic(clang::DiagnosticsEngine::Level DiagLevel,
- const clang::Diagnostic& Info);
-
- virtual clang::DiagnosticConsumer *
- clone(clang::DiagnosticsEngine &Diags) const;
+ const clang::Diagnostic &Info) override;
inline const std::string &str() const {
mSOS->flush();
@@ -54,7 +53,9 @@
}
inline void reset() {
- this->mSOS->str().clear();
+ mIncludedMessages.clear();
+ mSOS.reset();
+ mDiags.clear();
}
};
diff --git a/tests/F_unknown_function/stderr.txt.expect b/tests/F_unknown_function/stderr.txt.expect
new file mode 100644
index 0000000..c8329e3
--- /dev/null
+++ b/tests/F_unknown_function/stderr.txt.expect
@@ -0,0 +1 @@
+unknown_function.rs:6:5: error: implicit declaration of function 'bar' is invalid in C99
diff --git a/tests/P_unknown_function/stdout.txt.expect b/tests/F_unknown_function/stdout.txt.expect
similarity index 100%
rename from tests/P_unknown_function/stdout.txt.expect
rename to tests/F_unknown_function/stdout.txt.expect
diff --git a/tests/P_unknown_function/unknown_function.rs b/tests/F_unknown_function/unknown_function.rs
similarity index 100%
rename from tests/P_unknown_function/unknown_function.rs
rename to tests/F_unknown_function/unknown_function.rs
diff --git a/tests/P_unknown_function/zzz.rs b/tests/F_unknown_function/zzz.rs
similarity index 100%
rename from tests/P_unknown_function/zzz.rs
rename to tests/F_unknown_function/zzz.rs
diff --git a/tests/P_unknown_function/stderr.txt.expect b/tests/P_unknown_function/stderr.txt.expect
deleted file mode 100644
index 901cd3b..0000000
--- a/tests/P_unknown_function/stderr.txt.expect
+++ /dev/null
@@ -1 +0,0 @@
-unknown_function.rs:6:5: warning: implicit declaration of function 'bar' is invalid in C99
diff --git a/tests/P_warnings/stderr.txt.expect b/tests/P_warnings/stderr.txt.expect
index 7e049dc..00d6d40 100644
--- a/tests/P_warnings/stderr.txt.expect
+++ b/tests/P_warnings/stderr.txt.expect
@@ -1 +1,7 @@
-warnings.rs:5:1: warning: control reaches end of non-void function
+warnings.rs:6:1: warning: control reaches end of non-void function
+warnings.rs:9:7: warning: unused variable 'k'
+warnings.rs:11:7: warning: unused variable 'j'
+warnings.rs:11:11: warning: variable 'l' is uninitialized when used here
+warnings.rs:10:8: note: initialize the variable 'l' to silence this warning
+warnings.rs:5:12: warning: unused function 'foo'
+warnings.rs:8:13: warning: unused function 'bar'
diff --git a/tests/P_warnings/warnings.rs b/tests/P_warnings/warnings.rs
index 01b3cd0..f419d9c 100644
--- a/tests/P_warnings/warnings.rs
+++ b/tests/P_warnings/warnings.rs
@@ -1,6 +1,12 @@
+// -Wall
#pragma version(1)
#pragma rs java_package_name(foo)
static int foo() {
}
+static void bar() {
+ int k;
+ int l;
+ int j = l + 1;
+}
diff --git a/tests/P_warnings_deprecated/deprecated.rs b/tests/P_warnings_deprecated/deprecated.rs
new file mode 100644
index 0000000..4e5f5af
--- /dev/null
+++ b/tests/P_warnings_deprecated/deprecated.rs
@@ -0,0 +1,11 @@
+// -target-api 22
+#pragma version(1)
+#pragma rs java_package_name(foo)
+
+char out;
+rs_allocation al;
+
+void foo(char in) {
+ out = rsClamp(in, (char) 1, (char) 4);
+ al = rsGetAllocation((void*) 33);
+}
diff --git a/tests/P_warnings_deprecated/stderr.txt.expect b/tests/P_warnings_deprecated/stderr.txt.expect
new file mode 100644
index 0000000..32f00d6
--- /dev/null
+++ b/tests/P_warnings_deprecated/stderr.txt.expect
@@ -0,0 +1,4 @@
+deprecated.rs:9:9: warning: 'rsClamp' is deprecated: Use clamp() instead.
+../../../../../frameworks/rs/scriptc/rs_math.rsh:4091:5: note: 'rsClamp' has been explicitly marked deprecated here
+deprecated.rs:10:8: warning: 'rsGetAllocation' is deprecated: This function is deprecated and will be removed from the SDK in a future release.
+../../../../../frameworks/rs/scriptc/rs_object_info.rsh:381:5: note: 'rsGetAllocation' has been explicitly marked deprecated here
diff --git a/tests/P_unknown_function/stdout.txt.expect b/tests/P_warnings_deprecated/stdout.txt.expect
similarity index 100%
copy from tests/P_unknown_function/stdout.txt.expect
copy to tests/P_warnings_deprecated/stdout.txt.expect