[cfe-commits] r57778 - in /cfe/trunk: lib/Sema/SemaDeclAttr.cpp test/Sema/attr-noreturn.c test/Sema/attr-unused.c test/SemaObjC/method-attributes.m
Daniel Dunbar
daniel at zuster.org
Sat Oct 18 19:04:17 PDT 2008
Author: ddunbar
Date: Sat Oct 18 21:04:16 2008
New Revision: 57778
URL: http://llvm.org/viewvc/llvm-project?rev=57778&view=rev
Log:
Improve attribute parsing & tests.
- Support noreturn on function-typed variables.
- Extend isFunctionOrMethod to return true for K&R functions and
provide hasFunctionProto to check if a decl has information about
its arguments. This code needs some serious cleaning, but works.
- Add/improve test cases for noreturn and unused.
Added:
cfe/trunk/test/Sema/attr-noreturn.c
cfe/trunk/test/Sema/attr-unused.c
Modified:
cfe/trunk/lib/Sema/SemaDeclAttr.cpp
cfe/trunk/test/SemaObjC/method-attributes.m
Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=57778&r1=57777&r2=57778&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Sat Oct 18 21:04:16 2008
@@ -25,7 +25,7 @@
// Helper functions
//===----------------------------------------------------------------------===//
-static const FunctionTypeProto *getFunctionProto(Decl *d) {
+static const FunctionType *getFunctionType(Decl *d) {
QualType Ty;
if (ValueDecl *decl = dyn_cast<ValueDecl>(d))
Ty = decl->getType();
@@ -38,25 +38,38 @@
if (Ty->isFunctionPointerType())
Ty = Ty->getAsPointerType()->getPointeeType();
-
- if (const FunctionType *FnTy = Ty->getAsFunctionType())
- return dyn_cast<FunctionTypeProto>(FnTy->getAsFunctionType());
-
- return 0;
+
+ return Ty->getAsFunctionType();
}
// FIXME: We should provide an abstraction around a method or function
// to provide the following bits of information.
-/// isFunctionOrMethod - Return true if the given decl is a (non-K&R)
-/// function or an Objective-C method.
+/// isFunctionOrMethod - Return true if the given decl has function
+/// type (function or function-typed variable) or an Objective-C
+/// method.
static bool isFunctionOrMethod(Decl *d) {
- return getFunctionProto(d) || isa<ObjCMethodDecl>(d);
+ return getFunctionType(d) || isa<ObjCMethodDecl>(d);
+}
+/// hasFunctionProto - Return true if the given decl has a argument
+/// information. This decl should have already passed
+/// isFunctionOrMethod.
+static bool hasFunctionProto(Decl *d) {
+ if (const FunctionType *FnTy = getFunctionType(d)) {
+ return isa<FunctionTypeProto>(FnTy);
+ } else {
+ assert(isa<ObjCMethodDecl>(d));
+ return true;
+ }
}
+/// getFunctionOrMethodNumArgs - Return number of function or method
+/// arguments. It is an error to call this on a K&R function (use
+/// hasFunctionProto first).
static unsigned getFunctionOrMethodNumArgs(Decl *d) {
- if (const FunctionTypeProto *proto = getFunctionProto(d)) {
+ if (const FunctionType *FnTy = getFunctionType(d)) {
+ const FunctionTypeProto *proto = cast<FunctionTypeProto>(FnTy);
return proto->getNumArgs();
} else {
return cast<ObjCMethodDecl>(d)->getNumParams();
@@ -64,7 +77,8 @@
}
static QualType getFunctionOrMethodArgType(Decl *d, unsigned Idx) {
- if (const FunctionTypeProto *proto = getFunctionProto(d)) {
+ if (const FunctionType *FnTy = getFunctionType(d)) {
+ const FunctionTypeProto *proto = cast<FunctionTypeProto>(FnTy);
return proto->getArgType(Idx);
} else {
return cast<ObjCMethodDecl>(d)->getParamDecl(Idx)->getType();
@@ -72,7 +86,8 @@
}
static bool isFunctionOrMethodVariadic(Decl *d) {
- if (const FunctionTypeProto *proto = getFunctionProto(d)) {
+ if (const FunctionType *FnTy = getFunctionType(d)) {
+ const FunctionTypeProto *proto = cast<FunctionTypeProto>(FnTy);
return proto->isVariadic();
} else {
return cast<ObjCMethodDecl>(d)->isVariadic();
@@ -289,17 +304,15 @@
}
static void HandleNonNullAttr(Decl *d, const AttributeList &Attr, Sema &S) {
-
// GCC ignores the nonnull attribute on K&R style function
// prototypes, so we ignore it as well
- const FunctionTypeProto *proto = getFunctionProto(d);
- if (!proto) {
+ if (!isFunctionOrMethod(d) || !hasFunctionProto(d)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type,
"nonnull", "function");
return;
}
- unsigned NumArgs = proto->getNumArgs();
+ unsigned NumArgs = getFunctionOrMethodNumArgs(d);
// The nonnull attribute only applies to pointers.
llvm::SmallVector<unsigned, 10> NonNullArgs;
@@ -328,7 +341,7 @@
--x;
// Is the function argument a pointer type?
- if (!proto->getArgType(x)->isPointerType()) {
+ if (!getFunctionOrMethodArgType(d, x)->isPointerType()) {
// FIXME: Should also highlight argument in decl.
S.Diag(Attr.getLoc(), diag::err_nonnull_pointers_only,
"nonnull", Ex->getSourceRange());
@@ -341,12 +354,9 @@
// If no arguments were specified to __attribute__((nonnull)) then all
// pointer arguments have a nonnull attribute.
if (NonNullArgs.empty()) {
- unsigned idx = 0;
-
- for (FunctionTypeProto::arg_type_iterator
- I=proto->arg_type_begin(), E=proto->arg_type_end(); I!=E; ++I, ++idx)
- if ((*I)->isPointerType())
- NonNullArgs.push_back(idx);
+ for (unsigned I = 0, E = getFunctionOrMethodNumArgs(d); I != E; ++I)
+ if (getFunctionOrMethodArgType(d, I)->isPointerType())
+ NonNullArgs.push_back(I);
if (NonNullArgs.empty()) {
S.Diag(Attr.getLoc(), diag::warn_attribute_nonnull_no_pointers);
@@ -393,8 +403,8 @@
std::string("0"));
return;
}
-
- if (!isa<FunctionDecl>(d) && !isa<ObjCMethodDecl>(d)) {
+
+ if (!isFunctionOrMethod(d)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type,
"noreturn", "function");
return;
@@ -411,7 +421,7 @@
return;
}
- if (!isa<VarDecl>(d) && !getFunctionProto(d)) {
+ if (!isa<VarDecl>(d) && !isFunctionOrMethod(d)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type,
"unused", "variable and function");
return;
@@ -755,9 +765,7 @@
return;
}
- // GCC ignores the format attribute on K&R style function
- // prototypes, so we ignore it as well
- if (!isFunctionOrMethod(d)) {
+ if (!isFunctionOrMethod(d) || !hasFunctionProto(d)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type,
"format", "function");
return;
Added: cfe/trunk/test/Sema/attr-noreturn.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/attr-noreturn.c?rev=57778&view=auto
==============================================================================
--- cfe/trunk/test/Sema/attr-noreturn.c (added)
+++ cfe/trunk/test/Sema/attr-noreturn.c Sat Oct 18 21:04:16 2008
@@ -0,0 +1,14 @@
+// RUN: clang -verify -fsyntax-only %s
+
+static void (*fp0)(void) __attribute__((noreturn));
+
+static void __attribute__((noreturn)) f0(void) {
+ fatal();
+}
+
+// On K&R
+int f1() __attribute__((noreturn));
+
+int g0 __attribute__((noreturn)); // expected-warning {{'noreturn' attribute only applies to function types}}
+
+int f2() __attribute__((noreturn(1, 2))); // expected-error {{attribute requires 0 argument(s)}}
Added: cfe/trunk/test/Sema/attr-unused.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/attr-unused.c?rev=57778&view=auto
==============================================================================
--- cfe/trunk/test/Sema/attr-unused.c (added)
+++ cfe/trunk/test/Sema/attr-unused.c Sat Oct 18 21:04:16 2008
@@ -0,0 +1,12 @@
+// RUN: clang -verify -fsyntax-only %s
+
+static void (*fp0)(void) __attribute__((unused));
+
+static void __attribute__((unused)) f0(void);
+
+// On K&R
+int f1() __attribute__((unused));
+
+int g0 __attribute__((unused));
+
+int f2() __attribute__((unused(1, 2))); // expected-error {{attribute requires 0 argument(s)}}
Modified: cfe/trunk/test/SemaObjC/method-attributes.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/method-attributes.m?rev=57778&r1=57777&r2=57778&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/method-attributes.m (original)
+++ cfe/trunk/test/SemaObjC/method-attributes.m Sat Oct 18 21:04:16 2008
@@ -1,8 +1,10 @@
-// RUN: clang -fsyntax-only %s
+// RUN: clang -verify -fsyntax-only %s
@class NSString;
@interface A
-t1 __attribute__((noreturn));
- (NSString *)stringByAppendingFormat:(NSString *)format, ... __attribute__((format(__NSString__, 1, 2)));
+-(void) m0 __attribute__((noreturn));
+-(void) m1 __attribute__((unused));
@end
More information about the cfe-commits
mailing list