* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include <sys/types.h>
#include "printf_check.h"
#include "clang/AST/AST.h"
#include "clang/AST/Expr.h"
#include <vector>
#include <sstream>
#include <ctype.h>
+#include <signal.h>
+#include <assert.h>
+#include <cstdint>
using namespace clang;
struct PrintfArgChecker *ctx);
static bool long_double_arg_handler (const Expr *arg,
struct PrintfArgChecker *ctx);
+ static bool pointer_arg_handler (const Expr *arg,
+ struct PrintfArgChecker *ctx);
+ static bool pid_arg_handler (const Expr *arg,
+ struct PrintfArgChecker *ctx);
+ static bool int64_arg_handler (const Expr *arg,
+ struct PrintfArgChecker *ctx);
using arg_parser_t = bool (*) (const Expr *, struct PrintfArgChecker *);
case 'c':
return llvm::make_unique<PrintfArgChecker> (char_arg_handler,
this->pcontext);
+ case 'p':
+ return llvm::make_unique<PrintfArgChecker> (pointer_arg_handler,
+ this->pcontext);
+ case 'P':
+ return llvm::make_unique<PrintfArgChecker> (pid_arg_handler,
+ this->pcontext);
+ case 'L':
+ return llvm::make_unique<PrintfArgChecker> (int64_arg_handler,
+ this->pcontext);
default:
llvm::errs () << "unknown parser flag: " << type << "\n";
break;
BuiltinType::Kind::Int},
"%z");
}
+ else {
+ assert (0);
+ }
return true;
}
{BuiltinType::Kind::LongDouble},
"%F or %G");
}
+ static bool
+ pid_arg_handler (const Expr *arg, struct PrintfArgChecker *ctx)
+ {
+ if (sizeof (pid_t) == sizeof (long)) {
+ return check_builtin_type (arg,
+ ctx,
+ {BuiltinType::Kind::ULong,
+ BuiltinType::Kind::Long},
+ "%P");
+ }
+ else if (sizeof (pid_t) == sizeof (int)) {
+ return check_builtin_type (arg,
+ ctx,
+ {BuiltinType::Kind::UInt,
+ BuiltinType::Kind::Int},
+ "%P");
+ }
+ else {
+ assert (0);
+ }
+ }
+
+ static bool
+ pointer_arg_handler (const Expr *arg, struct PrintfArgChecker *ctx)
+ {
+ auto type = arg->getType ().split ().Ty;
+
+ if (!type->isPointerType ()) {
+ print_error (
+ std::string ("bad pointer argument for %p: ") +
+ arg->getType ().getAsString (), arg, ctx->past);
+ return false;
+ }
+
+ return true;
+ }
+
+ static bool
+ int64_arg_handler (const Expr *arg, struct PrintfArgChecker *ctx)
+ {
+ if (sizeof (int64_t) == sizeof (long long)) {
+ return check_builtin_type (arg,
+ ctx,
+ {BuiltinType::Kind::ULongLong,
+ BuiltinType::Kind::LongLong},
+ "%L");
+ }
+ else if (sizeof (int64_t) == sizeof (long)) {
+ return check_builtin_type (arg,
+ ctx,
+ {BuiltinType::Kind::ULong,
+ BuiltinType::Kind::Long},
+ "%z");
+ }
+ else {
+ assert (0);
+ }
+
+ return true;
+ }
};