summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorMehdi Amini <mehdi.amini@apple.com>2016-10-24 19:41:36 +0000
committerMehdi Amini <mehdi.amini@apple.com>2016-10-24 19:41:36 +0000
commit9c39fdcedae36a5ea7079459da953c929a3edb57 (patch)
treeafd5d609c3925ef76d76646760bd4a45ef4fad39 /clang/lib
parent6733564e5aff326bffb858fb0b2358905b792f24 (diff)
downloadbcm5719-llvm-9c39fdcedae36a5ea7079459da953c929a3edb57.tar.gz
bcm5719-llvm-9c39fdcedae36a5ea7079459da953c929a3edb57.zip
Revert "Add support for __builtin_os_log_format[_buffer_size]"
This reverts commit r284990, two opencl test are broken llvm-svn: 285007
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Analysis/CMakeLists.txt1
-rw-r--r--clang/lib/Analysis/FormatString.cpp3
-rw-r--r--clang/lib/Analysis/OSLog.cpp177
-rw-r--r--clang/lib/Analysis/PrintfFormatString.cpp43
-rw-r--r--clang/lib/CodeGen/CGBuiltin.cpp85
-rw-r--r--clang/lib/Sema/SemaChecking.cpp285
-rw-r--r--clang/lib/Sema/SemaDeclAttr.cpp29
7 files changed, 77 insertions, 546 deletions
diff --git a/clang/lib/Analysis/CMakeLists.txt b/clang/lib/Analysis/CMakeLists.txt
index fdc9e6cee8e..6c74c797d9b 100644
--- a/clang/lib/Analysis/CMakeLists.txt
+++ b/clang/lib/Analysis/CMakeLists.txt
@@ -16,7 +16,6 @@ add_clang_library(clangAnalysis
Dominators.cpp
FormatString.cpp
LiveVariables.cpp
- OSLog.cpp
ObjCNoReturn.cpp
PostOrderCFGView.cpp
PrintfFormatString.cpp
diff --git a/clang/lib/Analysis/FormatString.cpp b/clang/lib/Analysis/FormatString.cpp
index c62e537e92d..2a518cac394 100644
--- a/clang/lib/Analysis/FormatString.cpp
+++ b/clang/lib/Analysis/FormatString.cpp
@@ -591,8 +591,6 @@ const char *ConversionSpecifier::toString() const {
case cArg: return "c";
case sArg: return "s";
case pArg: return "p";
- case PArg:
- return "P";
case nArg: return "n";
case PercentArg: return "%";
case ScanListArg: return "[";
@@ -868,7 +866,6 @@ bool FormatSpecifier::hasStandardConversionSpecifier(
case ConversionSpecifier::ObjCObjArg:
case ConversionSpecifier::ScanListArg:
case ConversionSpecifier::PercentArg:
- case ConversionSpecifier::PArg:
return true;
case ConversionSpecifier::CArg:
case ConversionSpecifier::SArg:
diff --git a/clang/lib/Analysis/OSLog.cpp b/clang/lib/Analysis/OSLog.cpp
deleted file mode 100644
index b57e0d1d13f..00000000000
--- a/clang/lib/Analysis/OSLog.cpp
+++ /dev/null
@@ -1,177 +0,0 @@
-// TODO: header template
-
-#include "clang/Analysis/Analyses/OSLog.h"
-#include "clang/AST/Attr.h"
-#include "clang/AST/Decl.h"
-#include "clang/AST/DeclCXX.h"
-#include "clang/AST/ExprObjC.h"
-#include "clang/Analysis/Analyses/FormatString.h"
-#include "clang/Basic/Builtins.h"
-#include "llvm/ADT/SmallBitVector.h"
-
-using namespace clang;
-using llvm::APInt;
-
-using clang::analyze_os_log::OSLogBufferItem;
-using clang::analyze_os_log::OSLogBufferLayout;
-
-class OSLogFormatStringHandler
- : public analyze_format_string::FormatStringHandler {
-private:
- struct ArgData {
- const Expr *E = nullptr;
- Optional<OSLogBufferItem::Kind> Kind;
- Optional<unsigned> Size;
- unsigned char Flags = 0;
- };
- SmallVector<ArgData, 4> ArgsData;
- ArrayRef<const Expr *> Args;
-
- OSLogBufferItem::Kind
- getKind(analyze_format_string::ConversionSpecifier::Kind K) {
- switch (K) {
- case clang::analyze_format_string::ConversionSpecifier::sArg: // "%s"
- return OSLogBufferItem::StringKind;
- case clang::analyze_format_string::ConversionSpecifier::SArg: // "%S"
- return OSLogBufferItem::WideStringKind;
- case clang::analyze_format_string::ConversionSpecifier::PArg: { // "%P"
- return OSLogBufferItem::PointerKind;
- case clang::analyze_format_string::ConversionSpecifier::ObjCObjArg: // "%@"
- return OSLogBufferItem::ObjCObjKind;
- case clang::analyze_format_string::ConversionSpecifier::PrintErrno: // "%m"
- return OSLogBufferItem::ErrnoKind;
- default:
- return OSLogBufferItem::ScalarKind;
- }
- }
- }
-
-public:
- OSLogFormatStringHandler(ArrayRef<const Expr *> Args) : Args(Args) {
- ArgsData.reserve(Args.size());
- }
-
- virtual bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS,
- const char *StartSpecifier,
- unsigned SpecifierLen) {
- if (!FS.consumesDataArgument() &&
- FS.getConversionSpecifier().getKind() !=
- clang::analyze_format_string::ConversionSpecifier::PrintErrno)
- return false;
-
- ArgsData.emplace_back();
- unsigned ArgIndex = FS.getArgIndex();
- if (ArgIndex < Args.size())
- ArgsData.back().E = Args[ArgIndex];
-
- // First get the Kind
- ArgsData.back().Kind = getKind(FS.getConversionSpecifier().getKind());
- if (ArgsData.back().Kind != OSLogBufferItem::ErrnoKind &&
- !ArgsData.back().E) {
- // missing argument
- ArgsData.pop_back();
- return false;
- }
-
- switch (FS.getConversionSpecifier().getKind()) {
- case clang::analyze_format_string::ConversionSpecifier::sArg: // "%s"
- case clang::analyze_format_string::ConversionSpecifier::SArg: { // "%S"
- auto &precision = FS.getPrecision();
- switch (precision.getHowSpecified()) {
- case clang::analyze_format_string::OptionalAmount::NotSpecified: // "%s"
- break;
- case clang::analyze_format_string::OptionalAmount::Constant: // "%.16s"
- ArgsData.back().Size = precision.getConstantAmount();
- break;
- case clang::analyze_format_string::OptionalAmount::Arg: // "%.*s"
- ArgsData.back().Kind = OSLogBufferItem::CountKind;
- break;
- case clang::analyze_format_string::OptionalAmount::Invalid:
- return false;
- }
- break;
- }
- case clang::analyze_format_string::ConversionSpecifier::PArg: { // "%P"
- auto &precision = FS.getPrecision();
- switch (precision.getHowSpecified()) {
- case clang::analyze_format_string::OptionalAmount::NotSpecified: // "%P"
- return false; // length must be supplied with pointer format specifier
- case clang::analyze_format_string::OptionalAmount::Constant: // "%.16P"
- ArgsData.back().Size = precision.getConstantAmount();
- break;
- case clang::analyze_format_string::OptionalAmount::Arg: // "%.*P"
- ArgsData.back().Kind = OSLogBufferItem::CountKind;
- break;
- case clang::analyze_format_string::OptionalAmount::Invalid:
- return false;
- }
- break;
- }
- default:
- break;
- }
-
- if (FS.isPrivate()) {
- ArgsData.back().Flags |= OSLogBufferItem::IsPrivate;
- }
- if (FS.isPublic()) {
- ArgsData.back().Flags |= OSLogBufferItem::IsPublic;
- }
- return true;
- }
-
- void computeLayout(ASTContext &Ctx, OSLogBufferLayout &Layout) const {
- Layout.Items.clear();
- for (auto &Data : ArgsData) {
- if (Data.Size)
- Layout.Items.emplace_back(Ctx, CharUnits::fromQuantity(*Data.Size),
- Data.Flags);
- if (Data.Kind) {
- CharUnits Size;
- if (*Data.Kind == OSLogBufferItem::ErrnoKind)
- Size = CharUnits::Zero();
- else
- Size = Ctx.getTypeSizeInChars(Data.E->getType());
- Layout.Items.emplace_back(*Data.Kind, Data.E, Size, Data.Flags);
- } else {
- auto Size = Ctx.getTypeSizeInChars(Data.E->getType());
- Layout.Items.emplace_back(OSLogBufferItem::ScalarKind, Data.E, Size,
- Data.Flags);
- }
- }
- }
-};
-
-bool clang::analyze_os_log::computeOSLogBufferLayout(
- ASTContext &Ctx, const CallExpr *E, OSLogBufferLayout &Layout) {
- ArrayRef<const Expr *> Args(E->getArgs(), E->getArgs() + E->getNumArgs());
-
- const Expr *StringArg;
- ArrayRef<const Expr *> VarArgs;
- switch (E->getBuiltinCallee()) {
- case Builtin::BI__builtin_os_log_format_buffer_size:
- assert(E->getNumArgs() >= 1 &&
- "__builtin_os_log_format_buffer_size takes at least 1 argument");
- StringArg = E->getArg(0);
- VarArgs = Args.slice(1);
- break;
- case Builtin::BI__builtin_os_log_format:
- assert(E->getNumArgs() >= 2 &&
- "__builtin_os_log_format takes at least 2 arguments");
- StringArg = E->getArg(1);
- VarArgs = Args.slice(2);
- break;
- default:
- llvm_unreachable("non-os_log builtin passed to computeOSLogBufferLayout");
- }
-
- const StringLiteral *Lit = cast<StringLiteral>(StringArg->IgnoreParenCasts());
- assert(Lit && (Lit->isAscii() || Lit->isUTF8()));
- StringRef Data = Lit->getString();
- OSLogFormatStringHandler H(VarArgs);
- ParsePrintfString(H, Data.begin(), Data.end(), Ctx.getLangOpts(),
- Ctx.getTargetInfo(), /*isFreeBSDKPrintf*/ false);
-
- H.computeLayout(Ctx, Layout);
- return true;
-}
diff --git a/clang/lib/Analysis/PrintfFormatString.cpp b/clang/lib/Analysis/PrintfFormatString.cpp
index ed7193ecb43..ac6cef9d084 100644
--- a/clang/lib/Analysis/PrintfFormatString.cpp
+++ b/clang/lib/Analysis/PrintfFormatString.cpp
@@ -119,39 +119,6 @@ static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H,
return true;
}
- const char *OSLogVisibilityFlagsStart = nullptr,
- *OSLogVisibilityFlagsEnd = nullptr;
- if (*I == '{') {
- OSLogVisibilityFlagsStart = I++;
- // Find the end of the modifier.
- while (I != E && *I != '}') {
- I++;
- }
- if (I == E) {
- if (Warn)
- H.HandleIncompleteSpecifier(Start, E - Start);
- return true;
- }
- assert(*I == '}');
- OSLogVisibilityFlagsEnd = I++;
-
- // Just see if 'private' or 'public' is the first word. os_log itself will
- // do any further parsing.
- const char *P = OSLogVisibilityFlagsStart + 1;
- while (P < OSLogVisibilityFlagsEnd && isspace(*P))
- P++;
- const char *WordStart = P;
- while (P < OSLogVisibilityFlagsEnd && (isalnum(*P) || *P == '_'))
- P++;
- const char *WordEnd = P;
- StringRef Word(WordStart, WordEnd - WordStart);
- if (Word == "private") {
- FS.setIsPrivate(WordStart);
- } else if (Word == "public") {
- FS.setIsPublic(WordStart);
- }
- }
-
// Look for flags (if any).
bool hasMore = true;
for ( ; I != E; ++I) {
@@ -286,10 +253,6 @@ static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H,
// POSIX specific.
case 'C': k = ConversionSpecifier::CArg; break;
case 'S': k = ConversionSpecifier::SArg; break;
- // Apple extension for os_log
- case 'P':
- k = ConversionSpecifier::PArg;
- break;
// Objective-C.
case '@': k = ConversionSpecifier::ObjCObjArg; break;
// Glibc specific.
@@ -338,7 +301,7 @@ static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H,
conversionPosition);
return true;
}
-
+
PrintfConversionSpecifier CS(conversionPosition, k);
FS.setConversionSpecifier(CS);
if (CS.consumesDataArgument() && !FS.usesPositionalArg())
@@ -578,7 +541,6 @@ ArgType PrintfSpecifier::getArgType(ASTContext &Ctx,
return Ctx.IntTy;
return ArgType(Ctx.WideCharTy, "wchar_t");
case ConversionSpecifier::pArg:
- case ConversionSpecifier::PArg:
return ArgType::CPointerTy;
case ConversionSpecifier::ObjCObjArg:
return ArgType::ObjCPointerTy;
@@ -938,7 +900,7 @@ bool PrintfSpecifier::hasValidPrecision() const {
if (Precision.getHowSpecified() == OptionalAmount::NotSpecified)
return true;
- // Precision is only valid with the diouxXaAeEfFgGsP conversions
+ // Precision is only valid with the diouxXaAeEfFgGs conversions
switch (CS.getKind()) {
case ConversionSpecifier::dArg:
case ConversionSpecifier::DArg:
@@ -960,7 +922,6 @@ bool PrintfSpecifier::hasValidPrecision() const {
case ConversionSpecifier::sArg:
case ConversionSpecifier::FreeBSDrArg:
case ConversionSpecifier::FreeBSDyArg:
- case ConversionSpecifier::PArg:
return true;
default:
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 92a4447398b..a81a75b4135 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -11,15 +11,14 @@
//
//===----------------------------------------------------------------------===//
+#include "CodeGenFunction.h"
#include "CGCXXABI.h"
#include "CGObjCRuntime.h"
#include "CGOpenCLRuntime.h"
-#include "CodeGenFunction.h"
#include "CodeGenModule.h"
#include "TargetInfo.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
-#include "clang/Analysis/Analyses/OSLog.h"
#include "clang/Basic/TargetBuiltins.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/CodeGen/CGFunctionInfo.h"
@@ -565,18 +564,6 @@ Value *CodeGenFunction::EmitMSVCBuiltinExpr(MSVCIntrin BuiltinID,
llvm_unreachable("Incorrect MSVC intrinsic!");
}
-namespace {
-// ARC cleanup for __builtin_os_log_format
-struct CallObjCArcUse final : EHScopeStack::Cleanup {
- CallObjCArcUse(llvm::Value *object) : object(object) {}
- llvm::Value *object;
-
- void Emit(CodeGenFunction &CGF, Flags flags) override {
- CGF.EmitARCIntrinsicUse(object);
- }
-};
-}
-
RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
unsigned BuiltinID, const CallExpr *E,
ReturnValueSlot ReturnValue) {
@@ -2610,76 +2597,6 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
// Fall through - it's already mapped to the intrinsic by GCCBuiltin.
break;
}
- case Builtin::BI__builtin_os_log_format: {
- assert(E->getNumArgs() >= 2 &&
- "__builtin_os_log_format takes at least 2 arguments");
- analyze_os_log::OSLogBufferLayout Layout;
- analyze_os_log::computeOSLogBufferLayout(CGM.getContext(), E, Layout);
- Address BufAddr = EmitPointerWithAlignment(E->getArg(0));
- // Ignore argument 1, the format string. It is not currently used.
- CharUnits Offset;
- Builder.CreateStore(
- Builder.getInt8(Layout.getSummaryByte()),
- Builder.CreateConstByteGEP(BufAddr, Offset++, "summary"));
- Builder.CreateStore(
- Builder.getInt8(Layout.getNumArgsByte()),
- Builder.CreateConstByteGEP(BufAddr, Offset++, "numArgs"));
-
- llvm::SmallVector<llvm::Value *, 4> RetainableOperands;
- for (const auto &Item : Layout.Items) {
- Builder.CreateStore(
- Builder.getInt8(Item.getDescriptorByte()),
- Builder.CreateConstByteGEP(BufAddr, Offset++, "argDescriptor"));
- Builder.CreateStore(
- Builder.getInt8(Item.getSizeByte()),
- Builder.CreateConstByteGEP(BufAddr, Offset++, "argSize"));
- Address Addr = Builder.CreateConstByteGEP(BufAddr, Offset);
- if (const Expr *TheExpr = Item.getExpr()) {
- Addr = Builder.CreateElementBitCast(
- Addr, ConvertTypeForMem(TheExpr->getType()));
- // Check if this is a retainable type.
- if (TheExpr->getType()->isObjCRetainableType()) {
- assert(getEvaluationKind(TheExpr->getType()) == TEK_Scalar &&
- "Only scalar can be a ObjC retainable type");
- llvm::Value *SV = EmitScalarExpr(TheExpr, /*Ignore*/ false);
- RValue RV = RValue::get(SV);
- LValue LV = MakeAddrLValue(Addr, TheExpr->getType());
- EmitStoreThroughLValue(RV, LV);
- // Check if the object is constant, if not, save it in
- // RetainableOperands.
- if (!isa<Constant>(SV))
- RetainableOperands.push_back(SV);
- } else {
- EmitAnyExprToMem(TheExpr, Addr, Qualifiers(), /*isInit*/ true);
- }
- } else {
- Addr = Builder.CreateElementBitCast(Addr, Int32Ty);
- Builder.CreateStore(
- Builder.getInt32(Item.getConstValue().getQuantity()), Addr);
- }
- Offset += Item.size();
- }
-
- // Push a clang.arc.use cleanup for each object in RetainableOperands. The
- // cleanup will cause the use to appear after the final log call, keeping
- // the object valid while it’s held in the log buffer. Note that if there’s
- // a release cleanup on the object, it will already be active; since
- // cleanups are emitted in reverse order, the use will occur before the
- // object is released.
- if (!RetainableOperands.empty() && getLangOpts().ObjCAutoRefCount &&
- CGM.getCodeGenOpts().OptimizationLevel != 0)
- for (llvm::Value *object : RetainableOperands)
- pushFullExprCleanup<CallObjCArcUse>(getARCCleanupKind(), object);
-
- return RValue::get(BufAddr.getPointer());
- }
-
- case Builtin::BI__builtin_os_log_format_buffer_size: {
- analyze_os_log::OSLogBufferLayout Layout;
- analyze_os_log::computeOSLogBufferLayout(CGM.getContext(), E, Layout);
- return RValue::get(ConstantInt::get(ConvertType(E->getType()),
- Layout.size().getQuantity()));
- }
}
// If this is an alias for a lib function (e.g. __builtin_sin), emit
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 5e8be3c1f05..fd8e19876b9 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -1065,12 +1065,6 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
case Builtin::BIget_kernel_preferred_work_group_size_multiple:
if (SemaOpenCLBuiltinKernelWorkGroupSize(*this, TheCall))
return ExprError();
- case Builtin::BI__builtin_os_log_format:
- case Builtin::BI__builtin_os_log_format_buffer_size:
- if (SemaBuiltinOSLogFormat(TheCall)) {
- return ExprError();
- }
- break;
}
// Since the target specific builtins for each arch overlap, only check those
@@ -3484,31 +3478,6 @@ bool Sema::CheckObjCString(Expr *Arg) {
return false;
}
-/// CheckObjCString - Checks that the format string argument to the os_log()
-/// and os_trace() functions is correct, and converts it to const char *.
-ExprResult Sema::CheckOSLogFormatStringArg(Expr *Arg) {
- Arg = Arg->IgnoreParenCasts();
- auto *Literal = dyn_cast<StringLiteral>(Arg);
- if (!Literal) {
- if (auto *ObjcLiteral = dyn_cast<ObjCStringLiteral>(Arg)) {
- Literal = ObjcLiteral->getString();
- }
- }
-
- if (!Literal || (!Literal->isAscii() && !Literal->isUTF8())) {
- return ExprError(
- Diag(Arg->getLocStart(), diag::err_os_log_format_not_string_constant)
- << Arg->getSourceRange());
- }
-
- ExprResult Result(Literal);
- QualType ResultTy = Context.getPointerType(Context.CharTy.withConst());
- InitializedEntity Entity =
- InitializedEntity::InitializeParameter(Context, ResultTy, false);
- Result = PerformCopyInitialization(Entity, SourceLocation(), Result);
- return Result;
-}
-
/// Check the arguments to '__builtin_va_start' or '__builtin_ms_va_start'
/// for validity. Emit an error and return true on failure; return false
/// on success.
@@ -3970,86 +3939,6 @@ bool Sema::SemaBuiltinAssumeAligned(CallExpr *TheCall) {
return false;
}
-bool Sema::SemaBuiltinOSLogFormat(CallExpr *TheCall) {
- unsigned BuiltinID =
- cast<FunctionDecl>(TheCall->getCalleeDecl())->getBuiltinID();
- bool IsSizeCall = BuiltinID == Builtin::BI__builtin_os_log_format_buffer_size;
-
- unsigned NumArgs = TheCall->getNumArgs();
- unsigned NumRequiredArgs = IsSizeCall ? 1 : 2;
- if (NumArgs < NumRequiredArgs) {
- return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args)
- << 0 /* function call */ << NumRequiredArgs << NumArgs
- << TheCall->getSourceRange();
- }
- if (NumArgs >= NumRequiredArgs + 0x100) {
- return Diag(TheCall->getLocEnd(),
- diag::err_typecheck_call_too_many_args_at_most)
- << 0 /* function call */ << (NumRequiredArgs + 0xff) << NumArgs
- << TheCall->getSourceRange();
- }
- unsigned i = 0;
-
- // For formatting call, check buffer arg.
- if (!IsSizeCall) {
- ExprResult Arg(TheCall->getArg(i));
- InitializedEntity Entity = InitializedEntity::InitializeParameter(
- Context, Context.VoidPtrTy, false);
- Arg = PerformCopyInitialization(Entity, SourceLocation(), Arg);
- if (Arg.isInvalid())
- return true;
- TheCall->setArg(i, Arg.get());
- i++;
- }
-
- // Check string literal arg.
- unsigned FormatIdx = i;
- {
- ExprResult Arg = CheckOSLogFormatStringArg(TheCall->getArg(i));
- if (Arg.isInvalid())
- return true;
- TheCall->setArg(i, Arg.get());
- i++;
- }
-
- // Make sure variadic args are scalar.
- unsigned FirstDataArg = i;
- while (i < NumArgs) {
- ExprResult Arg = DefaultVariadicArgumentPromotion(
- TheCall->getArg(i), VariadicFunction, nullptr);
- if (Arg.isInvalid())
- return true;
- CharUnits ArgSize = Context.getTypeSizeInChars(Arg.get()->getType());
- if (ArgSize.getQuantity() >= 0x100) {
- return Diag(Arg.get()->getLocEnd(), diag::err_os_log_argument_too_big)
- << i << (int)ArgSize.getQuantity() << 0xff
- << TheCall->getSourceRange();
- }
- TheCall->setArg(i, Arg.get());
- i++;
- }
-
- // Check formatting specifiers. NOTE: We're only doing this for the non-size
- // call to avoid duplicate diagnostics.
- if (!IsSizeCall) {
- llvm::SmallBitVector CheckedVarArgs(NumArgs, false);
- ArrayRef<const Expr *> Args(TheCall->getArgs(), TheCall->getNumArgs());
- bool Success = CheckFormatArguments(
- Args, /*HasVAListArg*/ false, FormatIdx, FirstDataArg, FST_OSLog,
- VariadicFunction, TheCall->getLocStart(), SourceRange(),
- CheckedVarArgs);
- if (!Success)
- return true;
- }
-
- if (IsSizeCall) {
- TheCall->setType(Context.getSizeType());
- } else {
- TheCall->setType(Context.VoidPtrTy);
- }
- return false;
-}
-
/// SemaBuiltinConstantArg - Handle a check if argument ArgNum of CallExpr
/// TheCall is a constant expression.
bool Sema::SemaBuiltinConstantArg(CallExpr *TheCall, int ArgNum,
@@ -4680,16 +4569,15 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef<const Expr *> Args,
Sema::FormatStringType Sema::GetFormatStringType(const FormatAttr *Format) {
return llvm::StringSwitch<FormatStringType>(Format->getType()->getName())
- .Case("scanf", FST_Scanf)
- .Cases("printf", "printf0", FST_Printf)
- .Cases("NSString", "CFString", FST_NSString)
- .Case("strftime", FST_Strftime)
- .Case("strfmon", FST_Strfmon)
- .Cases("kprintf", "cmn_err", "vcmn_err", "zcmn_err", FST_Kprintf)
- .Case("freebsd_kprintf", FST_FreeBSDKPrintf)
- .Case("os_trace", FST_OSLog)
- .Case("os_log", FST_OSLog)
- .Default(FST_Unknown);
+ .Case("scanf", FST_Scanf)
+ .Cases("printf", "printf0", FST_Printf)
+ .Cases("NSString", "CFString", FST_NSString)
+ .Case("strftime", FST_Strftime)
+ .Case("strfmon", FST_Strfmon)
+ .Cases("kprintf", "cmn_err", "vcmn_err", "zcmn_err", FST_Kprintf)
+ .Case("freebsd_kprintf", FST_FreeBSDKPrintf)
+ .Case("os_trace", FST_OSTrace)
+ .Default(FST_Unknown);
}
/// CheckFormatArguments - Check calls to printf and scanf (and similar
@@ -4799,7 +4687,6 @@ protected:
Sema &S;
const FormatStringLiteral *FExpr;
const Expr *OrigFormatExpr;
- const Sema::FormatStringType FSType;
const unsigned FirstDataArg;
const unsigned NumDataArgs;
const char *Beg; // Start of format string.
@@ -4816,19 +4703,20 @@ protected:
public:
CheckFormatHandler(Sema &s, const FormatStringLiteral *fexpr,
- const Expr *origFormatExpr,
- const Sema::FormatStringType type, unsigned firstDataArg,
+ const Expr *origFormatExpr, unsigned firstDataArg,
unsigned numDataArgs, const char *beg, bool hasVAListArg,
- ArrayRef<const Expr *> Args, unsigned formatIdx,
- bool inFunctionCall, Sema::VariadicCallType callType,
+ ArrayRef<const Expr *> Args,
+ unsigned formatIdx, bool inFunctionCall,
+ Sema::VariadicCallType callType,
llvm::SmallBitVector &CheckedVarArgs,
UncoveredArgHandler &UncoveredArg)
- : S(s), FExpr(fexpr), OrigFormatExpr(origFormatExpr), FSType(type),
- FirstDataArg(firstDataArg), NumDataArgs(numDataArgs), Beg(beg),
- HasVAListArg(hasVAListArg), Args(Args), FormatIdx(formatIdx),
- usesPositionalArgs(false), atFirstArg(true),
- inFunctionCall(inFunctionCall), CallType(callType),
- CheckedVarArgs(CheckedVarArgs), UncoveredArg(UncoveredArg) {
+ : S(s), FExpr(fexpr), OrigFormatExpr(origFormatExpr),
+ FirstDataArg(firstDataArg), NumDataArgs(numDataArgs),
+ Beg(beg), HasVAListArg(hasVAListArg),
+ Args(Args), FormatIdx(formatIdx),
+ usesPositionalArgs(false), atFirstArg(true),
+ inFunctionCall(inFunctionCall), CallType(callType),
+ CheckedVarArgs(CheckedVarArgs), UncoveredArg(UncoveredArg) {
CoveredArgs.resize(numDataArgs);
CoveredArgs.reset();
}
@@ -5251,28 +5139,24 @@ void CheckFormatHandler::EmitFormatDiagnostic(
namespace {
class CheckPrintfHandler : public CheckFormatHandler {
+ bool ObjCContext;
+
public:
CheckPrintfHandler(Sema &s, const FormatStringLiteral *fexpr,
- const Expr *origFormatExpr,
- const Sema::FormatStringType type, unsigned firstDataArg,
- unsigned numDataArgs, bool isObjC, const char *beg,
- bool hasVAListArg, ArrayRef<const Expr *> Args,
+ const Expr *origFormatExpr, unsigned firstDataArg,
+ unsigned numDataArgs, bool isObjC,
+ const char *beg, bool hasVAListArg,
+ ArrayRef<const Expr *> Args,
unsigned formatIdx, bool inFunctionCall,
Sema::VariadicCallType CallType,
llvm::SmallBitVector &CheckedVarArgs,
UncoveredArgHandler &UncoveredArg)
- : CheckFormatHandler(s, fexpr, origFormatExpr, type, firstDataArg,
- numDataArgs, beg, hasVAListArg, Args, formatIdx,
- inFunctionCall, CallType, CheckedVarArgs,
- UncoveredArg) {}
-
- bool isObjCContext() const { return FSType == Sema::FST_NSString; }
-
- /// Returns true if '%@' specifiers are allowed in the format string.
- bool allowsObjCArg() const {
- return FSType == Sema::FST_NSString || FSType == Sema::FST_OSLog ||
- FSType == Sema::FST_OSTrace;
- }
+ : CheckFormatHandler(s, fexpr, origFormatExpr, firstDataArg,
+ numDataArgs, beg, hasVAListArg, Args,
+ formatIdx, inFunctionCall, CallType, CheckedVarArgs,
+ UncoveredArg),
+ ObjCContext(isObjC)
+ {}
bool HandleInvalidPrintfConversionSpecifier(
const analyze_printf::PrintfSpecifier &FS,
@@ -5626,54 +5510,11 @@ CheckPrintfHandler::HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier
// Check for using an Objective-C specific conversion specifier
// in a non-ObjC literal.
- if (!allowsObjCArg() && CS.isObjCArg()) {
- return HandleInvalidPrintfConversionSpecifier(FS, startSpecifier,
- specifierLen);
- }
-
- // %P can only be used with os_log.
- if (FSType != Sema::FST_OSLog && CS.getKind() == ConversionSpecifier::PArg) {
+ if (!ObjCContext && CS.isObjCArg()) {
return HandleInvalidPrintfConversionSpecifier(FS, startSpecifier,
specifierLen);
}
- // %n is not allowed with os_log.
- if (FSType == Sema::FST_OSLog && CS.getKind() == ConversionSpecifier::nArg) {
- EmitFormatDiagnostic(S.PDiag(diag::warn_os_log_format_narg),
- getLocationOfByte(CS.getStart()),
- /*IsStringLocation*/ false,
- getSpecifierRange(startSpecifier, specifierLen));
-
- return true;
- }
-
- // Only scalars are allowed for os_trace.
- if (FSType == Sema::FST_OSTrace &&
- (CS.getKind() == ConversionSpecifier::PArg ||
- CS.getKind() == ConversionSpecifier::sArg ||
- CS.getKind() == ConversionSpecifier::ObjCObjArg)) {
- return HandleInvalidPrintfConversionSpecifier(FS, startSpecifier,
- specifierLen);
- }
-
- // Check for use of public/private annotation outside of os_log().
- if (FSType != Sema::FST_OSLog) {
- if (FS.isPublic().isSet()) {
- EmitFormatDiagnostic(S.PDiag(diag::warn_format_invalid_annotation)
- << "public",
- getLocationOfByte(FS.isPublic().getPosition()),
- /*IsStringLocation*/ false,
- getSpecifierRange(startSpecifier, specifierLen));
- }
- if (FS.isPrivate().isSet()) {
- EmitFormatDiagnostic(S.PDiag(diag::warn_format_invalid_annotation)
- << "private",
- getLocationOfByte(FS.isPrivate().getPosition()),
- /*IsStringLocation*/ false,
- getSpecifierRange(startSpecifier, specifierLen));
- }
- }
-
// Check for invalid use of field width
if (!FS.hasValidFieldWidth()) {
HandleInvalidAmount(FS, FS.getFieldWidth(), /* field width */ 0,
@@ -5686,15 +5527,6 @@ CheckPrintfHandler::HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier
startSpecifier, specifierLen);
}
- // Precision is mandatory for %P specifier.
- if (CS.getKind() == ConversionSpecifier::PArg &&
- FS.getPrecision().getHowSpecified() == OptionalAmount::NotSpecified) {
- EmitFormatDiagnostic(S.PDiag(diag::warn_format_P_no_precision),
- getLocationOfByte(startSpecifier),
- /*IsStringLocation*/ false,
- getSpecifierRange(startSpecifier, specifierLen));
- }
-
// Check each flag does not conflict with any other component.
if (!FS.hasValidThousandsGroupingPrefix())
HandleFlag(FS, FS.hasThousandsGrouping(), startSpecifier, specifierLen);
@@ -5844,7 +5676,8 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
using namespace analyze_printf;
// Now type check the data expression that matches the
// format specifier.
- const analyze_printf::ArgType &AT = FS.getArgType(S.Context, isObjCContext());
+ const analyze_printf::ArgType &AT = FS.getArgType(S.Context,
+ ObjCContext);
if (!AT.isValid())
return true;
@@ -5899,7 +5732,7 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
// If the argument is an integer of some kind, believe the %C and suggest
// a cast instead of changing the conversion specifier.
QualType IntendedTy = ExprTy;
- if (isObjCContext() &&
+ if (ObjCContext &&
FS.getConversionSpecifier().getKind() == ConversionSpecifier::CArg) {
if (ExprTy->isIntegralOrUnscopedEnumerationType() &&
!ExprTy->isCharType()) {
@@ -5940,8 +5773,8 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
// We may be able to offer a FixItHint if it is a supported type.
PrintfSpecifier fixedFS = FS;
- bool success =
- fixedFS.fixType(IntendedTy, S.getLangOpts(), S.Context, isObjCContext());
+ bool success = fixedFS.fixType(IntendedTy, S.getLangOpts(),
+ S.Context, ObjCContext);
if (success) {
// Get the fix string from the fixed format specifier
@@ -6097,18 +5930,19 @@ namespace {
class CheckScanfHandler : public CheckFormatHandler {
public:
CheckScanfHandler(Sema &s, const FormatStringLiteral *fexpr,
- const Expr *origFormatExpr, Sema::FormatStringType type,
- unsigned firstDataArg, unsigned numDataArgs,
- const char *beg, bool hasVAListArg,
- ArrayRef<const Expr *> Args, unsigned formatIdx,
- bool inFunctionCall, Sema::VariadicCallType CallType,
+ const Expr *origFormatExpr, unsigned firstDataArg,
+ unsigned numDataArgs, const char *beg, bool hasVAListArg,
+ ArrayRef<const Expr *> Args,
+ unsigned formatIdx, bool inFunctionCall,
+ Sema::VariadicCallType CallType,
llvm::SmallBitVector &CheckedVarArgs,
UncoveredArgHandler &UncoveredArg)
- : CheckFormatHandler(s, fexpr, origFormatExpr, type, firstDataArg,
- numDataArgs, beg, hasVAListArg, Args, formatIdx,
- inFunctionCall, CallType, CheckedVarArgs,
- UncoveredArg) {}
-
+ : CheckFormatHandler(s, fexpr, origFormatExpr, firstDataArg,
+ numDataArgs, beg, hasVAListArg,
+ Args, formatIdx, inFunctionCall, CallType,
+ CheckedVarArgs, UncoveredArg)
+ {}
+
bool HandleScanfSpecifier(const analyze_scanf::ScanfSpecifier &FS,
const char *startSpecifier,
unsigned specifierLen) override;
@@ -6318,13 +6152,13 @@ static void CheckFormatString(Sema &S, const FormatStringLiteral *FExpr,
}
if (Type == Sema::FST_Printf || Type == Sema::FST_NSString ||
- Type == Sema::FST_FreeBSDKPrintf || Type == Sema::FST_OSLog ||
- Type == Sema::FST_OSTrace) {
- CheckPrintfHandler H(
- S, FExpr, OrigFormatExpr, Type, firstDataArg, numDataArgs,
- (Type == Sema::FST_NSString || Type == Sema::FST_OSTrace), Str,
- HasVAListArg, Args, format_idx, inFunctionCall, CallType,
- CheckedVarArgs, UncoveredArg);
+ Type == Sema::FST_FreeBSDKPrintf || Type == Sema::FST_OSTrace) {
+ CheckPrintfHandler H(S, FExpr, OrigFormatExpr, firstDataArg,
+ numDataArgs, (Type == Sema::FST_NSString ||
+ Type == Sema::FST_OSTrace),
+ Str, HasVAListArg, Args, format_idx,
+ inFunctionCall, CallType, CheckedVarArgs,
+ UncoveredArg);
if (!analyze_format_string::ParsePrintfString(H, Str, Str + StrLen,
S.getLangOpts(),
@@ -6332,9 +6166,10 @@ static void CheckFormatString(Sema &S, const FormatStringLiteral *FExpr,
Type == Sema::FST_FreeBSDKPrintf))
H.DoneProcessing();
} else if (Type == Sema::FST_Scanf) {
- CheckScanfHandler H(S, FExpr, OrigFormatExpr, Type, firstDataArg,
- numDataArgs, Str, HasVAListArg, Args, format_idx,
- inFunctionCall, CallType, CheckedVarArgs, UncoveredArg);
+ CheckScanfHandler H(S, FExpr, OrigFormatExpr, firstDataArg, numDataArgs,
+ Str, HasVAListArg, Args, format_idx,
+ inFunctionCall, CallType, CheckedVarArgs,
+ UncoveredArg);
if (!analyze_format_string::ParseScanfString(H, Str, Str + StrLen,
S.getLangOpts(),
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 88dd6ce7b5c..ee995e0702e 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -2804,21 +2804,20 @@ enum FormatAttrKind {
/// types.
static FormatAttrKind getFormatAttrKind(StringRef Format) {
return llvm::StringSwitch<FormatAttrKind>(Format)
- // Check for formats that get handled specially.
- .Case("NSString", NSStringFormat)
- .Case("CFString", CFStringFormat)
- .Case("strftime", StrftimeFormat)
-
- // Otherwise, check for supported formats.
- .Cases("scanf", "printf", "printf0", "strfmon", SupportedFormat)
- .Cases("cmn_err", "vcmn_err", "zcmn_err", SupportedFormat)
- .Case("kprintf", SupportedFormat) // OpenBSD.
- .Case("freebsd_kprintf", SupportedFormat) // FreeBSD.
- .Case("os_trace", SupportedFormat)
- .Case("os_log", SupportedFormat)
-
- .Cases("gcc_diag", "gcc_cdiag", "gcc_cxxdiag", "gcc_tdiag", IgnoredFormat)
- .Default(InvalidFormat);
+ // Check for formats that get handled specially.
+ .Case("NSString", NSStringFormat)
+ .Case("CFString", CFStringFormat)
+ .Case("strftime", StrftimeFormat)
+
+ // Otherwise, check for supported formats.
+ .Cases("scanf", "printf", "printf0", "strfmon", SupportedFormat)
+ .Cases("cmn_err", "vcmn_err", "zcmn_err", SupportedFormat)
+ .Case("kprintf", SupportedFormat) // OpenBSD.
+ .Case("freebsd_kprintf", SupportedFormat) // FreeBSD.
+ .Case("os_trace", SupportedFormat)
+
+ .Cases("gcc_diag", "gcc_cdiag", "gcc_cxxdiag", "gcc_tdiag", IgnoredFormat)
+ .Default(InvalidFormat);
}
/// Handle __attribute__((init_priority(priority))) attributes based on
OpenPOWER on IntegriCloud