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