]> granicus.if.org Git - clang/commitdiff
Fix behavior of [[gnu::]] function attributes. Per g++'s behavior, these
authorRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 15 Jan 2013 02:48:13 +0000 (02:48 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 15 Jan 2013 02:48:13 +0000 (02:48 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@172504 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaType.cpp
test/Parser/objcxx11-attributes.mm
test/SemaCXX/cxx11-gnu-attrs.cpp

index 3b1dac348e8361bdad35c90758f27d37c11a63dc..e849e05c7b42e9c97f8df5dfdc0781f04650b642 100644 (file)
@@ -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);
index ad54208286826fe9e756266819a4262c159e6af3..9ad85d310f989d7833a9b8321aba69da583a90c8 100644 (file)
@@ -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 ()'}}
 
index fdcb75057e7f4286dd9e2a966fb7e609e43686d2..a9fcee3da3f61add249d4ff37071e10019287125 100644 (file)
@@ -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");