diff options
Diffstat (limited to 'clang/lib/AST')
-rw-r--r-- | clang/lib/AST/FormatString.cpp | 43 | ||||
-rw-r--r-- | clang/lib/AST/FormatStringParsing.h | 4 | ||||
-rw-r--r-- | clang/lib/AST/PrintfFormatString.cpp | 49 |
3 files changed, 77 insertions, 19 deletions
diff --git a/clang/lib/AST/FormatString.cpp b/clang/lib/AST/FormatString.cpp index 565bd03a7bb..04bd48f14a2 100644 --- a/clang/lib/AST/FormatString.cpp +++ b/clang/lib/AST/FormatString.cpp @@ -179,6 +179,36 @@ clang::analyze_format_string::ParseArgPosition(FormatStringHandler &H, } 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, QualType argTy) const { 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::toString() const { // MS specific specifiers. case ZArg: return "Z"; - - // OpenCL specific specifiers. - case VArg: return "v"; } return nullptr; } @@ -878,8 +913,6 @@ bool FormatSpecifier::hasStandardConversionSpecifier( case ConversionSpecifier::CArg: case ConversionSpecifier::SArg: return LangOpt.ObjC; - case ConversionSpecifier::VArg: - return LangOpt.OpenCL; case ConversionSpecifier::InvalidSpecifier: case ConversionSpecifier::FreeBSDbArg: case ConversionSpecifier::FreeBSDDArg: diff --git a/clang/lib/AST/FormatStringParsing.h b/clang/lib/AST/FormatStringParsing.h index 91fab155e4c..9da829adcb4 100644 --- a/clang/lib/AST/FormatStringParsing.h +++ b/clang/lib/AST/FormatStringParsing.h @@ -41,6 +41,10 @@ bool ParseArgPosition(FormatStringHandler &H, 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, diff --git a/clang/lib/AST/PrintfFormatString.cpp b/clang/lib/AST/PrintfFormatString.cpp index 877f89055ab..e0a0c5b7582 100644 --- a/clang/lib/AST/PrintfFormatString.cpp +++ b/clang/lib/AST/PrintfFormatString.cpp @@ -247,6 +247,9 @@ static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H, } } + 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 ParsePrintfSpecifier(FormatStringHandler &H, 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::ParseFormatStringHasSArg(const char *I, // 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(ASTContext &Ctx, 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 QT, const LangOptions &LangOpt, 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_ostream &os) const { 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() const { case ConversionSpecifier::FreeBSDrArg: case ConversionSpecifier::FreeBSDyArg: case ConversionSpecifier::PArg: - case ConversionSpecifier::VArg: return true; default: |