summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2013-01-15 02:48:13 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2013-01-15 02:48:13 +0000
commit0faa2b1ae45d20c8287a329d505373ae062153ca (patch)
tree41662c41ca0bbac588448dd45c8ab1516fc0d6c4 /clang
parent184e981111d74fe650b7ea4506adc9bc356273ee (diff)
downloadbcm5719-llvm-0faa2b1ae45d20c8287a329d505373ae062153ca.tar.gz
bcm5719-llvm-0faa2b1ae45d20c8287a329d505373ae062153ca.zip
Fix behavior of [[gnu::]] function attributes. Per g++'s behavior, these
attributes appertain to a declaration, even though they would be much more naturally modelled as appertaining to a function type. Previously, we would try to distribute them from the declarator to the function type, then reject them for being at an incorrect location. Now, we just distribute them as far as the declarator; the existing attribute handling code can actually apply them there just fine. llvm-svn: 172504
Diffstat (limited to 'clang')
-rw-r--r--clang/lib/Sema/SemaType.cpp14
-rw-r--r--clang/test/Parser/objcxx11-attributes.mm2
-rw-r--r--clang/test/SemaCXX/cxx11-gnu-attrs.cpp10
3 files changed, 25 insertions, 1 deletions
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 3b1dac348e8..e849e05c7b4 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -463,6 +463,15 @@ distributeFunctionTypeAttrFromDeclSpec(TypeProcessingState &state,
QualType &declSpecType) {
state.saveDeclSpecAttrs();
+ // C++11 attributes before the decl specifiers actually appertain to
+ // the declarators. Move them straight there. We don't support the
+ // 'put them wherever you like' semantics we allow for GNU attributes.
+ if (attr.isCXX11Attribute()) {
+ moveAttrFromListToList(attr, state.getCurrentAttrListRef(),
+ state.getDeclarator().getAttrListRef());
+ return;
+ }
+
// Try to distribute to the innermost.
if (distributeFunctionTypeAttrToInnermost(state, attr,
state.getCurrentAttrListRef(),
@@ -512,6 +521,11 @@ static void distributeTypeAttrsFromDeclarator(TypeProcessingState &state,
do {
next = attr->getNext();
+ // Do not distribute C++11 attributes. They have strict rules for what
+ // they appertain to.
+ if (attr->isCXX11Attribute())
+ continue;
+
switch (attr->getKind()) {
OBJC_POINTER_TYPE_ATTRS_CASELIST:
distributeObjCPointerTypeAttrFromDeclarator(state, *attr, declSpecType);
diff --git a/clang/test/Parser/objcxx11-attributes.mm b/clang/test/Parser/objcxx11-attributes.mm
index ad542082868..9ad85d310f9 100644
--- a/clang/test/Parser/objcxx11-attributes.mm
+++ b/clang/test/Parser/objcxx11-attributes.mm
@@ -44,7 +44,7 @@ void f(X *noreturn) {
int e2(); // expected-warning {{interpreted as a function declaration}} expected-note{{}}
// A function taking a noreturn function.
- int(f)([[noreturn]] int()); // expected-note {{here}}
+ int(f)([[gnu::noreturn]] int ()); // expected-note {{here}}
f(e);
f(e2); // expected-error {{cannot initialize a parameter of type 'int (*)() __attribute__((noreturn))' with an lvalue of type 'int ()'}}
diff --git a/clang/test/SemaCXX/cxx11-gnu-attrs.cpp b/clang/test/SemaCXX/cxx11-gnu-attrs.cpp
index fdcb75057e7..a9fcee3da3f 100644
--- a/clang/test/SemaCXX/cxx11-gnu-attrs.cpp
+++ b/clang/test/SemaCXX/cxx11-gnu-attrs.cpp
@@ -39,7 +39,17 @@ void deprecated3() {
void nonnull [[gnu::nonnull]] (); // expected-warning {{applied to function with no pointer arguments}}
+// [[gnu::noreturn]] appertains to a declaration, and marks the innermost
+// function declarator in that declaration as being noreturn.
int noreturn [[gnu::noreturn]]; // expected-warning {{'noreturn' only applies to function types}}
+int noreturn_fn_1();
+int noreturn_fn_2() [[gnu::noreturn]]; // expected-warning {{cannot be applied to a type}}
+int noreturn_fn_3 [[gnu::noreturn]] ();
+[[gnu::noreturn]] int noreturn_fn_4();
+int (*noreturn_fn_ptr_1 [[gnu::noreturn]])() = &noreturn_fn_1; // expected-error {{cannot initialize}}
+int (*noreturn_fn_ptr_2 [[gnu::noreturn]])() = &noreturn_fn_3;
+[[gnu::noreturn]] int (*noreturn_fn_ptr_3)() = &noreturn_fn_1; // expected-error {{cannot initialize}}
+[[gnu::noreturn]] int (*noreturn_fn_ptr_4)() = &noreturn_fn_3;
struct [[gnu::packed]] packed { char c; int n; };
static_assert(sizeof(packed) == sizeof(char) + sizeof(int), "not packed");
OpenPOWER on IntegriCloud