diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/FormatString.cpp | 34 | ||||
-rw-r--r-- | clang/lib/AST/PrintfFormatString.cpp | 34 | ||||
-rw-r--r-- | clang/lib/AST/ScanfFormatString.cpp | 9 | ||||
-rw-r--r-- | clang/lib/Headers/opencl-c.h | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 6 |
5 files changed, 64 insertions, 21 deletions
diff --git a/clang/lib/AST/FormatString.cpp b/clang/lib/AST/FormatString.cpp index e743e23078a..578d5bc5673 100644 --- a/clang/lib/AST/FormatString.cpp +++ b/clang/lib/AST/FormatString.cpp @@ -223,6 +223,9 @@ clang::analyze_format_string::ParseLengthModifier(FormatSpecifier &FS, if (I != E && *I == 'h') { ++I; lmKind = LengthModifier::AsChar; + } else if (I != E && *I == 'l' && LO.OpenCL) { + ++I; + lmKind = LengthModifier::AsShortLong; } else { lmKind = LengthModifier::AsShort; } @@ -487,7 +490,8 @@ ArgType::matchesType(ASTContext &C, QualType argTy) const { } ArgType ArgType::makeVectorType(ASTContext &C, unsigned NumElts) const { - if (K != SpecificTy) // Won't be a valid vector element type. + // Check for valid vector element types. + if (T.isNull()) return ArgType::Invalid(); QualType Vec = C.getExtVectorType(T, NumElts); @@ -572,6 +576,8 @@ analyze_format_string::LengthModifier::toString() const { return "hh"; case AsShort: return "h"; + case AsShortLong: + return "hl"; case AsLong: // or AsWideChar return "l"; case AsLongLong: @@ -707,13 +713,18 @@ void OptionalAmount::toString(raw_ostream &os) const { } } -bool FormatSpecifier::hasValidLengthModifier(const TargetInfo &Target) const { +bool FormatSpecifier::hasValidLengthModifier(const TargetInfo &Target, + const LangOptions &LO) const { switch (LM.getKind()) { case LengthModifier::None: return true; // Handle most integer flags case LengthModifier::AsShort: + // Length modifier only applies to FP vectors. + if (LO.OpenCL && CS.isDoubleArg()) + return !VectorNumElts.isInvalid(); + if (Target.getTriple().isOSMSVCRT()) { switch (CS.getKind()) { case ConversionSpecifier::cArg: @@ -752,8 +763,18 @@ bool FormatSpecifier::hasValidLengthModifier(const TargetInfo &Target) const { return false; } + case LengthModifier::AsShortLong: + return LO.OpenCL && !VectorNumElts.isInvalid(); + // Handle 'l' flag case LengthModifier::AsLong: // or AsWideChar + if (CS.isDoubleArg()) { + // Invalid for OpenCL FP scalars. + if (LO.OpenCL && VectorNumElts.isInvalid()) + return false; + return true; + } + switch (CS.getKind()) { case ConversionSpecifier::dArg: case ConversionSpecifier::DArg: @@ -764,14 +785,6 @@ bool FormatSpecifier::hasValidLengthModifier(const TargetInfo &Target) const { case ConversionSpecifier::UArg: case ConversionSpecifier::xArg: case ConversionSpecifier::XArg: - case ConversionSpecifier::aArg: - case ConversionSpecifier::AArg: - case ConversionSpecifier::fArg: - case ConversionSpecifier::FArg: - case ConversionSpecifier::eArg: - case ConversionSpecifier::EArg: - case ConversionSpecifier::gArg: - case ConversionSpecifier::GArg: case ConversionSpecifier::nArg: case ConversionSpecifier::cArg: case ConversionSpecifier::sArg: @@ -878,6 +891,7 @@ bool FormatSpecifier::hasStandardLengthModifier() const { case LengthModifier::AsInt3264: case LengthModifier::AsInt64: case LengthModifier::AsWide: + case LengthModifier::AsShortLong: // ??? return false; } llvm_unreachable("Invalid LengthModifier Kind!"); diff --git a/clang/lib/AST/PrintfFormatString.cpp b/clang/lib/AST/PrintfFormatString.cpp index df0a66456c3..a1207aae5aa 100644 --- a/clang/lib/AST/PrintfFormatString.cpp +++ b/clang/lib/AST/PrintfFormatString.cpp @@ -315,7 +315,11 @@ static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H, case 'f': k = ConversionSpecifier::fArg; break; case 'g': k = ConversionSpecifier::gArg; break; case 'i': k = ConversionSpecifier::iArg; break; - case 'n': k = ConversionSpecifier::nArg; break; + case 'n': + // Not handled, but reserved in OpenCL. + if (!LO.OpenCL) + k = ConversionSpecifier::nArg; + break; case 'o': k = ConversionSpecifier::oArg; break; case 'p': k = ConversionSpecifier::pArg; break; case 's': k = ConversionSpecifier::sArg; break; @@ -486,10 +490,12 @@ ArgType PrintfSpecifier::getScalarArgType(ASTContext &Ctx, // GNU extension. return Ctx.LongLongTy; case LengthModifier::None: + case LengthModifier::AsShortLong: return Ctx.IntTy; case LengthModifier::AsInt32: return ArgType(Ctx.IntTy, "__int32"); - case LengthModifier::AsChar: return ArgType::AnyCharTy; + case LengthModifier::AsChar: + return ArgType::AnyCharTy; case LengthModifier::AsShort: return Ctx.ShortTy; case LengthModifier::AsLong: return Ctx.LongTy; case LengthModifier::AsLongLong: @@ -520,6 +526,7 @@ ArgType PrintfSpecifier::getScalarArgType(ASTContext &Ctx, // GNU extension. return Ctx.UnsignedLongLongTy; case LengthModifier::None: + case LengthModifier::AsShortLong: return Ctx.UnsignedIntTy; case LengthModifier::AsInt32: return ArgType(Ctx.UnsignedIntTy, "unsigned __int32"); @@ -549,6 +556,18 @@ ArgType PrintfSpecifier::getScalarArgType(ASTContext &Ctx, } if (CS.isDoubleArg()) { + if (!VectorNumElts.isInvalid()) { + switch (LM.getKind()) { + case LengthModifier::AsShort: + return Ctx.HalfTy; + case LengthModifier::AsShortLong: + return Ctx.FloatTy; + case LengthModifier::AsLong: + default: + return Ctx.DoubleTy; + } + } + if (LM.getKind() == LengthModifier::AsLongDouble) return Ctx.LongDoubleTy; return Ctx.DoubleTy; @@ -582,6 +601,8 @@ ArgType PrintfSpecifier::getScalarArgType(ASTContext &Ctx, case LengthModifier::AsInt64: case LengthModifier::AsWide: return ArgType::Invalid(); + case LengthModifier::AsShortLong: + llvm_unreachable("only used for OpenCL which doesn not handle nArg"); } } @@ -760,10 +781,13 @@ bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt, case BuiltinType::UInt: case BuiltinType::Int: case BuiltinType::Float: + LM.setKind(VectorNumElts.isInvalid() ? + LengthModifier::None : LengthModifier::AsShortLong); + break; case BuiltinType::Double: - LM.setKind(LengthModifier::None); + LM.setKind(VectorNumElts.isInvalid() ? + LengthModifier::None : LengthModifier::AsLong); break; - case BuiltinType::Char_U: case BuiltinType::UChar: case BuiltinType::Char_S: @@ -796,7 +820,7 @@ bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt, namedTypeToLengthModifier(QT, LM); // If fixing the length modifier was enough, we might be done. - if (hasValidLengthModifier(Ctx.getTargetInfo())) { + if (hasValidLengthModifier(Ctx.getTargetInfo(), LangOpt)) { // If we're going to offer a fix anyway, make sure the sign matches. switch (CS.getKind()) { case ConversionSpecifier::uArg: diff --git a/clang/lib/AST/ScanfFormatString.cpp b/clang/lib/AST/ScanfFormatString.cpp index ff4883305a7..1a87de70f86 100644 --- a/clang/lib/AST/ScanfFormatString.cpp +++ b/clang/lib/AST/ScanfFormatString.cpp @@ -261,9 +261,10 @@ ArgType ScanfSpecifier::getArgType(ASTContext &Ctx) const { case LengthModifier::AsInt32: case LengthModifier::AsInt3264: case LengthModifier::AsWide: + case LengthModifier::AsShortLong: return ArgType::Invalid(); } - llvm_unreachable("Unsupported LenghtModifier Type"); + llvm_unreachable("Unsupported LengthModifier Type"); // Unsigned int. case ConversionSpecifier::oArg: @@ -301,9 +302,10 @@ ArgType ScanfSpecifier::getArgType(ASTContext &Ctx) const { case LengthModifier::AsInt32: case LengthModifier::AsInt3264: case LengthModifier::AsWide: + case LengthModifier::AsShortLong: return ArgType::Invalid(); } - llvm_unreachable("Unsupported LenghtModifier Type"); + llvm_unreachable("Unsupported LengthModifier Type"); // Float. case ConversionSpecifier::aArg: @@ -396,6 +398,7 @@ ArgType ScanfSpecifier::getArgType(ASTContext &Ctx) const { case LengthModifier::AsInt32: case LengthModifier::AsInt3264: case LengthModifier::AsWide: + case LengthModifier::AsShortLong: return ArgType::Invalid(); } @@ -501,7 +504,7 @@ bool ScanfSpecifier::fixType(QualType QT, QualType RawQT, namedTypeToLengthModifier(PT, LM); // If fixing the length modifier was enough, we are done. - if (hasValidLengthModifier(Ctx.getTargetInfo())) { + if (hasValidLengthModifier(Ctx.getTargetInfo(), LangOpt)) { const analyze_scanf::ArgType &AT = getArgType(Ctx); if (AT.isValid() && AT.matchesType(Ctx, QT)) return true; diff --git a/clang/lib/Headers/opencl-c.h b/clang/lib/Headers/opencl-c.h index e1349cbe199..0a36a84deb8 100644 --- a/clang/lib/Headers/opencl-c.h +++ b/clang/lib/Headers/opencl-c.h @@ -14469,7 +14469,7 @@ half16 __ovld __cnfn shuffle2(half16 x, half16 y, ushort16 mask); #if __OPENCL_C_VERSION__ >= CL_VERSION_1_2 // OpenCL v1.2 s6.12.13, v2.0 s6.13.13 - printf -int printf(__constant const char* st, ...); +int printf(__constant const char* st, ...) __attribute__((format(printf, 1, 2))); #endif // OpenCL v1.1 s6.11.3, v1.2 s6.12.14, v2.0 s6.13.14 - Image Read and Write Functions diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 0598da214ec..5a5e5616e80 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -7650,7 +7650,8 @@ CheckPrintfHandler::HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier startSpecifier, specifierLen); // Check the length modifier is valid with the given conversion specifier. - if (!FS.hasValidLengthModifier(S.getASTContext().getTargetInfo())) + if (!FS.hasValidLengthModifier(S.getASTContext().getTargetInfo(), + S.getLangOpts())) HandleInvalidLengthModifier(FS, CS, startSpecifier, specifierLen, diag::warn_format_nonsensical_length); else if (!FS.hasStandardLengthModifier()) @@ -8154,7 +8155,8 @@ bool CheckScanfHandler::HandleScanfSpecifier( } // Check the length modifier is valid with the given conversion specifier. - if (!FS.hasValidLengthModifier(S.getASTContext().getTargetInfo())) + if (!FS.hasValidLengthModifier(S.getASTContext().getTargetInfo(), + S.getLangOpts())) HandleInvalidLengthModifier(FS, CS, startSpecifier, specifierLen, diag::warn_format_nonsensical_length); else if (!FS.hasStandardLengthModifier()) |