r279374 - [Sema] Don't crash on scanf on forward-declared enums.
Benjamin Kramer via cfe-commits
cfe-commits at lists.llvm.org
Sat Aug 20 11:29:57 PDT 2016
It cycled back to green. flake?
On Sat, Aug 20, 2016 at 7:27 PM, Vitaly Buka <vitalybuka at google.com> wrote:
> msan is not happy about this change
> http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-fast/builds/15681/steps/check-llvm%20msan/logs/stdio
>
> On Sat, Aug 20, 2016 at 9:59 AM Benjamin Kramer via cfe-commits
> <cfe-commits at lists.llvm.org> wrote:
>>
>> Author: d0k
>> Date: Sat Aug 20 11:51:33 2016
>> New Revision: 279374
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=279374&view=rev
>> Log:
>> [Sema] Don't crash on scanf on forward-declared enums.
>>
>> This is valid in GNU C, which allows pointers to incomplete enums. GCC
>> just pretends that the underlying type is 'int' in those cases, follow
>> that behavior.
>>
>> Modified:
>> cfe/trunk/lib/Analysis/FormatString.cpp
>> cfe/trunk/lib/Analysis/ScanfFormatString.cpp
>> cfe/trunk/test/Sema/format-strings-enum.c
>>
>> Modified: cfe/trunk/lib/Analysis/FormatString.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/FormatString.cpp?rev=279374&r1=279373&r2=279374&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/lib/Analysis/FormatString.cpp (original)
>> +++ cfe/trunk/lib/Analysis/FormatString.cpp Sat Aug 20 11:51:33 2016
>> @@ -310,8 +310,13 @@ ArgType::matchesType(ASTContext &C, Qual
>> return Match;
>>
>> case AnyCharTy: {
>> - if (const EnumType *ETy = argTy->getAs<EnumType>())
>> + if (const EnumType *ETy = argTy->getAs<EnumType>()) {
>> + // If the enum is incomplete we know nothing about the underlying
>> type.
>> + // Assume that it's 'int'.
>> + if (!ETy->getDecl()->isComplete())
>> + return NoMatch;
>> argTy = ETy->getDecl()->getIntegerType();
>> + }
>>
>> if (const BuiltinType *BT = argTy->getAs<BuiltinType>())
>> switch (BT->getKind()) {
>> @@ -327,8 +332,14 @@ ArgType::matchesType(ASTContext &C, Qual
>> }
>>
>> case SpecificTy: {
>> - if (const EnumType *ETy = argTy->getAs<EnumType>())
>> - argTy = ETy->getDecl()->getIntegerType();
>> + if (const EnumType *ETy = argTy->getAs<EnumType>()) {
>> + // If the enum is incomplete we know nothing about the underlying
>> type.
>> + // Assume that it's 'int'.
>> + if (!ETy->getDecl()->isComplete())
>> + argTy = C.IntTy;
>> + else
>> + argTy = ETy->getDecl()->getIntegerType();
>> + }
>> argTy = C.getCanonicalType(argTy).getUnqualifiedType();
>>
>> if (T == argTy)
>>
>> Modified: cfe/trunk/lib/Analysis/ScanfFormatString.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/ScanfFormatString.cpp?rev=279374&r1=279373&r2=279374&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/lib/Analysis/ScanfFormatString.cpp (original)
>> +++ cfe/trunk/lib/Analysis/ScanfFormatString.cpp Sat Aug 20 11:51:33 2016
>> @@ -418,8 +418,12 @@ bool ScanfSpecifier::fixType(QualType QT
>> QualType PT = QT->getPointeeType();
>>
>> // If it's an enum, get its underlying type.
>> - if (const EnumType *ETy = PT->getAs<EnumType>())
>> + if (const EnumType *ETy = PT->getAs<EnumType>()) {
>> + // Don't try to fix incomplete enums.
>> + if (!ETy->getDecl()->isComplete())
>> + return false;
>> PT = ETy->getDecl()->getIntegerType();
>> + }
>>
>> const BuiltinType *BT = PT->getAs<BuiltinType>();
>> if (!BT)
>>
>> Modified: cfe/trunk/test/Sema/format-strings-enum.c
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/format-strings-enum.c?rev=279374&r1=279373&r2=279374&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/test/Sema/format-strings-enum.c (original)
>> +++ cfe/trunk/test/Sema/format-strings-enum.c Sat Aug 20 11:51:33 2016
>> @@ -11,6 +11,7 @@
>> #endif
>>
>> EXTERN_C int printf(const char *,...);
>> +EXTERN_C int scanf(const char *, ...);
>>
>> typedef enum { Constant = 0 } TestEnum;
>> // Note that in C, the type of 'Constant' is 'int'. In C++ it is
>> 'TestEnum'.
>> @@ -34,3 +35,18 @@ void testLong(LongEnum input) {
>> printf("%lu", input);
>> printf("%lu", LongConstant);
>> }
>> +
>> +#ifndef __cplusplus
>> +// GNU C allows forward declaring enums.
>> +extern enum forward_declared *fwd;
>> +
>> +void forward_enum() {
>> + printf("%u", fwd); // expected-warning{{format specifies type 'unsigned
>> int' but the argument has type 'enum forward_declared *}}
>> + printf("%p", fwd);
>> +
>> + scanf("%c", fwd); // expected-warning{{format specifies type 'char *'
>> but the argument has type 'enum forward_declared *}}
>> + scanf("%u", fwd);
>> + scanf("%lu", fwd); // expected-warning{{format specifies type 'unsigned
>> long *' but the argument has type 'enum forward_declared *}}
>> + scanf("%p", fwd); // expected-warning{{format specifies type 'void **'
>> but the argument has type 'enum forward_declared *}}
>> +}
>> +#endif
>>
>>
>> _______________________________________________
>> cfe-commits mailing list
>> cfe-commits at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
More information about the cfe-commits
mailing list