diff options
author | Mehdi Amini <mehdi.amini@apple.com> | 2016-10-24 19:41:36 +0000 |
---|---|---|
committer | Mehdi Amini <mehdi.amini@apple.com> | 2016-10-24 19:41:36 +0000 |
commit | 9c39fdcedae36a5ea7079459da953c929a3edb57 (patch) | |
tree | afd5d609c3925ef76d76646760bd4a45ef4fad39 /clang/lib | |
parent | 6733564e5aff326bffb858fb0b2358905b792f24 (diff) | |
download | bcm5719-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.txt | 1 | ||||
-rw-r--r-- | clang/lib/Analysis/FormatString.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Analysis/OSLog.cpp | 177 | ||||
-rw-r--r-- | clang/lib/Analysis/PrintfFormatString.cpp | 43 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGBuiltin.cpp | 85 | ||||
-rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 285 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 29 |
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 |