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@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@lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits >
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits