From: Richard Smith Date: Sat, 16 Nov 2013 01:57:09 +0000 (+0000) Subject: If a replaceable global operator new/delete is marked inline, don't warn if X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=cf19e5bad3efe2c7efa886e984988ea21825c45d;p=clang If a replaceable global operator new/delete is marked inline, don't warn if 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 --- diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 0527e49579..3cdb72714f 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -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()) + 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) { diff --git a/test/SemaCXX/new-delete.cpp b/test/SemaCXX/new-delete.cpp index 2f408525ea..7facd10ca5 100644 --- a/test/SemaCXX/new-delete.cpp +++ b/test/SemaCXX/new-delete.cpp @@ -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()