summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaDeclAttr.cpp
diff options
context:
space:
mode:
authorDaniel Dunbar <daniel@zuster.org>2009-10-18 02:09:17 +0000
committerDaniel Dunbar <daniel@zuster.org>2009-10-18 02:09:17 +0000
commitccbd9a46e762474a2d89571eb74743eeda72bdb7 (patch)
tree72f8870c528f85ea88f841bce0c5263ac5b8c827 /clang/lib/Sema/SemaDeclAttr.cpp
parentcb2a056980fd2d2546ebb4ee5e23d4255a4c2356 (diff)
downloadbcm5719-llvm-ccbd9a46e762474a2d89571eb74743eeda72bdb7.tar.gz
bcm5719-llvm-ccbd9a46e762474a2d89571eb74743eeda72bdb7.zip
Simplify HandleFormatAttr.
- I have this crazy dream that one day someone will invent a miraculous tool so that developers, instead of hand optimizing their source code to obscure its intent and decrease its maleability, will instead write what they mean, and this strange and wonderful tool -- which I imagine would be called something fancy sounding like "an optimizing compiler" -- will make their code fast *for* them. With all the saved time, developers could maybe even focus on making the magic "optimizing compiler" better!! - No intended functionality change, all though I expect the universe to mock me for snarkiness. llvm-svn: 84390
Diffstat (limited to 'clang/lib/Sema/SemaDeclAttr.cpp')
-rw-r--r--clang/lib/Sema/SemaDeclAttr.cpp76
1 files changed, 41 insertions, 35 deletions
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 50ebb49e7d5..e57111f6cd8 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -1202,6 +1202,35 @@ static void HandleFormatArgAttr(Decl *d, const AttributeList &Attr, Sema &S) {
d->addAttr(::new (S.Context) FormatArgAttr(Idx.getZExtValue()));
}
+enum FormatAttrKind {
+ CFStringFormat,
+ NSStringFormat,
+ StrftimeFormat,
+ SupportedFormat,
+ InvalidFormat
+};
+
+/// getFormatAttrKind - Map from format attribute names to supported format
+/// types.
+static FormatAttrKind getFormatAttrKind(llvm::StringRef Format) {
+ // Check for formats that get handled specially.
+ if (Format == "NSString")
+ return NSStringFormat;
+ if (Format == "CFString")
+ return CFStringFormat;
+ if (Format == "strftime")
+ return StrftimeFormat;
+
+ // Otherwise, check for supported formats.
+ if (Format == "scanf" || Format == "printf" || Format == "printf0" ||
+ Format == "strfmon" || Format == "cmn_err" || Format == "strftime" ||
+ Format == "NSString" || Format == "CFString" || Format == "vcmn_err" ||
+ Format == "zcmn_err")
+ return SupportedFormat;
+
+ return InvalidFormat;
+}
+
/// Handle __attribute__((format(type,idx,firstarg))) attributes based on
/// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -1226,40 +1255,17 @@ static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) {
unsigned NumArgs = getFunctionOrMethodNumArgs(d);
unsigned FirstIdx = 1;
- const char *Format = Attr.getParameterName()->getName();
- unsigned FormatLen = Attr.getParameterName()->getLength();
+ llvm::StringRef Format = Attr.getParameterName()->getNameStr();
// Normalize the argument, __foo__ becomes foo.
- if (FormatLen > 4 && Format[0] == '_' && Format[1] == '_' &&
- Format[FormatLen - 2] == '_' && Format[FormatLen - 1] == '_') {
- Format += 2;
- FormatLen -= 4;
- }
-
- bool Supported = false;
- bool is_NSString = false;
- bool is_strftime = false;
- bool is_CFString = false;
-
- switch (FormatLen) {
- default: break;
- case 5: Supported = !memcmp(Format, "scanf", 5); break;
- case 6: Supported = !memcmp(Format, "printf", 6); break;
- case 7: Supported = !memcmp(Format, "printf0", 7) ||
- !memcmp(Format, "strfmon", 7) ||
- !memcmp(Format, "cmn_err", 7); break;
- case 8:
- Supported = (is_strftime = !memcmp(Format, "strftime", 8)) ||
- (is_NSString = !memcmp(Format, "NSString", 8)) ||
- !memcmp(Format, "vcmn_err", 8) ||
- !memcmp(Format, "zcmn_err", 8) ||
- (is_CFString = !memcmp(Format, "CFString", 8));
- break;
- }
+ if (Format.startswith("__") && Format.endswith("__"))
+ Format = Format.substr(2, Format.size() - 4);
- if (!Supported) {
+ // Check for supported formats.
+ FormatAttrKind Kind = getFormatAttrKind(Format);
+ if (Kind == InvalidFormat) {
S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
- << "format" << Attr.getParameterName()->getName();
+ << "format" << Attr.getParameterName()->getNameStr();
return;
}
@@ -1296,13 +1302,13 @@ static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) {
// make sure the format string is really a string
QualType Ty = getFunctionOrMethodArgType(d, ArgIdx);
- if (is_CFString) {
+ if (Kind == CFStringFormat) {
if (!isCFStringType(Ty, S.Context)) {
S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
<< "a CFString" << IdxExpr->getSourceRange();
return;
}
- } else if (is_NSString) {
+ } else if (Kind == NSStringFormat) {
// FIXME: do we need to check if the type is NSString*? What are the
// semantics?
if (!isNSStringType(Ty, S.Context)) {
@@ -1340,7 +1346,7 @@ static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) {
// strftime requires FirstArg to be 0 because it doesn't read from any
// variable the input is just the current time + the format string.
- if (is_strftime) {
+ if (Kind == StrftimeFormat) {
if (FirstArg != 0) {
S.Diag(Attr.getLoc(), diag::err_format_strftime_third_parameter)
<< FirstArgExpr->getSourceRange();
@@ -1353,8 +1359,8 @@ static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) FormatAttr(std::string(Format, FormatLen),
- Idx.getZExtValue(), FirstArg.getZExtValue()));
+ d->addAttr(::new (S.Context) FormatAttr(Format, Idx.getZExtValue(),
+ FirstArg.getZExtValue()));
}
static void HandleTransparentUnionAttr(Decl *d, const AttributeList &Attr,
OpenPOWER on IntegriCloud