r348084 - OpenCL: Improve vector printf warnings

Matt Arsenault via cfe-commits cfe-commits at lists.llvm.org
Sat Dec 1 14:16:28 PST 2018


Author: arsenm
Date: Sat Dec  1 14:16:27 2018
New Revision: 348084

URL: http://llvm.org/viewvc/llvm-project?rev=348084&view=rev
Log:
OpenCL: Improve vector printf warnings

The vector modifier is considered separate, so
don't treat it as a conversion specifier.

This is still not warning on some cases, like
using a type that isn't a valid vector element.

Fixes bug 39652

Added:
    cfe/trunk/test/SemaOpenCL/format-strings-fixit.cl
Modified:
    cfe/trunk/include/clang/AST/FormatString.h
    cfe/trunk/lib/AST/FormatString.cpp
    cfe/trunk/lib/AST/FormatStringParsing.h
    cfe/trunk/lib/AST/PrintfFormatString.cpp
    cfe/trunk/test/SemaOpenCL/printf-format-strings.cl

Modified: cfe/trunk/include/clang/AST/FormatString.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/FormatString.h?rev=348084&r1=348083&r2=348084&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/FormatString.h (original)
+++ cfe/trunk/include/clang/AST/FormatString.h Sat Dec  1 14:16:27 2018
@@ -166,8 +166,6 @@ public:
 
     ZArg, // MS extension
 
-    VArg, // OpenCL vectors
-
     // Objective-C specific specifiers.
     ObjCObjArg, // '@'
     ObjCBeg = ObjCObjArg,
@@ -305,6 +303,8 @@ public:
 
   QualType getRepresentativeType(ASTContext &C) const;
 
+  ArgType makeVectorType(ASTContext &C, unsigned NumElts) const;
+
   std::string getRepresentativeTypeName(ASTContext &C) const;
 };
 
@@ -324,6 +324,10 @@ public:
   : start(nullptr),length(0), hs(valid ? NotSpecified : Invalid), amt(0),
   UsesPositionalArg(0), UsesDotPrefix(0) {}
 
+  explicit OptionalAmount(unsigned Amount)
+    : start(nullptr), length(0), hs(Constant), amt(Amount),
+    UsesPositionalArg(false), UsesDotPrefix(false) {}
+
   bool isInvalid() const {
     return hs == Invalid;
   }
@@ -381,6 +385,8 @@ protected:
   LengthModifier LM;
   OptionalAmount FieldWidth;
   ConversionSpecifier CS;
+  OptionalAmount VectorNumElts;
+
   /// Positional arguments, an IEEE extension:
   ///  IEEE Std 1003.1, 2004 Edition
   ///  http://www.opengroup.org/onlinepubs/009695399/functions/printf.html
@@ -388,7 +394,8 @@ protected:
   unsigned argIndex;
 public:
   FormatSpecifier(bool isPrintf)
-    : CS(isPrintf), UsesPositionalArg(false), argIndex(0) {}
+    : CS(isPrintf), VectorNumElts(false),
+      UsesPositionalArg(false), argIndex(0) {}
 
   void setLengthModifier(LengthModifier lm) {
     LM = lm;
@@ -416,6 +423,14 @@ public:
     return FieldWidth;
   }
 
+  void setVectorNumElts(const OptionalAmount &Amt) {
+    VectorNumElts = Amt;
+  }
+
+  const OptionalAmount &getVectorNumElts() const {
+    return VectorNumElts;
+  }
+
   void setFieldWidth(const OptionalAmount &Amt) {
     FieldWidth = Amt;
   }
@@ -480,6 +495,9 @@ class PrintfSpecifier : public analyze_f
   OptionalFlag IsSensitive;          // '{sensitive}'
   OptionalAmount Precision;
   StringRef MaskType;
+
+  ArgType getScalarArgType(ASTContext &Ctx, bool IsObjCLiteral) const;
+
 public:
   PrintfSpecifier()
       : FormatSpecifier(/* isPrintf = */ true), HasThousandsGrouping("'"),

Modified: cfe/trunk/lib/AST/FormatString.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/FormatString.cpp?rev=348084&r1=348083&r2=348084&view=diff
==============================================================================
--- cfe/trunk/lib/AST/FormatString.cpp (original)
+++ cfe/trunk/lib/AST/FormatString.cpp Sat Dec  1 14:16:27 2018
@@ -179,6 +179,36 @@ clang::analyze_format_string::ParseArgPo
 }
 
 bool
+clang::analyze_format_string::ParseVectorModifier(FormatStringHandler &H,
+                                                  FormatSpecifier &FS,
+                                                  const char *&I,
+                                                  const char *E,
+                                                  const LangOptions &LO) {
+  if (!LO.OpenCL)
+    return false;
+
+  const char *Start = I;
+  if (*I == 'v') {
+    ++I;
+
+    if (I == E) {
+      H.HandleIncompleteSpecifier(Start, E - Start);
+      return true;
+    }
+
+    OptionalAmount NumElts = ParseAmount(I, E);
+    if (NumElts.getHowSpecified() != OptionalAmount::Constant) {
+      H.HandleIncompleteSpecifier(Start, E - Start);
+      return true;
+    }
+
+    FS.setVectorNumElts(NumElts);
+  }
+
+  return false;
+}
+
+bool
 clang::analyze_format_string::ParseLengthModifier(FormatSpecifier &FS,
                                                   const char *&I,
                                                   const char *E,
@@ -457,6 +487,14 @@ ArgType::matchesType(ASTContext &C, Qual
   llvm_unreachable("Invalid ArgType Kind!");
 }
 
+ArgType ArgType::makeVectorType(ASTContext &C, unsigned NumElts) const {
+  if (K != SpecificTy) // Won't be a valid vector element type.
+    return ArgType::Invalid();
+
+  QualType Vec = C.getExtVectorType(T, NumElts);
+  return ArgType(Vec, Name);
+}
+
 QualType ArgType::getRepresentativeType(ASTContext &C) const {
   QualType Res;
   switch (K) {
@@ -618,9 +656,6 @@ const char *ConversionSpecifier::toStrin
 
   // MS specific specifiers.
   case ZArg: return "Z";
-
- // OpenCL specific specifiers.
-  case VArg: return "v";
   }
   return nullptr;
 }
@@ -878,8 +913,6 @@ bool FormatSpecifier::hasStandardConvers
     case ConversionSpecifier::CArg:
     case ConversionSpecifier::SArg:
       return LangOpt.ObjC;
-    case ConversionSpecifier::VArg:
-      return LangOpt.OpenCL;
     case ConversionSpecifier::InvalidSpecifier:
     case ConversionSpecifier::FreeBSDbArg:
     case ConversionSpecifier::FreeBSDDArg:

Modified: cfe/trunk/lib/AST/FormatStringParsing.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/FormatStringParsing.h?rev=348084&r1=348083&r2=348084&view=diff
==============================================================================
--- cfe/trunk/lib/AST/FormatStringParsing.h (original)
+++ cfe/trunk/lib/AST/FormatStringParsing.h Sat Dec  1 14:16:27 2018
@@ -41,6 +41,10 @@ bool ParseArgPosition(FormatStringHandle
                       FormatSpecifier &CS, const char *Start,
                       const char *&Beg, const char *E);
 
+bool ParseVectorModifier(FormatStringHandler &H,
+                         FormatSpecifier &FS, const char *&Beg, const char *E,
+                         const LangOptions &LO);
+
 /// Returns true if a LengthModifier was parsed and installed in the
 /// FormatSpecifier& argument, and false otherwise.
 bool ParseLengthModifier(FormatSpecifier &FS, const char *&Beg, const char *E,

Modified: cfe/trunk/lib/AST/PrintfFormatString.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/PrintfFormatString.cpp?rev=348084&r1=348083&r2=348084&view=diff
==============================================================================
--- cfe/trunk/lib/AST/PrintfFormatString.cpp (original)
+++ cfe/trunk/lib/AST/PrintfFormatString.cpp Sat Dec  1 14:16:27 2018
@@ -247,6 +247,9 @@ static PrintfSpecifierResult ParsePrintf
     }
   }
 
+  if (ParseVectorModifier(H, FS, I, E, LO))
+    return true;
+
   // Look for the length modifier.
   if (ParseLengthModifier(FS, I, E, LO) && I == E) {
     // No more characters left?
@@ -363,11 +366,6 @@ static PrintfSpecifierResult ParsePrintf
       if (Target.getTriple().isOSMSVCRT())
         k = ConversionSpecifier::ZArg;
       break;
-    // OpenCL specific.
-    case 'v':
-      if (LO.OpenCL)
-        k = ConversionSpecifier::VArg;
-      break;
   }
 
   // Check to see if we used the Objective-C modifier flags with
@@ -466,13 +464,8 @@ bool clang::analyze_format_string::Parse
 // Methods on PrintfSpecifier.
 //===----------------------------------------------------------------------===//
 
-ArgType PrintfSpecifier::getArgType(ASTContext &Ctx,
-                                    bool IsObjCLiteral) const {
-  const PrintfConversionSpecifier &CS = getConversionSpecifier();
-
-  if (!CS.consumesDataArgument())
-    return ArgType::Invalid();
-
+ArgType PrintfSpecifier::getScalarArgType(ASTContext &Ctx,
+                                          bool IsObjCLiteral) const {
   if (CS.getKind() == ConversionSpecifier::cArg)
     switch (LM.getKind()) {
       case LengthModifier::None:
@@ -632,6 +625,21 @@ ArgType PrintfSpecifier::getArgType(ASTC
   return ArgType();
 }
 
+
+ArgType PrintfSpecifier::getArgType(ASTContext &Ctx,
+                                    bool IsObjCLiteral) const {
+  const PrintfConversionSpecifier &CS = getConversionSpecifier();
+
+  if (!CS.consumesDataArgument())
+    return ArgType::Invalid();
+
+  ArgType ScalarTy = getScalarArgType(Ctx, IsObjCLiteral);
+  if (!ScalarTy.isValid() || VectorNumElts.isInvalid())
+    return ScalarTy;
+
+  return ScalarTy.makeVectorType(Ctx, VectorNumElts.getConstantAmount());
+}
+
 bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt,
                               ASTContext &Ctx, bool IsObjCLiteral) {
   // %n is different from other conversion specifiers; don't try to fix it.
@@ -681,8 +689,17 @@ bool PrintfSpecifier::fixType(QualType Q
   if (const EnumType *ETy = QT->getAs<EnumType>())
     QT = ETy->getDecl()->getIntegerType();
 
-  // We can only work with builtin types.
   const BuiltinType *BT = QT->getAs<BuiltinType>();
+  if (!BT) {
+    const VectorType *VT = QT->getAs<VectorType>();
+    if (VT) {
+      QT = VT->getElementType();
+      BT = QT->getAs<BuiltinType>();
+      VectorNumElts = OptionalAmount(VT->getNumElements());
+    }
+  }
+
+  // We can only work with builtin types.
   if (!BT)
     return false;
 
@@ -854,6 +871,11 @@ void PrintfSpecifier::toString(raw_ostre
   FieldWidth.toString(os);
   // Precision
   Precision.toString(os);
+
+  // Vector modifier
+  if (!VectorNumElts.isInvalid())
+    os << 'v' << VectorNumElts.getConstantAmount();
+
   // Length modifier
   os << LM.toString();
   // Conversion specifier
@@ -1032,7 +1054,6 @@ bool PrintfSpecifier::hasValidPrecision(
   case ConversionSpecifier::FreeBSDrArg:
   case ConversionSpecifier::FreeBSDyArg:
   case ConversionSpecifier::PArg:
-  case ConversionSpecifier::VArg:
     return true;
 
   default:

Added: cfe/trunk/test/SemaOpenCL/format-strings-fixit.cl
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaOpenCL/format-strings-fixit.cl?rev=348084&view=auto
==============================================================================
--- cfe/trunk/test/SemaOpenCL/format-strings-fixit.cl (added)
+++ cfe/trunk/test/SemaOpenCL/format-strings-fixit.cl Sat Dec  1 14:16:27 2018
@@ -0,0 +1,24 @@
+// RUN: cp %s %t
+// RUN: %clang_cc1 -cl-std=CL1.2 -pedantic -Wall -fixit %t
+// RUN: %clang_cc1 -cl-std=CL1.2 -fsyntax-only -pedantic -Wall -Werror %t
+// RUN: %clang_cc1 -cl-std=CL1.2 -E -o - %t | FileCheck %s
+
+typedef __attribute__((ext_vector_type(4))) int int4;
+typedef __attribute__((ext_vector_type(8))) int int8;
+
+int printf(__constant const char* st, ...) __attribute__((format(printf, 1, 2)));
+
+
+void vector_fixits() {
+  printf("%v4f", (int4) 123);
+  // CHECK: printf("%v4d", (int4) 123);
+
+  printf("%v8d", (int4) 123);
+  // CHECK: printf("%v4d", (int4) 123);
+
+  printf("%v4d", (int8) 123);
+  // CHECK: printf("%v8d", (int8) 123);
+
+  printf("%v4f", (int8) 123);
+  // CHECK: printf("%v8d", (int8) 123);
+}

Modified: cfe/trunk/test/SemaOpenCL/printf-format-strings.cl
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaOpenCL/printf-format-strings.cl?rev=348084&r1=348083&r2=348084&view=diff
==============================================================================
--- cfe/trunk/test/SemaOpenCL/printf-format-strings.cl (original)
+++ cfe/trunk/test/SemaOpenCL/printf-format-strings.cl Sat Dec  1 14:16:27 2018
@@ -1,34 +1,94 @@
-// RUN: %clang_cc1 -cl-std=CL1.2 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -cl-std=CL1.2 -cl-ext=+cl_khr_fp64 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -cl-std=CL1.2 -cl-ext=-cl_khr_fp64 -fsyntax-only -verify %s
 
 typedef __attribute__((ext_vector_type(2))) float float2;
 typedef __attribute__((ext_vector_type(4))) float float4;
+
+typedef __attribute__((ext_vector_type(2))) int int2;
 typedef __attribute__((ext_vector_type(4))) int int4;
+typedef __attribute__((ext_vector_type(16))) int int16;
 
 int printf(__constant const char* st, ...) __attribute__((format(printf, 1, 2)));
 
 kernel void format_v4f32(float4 arg)
 {
-    printf("%v4f\n", arg); // expected-no-diagnostics
+#ifdef cl_khr_fp64
+    printf("%v4f\n", arg);
+
+    // Precision modifier
+    printf("%.2v4f\n", arg);
+#else
+    // FIXME: These should not warn, and the type should be expected to be float.
+    printf("%v4f\n", arg);  // expected-warning {{double __attribute__((ext_vector_type(4)))' but the argument has type 'float4' (vector of 4 'float' values)}}
+
+    // Precision modifier
+    printf("%.2v4f\n", arg); // expected-warning {{double __attribute__((ext_vector_type(4)))' but the argument has type 'float4' (vector of 4 'float' values)}}
+#endif
 }
 
-kernel void format_v4f32_wrong_num_elts(float2 arg)
+kernel void format_only_v(int arg)
 {
-    printf("%v4f\n", arg); // expected-no-diagnostics
+    printf("%v", arg); // expected-warning {{incomplete format specifier}}
 }
 
-kernel void vector_precision_modifier_v4f32(float4 arg)
+kernel void format_missing_num(int arg)
 {
-    printf("%.2v4f\n", arg); // expected-no-diagnostics
+    printf("%v4", arg); // expected-warning {{incomplete format specifier}}
+}
+
+kernel void format_not_num(int arg)
+{
+    printf("%vNd", arg); // expected-warning {{incomplete format specifier}}
+    printf("%v*d", arg); // expected-warning {{incomplete format specifier}}
+}
+
+kernel void format_v16i32(int16 arg)
+{
+    printf("%v16d\n", arg);
+}
+
+kernel void format_v4i32_scalar(int arg)
+{
+   printf("%v4d\n", arg); // expected-warning  {{format specifies type 'int __attribute__((ext_vector_type(4)))' but the argument has type 'int'}}
+}
+
+kernel void format_v4i32_wrong_num_elts_2_to_4(int2 arg)
+{
+    printf("%v4d\n", arg); // expected-warning {{format specifies type 'int __attribute__((ext_vector_type(4)))' but the argument has type 'int2' (vector of 2 'int' values)}}
+}
+
+kernel void format_missing_num_elts_format(int4 arg)
+{
+    printf("%vd\n", arg); // expected-warning {{incomplete format specifier}}
+}
+
+kernel void format_v4f32_scalar(float arg)
+{
+    printf("%v4f\n", arg); // expected-warning {{format specifies type 'double __attribute__((ext_vector_type(4)))' but the argument has type 'float'}}
+}
+
+kernel void format_v4f32_wrong_num_elts(float2 arg)
+{
+    printf("%v4f\n", arg); // expected-warning {{format specifies type 'double __attribute__((ext_vector_type(4)))' but the argument has type 'float2' (vector of 2 'float' values)}}
 }
 
-// FIXME: This should warn
 kernel void format_missing_num_elts(float4 arg)
 {
-    printf("%vf\n", arg); // expected-no-diagnostics
+    printf("%vf\n", arg); // expected-warning {{incomplete format specifier}}
+}
+
+kernel void vector_precision_modifier_v4i32_to_v4f32(int4 arg)
+{
+    printf("%.2v4f\n", arg); // expected-warning {{format specifies type 'double __attribute__((ext_vector_type(4)))' but the argument has type 'int4' (vector of 4 'int' values)}}
+}
+
+kernel void invalid_Y(int4 arg)
+{
+    printf("%v4Y\n", arg); // expected-warning {{invalid conversion specifier 'Y'}}
 }
 
 // FIXME: This should warn
-kernel void vector_precision_modifier_v4i32(int4 arg)
+kernel void crash_on_s(int4 arg)
 {
-    printf("%.2v4f\n", arg); // expected-no-diagnostics
+    printf("%v4s\n", arg);
 }




More information about the cfe-commits mailing list