mirror of
https://github.com/intel/llvm.git
synced 2026-01-27 06:06:34 +08:00
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). llvm-svn: 200729
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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<ParmVarDecl*>(ParamDecls, NumParams));
|
||||
|
||||
// FIXME: Also add this declaration to the IdentifierResolver, but
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 *p2 = operator new[](0); // no warn
|
||||
void *p1 = operator new(0, x); // no warn
|
||||
|
||||
int *p3 = new int; // no warn
|
||||
void *p2 = operator new[](0, x); // no warn
|
||||
|
||||
int *p4 = new int[0]; // no warn
|
||||
int *p3 = new (x) int; // no warn
|
||||
|
||||
int *p4 = new (x) int[0]; // no warn
|
||||
}
|
||||
|
||||
@@ -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 *'}}
|
||||
|
||||
@@ -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}}
|
||||
|
||||
@@ -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}}
|
||||
|
||||
Reference in New Issue
Block a user