diff options
Diffstat (limited to 'lib/Analysis/PrintfFormatString.cpp')
-rw-r--r-- | lib/Analysis/PrintfFormatString.cpp | 114 |
1 files changed, 81 insertions, 33 deletions
diff --git a/lib/Analysis/PrintfFormatString.cpp b/lib/Analysis/PrintfFormatString.cpp index dfaed26564e6..00591ab2b048 100644 --- a/lib/Analysis/PrintfFormatString.cpp +++ b/lib/Analysis/PrintfFormatString.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "clang/Analysis/Analyses/FormatString.h" +#include "clang/Analysis/Analyses/OSLog.h" #include "FormatStringParsing.h" #include "clang/Basic/TargetInfo.h" @@ -119,36 +120,56 @@ 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); + ++I; + unsigned char PrivacyFlags = 0; + StringRef MatchedStr; + + do { + StringRef Str(I, E - I); + std::string Match = "^[\t\n\v\f\r ]*(private|public)[\t\n\v\f\r ]*(,|})"; + llvm::Regex R(Match); + SmallVector<StringRef, 2> Matches; + + if (R.match(Str, &Matches)) { + MatchedStr = Matches[1]; + I += Matches[0].size(); + + // Set the privacy flag if the privacy annotation in the + // comma-delimited segment is at least as strict as the privacy + // annotations in previous comma-delimited segments. + if (MatchedStr.equals("private")) + PrivacyFlags = clang::analyze_os_log::OSLogBufferItem::IsPrivate; + else if (PrivacyFlags == 0 && MatchedStr.equals("public")) + PrivacyFlags = clang::analyze_os_log::OSLogBufferItem::IsPublic; + } else { + size_t CommaOrBracePos = + Str.find_if([](char c) { return c == ',' || c == '}'; }); + + if (CommaOrBracePos == StringRef::npos) { + // Neither a comma nor the closing brace was found. + if (Warn) + H.HandleIncompleteSpecifier(Start, E - Start); + return true; + } + + I += CommaOrBracePos + 1; + } + // Continue until the closing brace is found. + } while (*(I - 1) == ','); + + // Set the privacy flag. + switch (PrivacyFlags) { + case 0: + break; + case clang::analyze_os_log::OSLogBufferItem::IsPrivate: + FS.setIsPrivate(MatchedStr.data()); + break; + case clang::analyze_os_log::OSLogBufferItem::IsPublic: + FS.setIsPublic(MatchedStr.data()); + break; + default: + llvm_unreachable("Unexpected privacy flag value"); } } @@ -466,13 +487,14 @@ ArgType PrintfSpecifier::getArgType(ASTContext &Ctx, case LengthModifier::AsIntMax: return ArgType(Ctx.getIntMaxType(), "intmax_t"); case LengthModifier::AsSizeT: - return ArgType(Ctx.getSignedSizeType(), "ssize_t"); + return ArgType::makeSizeT(ArgType(Ctx.getSignedSizeType(), "ssize_t")); case LengthModifier::AsInt3264: return Ctx.getTargetInfo().getTriple().isArch64Bit() ? ArgType(Ctx.LongLongTy, "__int64") : ArgType(Ctx.IntTy, "__int32"); case LengthModifier::AsPtrDiff: - return ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"); + return ArgType::makePtrdiffT( + ArgType(Ctx.getPointerDiffType(), "ptrdiff_t")); case LengthModifier::AsAllocate: case LengthModifier::AsMAllocate: case LengthModifier::AsWide: @@ -499,13 +521,14 @@ ArgType PrintfSpecifier::getArgType(ASTContext &Ctx, case LengthModifier::AsIntMax: return ArgType(Ctx.getUIntMaxType(), "uintmax_t"); case LengthModifier::AsSizeT: - return ArgType(Ctx.getSizeType(), "size_t"); + return ArgType::makeSizeT(ArgType(Ctx.getSizeType(), "size_t")); case LengthModifier::AsInt3264: return Ctx.getTargetInfo().getTriple().isArch64Bit() ? ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64") : ArgType(Ctx.UnsignedIntTy, "unsigned __int32"); case LengthModifier::AsPtrDiff: - return ArgType(Ctx.getUnsignedPointerDiffType(), "unsigned ptrdiff_t"); + return ArgType::makePtrdiffT( + ArgType(Ctx.getUnsignedPointerDiffType(), "unsigned ptrdiff_t")); case LengthModifier::AsAllocate: case LengthModifier::AsMAllocate: case LengthModifier::AsWide: @@ -647,6 +670,7 @@ bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt, case BuiltinType::Bool: case BuiltinType::WChar_U: case BuiltinType::WChar_S: + case BuiltinType::Char8: // FIXME: Treat like 'char'? case BuiltinType::Char16: case BuiltinType::Char32: case BuiltinType::UInt128: @@ -654,6 +678,30 @@ bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt, case BuiltinType::Half: case BuiltinType::Float16: case BuiltinType::Float128: + case BuiltinType::ShortAccum: + case BuiltinType::Accum: + case BuiltinType::LongAccum: + case BuiltinType::UShortAccum: + case BuiltinType::UAccum: + case BuiltinType::ULongAccum: + case BuiltinType::ShortFract: + case BuiltinType::Fract: + case BuiltinType::LongFract: + case BuiltinType::UShortFract: + case BuiltinType::UFract: + case BuiltinType::ULongFract: + case BuiltinType::SatShortAccum: + case BuiltinType::SatAccum: + case BuiltinType::SatLongAccum: + case BuiltinType::SatUShortAccum: + case BuiltinType::SatUAccum: + case BuiltinType::SatULongAccum: + case BuiltinType::SatShortFract: + case BuiltinType::SatFract: + case BuiltinType::SatLongFract: + case BuiltinType::SatUShortFract: + case BuiltinType::SatUFract: + case BuiltinType::SatULongFract: // Various types which are non-trivial to correct. return false; |