From 661bb397eb18942cb53ca14399065ad3489bf40c Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Tue, 4 Feb 2014 01:14:30 +0000 Subject: [PATCH] Add implicit declarations of allocation functions when looking them up for redeclaration, not just when looking them up for a use -- we need the implicit declaration to appropriately check various properties of them (notably, whether they're deleted). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@200729 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaDecl.cpp | 29 ++++++++------ lib/Sema/SemaDeclCXX.cpp | 9 +++-- lib/Sema/SemaExprCXX.cpp | 4 +- lib/Sema/SemaLookup.cpp | 40 +++++++++---------- test/Analysis/NewDelete-variadic.cpp | 16 +++++--- .../basic.stc.dynamic.allocation/p1.cpp | 3 +- .../basic.stc.dynamic.deallocation/p1.cpp | 3 +- test/SemaCXX/cxx0x-cursory-default-delete.cpp | 4 ++ 8 files changed, 62 insertions(+), 46 deletions(-) diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index d102cdf55d..995898aea4 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -2304,11 +2304,14 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S, // Determine whether the previous declaration was a definition, // implicit declaration, or a declaration. diag::kind PrevDiag; + SourceLocation OldLocation = Old->getLocation(); if (Old->isThisDeclarationADefinition()) PrevDiag = diag::note_previous_definition; - else if (Old->isImplicit()) + else if (Old->isImplicit()) { PrevDiag = diag::note_previous_implicit_declaration; - else + if (OldLocation.isInvalid()) + OldLocation = New->getLocation(); + } else PrevDiag = diag::note_previous_declaration; // Don't complain about this if we're in GNU89 mode and the old function @@ -2322,10 +2325,10 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S, !canRedefineFunction(Old, getLangOpts())) { if (getLangOpts().MicrosoftExt) { Diag(New->getLocation(), diag::warn_static_non_static) << New; - Diag(Old->getLocation(), PrevDiag); + Diag(OldLocation, PrevDiag); } else { Diag(New->getLocation(), diag::err_static_non_static) << New; - Diag(Old->getLocation(), PrevDiag); + Diag(OldLocation, PrevDiag); return true; } } @@ -2391,7 +2394,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S, Diag(New->getLocation(), diag::err_regparm_mismatch) << NewType->getRegParmType() << OldType->getRegParmType(); - Diag(Old->getLocation(), diag::note_previous_declaration); + Diag(OldLocation, diag::note_previous_declaration); return true; } @@ -2403,7 +2406,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S, if (OldTypeInfo.getProducesResult() != NewTypeInfo.getProducesResult()) { if (NewTypeInfo.getProducesResult()) { Diag(New->getLocation(), diag::err_returns_retained_mismatch); - Diag(Old->getLocation(), diag::note_previous_declaration); + Diag(OldLocation, diag::note_previous_declaration); return true; } @@ -2468,7 +2471,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S, diag::err_member_def_does_not_match_ret_type) << New; else Diag(New->getLocation(), diag::err_ovl_diff_return_type); - Diag(Old->getLocation(), PrevDiag) << Old << Old->getType(); + Diag(OldLocation, PrevDiag) << Old << Old->getType(); return true; } else @@ -2514,7 +2517,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S, // is a static member function declaration. if (OldMethod->isStatic() != NewMethod->isStatic()) { Diag(New->getLocation(), diag::err_ovl_static_nonstatic_member); - Diag(Old->getLocation(), PrevDiag) << Old << Old->getType(); + Diag(OldLocation, PrevDiag) << Old << Old->getType(); return true; } @@ -2538,7 +2541,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S, Diag(New->getLocation(), diag::err_member_redeclared_in_instantiation) << New << New->getType(); } - Diag(Old->getLocation(), PrevDiag) << Old << Old->getType(); + Diag(OldLocation, PrevDiag) << Old << Old->getType(); // Complain if this is an explicit declaration of a special // member that was initially declared implicitly. @@ -2611,10 +2614,10 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S, // Check cautiously as the friend object kind isn't yet complete. if (New->getFriendObjectKind() != Decl::FOK_None) { Diag(New->getLocation(), diag::ext_retained_language_linkage) << New; - Diag(Old->getLocation(), PrevDiag); + Diag(OldLocation, PrevDiag); } else { Diag(New->getLocation(), diag::err_different_language_linkage) << New; - Diag(Old->getLocation(), PrevDiag); + Diag(OldLocation, PrevDiag); return true; } } @@ -2751,7 +2754,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S, // or 'printf', just warn about the incompatible redeclaration. if (Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) { Diag(New->getLocation(), diag::warn_redecl_library_builtin) << New; - Diag(Old->getLocation(), diag::note_previous_builtin_declaration) + Diag(OldLocation, diag::note_previous_builtin_declaration) << Old << Old->getType(); // If this is a global redeclaration, just forget hereafter @@ -2772,7 +2775,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S, } Diag(New->getLocation(), diag::err_conflicting_types) << New->getDeclName(); - Diag(Old->getLocation(), PrevDiag) << Old << Old->getType(); + Diag(OldLocation, PrevDiag) << Old << Old->getType(); return true; } diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 9b6407b0b2..fbaf5115b6 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -11948,10 +11948,13 @@ void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) { if (const FunctionDecl *Prev = Fn->getPreviousDecl()) { // Don't consider the implicit declaration we generate for explicit // specializations. FIXME: Do not generate these implicit declarations. - if ((Prev->getTemplateSpecializationKind() != TSK_ExplicitSpecialization - || Prev->getPreviousDecl()) && !Prev->isDefined()) { + if ((Prev->getTemplateSpecializationKind() != TSK_ExplicitSpecialization || + Prev->getPreviousDecl()) && + !Prev->isDefined()) { Diag(DelLoc, diag::err_deleted_decl_not_first); - Diag(Prev->getLocation(), diag::note_previous_declaration); + Diag(Prev->getLocation().isInvalid() ? DelLoc : Prev->getLocation(), + Prev->isImplicit() ? diag::note_previous_implicit_declaration + : diag::note_previous_declaration); } // If the declaration wasn't the first, we delete the function anyway for // recovery. diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 395a02a8fe..8664ef9649 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -2111,11 +2111,13 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, Alloc->addAttr(MallocAttr::CreateImplicit(Context)); ParmVarDecl *ParamDecls[2]; - for (unsigned I = 0; I != NumParams; ++I) + for (unsigned I = 0; I != NumParams; ++I) { ParamDecls[I] = ParmVarDecl::Create(Context, Alloc, SourceLocation(), SourceLocation(), 0, Params[I], /*TInfo=*/0, SC_None, 0); + ParamDecls[I]->setImplicit(); + } Alloc->setParams(ArrayRef(ParamDecls, NumParams)); // FIXME: Also add this declaration to the IdentifierResolver, but diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 76ea8f3bae..39dd555aea 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -288,29 +288,27 @@ void LookupResult::configure() { IDNS = getIDNS(LookupKind, SemaRef.getLangOpts().CPlusPlus, isForRedeclaration()); - if (!isForRedeclaration()) { - // If we're looking for one of the allocation or deallocation - // operators, make sure that the implicitly-declared new and delete - // operators can be found. - switch (NameInfo.getName().getCXXOverloadedOperator()) { - case OO_New: - case OO_Delete: - case OO_Array_New: - case OO_Array_Delete: - SemaRef.DeclareGlobalNewDelete(); - break; + // If we're looking for one of the allocation or deallocation + // operators, make sure that the implicitly-declared new and delete + // operators can be found. + switch (NameInfo.getName().getCXXOverloadedOperator()) { + case OO_New: + case OO_Delete: + case OO_Array_New: + case OO_Array_Delete: + SemaRef.DeclareGlobalNewDelete(); + break; - default: - break; - } + default: + break; + } - // Compiler builtins are always visible, regardless of where they end - // up being declared. - if (IdentifierInfo *Id = NameInfo.getName().getAsIdentifierInfo()) { - if (unsigned BuiltinID = Id->getBuiltinID()) { - if (!SemaRef.Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) - AllowHidden = true; - } + // Compiler builtins are always visible, regardless of where they end + // up being declared. + if (IdentifierInfo *Id = NameInfo.getName().getAsIdentifierInfo()) { + if (unsigned BuiltinID = Id->getBuiltinID()) { + if (!SemaRef.Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) + AllowHidden = true; } } } diff --git a/test/Analysis/NewDelete-variadic.cpp b/test/Analysis/NewDelete-variadic.cpp index 53dba463bb..62a7d17e1b 100644 --- a/test/Analysis/NewDelete-variadic.cpp +++ b/test/Analysis/NewDelete-variadic.cpp @@ -5,15 +5,19 @@ namespace std { typedef __typeof__(sizeof(int)) size_t; } -void *operator new(std::size_t, ...); -void *operator new[](std::size_t, ...); +struct X {}; + +void *operator new(std::size_t, X, ...); +void *operator new[](std::size_t, X, ...); void testGlobalCustomVariadicNew() { - void *p1 = operator new(0); // no warn + X x; + + void *p1 = operator new(0, x); // no warn - void *p2 = operator new[](0); // no warn + void *p2 = operator new[](0, x); // no warn - int *p3 = new int; // no warn + int *p3 = new (x) int; // no warn - int *p4 = new int[0]; // no warn + int *p4 = new (x) int[0]; // no warn } diff --git a/test/CXX/basic/basic.stc/basic.stc.dynamic/basic.stc.dynamic.allocation/p1.cpp b/test/CXX/basic/basic.stc/basic.stc.dynamic/basic.stc.dynamic.allocation/p1.cpp index 8a62ae84e2..3b77a62ce7 100644 --- a/test/CXX/basic/basic.stc/basic.stc.dynamic/basic.stc.dynamic.allocation/p1.cpp +++ b/test/CXX/basic/basic.stc/basic.stc.dynamic/basic.stc.dynamic.allocation/p1.cpp @@ -9,7 +9,8 @@ namespace NS { void *operator new(size_t);; // expected-error {{'operator new' cannot be declared inside a namespace}} } -static void *operator new(size_t); // expected-error {{'operator new' cannot be declared static in global scope}} +static void *operator new(size_t); // expected-error {{static declaration of 'operator new' follows non-static declaration}} expected-note {{previous}} +static void *operator new(size_t, int, int); // expected-error {{'operator new' cannot be declared static in global scope}} struct B { void operator new(size_t); // expected-error {{'operator new' must return type 'void *'}} diff --git a/test/CXX/basic/basic.stc/basic.stc.dynamic/basic.stc.dynamic.deallocation/p1.cpp b/test/CXX/basic/basic.stc/basic.stc.dynamic/basic.stc.dynamic.deallocation/p1.cpp index e00e9486f0..09dde8efde 100644 --- a/test/CXX/basic/basic.stc/basic.stc.dynamic/basic.stc.dynamic.deallocation/p1.cpp +++ b/test/CXX/basic/basic.stc/basic.stc.dynamic/basic.stc.dynamic.deallocation/p1.cpp @@ -8,4 +8,5 @@ namespace NS { void operator delete(void *); // expected-error {{'operator delete' cannot be declared inside a namespace}} } -static void operator delete(void *); // expected-error {{'operator delete' cannot be declared static in global scope}} +static void operator delete(void *); // expected-error {{follows non-static declaration}} expected-note {{implicit}} +static void operator delete(void *, int, int); // expected-error {{'operator delete' cannot be declared static in global scope}} diff --git a/test/SemaCXX/cxx0x-cursory-default-delete.cpp b/test/SemaCXX/cxx0x-cursory-default-delete.cpp index b1078dc404..94d5c297ef 100644 --- a/test/SemaCXX/cxx0x-cursory-default-delete.cpp +++ b/test/SemaCXX/cxx0x-cursory-default-delete.cpp @@ -80,3 +80,7 @@ struct except_spec_d_match : except_spec_a, except_spec_b { // (but not normal definitions) struct S { S(); }; S::S() __attribute((pure)) = default; + +using size_t = decltype(sizeof(0)); +void *operator new(size_t) = delete; // expected-error {{deleted definition must be first declaration}} expected-note {{implicit}} +void operator delete(void *) = delete; // expected-error {{deleted definition must be first declaration}} expected-note {{implicit}} -- 2.40.0