]> granicus.if.org Git - clang/commitdiff
Add implicit declarations of allocation functions when looking them up for
authorRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 4 Feb 2014 01:14:30 +0000 (01:14 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 4 Feb 2014 01:14:30 +0000 (01:14 +0000)
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
lib/Sema/SemaDeclCXX.cpp
lib/Sema/SemaExprCXX.cpp
lib/Sema/SemaLookup.cpp
test/Analysis/NewDelete-variadic.cpp
test/CXX/basic/basic.stc/basic.stc.dynamic/basic.stc.dynamic.allocation/p1.cpp
test/CXX/basic/basic.stc/basic.stc.dynamic/basic.stc.dynamic.deallocation/p1.cpp
test/SemaCXX/cxx0x-cursory-default-delete.cpp

index d102cdf55ddc8051631fc819ec4b8da282a499e6..995898aea48da4b18955f83495bb2792b544a099 100644 (file)
@@ -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;
 }
 
index 9b6407b0b28c61ee6a9c7f0b7b6804b184cb1bba..fbaf5115b612589ace6b55fb20e3b6e1276a03e6 100644 (file)
@@ -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.
index 395a02a8fefa962d102a1be070bc1276c69b3727..8664ef96497ca15c15dedaba05f6c308cc6aa75c 100644 (file)
@@ -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
index 76ea8f3bae0337f912d7b51eb9fc3b16255c4fee..39dd555aeae726c7a58fc9aba270a8ebe6ff2e51 100644 (file)
@@ -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;
     }
   }
 }
index 53dba463bbf9266863e6f83d1c38ba403a6150bf..62a7d17e1b2ad537fc1206f78dcd8510a570a8aa 100644 (file)
@@ -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
 }
index 8a62ae84e2afce2ca010b0ee4a6f0cf866c7f07e..3b77a62ce7d6f8832a232403212c4b1e50263305 100644 (file)
@@ -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 *'}}
index e00e9486f0bfa9b080ed25def74650d5bee6e6eb..09dde8efde00e214efa4291c95e48fb64f9995c9 100644 (file)
@@ -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}}
index b1078dc404b17a76d3eb4ff3ddb7c4e1ae3cae90..94d5c297efa83a142e5160741156d731e43266a7 100644 (file)
@@ -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}}