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