]> granicus.if.org Git - clang/commitdiff
If a replaceable global operator new/delete is marked inline, don't warn if
authorRichard Smith <richard-llvm@metafoo.co.uk>
Sat, 16 Nov 2013 01:57:09 +0000 (01:57 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Sat, 16 Nov 2013 01:57:09 +0000 (01:57 +0000)
it's also __attribute__((used)), since that undoes the problematic part of
'inline'.

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

lib/Sema/SemaDecl.cpp
test/SemaCXX/new-delete.cpp

index 0527e4957913aa23c46dac1f5a814fae3ccdfb1a..3cdb72714f46256354a90aede99deb10eb02f914 100644 (file)
@@ -6872,15 +6872,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
       NewFD->setType(Context.getFunctionType(FPT->getResultType(),
                                              FPT->getArgTypes(), EPI));
     }
-
-    // C++11 [replacement.functions]p3:
-    //  The program's definitions shall not be specified as inline.
-    //
-    // N.B. We diagnose declarations instead of definitions per LWG issue 2340.
-    if (isInline && NewFD->isReplaceableGlobalAllocationFunction())
-      Diag(D.getDeclSpec().getInlineSpecLoc(),
-           diag::ext_operator_new_delete_declared_inline)
-        << NewFD->getDeclName();
   }
 
   // Filter out previous declarations that don't match the scope.
@@ -7015,6 +7006,20 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
             Previous.getResultKind() != LookupResult::FoundOverloaded) &&
            "previous declaration set still overloaded");
   } else {
+    // C++11 [replacement.functions]p3:
+    //  The program's definitions shall not be specified as inline.
+    //
+    // N.B. We diagnose declarations instead of definitions per LWG issue 2340.
+    //
+    // Suppress the diagnostic if the function is __attribute__((used)), since
+    // that forces an external definition to be emitted.
+    if (D.getDeclSpec().isInlineSpecified() &&
+        NewFD->isReplaceableGlobalAllocationFunction() &&
+        !NewFD->hasAttr<UsedAttr>())
+      Diag(D.getDeclSpec().getInlineSpecLoc(),
+           diag::ext_operator_new_delete_declared_inline)
+        << NewFD->getDeclName();
+
     // If the declarator is a template-id, translate the parser's template 
     // argument list into our AST format.
     if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) {
index 2f408525ea3d1fd5e689b3da2bc9c7fa1d80cc04..7facd10ca5fc8d93de9deca0338f79ee6a084265 100644 (file)
@@ -18,14 +18,19 @@ struct V : U
 {
 };
 
+inline void operator delete(void *); // expected-warning {{replacement function 'operator delete' cannot be declared 'inline'}}
+
+__attribute__((used))
+inline void *operator new(size_t) { // no warning, due to __attribute__((used))
+  return 0;
+}
+
 // PR5823
 void* operator new(const size_t); // expected-note 2 {{candidate}}
 void* operator new(size_t, int*); // expected-note 3 {{candidate}}
 void* operator new(size_t, float*); // expected-note 3 {{candidate}}
 void* operator new(size_t, S); // expected-note 2 {{candidate}}
 
-inline void operator delete(void *); // expected-warning {{replacement function 'operator delete' cannot be declared 'inline'}}
-
 struct foo { };
 
 void good_news()