summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/FormatString.cpp34
-rw-r--r--clang/lib/AST/PrintfFormatString.cpp34
-rw-r--r--clang/lib/AST/ScanfFormatString.cpp9
-rw-r--r--clang/lib/Headers/opencl-c.h2
-rw-r--r--clang/lib/Sema/SemaChecking.cpp6
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())
OpenPOWER on IntegriCloud