r337470 - [Sema] Add a new warning, -Wmemset-transposed-args
Erik Pilkington via cfe-commits
cfe-commits at lists.llvm.org
Thu Jul 26 14:02:45 PDT 2018
On 7/26/18 1:38 PM, Richard Smith wrote:
> On Thu, 26 Jul 2018 at 13:14, Erik Pilkington via cfe-commits
> <cfe-commits at lists.llvm.org <mailto:cfe-commits at lists.llvm.org>> wrote:
>
>
>
> On 7/26/18 12:52 PM, Richard Smith wrote:
>> Other than the (fixed) ffmpeg false positive, I see this firing
>> in three places.
>>
>> One of them is in the libc tests for memset and bzero, where the
>> 0 argument is intentional.
>
> I don't find this case very convincing, if you're literally the
> one person that has to test memset then you should probably just
> compile with -Wno-suspicious-memaccess.
>
>
> I think you're missing the point. In our tests, the false positive
> rate for this was extremely high. If the warning should be turned off
> in two-thirds of the places where it appears, then it should not be on
> by default. That's why I was asking for evidence that it's actually
> got a much higher true-positive rate than we saw.
>
>> One of them is here:
>> https://github.com/apache/xerces-c/blob/trunk/src/xercesc/util/XMLUTF16Transcoder.cpp#L114
>> (note that this code is correct).
>> And one of them was a real bug where the second and third
>> arguments of memset were transposed.
>>
>> That's an extremely low false positive rate, much lower than what
>> we'd expect for an enabled-by-default warning. I find this
>> extremely surprising; I would have expected the ratio of true--
>> to false-positives to be much much higher. But ultimately data
>> wins out over expectations.
>> How does our experience compare to other people's experiences?
>> Are our findings abnormal? (They may well be; our corpus is very
>> C++-heavy.) If this is indeed typical, we should reconsider
>> whether to have these warnings enabled by default, as they do not
>> meet our bar for false positives.
>
> I tested this internally, and it found ~50 true-positives and only
> one false-positive (similar to apache bug above, where someone was
> memsetting to a sizeof exression). Given those numbers, my
> position is to keep it on-by-default, but I'm open to hear more.
> We might be able to make this warning even more conservative in
> this case by checking if the sizeof expression is actually
> computing a size that corresponds to the type of the third
> argument. I think that would be a good tradeoff if it meant we
> could keep this on by default.
>
>
> 50:1 sounds a lot more reasonable than what I was seeing (1:3). In the
> past we've said >99% true-positive was a good threshold for
> on-by-default warnings; your data is a plausible sample set from such
> a Bernoulli distribution (whereas mine is ... not so much -- but I
> think this is at least evidence that in my corpus, something else had
> already caught most of these bugs already; do we have a pre-existing
> ClangTidy check for this or similar? Does GCC warn on it?).
Yep, GCC has -Wmemset-transposed-args already, and there is also a
clang-tidy check. If your codebase already has to pass through those
tools then I agree thats probably the reason your seeing those numbers.
> If we can improve the true-positive rate further, that'd be a
> nice-to-have, but given the sizes of our respective sample sets, I
> think we lack the data to know if we've really helped the
> true-positive rate very much.
>
>> On Mon, 23 Jul 2018 at 09:28, Erik Pilkington via cfe-commits
>> <cfe-commits at lists.llvm.org <mailto:cfe-commits at lists.llvm.org>>
>> wrote:
>>
>> Sure, that seems pretty reasonable. r337706. Thanks for the
>> suggestion!
>>
>>
>> On 7/21/18 1:40 PM, Arthur O'Dwyer wrote:
>>> In this case Clang is complaining about
>>>
>>> memset(complicated-expr, 0, 0);
>>>
>>> which means that transposing the last two arguments would
>>> not "fix" anything. Clang ought to not complain in this case.
>>> It doesn't have anything to do with coming from a macro;
>>> it's just that /both/ arguments are zero.
>>> (I would also expect that `memset(complicated-expr,
>>> (unsigned char)fill, (size_t)0)` shouldn't warn, either. But
>>> we had some disagreement that casts to `(unsigned char)`
>>> resp. `(size_t)` should be the right way to shut up the
>>> warning in the first place...)
>>> Basically Clang should only be suggesting a swap (and thus
>>> complaining at all) in the case that swapping the arguments
>>> would actually improve the situation.
>>>
>>> –Arthur
>>>
>>> On Sat, Jul 21, 2018 at 1:33 PM, Nico Weber via cfe-commits
>>> <cfe-commits at lists.llvm.org
>>> <mailto:cfe-commits at lists.llvm.org>> wrote:
>>>
>>> This has a false positive on ffmpeg:
>>>
>>> ../../third_party/ffmpeg/libavcodec/options.c:273:64:
>>> error: 'size' argument to memset is '0'; did you mean to
>>> transpose the last two arguments?
>>> [-Werror,-Wmemset-transposed-args]
>>> alloc_and_copy_or_fail(intra_matrix, 64 *
>>> sizeof(int16_t), 0);
>>>
>>> With:
>>>
>>> #define alloc_and_copy_or_fail(obj, size, pad) \
>>> if (src->obj && size > 0) { \
>>> dest->obj = av_malloc(size + pad); \
>>> if (!dest->obj) \
>>> goto fail; \
>>> memcpy(dest->obj, src->obj, size); \
>>> if (pad) \
>>> memset(((uint8_t *) dest->obj) + size, 0,
>>> pad); \
>>> }
>>>
>>> (https://cs.chromium.org/chromium/src/third_party/ffmpeg/libavcodec/options.c?q=alloc_and_copy_or_fail&sq=package:chromium&g=0&l=261
>>> ;
>>> https://bugs.chromium.org/p/chromium/issues/detail?id=866202)
>>>
>>> Maybe the warning shouldn't fire if the memset is from a
>>> macro?
>>>
>>> On Thu, Jul 19, 2018 at 12:51 PM Erik Pilkington via
>>> cfe-commits <cfe-commits at lists.llvm.org
>>> <mailto:cfe-commits at lists.llvm.org>> wrote:
>>>
>>> Author: epilk
>>> Date: Thu Jul 19 09:46:15 2018
>>> New Revision: 337470
>>>
>>> URL:
>>> http://llvm.org/viewvc/llvm-project?rev=337470&view=rev
>>> Log:
>>> [Sema] Add a new warning, -Wmemset-transposed-args
>>>
>>> This diagnoses calls to memset that have the second
>>> and third arguments
>>> transposed, for example:
>>>
>>> memset(buf, sizeof(buf), 0);
>>>
>>> This is done by checking if the third argument is a
>>> literal 0, or if the second
>>> is a sizeof expression (and the third isn't). The
>>> first check is also done for
>>> calls to bzero.
>>>
>>> Differential revision: https://reviews.llvm.org/D49112
>>>
>>> Added:
>>> cfe/trunk/test/Sema/transpose-memset.c
>>> Modified:
>>> cfe/trunk/include/clang/Basic/DiagnosticGroups.td
>>> cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
>>> cfe/trunk/lib/Sema/SemaChecking.cpp
>>>
>>> Modified:
>>> cfe/trunk/include/clang/Basic/DiagnosticGroups.td
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?rev=337470&r1=337469&r2=337470&view=diff
>>> ==============================================================================
>>> ---
>>> cfe/trunk/include/clang/Basic/DiagnosticGroups.td
>>> (original)
>>> +++
>>> cfe/trunk/include/clang/Basic/DiagnosticGroups.td
>>> Thu Jul 19 09:46:15 2018
>>> @@ -443,6 +443,13 @@ def : DiagGroup<"synth">;
>>> def SizeofArrayArgument :
>>> DiagGroup<"sizeof-array-argument">;
>>> def SizeofArrayDecay : DiagGroup<"sizeof-array-decay">;
>>> def SizeofPointerMemaccess :
>>> DiagGroup<"sizeof-pointer-memaccess">;
>>> +def MemsetTransposedArgs :
>>> DiagGroup<"memset-transposed-args">;
>>> +def DynamicClassMemaccess :
>>> DiagGroup<"dynamic-class-memaccess">;
>>> +def NonTrivialMemaccess :
>>> DiagGroup<"nontrivial-memaccess">;
>>> +def SuspiciousBzero : DiagGroup<"suspicious-bzero">;
>>> +def SuspiciousMemaccess :
>>> DiagGroup<"suspicious-memaccess",
>>> + [SizeofPointerMemaccess, DynamicClassMemaccess,
>>> + NonTrivialMemaccess, MemsetTransposedArgs,
>>> SuspiciousBzero]>;
>>> def StaticInInline : DiagGroup<"static-in-inline">;
>>> def StaticLocalInInline :
>>> DiagGroup<"static-local-in-inline">;
>>> def GNUStaticFloatInit :
>>> DiagGroup<"gnu-static-float-init">;
>>>
>>> Modified:
>>> cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=337470&r1=337469&r2=337470&view=diff
>>> ==============================================================================
>>> ---
>>> cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
>>> (original)
>>> +++
>>> cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
>>> Thu Jul 19 09:46:15 2018
>>> @@ -619,14 +619,14 @@ def warn_cstruct_memaccess :
>>> Warning<
>>> "%select{destination for|source of|first operand
>>> of|second operand of}0 this "
>>> "%1 call is a pointer to record %2 that is not
>>> trivial to "
>>> "%select{primitive-default-initialize|primitive-copy}3">,
>>> - InGroup<DiagGroup<"nontrivial-memaccess">>;
>>> + InGroup<NonTrivialMemaccess>;
>>> def note_nontrivial_field : Note<
>>> "field is non-trivial to
>>> %select{copy|default-initialize}0">;
>>> def warn_dyn_class_memaccess : Warning<
>>> "%select{destination for|source of|first operand
>>> of|second operand of}0 this "
>>> "%1 call is a pointer to %select{|class
>>> containing a }2dynamic class %3; "
>>> "vtable pointer will be
>>> %select{overwritten|copied|moved|compared}4">,
>>> - InGroup<DiagGroup<"dynamic-class-memaccess">>;
>>> + InGroup<DynamicClassMemaccess>;
>>> def note_bad_memaccess_silence : Note<
>>> "explicitly cast the pointer to silence this
>>> warning">;
>>> def warn_sizeof_pointer_expr_memaccess : Warning<
>>> @@ -655,7 +655,19 @@ def
>>> note_memsize_comparison_paren : Note
>>> "did you mean to compare the result of %0 instead?">;
>>> def note_memsize_comparison_cast_silence : Note<
>>> "explicitly cast the argument to size_t to
>>> silence this warning">;
>>> -
>>> +def warn_suspicious_sizeof_memset : Warning<
>>> + "%select{'size' argument to memset is '0'|"
>>> + "setting buffer to a 'sizeof' expression}0"
>>> + "; did you mean to transpose the last two
>>> arguments?">,
>>> + InGroup<MemsetTransposedArgs>;
>>> +def note_suspicious_sizeof_memset_silence : Note<
>>> + "%select{parenthesize the third argument|"
>>> + "cast the second argument to 'int'}0 to silence">;
>>> +def warn_suspicious_bzero_size : Warning<"'size'
>>> argument to bzero is '0'">,
>>> + InGroup<SuspiciousBzero>;
>>> +def note_suspicious_bzero_size_silence : Note<
>>> + "parenthesize the second argument to silence">;
>>> +
>>> def warn_strncat_large_size : Warning<
>>> "the value of the size argument in 'strncat' is
>>> too large, might lead to a "
>>> "buffer overflow">, InGroup<StrncatSize>;
>>>
>>> Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=337470&r1=337469&r2=337470&view=diff
>>> ==============================================================================
>>> --- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
>>> +++ cfe/trunk/lib/Sema/SemaChecking.cpp Thu Jul 19
>>> 09:46:15 2018
>>> @@ -8629,24 +8629,26 @@ static const CXXRecordDecl
>>> *getContained
>>> return nullptr;
>>> }
>>>
>>> +static const UnaryExprOrTypeTraitExpr
>>> *getAsSizeOfExpr(const Expr *E) {
>>> + if (const auto *Unary =
>>> dyn_cast<UnaryExprOrTypeTraitExpr>(E))
>>> + if (Unary->getKind() == UETT_SizeOf)
>>> + return Unary;
>>> + return nullptr;
>>> +}
>>> +
>>> /// If E is a sizeof expression, returns its
>>> argument expression,
>>> /// otherwise returns NULL.
>>> static const Expr *getSizeOfExprArg(const Expr *E) {
>>> - if (const UnaryExprOrTypeTraitExpr *SizeOf =
>>> - dyn_cast<UnaryExprOrTypeTraitExpr>(E))
>>> - if (SizeOf->getKind() == UETT_SizeOf &&
>>> !SizeOf->isArgumentType())
>>> + if (const UnaryExprOrTypeTraitExpr *SizeOf =
>>> getAsSizeOfExpr(E))
>>> + if (!SizeOf->isArgumentType())
>>> return
>>> SizeOf->getArgumentExpr()->IgnoreParenImpCasts();
>>> -
>>> return nullptr;
>>> }
>>>
>>> /// If E is a sizeof expression, returns its
>>> argument type.
>>> static QualType getSizeOfArgType(const Expr *E) {
>>> - if (const UnaryExprOrTypeTraitExpr *SizeOf =
>>> - dyn_cast<UnaryExprOrTypeTraitExpr>(E))
>>> - if (SizeOf->getKind() == UETT_SizeOf)
>>> - return SizeOf->getTypeOfArgument();
>>> -
>>> + if (const UnaryExprOrTypeTraitExpr *SizeOf =
>>> getAsSizeOfExpr(E))
>>> + return SizeOf->getTypeOfArgument();
>>> return QualType();
>>> }
>>>
>>> @@ -8742,6 +8744,86 @@ struct
>>> SearchNonTrivialToCopyField
>>>
>>> }
>>>
>>> +/// Detect if \c SizeofExpr is likely to calculate
>>> the sizeof an object.
>>> +static bool doesExprLikelyComputeSize(const Expr
>>> *SizeofExpr) {
>>> + SizeofExpr = SizeofExpr->IgnoreParenImpCasts();
>>> +
>>> + if (const auto *BO =
>>> dyn_cast<BinaryOperator>(SizeofExpr)) {
>>> + if (BO->getOpcode() != BO_Mul &&
>>> BO->getOpcode() != BO_Add)
>>> + return false;
>>> +
>>> + return doesExprLikelyComputeSize(BO->getLHS()) ||
>>> + doesExprLikelyComputeSize(BO->getRHS());
>>> + }
>>> +
>>> + return getAsSizeOfExpr(SizeofExpr) != nullptr;
>>> +}
>>> +
>>> +/// Check if the ArgLoc originated from a macro
>>> passed to the call at CallLoc.
>>> +///
>>> +/// \code
>>> +/// #define MACRO 0
>>> +/// foo(MACRO);
>>> +/// foo(0);
>>> +/// \endcode
>>> +///
>>> +/// This should return true for the first call to
>>> foo, but not for the second
>>> +/// (regardless of whether foo is a macro or function).
>>> +static bool
>>> isArgumentExpandedFromMacro(SourceManager &SM,
>>> + SourceLocation CallLoc,
>>> + SourceLocation ArgLoc) {
>>> + if (!CallLoc.isMacroID())
>>> + return SM.getFileID(CallLoc) !=
>>> SM.getFileID(ArgLoc);
>>> +
>>> + return
>>> SM.getFileID(SM.getImmediateMacroCallerLoc(CallLoc)) !=
>>> + SM.getFileID(SM.getImmediateMacroCallerLoc(ArgLoc));
>>> +}
>>> +
>>> +/// Diagnose cases like 'memset(buf, sizeof(buf),
>>> 0)', which should have the
>>> +/// last two arguments transposed.
>>> +static void CheckMemaccessSize(Sema &S, unsigned
>>> BId, const CallExpr *Call) {
>>> + if (BId != Builtin::BImemset && BId !=
>>> Builtin::BIbzero)
>>> + return;
>>> +
>>> + const Expr *SizeArg =
>>> + Call->getArg(BId == Builtin::BImemset ? 2 :
>>> 1)->IgnoreImpCasts();
>>> +
>>> + // If we're memsetting or bzeroing 0 bytes, then
>>> this is likely an error.
>>> + SourceLocation CallLoc = Call->getRParenLoc();
>>> + SourceManager &SM = S.getSourceManager();
>>> + if (isa<IntegerLiteral>(SizeArg) &&
>>> + cast<IntegerLiteral>(SizeArg)->getValue() == 0 &&
>>> + !isArgumentExpandedFromMacro(SM, CallLoc,
>>> SizeArg->getExprLoc())) {
>>> +
>>> + SourceLocation DiagLoc = SizeArg->getExprLoc();
>>> +
>>> + // Some platforms #define bzero to
>>> __builtin_memset. See if this is the
>>> + // case, and if so, emit a better diagnostic.
>>> + if (BId == Builtin::BIbzero ||
>>> + (CallLoc.isMacroID() &&
>>> Lexer::getImmediateMacroName(
>>> + CallLoc, SM, S.getLangOpts()) == "bzero")) {
>>> + S.Diag(DiagLoc,
>>> diag::warn_suspicious_bzero_size);
>>> + S.Diag(DiagLoc,
>>> diag::note_suspicious_bzero_size_silence);
>>> + } else {
>>> + S.Diag(DiagLoc,
>>> diag::warn_suspicious_sizeof_memset) << 0;
>>> + S.Diag(DiagLoc,
>>> diag::note_suspicious_sizeof_memset_silence) << 0;
>>> + }
>>> + return;
>>> + }
>>> +
>>> + // If the second argument to a memset is a sizeof
>>> expression and the third
>>> + // isn't, this is also likely an error. This
>>> should catch
>>> + // 'memset(buf, sizeof(buf), 0xff)'.
>>> + if (BId == Builtin::BImemset &&
>>> + doesExprLikelyComputeSize(Call->getArg(1)) &&
>>> + !doesExprLikelyComputeSize(Call->getArg(2))) {
>>> + SourceLocation DiagLoc =
>>> Call->getArg(1)->getExprLoc();
>>> + S.Diag(DiagLoc,
>>> diag::warn_suspicious_sizeof_memset) << 1;
>>> + S.Diag(DiagLoc,
>>> diag::note_suspicious_sizeof_memset_silence) << 1;
>>> + return;
>>> + }
>>> +}
>>> +
>>> /// Check for dangerous or invalid arguments to
>>> memset().
>>> ///
>>> /// This issues warnings on known problematic,
>>> dangerous or unspecified
>>> @@ -8771,6 +8853,9 @@ void
>>> Sema::CheckMemaccessArguments(const
>>> Call->getLocStart(), Call->getRParenLoc()))
>>> return;
>>>
>>> + // Catch cases like 'memset(buf, sizeof(buf), 0)'.
>>> + CheckMemaccessSize(*this, BId, Call);
>>> +
>>> // We have special checking when the length is a
>>> sizeof expression.
>>> QualType SizeOfArgTy = getSizeOfArgType(LenExpr);
>>> const Expr *SizeOfArg = getSizeOfExprArg(LenExpr);
>>>
>>> Added: cfe/trunk/test/Sema/transpose-memset.c
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/transpose-memset.c?rev=337470&view=auto
>>> ==============================================================================
>>> --- cfe/trunk/test/Sema/transpose-memset.c (added)
>>> +++ cfe/trunk/test/Sema/transpose-memset.c Thu Jul
>>> 19 09:46:15 2018
>>> @@ -0,0 +1,60 @@
>>> +// RUN: %clang_cc1 -Wmemset-transposed-args -verify %s
>>> +// RUN: %clang_cc1 -xc++ -Wmemset-transposed-args
>>> -verify %s
>>> +
>>> +#define memset(...) __builtin_memset(__VA_ARGS__)
>>> +#define bzero(x,y) __builtin_memset(x, 0, y)
>>> +#define real_bzero(x,y) __builtin_bzero(x,y)
>>> +
>>> +int array[10];
>>> +int *ptr;
>>> +
>>> +int main() {
>>> + memset(array, sizeof(array), 0); //
>>> expected-warning{{'size' argument to memset is '0';
>>> did you mean to transpose the last two arguments?}}
>>> expected-note{{parenthesize the third argument to
>>> silence}}
>>> + memset(array, sizeof(array), 0xff); //
>>> expected-warning{{setting buffer to a 'sizeof'
>>> expression; did you mean to transpose the last two
>>> arguments?}} expected-note{{cast the second argument
>>> to 'int' to silence}}
>>> + memset(ptr, sizeof(ptr), 0); //
>>> expected-warning{{'size' argument to memset is '0';
>>> did you mean to transpose the last two arguments?}}
>>> expected-note{{parenthesize the third argument to
>>> silence}}
>>> + memset(ptr, sizeof(*ptr) * 10, 1); //
>>> expected-warning{{setting buffer to a 'sizeof'
>>> expression; did you mean to transpose the last two
>>> arguments?}} expected-note{{cast the second argument
>>> to 'int' to silence}}
>>> + memset(ptr, 10 * sizeof(int *), 1); //
>>> expected-warning{{setting buffer to a 'sizeof'
>>> expression; did you mean to transpose the last two
>>> arguments?}} expected-note{{cast the second argument
>>> to 'int' to silence}}
>>> + memset(ptr, 10 * sizeof(int *) + 10, 0xff); //
>>> expected-warning{{setting buffer to a 'sizeof'
>>> expression; did you mean to transpose the last two
>>> arguments?}} expected-note{{cast the second argument
>>> to 'int' to silence}}
>>> + memset(ptr, sizeof(char) * sizeof(int *), 0xff);
>>> // expected-warning{{setting buffer to a 'sizeof'
>>> expression; did you mean to transpose the last two
>>> arguments?}} expected-note{{cast the second argument
>>> to 'int' to silence}}
>>> + memset(array, sizeof(array), sizeof(array)); //
>>> Uh... fine I guess.
>>> + memset(array, 0, sizeof(array));
>>> + memset(ptr, 0, sizeof(int *) * 10);
>>> + memset(array, (int)sizeof(array), (0)); // no warning
>>> + memset(array, (int)sizeof(array), 32); // no warning
>>> + memset(array, 32, (0)); // no warning
>>> +
>>> + bzero(ptr, 0); // expected-warning{{'size'
>>> argument to bzero is '0'}}
>>> expected-note{{parenthesize the second argument to
>>> silence}}
>>> + real_bzero(ptr, 0); // expected-warning{{'size'
>>> argument to bzero is '0'}}
>>> expected-note{{parenthesize the second argument to
>>> silence}}
>>> +}
>>> +
>>> +void macros() {
>>> +#define ZERO 0
>>> + int array[10];
>>> + memset(array, 0xff, ZERO); // no warning
>>> + // Still emit a diagnostic for memsetting a
>>> sizeof expression:
>>> + memset(array, sizeof(array), ZERO); //
>>> expected-warning{{'sizeof'}} expected-note{{cast}}
>>> + bzero(array, ZERO); // no warning
>>> + real_bzero(array, ZERO); // no warning
>>> +#define NESTED_DONT_DIAG \
>>> + memset(array, 0xff, ZERO); \
>>> + real_bzero(array, ZERO);
>>> +
>>> + NESTED_DONT_DIAG;
>>> +
>>> +#define NESTED_DO_DIAG \
>>> + memset(array, 0xff, 0); \
>>> + real_bzero(array, 0)
>>> +
>>> + NESTED_DO_DIAG; // expected-warning{{'size'
>>> argument to memset}} expected-warning{{'size'
>>> argument to bzero}} expected-note2{{parenthesize}}
>>> +
>>> +#define FN_MACRO(p) \
>>> + memset(array, 0xff, p)
>>> +
>>> + FN_MACRO(ZERO);
>>> + FN_MACRO(0); // FIXME: should we diagnose this?
>>> +
>>> + __builtin_memset(array, 0, ZERO); // no warning
>>> + __builtin_bzero(array, ZERO);
>>> + __builtin_memset(array, 0, 0); //
>>> expected-warning{{'size' argument to memset}} //
>>> expected-note{{parenthesize}}
>>> + __builtin_bzero(array, 0); //
>>> expected-warning{{'size' argument to bzero}} //
>>> expected-note{{parenthesize}}
>>> +}
>>>
>>>
>>> _______________________________________________
>>> cfe-commits mailing list
>>> cfe-commits at lists.llvm.org
>>> <mailto:cfe-commits at lists.llvm.org>
>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>>>
>>>
>>> _______________________________________________
>>> cfe-commits mailing list
>>> cfe-commits at lists.llvm.org
>>> <mailto:cfe-commits at lists.llvm.org>
>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>>>
>>>
>>
>> _______________________________________________
>> cfe-commits mailing list
>> cfe-commits at lists.llvm.org <mailto:cfe-commits at lists.llvm.org>
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org <mailto:cfe-commits at lists.llvm.org>
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20180726/cea3d613/attachment-0001.html>
More information about the cfe-commits
mailing list