aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Sema/SemaType.cpp14
-rw-r--r--test/Parser/objcxx11-attributes.mm2
-rw-r--r--test/SemaCXX/cxx11-gnu-attrs.cpp10
3 files changed, 25 insertions, 1 deletions
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 3b1dac348e..e849e05c7b 100644
--- a/lib/Sema/SemaType.cpp
+++ b/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/test/Parser/objcxx11-attributes.mm b/test/Parser/objcxx11-attributes.mm
index ad54208286..9ad85d310f 100644
--- a/test/Parser/objcxx11-attributes.mm
+++ b/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/test/SemaCXX/cxx11-gnu-attrs.cpp b/test/SemaCXX/cxx11-gnu-attrs.cpp
index fdcb75057e..a9fcee3da3 100644
--- a/test/SemaCXX/cxx11-gnu-attrs.cpp
+++ b/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");